1 2 Previous Next 17 Replies Latest reply on Jan 3, 2012 2:53 AM by bosschaert

    Weld-OSGi integration in AS7

    bosschaert

      Looking at the weld-osgi project (https://github.com/mathieuancelin/weld-osgi) I've been thinking how this would ideally work in AS7.

       

      So I started writing a little demo that does what I think would be a nice place to get to. It contains the following components:

      • An API OSGi bundle. This bundle contains 2 interfaces which are shared by all the other components.
      • A provider OSGi Bundle. This bundle provides an implementation of intfA and registers that with the OSGi Service Registry.
      • A .war file. This war file has a servlet that uses CDI to inject intfA into it. It also provides intfB through CDI. The servlet uses a properietary AS7 manifest header 'Dependencies' to allow it to load the interfaces from the api-bundle.
      • A consumer OSGi Bundle. This consumer looks up implementations of intfB in the OSGi Service Registry and invokes on it.

      cdiosgidemo.png

      So the servlet has a dependency on an OSGi service, and the consumer-bundle has a dependency on a CDI bean provided in the .war file.

       

      The code for the demo is here: https://github.com/bosschaert/coderthoughts/tree/master/CDI

      Just run mvn install to build it all.

       

      The question is: what needs to be done to get this demo to work? BTW this might include changing the demo

        • 1. Weld-OSGi integration in AS7
          alesj

          Nice demo, once it works. :-)

          The question is: what needs to be done to get this demo to work?

          I must admit I'm yet to look into weld-osgi in more details -- busy with EAP stuff atm.

           

          But for this to work, AS Weld integration should probably expose proper hooks.

          Or is this what Weld-OSGi adds on top?

           

          Since the AS' Weld integration should be able to understand OSGi ServiceRegistry,

          while it should also expose all Weld beans as an OSGi service into ServiceRegistry.

           

          This sounds like an over-kill if not really needed,

          hence it should probably made optional per application.

          • 2. Weld-OSGi integration in AS7
            kevinpollet

            Hi David,

             

            First of all really nice demo. And I think we all agree that we want to see it working one day :-)

            Mathieu and I have a long discussion about that and this is our thoughts.

             

            The very first step is to mark the CDI service as publishable in the OSGi world. Here we have two options. First one, we put an annotation on the service implementation to mark it publishable (like Weld-OSGi @Publish). The other, as says Ales, is to publish all CDI beans as OSGi services and we agree when he says that this option sounds overkill.

             

            Now that the service is marked has publishable, we need to publish it :-) One solution might be to create a pure CDI extension which scans the @Publish annotation and talk to an OSGi bridge (provided by the container, here the web container). But in the idea this bridge is not in the OSGi spirit. This bridge could offer an API with differents methods like register... (something like https://gist.github.com/970202). Here we can easily see that the symetric approach could be done with this stuff. It will be easy to inject OSGi services into a JavaEE application with this mechanism.

             

            WDYT?

             

            Another point is that this reflexion is not related to Weld-OSGi. I mean that this stuff was initially done to make Weld working in an OSGi container and to provide an extension based on it to simplify the use of OSGi with a CDI approach. Regarding your example, what do you think about adding a new bundle which consume the service B with Weld-OSGi?

             

            Cheers,

            Kevin & Mathieu

            • 3. Weld-OSGi integration in AS7
              sahoo

              It's good to see this being worked out here. In GlassFish project, we have developed a CDI portable extension that allows consumption of OSGi services from a WAB or other EE apps with OSGi bundle context. We have added a qualifier called org.glassfish.osgicdi.OSGiService which can be used like this:

               

              @Inject @OSGiService

              IntfA a;

               

              An example is available at http://blogs.oracle.com/alexismp/entry/screencast_dynamic_osgi_services_using. The portable extension can be downloaded from our maven repo at

              http://download.java.net/maven/glassfish/org/glassfish/fighterfish/osgi-cdi/1.0.0/osgi-cdi-1.0.0.jar

               

              I thought I showed this to Ales at OpenBlend.

               

              Sahoo

              • 4. Weld-OSGi integration in AS7
                alesj
                I thought I showed this to Ales at OpenBlend.

                Yup.

                And we also already tried to do this (to some extent) within AS6+OSGi.

                 

                So, Sahoo, afaiu you're simply making this CDI extension available to every deployment; e.g. putting it dynamically on the classpath,

                and Weld' extension handling does all the rest?

                 

                This sounds like the right way to do it, *but* how do you then tie-in the actual extension instance into app. server' container?

                Since afaik, the instance is created by Weld internals, which knows nothing about your custom app server container.

                Or is there already some hook available in Weld wrt extensions handling in diff env/containers?

                • 5. Weld-OSGi integration in AS7
                  alesj
                  @Inject @OSGiService

                  IntfA a;

                  I actually don't like this approach or I don't see why it's needed, even though non-existing annotations are mostly harmless.

                  I would simply stay -- code wise -- on the plain CDI,

                  where configuration wise one could -- due to potential over-kill --- flag the deployment as OSGi aware,

                  meaning it would also try to resolve injections against registered OSGi services; wrt type matching.

                  • 6. Weld-OSGi integration in AS7
                    alesj
                    This sounds like the right way to do it, *but* how do you then tie-in the actual extension instance into app. server' container?

                    Since afaik, the instance is created by Weld internals, which knows nothing about your custom app server container.

                    Or is there already some hook available in Weld wrt extensions handling in diff env/containers?

                    Meaning it would need to get a hold of existing app. server' OSGi service registry and vice-versa.

                    • 7. Weld-OSGi integration in AS7
                      sahoo

                      We don't do anything special for the extension. It is automatically discovered via META-INF/services/ mechanism. This extension understands @OSGiService. OSGiService like qualifier is essential to build dynamic applications, for it has parameters like timeOut, dynamic, serviceProperties.

                       

                      Sahoo

                      • 8. Re: Weld-OSGi integration in AS7
                        bosschaert

                        Thanks all for the responses.

                         

                        One hand I like the idea of not introducing any new Annotations and to simply do the injection based on type as CDI already does. Yes, the OSGi Service Registry might get full of CDI beans but I don't really see the problem with that. Service Lookups are generally based on type which means that all the services you're not interested in are ignored anyway.

                         

                        One the other hand, if you're injecting purely on type then you're certainly losing out on some of the OSGi service lookup features, for example filtering - which I think the weld-osgi project currenly also supports via an annotation.

                         

                        Maybe we can combine these two to offer the best of both worlds?

                         

                        Let's say we have the system enabled to provide a unified CDI/OSGi service registry view. (BTW re configuration we could look at OSGi Config Admin - AS7 has that built in).

                         

                        With no other qualifiers this would mean that @Inject's can be satisfied by any CDI bean or OSGi Service that matches the interface. The service should be proxied so that if it is replaced the client can continue to use the same proxy.

                         

                        Also all of the CDI beans would be available in the OSGi Service Registry. So no need for an @Publish IMHO.

                         

                        If the CDI client wants to put additional requirements on the OSGi Service (and is therefore aware of the OSGi integration) it can express this via additional @Filter or @OSGiService annotations. This would possibly include things like timeouts, dynamic flags etc.

                         

                        On the OSGi Service Consumer side. The consumer can narrow down the set of possibilities by using an ordinary filter. This could look up a CDI service by name (we'd have to come up with a service property to convey the name for a named bean) or additional properties (we might consider an annotation to add OSGi service properties to a CDI bean).

                         

                        So all in all, this would allow for a relatively simple cross OSGi/CDI case to work without any special annotations, but it would give people the option to deviate/fine-tune if needed...

                         

                        Thoughts?

                        • 9. Re: Weld-OSGi integration in AS7
                          alesj
                          Thoughts?

                          I agree with you.

                           

                          Additional annotation(s) should only be used to add OSGi filtering/prop information,

                          but *not* for additional CDI qualifiers.

                          e.g.

                          @Properties on type to add service' properties

                          @Filter on injection point to specify OSGi LDAP filter

                           

                          In an env/runtime which doesn't have this filtering capability,

                          one could still use CDI' Instance<X> and then iterate over and do filtering manually.

                          • 10. Re: Weld-OSGi integration in AS7
                            alesj
                            We don't do anything special for the extension. It is automatically discovered via META-INF/services/ mechanism.

                            Yes, but it somehow needs to become part of deployment's classpath.

                            What I meant was, do you dynamically add this CDIExtension module/bundle to every deployment's module you recognize as CDI depolyment?

                             

                            This extension understands @OSGiService. OSGiService like qualifier is essential to build dynamic applications, for it has parameters like timeOut, dynamic, serviceProperties.

                            I see why it's neccessary -- see above, but I don't see why it needs to be a qualifier.

                            • 11. Re: Weld-OSGi integration in AS7
                              kevinpollet
                              Thoughts?

                               

                              Hi all,

                               

                              I just want to give you my thinking and Mathieu's thinking about the use of the OSGiService qualifier. First of all, we agree with you that it's possible to get rid of the OSGiService qualifier (if a service is not found in CDI, it's possible to look at the OSGi service registry).

                               

                              I thought a lot about this and one interrogation comes to my mind. How differentiate the case of a missing CDI binding and the case of a local implementation for a service? The default behavior of CDI is to throw an exception specifying that there is no binding for this injection target but in this case, a proxy waiting for an hypothetical OSGi service will be injected (and obviously will fail at runtime). IMHO, doing this will break the default CDI programming model. I mean that the user applicition will start without any problem in our case but in the default CDI programming model an exception will be thrown. We think that the user have to specify where he wants to use OSGi (so the user will knows where to deal with OSGi dynamism).

                               

                              On the other hand, as you say in your above comments, this feature has to be enabled by the user. In this case he could be aware of this behavior, but we think it's too much changes for the CDI programming model.

                               

                              WDYT?

                               

                              Kevin & Mathieu

                              • 12. Re: Weld-OSGi integration in AS7
                                alesj
                                WDYT?

                                Good question.

                                 

                                I agree with you on the "surprise" from a CDI user,

                                which expects its beans to be available at runtime, since validation "said" so.

                                 

                                What we could do is add a dependency on a OSGi bundle from a CDI deployment which uses some bundle's service.

                                This should / would be transparently added via Weld/OSGi+AS integration,

                                which would then also unwind the CDI deployment if the required OSGi service would go away.

                                (and could potentially re-wind it back, if the service came back)

                                 

                                This might again be an over-kill, but I don't see how else you can properly handle this from CDI side.

                                 

                                Otoh, OSGi side could easily live with dynamic CDI beans, as this is what it already does.

                                • 13. Re: Weld-OSGi integration in AS7
                                  sahoo

                                  Yes, we add glassfish osgi-cdi portable extension to every CDI module's deployment classpath.

                                   

                                  A qualifier makes it more typesafe. More over, there is a departure from CDI model as some have already pointed out in this discussion thread, so we feel having an extra qualifier to indicate a dependency on a bean actually realized via an OSGi service makes more sense.

                                  • 14. Re: Weld-OSGi integration in AS7
                                    bosschaert

                                    Kevin Pollet wrote:

                                    WDYT?

                                     

                                    The OSGi Blueprint Specification deals with a similar problem using something called 'the Grace Period' (OSGi 4.2 Enterprise spec section 121.3.7). Essentially this is a period of time during which the system gives all the components a chance to initialize and injection to happen. If after the grace period has expired there are still missing dependencies, the deployment will fail. This might also work for CDI.

                                     

                                    Re Ales, suggestion of taking the CDI deployment away when a mandatory dependency goes away. This is what OSGi Declarative Services (DS) do as well.

                                    Essentially one of the main differences between Blueprint and DS is how they react to changes in dependencies. Blueprint keeps the dependent component alive in the hope that a replacement service will be made available at some point where DS takes the dependent away and potentially instantiates a new one when a replacement service arrives. So the Blueprint model has a dampening effect on the liveness of OSGi services whereas DS follows it directly.

                                     

                                    I think both have their uses and ideally this kind of behaviour would be configurable for OSGi/CDI - but I guess it would be fine to pick either of the two as an initial model...

                                    1 2 Previous Next