13 Replies Latest reply on Apr 10, 2012 3:31 PM by aeternitas

    How to invoke the bundle osgi service from ejb3?

    bigriver1973

      Thougth the 1.0.0 final release shows the feature "OSGi service invocation from EJB3 and Webap" is supported, in which I think the EJB3 is deployed as JBoss AS7 modules not an OSGi bundle, but there is no clear narration in the user guide document. I do find two methods, but they do not work:

      1)  Create a JNDI entry when the bundle starts, and let the EJB3 invoke it by lookup up it from JNDI 

              ServiceReference sref = context.getServiceReference(InitialContext.class.getName());

              InitialContext initCtx = (InitialContext) context.getService(sref);

       

             SendDownSrv downImpl = new DownLinkImpl();

       

             initCtx.createSubcontext("OTAMediation").bind("sendDownSrv", downImpl);

           

             But the bundle can not start because the system prompts "the InitialContext is read-only".

       

      2) Register an instance of that service with the OSGi service registry. And use a injected bundle context in the EJB3 to invoke it, which is provided by "Thomas Diesler" in the JBoss OSGI Diary.

           

               InjectedValue<BundleContext> injectedBundleContext = new InjectedValue<BundleContext>();

               BundleContext systemContext = injectedBundleContext.getValue();

               ServiceReference sref = systemContext.getServiceReference(SendDownSrv.class.getName());

       

      But there is such exception raised when the line 2 of above codes is reached:

       

      java.lang.IllegalStateException

      at org.jboss.msc.value.InjectedValue.getValue(InjectedValue.java:47)

       

      So what is the true method to invoke a osgi service from an EJB3?

        • 1. Re: How to invoke the bundle osgi service from ejb3?
          bosschaert

          Hi Matthew,

           

          I'm working on some documentation for this, but until that's ready you can have a look at this integration test that Thomas added recently: https://github.com/jbossas/jboss-as/blob/master/testsuite/integration/src/test/java/org/jboss/as/testsuite/integration/osgi/ejb3/SimpleStatelessSessionBean.java

           

          It basically shows how you can get a BundleContext injected in your EJB. However, this code didn't make 7.0.0 so to use it you need to build the laster AS7 master.

           

          If you need something that works with 7.0.0, let us know. It's possible to do this with 7.0.0 as well, but it requires a little more code.

          • 2. Re: How to invoke the bundle osgi service from ejb3?
            bigriver1973

            Hi, David

            Thanks a lot for your kind reply. I use the similar codes as the link your provided, but it does not work. I note that you metioned the AS7. Acctually I do deploy my EJB3 in AS7, not as a OSGi bundle ejb. So could you please give the codes can be used in AS7? Thanks!

             

            The "NullPointerException" exception is raised when the line underlined is reached in my codes below. It seems that the BundleContext has not be injected in the EJB successfully.

             

            @Remote(SendUpCommandRemote.class)
            @Stateless
            public class SendUpCommandBean implements SendUpCommandRemote
            {

                @Resource   
                BundleContext context;

                ....

                 public void sendDown() {
                     try {
                          ServiceReference sref = context.getServiceReference(SendDownSrv.class.getName());           
                          SendDownSrv sdSrv = (SendDownSrv)context.getService(sref);
                       
                             sdSrv.sendDownGenSMS(123L, "13012345678", 5, "Hello");
                       
                      } catch (Exception ex) {
                           ex.printStackTrace();
                      }
                
                 }

            • 3. Re: How to invoke the bundle osgi service from ejb3?
              bosschaert

              Hi Matthew,

               

              Sorry to hear you're getting a NPE. BundleContext injection has been added very recently to the codebase (it's not in 7.0.0 final, only in the latest 7.1.0-SNAPSHOT builds).

               

              As an alternative you might want to try the following mechanism, which is a little more verbose, but it does work with 7.0.0.final. Take a look at the WebAppOSGiService project here on github: http://github.com/bosschaert/coderthoughts/tree/master/WebAppOSGiService

               

              Although this demo isn't completely finished yet (and needs to be furter documented) you should be able to experiment with it. It contains an OSGi bundle and a Web Application that uses that Bundle (you can probably use a similar mechanism from your EJB). The web app uses an MSC service to get hold of the OSGi BundleContext. See here: http://github.com/bosschaert/coderthoughts/blob/master/WebAppOSGiService/osgi-webapp-demo-war/src/main/java/org/coderthoughts/demo/web/osgi/OSGiServiceConnector.java

               

              The servlet then uses this connector class to invoke on the OSGi service, it calls

              {code}OSGiServiceConnector.getInvoker().getStockQuote("ACME");{code}

              The MSC service (OSGiServiceConnector) needs to be declared by adding a WEB-INF/classes/META-INF/services/org.jboss.msc.service.ServiceActivator file in the .WAR file (see https://issues.jboss.org/browse/AS7-1133)

               

              One other thing that's being done here is that the webapp needs to be able to see the OSGi bundle that contains the interfaces used so that these classes are shared. This is achieved with the dependencies header in MANIFEST.MF:

              {code}Dependencies: org.osgi.core,org.jboss.modules,org.jboss.logging,deploy

              ment.osgi-webapp-demo-bundle:7.0.0{code}

               

              To see it all in action, do a mvn install from the root pom at http://github.com/bosschaert/coderthoughts/tree/master/WebAppOSGiService, then deploy the OSGi bundle and Web application in AS7. Once both deployed you can access the webapp at: http://localhost:8080/osgi-webapp-demo-war/DemoServlet

               

              This mechanism works for me but it clearly would be much easier to use the @BundleContext injection as mentioned earlier. However using this mechanism might keep you going for the moment.

               

              Best regards,

               

              David

              1 of 1 people found this helpful
              • 4. Re: How to invoke the bundle osgi service from ejb3?
                thomas.diesler

                Have a look at the JBoss AS7 OSGi Presentation + Demo

                The demo code is available here.

                 

                there is no clear narration in the user guide document

                Please monitor JBOSGI-489 for a documentation update

                • 5. Re: How to invoke the bundle osgi service from ejb3?
                  thomas.diesler

                  Despite that @Resource injection is not available in 7.0.0.Final, you can get at the BundleContext from any component that has a wire to an OSGi Bundle. The code is trivial and relies on BundleReference


                  {code}

                          ClassLoader classLoader = SomeClassFromBundle.class.getClassLoader();

                          Bundle bundle = ((BundleReference) classLoader).getBundle();

                          BundleContext context = bundle.getBundleContext();

                  {code}

                   

                  The component must have a Dependency on the Bundle declared in the Manifest

                  • 6. Re: How to invoke the bundle osgi service from ejb3?
                    bigriver1973

                    Hi, Thomas

                     

                    Thanks a lot for your kind reply. The method you provided does work. But as my personal view, it has an obvious pitfall that the EJB should know a concrete class of the bundle. It doest not meet the well-known rule of "program for interface" or as the EJB or OSGi promgram model, it is better to expose the service of a moudule, but not the class. Anyway, I do appreciate the new feature of JBoss AS7 to eliminate the gap between OSGi and JavaEE platform. And thanks a lot for your team's greate effort on the project.

                    • 7. Re: How to invoke the bundle osgi service from ejb3?
                      bigriver1973

                      Hi, David

                       

                      It is greate that your method does work. As my understanding, it is based a MSC service. I have only used JBoss 4.2.2 and 5.0.1 in my project, in which there is no such feature. Could you please tell me where can I get the reference for MSC service? Thanks!

                      • 8. Re: How to invoke the bundle osgi service from ejb3?
                        bosschaert

                        Hi Matthew,

                         

                        The version of JBoss MSC shipped with AS7.0.0 is 1.0.0.GA, you can find the javadoc for it here: http://docs.jboss.org/jbossmsc/1.0.0.GA/api

                        • 9. Re: How to invoke the bundle osgi service from ejb3?
                          thomas.diesler

                          The recommended way to get at the OSGi system bundle context is

                           

                          @Resource
                          BundleContext context;
                          

                           

                          which will be supported with the next AS7 version. The above is a temporary hack/workaround to get around this missing feature. You can of course use an interface too. The only requiremnet for BundleReference to work is that the artefact comes from a Bundle.

                          • 10. Re: How to invoke the bundle osgi service from ejb3?
                            bigriver1973

                            Hi, Thomas

                             

                            Thanks a lot!  Your method does work! The EJB just should know a class of the bundle of which the service will be invoked by it. Of cause it can be an interface or a class. I misunderstood it just a class which should has the class declare in last mail. Now I get the answer of my question, there are three methods:

                            1) As your method, get the bundle service by a trick to get the OSGi system bundle context from the class loader of a bundle class

                            2) As David's method, get the bundle service by creating a MSC service

                            3) In the future release of AS7, get the bundle service by geting OSGi system context from the Resource injection.

                             

                            BR

                            Matthew

                             

                             

                            • 11. Re: How to invoke the bundle osgi service from ejb3?
                              aeternitas

                              Hi David, I have a question: I downloaded your sample application from github (WebAppOSGiService), the question is can I deploy osdi bundle to the bundles folder of jboss7? when I do it, and after adding

                               

                              <capability name="osgi-webapp-demo-bundle" startlevel="1"/>
                              

                               

                              to the standalone.xml I have a warning:

                               

                              22:17:00,453 WARN  [org.jboss.as.osgi] (MSC service thread 1-1) JBAS011922: Cannot resolve capability: osgi-webapp-demo-bundle
                              

                               

                              and application is not deployed. How should I change that application and what configuration do I need to get it deployed that way, bundle to bundles, war to deployment? as I get it is possible, I made a mistake, which I can't find, or misunderstood something.. thank you!

                              • 12. Re: How to invoke the bundle osgi service from ejb3?
                                bosschaert

                                Hi Maxym,

                                 

                                While I haven't tried that WebAppOSGiService in AS 7.1.1 yet, you can automatically deploy bundles using the capability tag as follows.

                                Let's say you have a bundle TestBundle.jar. If you place that bundle in the directory

                                  bundles/org/acme/test/main

                                It doesn't matter what the name of the bundle is in that directory.

                                 

                                Then, you can pick it up by adding

                                {code:xml}  <capability name="org.acme.test" startlevel="1"/>{code}

                                to standalone.xml. Also make sure to set the activation to 'eager', but I think you already have that.

                                 

                                Best regards,

                                 

                                David

                                • 13. Re: How to invoke the bundle osgi service from ejb3?
                                  aeternitas

                                  Hi David!

                                   

                                  thank you so much! now I see what kind of mistake I did, just followed your advice and it works. I used JBoss 7.1.1, so here everything is ok. Thank you once more!