Return-Path: X-Original-To: apmail-felix-dev-archive@www.apache.org Delivered-To: apmail-felix-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 121EE11D24 for ; Mon, 13 May 2013 17:39:56 +0000 (UTC) Received: (qmail 81213 invoked by uid 500); 13 May 2013 17:13:16 -0000 Delivered-To: apmail-felix-dev-archive@felix.apache.org Received: (qmail 81138 invoked by uid 500); 13 May 2013 17:13:16 -0000 Mailing-List: contact dev-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list dev@felix.apache.org Received: (qmail 81129 invoked by uid 99); 13 May 2013 17:13:16 -0000 Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 May 2013 17:13:16 +0000 Date: Mon, 13 May 2013 17:13:16 +0000 (UTC) From: "Pierre De Rop (JIRA)" To: dev@felix.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Commented] (FELIX-4050) Named dependencies are not injected if new dependencies are added at init phase. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 [ https://issues.apache.org/jira/browse/FELIX-4050?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13656128#comment-13656128 ] Pierre De Rop commented on FELIX-4050: -------------------------------------- I'm not sure I fully understand the described issue. May be you could attach a sample code reproducing the exact problem you are describing ? In the mean time, here is more information about the @Init annotation, and also about the @ServiceDependency used with a "name" attribute: 1- @Init annotation: ============== >From the method annotated with @Init, you are allowed to dynamically add dependencies using the API. For instance, assuming that S depends on S1/S2/S3, you can then declare "S" as in the following example: @Component public class S { // required dependency on service "S1" @ServiceDependency S1 _s1; // S2, which dependency is dynamically added in init() method S2 _s2; // S3, which dependency is dynamically added in init() mehtod S3 _s3; // Inject the API, used by our init() method @Inject org.apache.felix.dm.Component _c; // Atomically adds dependencies on S2/S3 @Init void init() { List l = new ArrayList(); l.add(_c.getDependencyManager().createServiceDependency() .setService(S2.class) .setRequired(true) .setAutoConfig("_s2") .setInstanceBound(true)); l.add(_c.getDependencyManager().createServiceDependency() .setService(S3.class, "(foo=bar)") .setRequired(true) .setAutoConfig("_s3") .setInstanceBound(true)); _c.add(l); } @Start void start() { System.out.println("started: s2=" + _s2 + ", s3=" + _s3); } } In the init() method, notice the following important points: - S2/S3 dependencies are added atomically, using Component.add(List) method. When more than one dependency is added from the init() method, it is better to add them using a List, because List of Dependencies are added atomically: doing so prevent the @Start method to be called if the first dependency (S2) is available before we add the last dependency S3. Here, the @Start method will be called only after S2 and S3 dependencies have been added and are available. - the S2/S3 extra dependencies are "instance bound": it means that even if S2 and/or S3 are not available, then "S" component won't be destroyed immediately. You can refer to the following post, where Marcel explains "instance bound" dependencies: http://www.mail-archive.com/users@felix.apache.org/msg09314.html 2- Named @ServiceDependencies ========================= Now, let's describe when to declare a @ServiceDependency with a "name" attribute: "named" dependencies are only available using the annotations, not using the API. When you declare a @ServiceDependency with a "name" attribute, you can configure its 'required' flag and its filter by returning a Map from the @Init method. For instance, assuming that you want to configure the S2 'required' flag and also its filter from ConfigAdmin, then you can do it like this: @Component public class S { // Config Admin properties, where the S2 'required' flag and filter is configured private Dictionary config; // Inject our configuration @ConfigurationDependency(pid="MyPid") void configure(Dictionary config) { this.config = config; } // S2 dependency, whose 'required' flag and filter is dynamically configured from init() method. @ServiceDependency(name="S2") S2 s2; /** * Configure our "S2" dependency, using the already injected configuration. * The returned Map will be used to configure our "S2" Dependency (see above). * The convention is: each Map keys must be prefixed with a dependency name, and must then * be suffixed with either "filter" (for the dependency filter) or "required" (for the dependency 'required' flag). */ @Init Map init() { return new HashMap() {{ put("S2.filter", m_config.get("filter")); put("S2.required", m_config.get("required")); }}; } @Start void start() { System.out.println("started: s2=" + _s2 + ", s3=" + _s3); } } You can refer to the following documentation for more information about named dependencies: http://felix.apache.org/site/apache-felix-dependency-manager-using-annotations-lifecycle.html Please, check "Dynamic Dependency Configuration" section. by the way, I just saw that dependencymanager documentation is somewhat broken from URL: http://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager/apache-felix-dependency-manager-using-annotations.html Please refer to the old site for dm annotation documentation: http://felix.apache.org/site/apache-felix-dependency-manager-using-annotations.html (I will fix the doc from http://felix.apache.org/documentation asap). > Named dependencies are not injected if new dependencies are added at init phase. > -------------------------------------------------------------------------------- > > Key: FELIX-4050 > URL: https://issues.apache.org/jira/browse/FELIX-4050 > Project: Felix > Issue Type: Bug > Components: Dependency Manager > Affects Versions: dependencymanager-3.1.0 > Reporter: Tuomas Kiviaho > > Spec says that "In the Init method, you are yet allowed to add some additional dependencies (but using the API)." > I guess this means that I am allowed to call Component.add(). This leads to state transition for instance when new service dependency is added since it's started right away because component is already instantiated at this point. Component.dependencyAvailable() is called if service tracker finds a match right away and this in turn starts the state change calculation. > Problem is that State uses components current instantiated status to determinate whether it is bound or not and not the status what the component was given to the activateService() method. State change calculation transitions to bound state prematurely because component is now instantiated. All required dependencies are available, because component is still unaware of forthcoming named dependencies at this point. > I suggest that some sort of placeholder dependencies are used which the named dependencies will replace when they are created/configured. This also approach also preserves the order in which dependencies were actually added to the component. In the future there could be a new is/SetActive property to DependencyActivation which could be used to turn on/off an already added dependencies. Then named dependencies could be used as such instead of placeholders and user could even configure them directly. -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira