1 2 3 Previous Next 37 Replies Latest reply on Nov 23, 2009 8:46 AM by adrian.brock Go to original post
      • 15. Re: Service integration with MC
        thomas.diesler

         

        "alesj" wrote:

        * OSGi services will be exposed as MC beans


        I suppose that means you can reference/inject OSGi services in the an MC descriptor. Could you describe/show how this would look like? How would this work with service properties. How would this work with multiple implementations of the same service interface?

        "alesj" wrote:

        * MC beans will be listed as a OSGi services


        I suppose that means you can reference/inject MC beans in a BP descriptor. Here as well, could you please describe/show how this would look like? Do MC beans support service properties i.e. Can I use an LDAP filter to find the target service? Can you have multiple implementations of the same service interface? How would the service event model work i.e. Can I use ServiceTracker to track MC beans?

        • 16. Re: Service integration with MC
          alesj

          Thomas, hold your horses. ;-)
          It will all be presented when some initial work is done.

          • 17. Re: Service integration with MC
            alesj

             

            "alesj" wrote:

            But what to do with stop, destroy and uninstalls?
            try {
             uninstallMethod.invoke(target, VMD::get)
            } finally {
             VDM::unget
            }
            

            whereas service could still hold onto the ref - which might be an issue if that ref is ServiceFactory,
            as ServiceFactory::unget could modify the actual created service.

            Another problem/ugliness that I see is the usage of "external" service to do proper parameter type matching at uninstall.

            e.g. bean + parameters at uninstalls, bean + parameters in value-factory, ...

            This can be "properly" dealt with double call to ungetTarget.
            if (unget)
            {
             try
             {
             Object target = context.getTarget();
             // do parameter type matching
             ...
             }
             finally
             {
             context.ungetTarget();
             }
             context.ungetTarget();
            }
            


            • 18. Re: Service integration with MC
              alesj

               

              "alesj" wrote:

              Another problem/ugliness that I see is the usage of "external" service to do proper parameter type matching at uninstall.

              OK, I think I know how to get past this one.

              But that still leaves the problem of actual service usage at undeploy:
              "alesj" wrote:

              whereas service could still hold onto the ref - which might be an issue if that ref is ServiceFactory,
              as ServiceFactory::unget could modify the actual created service.


              • 19. Re: Service integration with MC
                alesj

                 

                "alesj" wrote:

                But that still leaves the problem of actual service usage at undeploy:
                "alesj" wrote:

                whereas service could still hold onto the ref - which might be an issue if that ref is ServiceFactory,
                as ServiceFactory::unget could modify the actual created service.

                Actually SF::unget is called at service unregister,
                so this is a bit different, but doesn't change the problem that much.

                We could still end up with "illegal" service,
                but that's also the case right now - any install/uninstall that keeps injected service ref,
                would be unwinded to appropriate state, but the ref would still be there,
                once it's re-winded.

                e.g.
                public someInstall(@Inject Foo bar)
                {
                 if (this.bar != null) // which is true after unwind/re-wind
                 ... // do some crazy stuff on it
                
                 this.bar = bar;
                }
                


                But I guess that's the problem of encapsulation,
                where we go beyond plain java beans.

                So, the problem just remains with the ugliness,
                but I guess we can cope with that.
                try
                {
                 // do some uninstall on CC:getTarget
                }
                finally
                {
                 // invoke CC:ungetTarget
                }
                


                • 20. Re: Service integration with MC

                  I'm not following what you are talking about?

                  Anything you getTarget() during the install() phase should have
                  a corresponding ungetTarget() during the uninstall() of the lifecycle.

                  If somebody is using the api manually (either the MC api directly or the OSGi api)
                  then it is up to them to make sure they don't have stale references.

                  With OSGi the references can go stale at anytime anyway, which is why the
                  service notification mechanism exists (in principle we should automatically
                  respond those if IOC is used and "redeploy" whatever it was injected into?)

                  Even if they do, they will/should be tidied up at Deployment/Bundle.stop()
                  when the ServiceTracking for that context should be disabled/cleaned up.

                  The ServiceFactory is just a lazy version of the service. i.e. you only construct it
                  if somebody wants to use it. Its still a singleton. It only controls when the object
                  is constructed (first access instead of upfront).

                  • 21. Re: Service integration with MC

                    On the blueprint stuff, I'll repeat from an earlier thread.

                    This should just be another facade on the MC like the spring-int project is.
                    There is no reason to re-implement it when we already know there
                    is a mapping from the spring-int example.

                    Its just a change of namespace and some xml element/attribute names. :-)

                    Any missing features/metadata should be implemented in the MC.

                    In fact, from my (incomplete ;-) understanding of blueprint, its basically two different
                    injection mechanisms in one xml file.
                    One using a "Spring" type api and one using an "OSGi" type for the two different
                    mechanisms.

                    When Ales has this working, you should able to use either type to inject any service
                    within JBoss. Just choose your poison. ;-)

                    • 22. Re: Service integration with MC
                      alesj

                       

                      "adrian@jboss.org" wrote:

                      Anything you getTarget() during the install() phase should have
                      a corresponding ungetTarget() during the uninstall() of the lifecycle.

                      Sure, that's what I'm doing, for symmetric usage that's trivial/natural to support.
                      But that's not the case with our installs, actually uninstalls.

                      e.g.
                      my install - someXInstall(Foo foo, Bar bar, int x)
                      "matching" uninstall - undoXInstall(Baz baz, double y)
                      Where we inject this Baz instance.

                      And since this is the last time we actually know something about this injection,
                      we need to clean it up right after the invocation. Or how else?

                      See doUninstalls:
                      * http://anonsvn.jboss.org/repos/jbossas/projects/kernel/trunk/kernel/src/main/java/org/jboss/kernel/plugins/dependency/InstallsAwareAction.java

                      • 23. Re: Service integration with MC

                        Of course, if you are already in the uninstall lifecycle like the uninstalls or stop/destroy
                        then you effectively do:

                        Object parameter = dependency.getTarget(me);
                        try
                        {
                         invokeStop(parameter);
                        }
                        finally
                        {
                         dependency.ungetTarget(me);
                        }
                        


                        • 24. Re: Service integration with MC
                          kabirkhan

                           

                          "adrian@jboss.org" wrote:

                          As part of the OSGi stuff, I've made the DeploymentUnit part of the MDR's
                          deployment level metadata. You should extend this concept so that the
                          dependency project can look for a "ServiceTracker" in the MDR rather than
                          a DeploymentUnit. The deployers project would then add the ServiceTracker
                          attachment by the default to the deployment level metadata.

                          Where is this code?

                          • 25. Re: Service integration with MC
                            thomas.diesler

                             

                            "adrian" wrote:

                            The ServiceFactory is just a lazy version of the service. i.e. you only construct it
                            if somebody wants to use it. Its still a singleton. It only controls when the object
                            is constructed (first access instead of upfront).


                            Not quite. The main purpose of the ServiceFactory is that every client (bundle) of the service gets its own individual instance of the service. The service implementation may be stateful and maintain state on behalf of the client bundle. If the same bundle gets the service multiple times, it will receive the same service instance. An internal usage count is used to determine when the service can cleanup its state (i.e. when the usage count is 0)

                            • 26. Re: Service integration with MC
                              alesj

                               

                              "adrian@jboss.org" wrote:

                              So we add a "ServiceTracker" to the MDR which for deployments will be in the deployment level (really the application/top level deployment)
                              for others it will be as you say a default one at the Server level, what osgi calls the "SystemBundle".
                              You can imagine others might choose to track at some other level. e.g.
                              for JavaEE we might choose to track at sub-deployment level, what MDR
                              confusingly calls the deployment level. :-)

                              When you do any type of injection (or the api is invoked from somewhere else)
                              this should invoke the equivalent of get/unget of the ServiceTracker for that context.

                              Once that is done, the queries can go through the ServiceTracker at the relevant level.
                              The deployment level for normal OSGiBundleState and the server level for the SystemBundle.

                              You still need a "global" list of services for the getXXXServiceXXX() queries.
                              That should primarily be based on an index by class (it doesn't have to be
                              its a performance optimization and only available when you have been asked
                              to query by class). But once you've subsetted by class then you do a
                              "read and skip" over those contexts to locate the ones that match any passed filter on the properties (instance level MDR).

                              I fail to see why I would need two different levels of ServiceTracker.
                              As I also always have to check the "global" list.

                              When would I check just deployment level ServiceTracker?
                              For non-system bundle, to lookup non-osgi services that belong just to this bundle / jar / deployment?


                              • 27. Re: Service integration with MC

                                 

                                "alesj" wrote:

                                I fail to see why I would need two different levels of ServiceTracker.
                                As I also always have to check the "global" list.

                                When would I check just deployment level ServiceTracker?
                                For non-system bundle, to lookup non-osgi services that belong just to this bundle / jar / deployment?


                                It is the stats that are at different levels.

                                * The queries are global.
                                * The inuse tracking is at system/application/deployment level, i.e. this deployment
                                uses a service from some other deployment and the some other deployment's service
                                has its "in use" count integrated.

                                See the current OSGi code. The queries run against the OSGiBundleManager (should be Controller).
                                The other statistics are at BundleState level (should be ServiceTracker at whatever
                                level the deployers setup for that context).


                                • 28. Re: Service integration with MC
                                  alesj

                                   

                                  "adrian@jboss.org" wrote:

                                  * The inuse tracking is at system/application/deployment level, i.e. this deployment
                                  uses a service from some other deployment and the some other deployment's service has its "in use" count integrated.

                                  This looks to me that the best way to make this OO
                                  would be to introduce ControllerContext::(un)usesContext(ControllerContext other),
                                  where the impl details would then use Tracker to properly count this.

                                  Or is this outside ControllerContexts boundaries / usage?
                                  Otoh, doing a MDR lookup for Tracker on Context's MetaData also doesn't feel right.


                                  • 29. Re: Service integration with MC

                                    It should be done on the calls to (un)getTarget()
                                    Having the calling code do all this work would inefficient and error prone.

                                    And besides a context may want to change the way this work, e.g. by providing
                                    a specific ServiceTracker rather than using the one determined from the MDR.

                                    You need a signature like I suggested above,
                                    i.e. something like the following:

                                    // Mixin interface for service tracking
                                    public interface ServiceTracking
                                    {
                                    /**
                                     * Get the service tracker associated with this context
                                     *
                                     * @return the tracker or null if it doesn't have one
                                     */
                                    ServiceTracker getServiceTracker();
                                    
                                    /**
                                     * Get the target and update the service tracking
                                     *
                                     * @param me the controller context that will use the target
                                     * @return the object
                                     * @throws Exception for any error
                                     */
                                    Object getTarget(ControllerContext me) throws Exception;
                                    
                                    /**
                                     * Unget the target and update the service tracking
                                     *
                                     * @param me the controller context that used the target
                                     */
                                    void ungetTarget(ControllerContext me);
                                    }
                                    
                                    public Object ControllerContext::getTarget(ControllerContext me) throws Exception
                                    {
                                     Object result = getTarget();
                                     if (result != null)
                                     {
                                     ServiceTracker myTracker = getServiceTracker();
                                     if (myTracker != null)
                                     myTracker.incrementInUse(me, this);
                                     if (me instanceOf ServiceTracking)
                                     {
                                     ServiceTracker otherTracker = me.getServiceTracker();
                                     if (otherTracker != null)
                                     otherTracker.incrementUsing(this);
                                     }
                                     }
                                     return result;
                                    }
                                    
                                    public void ControllerContext::ungetTarget(ControllerContext me)
                                    {
                                     Object result = getTarget();
                                     if (result != null)
                                     {
                                     ServiceTracker myTracker = getServiceTracker();
                                     if (myTracker != null)
                                     myTracker.decrementInUse(me, this);
                                     if (me instanceOf ServiceTracking)
                                     {
                                     ServiceTracker otherTracker = me.getServiceTracker();
                                     if (otherTracker != null)
                                     otherTracker.decrementUsing(this);
                                     }
                                     }
                                    }
                                    


                                    The instanceOf ServiceTracking is for backwards compatibilty in case
                                    some old ControllerContext doesn't know about ServiceTracking.

                                    You should make AbstractControllerContext implement the getServiceTracker() by
                                    looking in the MDR (probably during the original install for performance and
                                    consistency - or you could do it lazily on first request?).