1 2 Previous Next 27 Replies Latest reply on Sep 14, 2009 9:44 AM by wolfgangknauf

    @EJB injection in JBoss 5 application clients?

    wolfgangknauf

      Hello everybody,

      I try to find out how EJB injection in a JBoss5 CR2 application client might work.
      A plain "@EJB" annotation on a member variable does not seem to work. On deployment of the EAR file containing the client JARs, I see some entries in the server log about binding something to "/env/variableName", but the variable itself is null.
      Is applicatication client injection supported? What are the required steps?
      Currently I do it the old way: specifiying ejb-ref in "application-client.xml", mapping to JNDI name in "jboss-client.xml" and JNDI lookup in the client code.

      Thanks

      Wolfgang Knauf

        • 1. Re: @EJB injection in JBoss 5 application clients?
          juergen.zimmermann

          IMHO, the @EJB annotation should only be supported for static members in classes with a main() function [see the spec for EJB 3 and the app client container]

          • 2. Re: @EJB injection in JBoss 5 application clients?
            wolfgangknauf

            This resulted in JBoss exceptions on deploy. I will try to create a full (broken) sample in the next few days.

            Best regards

            Wolfgang

            • 3. Re: @EJB injection in JBoss 5 application clients?
              wolfgangknauf

              I placed a sample at http://www.informatik.fh-wiesbaden.de/~knauf/private/Stateless_BrokenAppClient.ear (created with Eclipse/WTP and includes sources). Hopefully, someone can take a look at it and tell me whats wrong.

              The app client is this:

              public class GeometricModelApplicationClient
              {
               @EJB()
               public static GeometricModelRemote geometricModel;
              
               public static void main(String[] args)
               {
               ...
               double dblVolume = geometricModel.computeCuboidVolume(10, 5, 7);
               ...
               }
              }


              I have no deploy descriptors in the app client project (actually, "application-client.xml" and "jboss-client.xml" exist, but are renamed so that they don't work).

              Deploying this sample results in:
              21:03:16,921 ERROR [AbstractKernelController] Error installing to Real: name=vfszip:/C:/temp/jboss-5.0.0.CR2/server/default/tmp/jsr88/Stateless.ear state=PreReal mode=Manual requiredState=Real
              org.jboss.deployers.spi.DeploymentException: Error deploying StatelessClient.jar: failed to initialize bean container
               at org.jboss.ejb3.deployers.Ejb3Deployer.deploy(Ejb3Deployer.java:209)
               at org.jboss.ejb3.deployers.Ejb3Deployer.deploy(Ejb3Deployer.java:108)
               at org.jboss.deployers.vfs.spi.deployer.AbstractVFSRealDeployer.internalDeploy(AbstractVFSRealDeployer.java:45)
               ...
              Caused by: java.lang.IllegalStateException: Null beannMetaData
               at org.jboss.ejb3.interceptors.metadata.BeanInterceptorMetaDataBridge.setupMetaDataLists(BeanInterceptorMetaDataBridge.java:266)
               at org.jboss.ejb3.interceptors.metadata.BeanInterceptorMetaDataBridge.initialise(BeanInterceptorMetaDataBridge.java:186)
               at org.jboss.ejb3.interceptors.metadata.BeanInterceptorMetaDataBridge.<init>(BeanInterceptorMetaDataBridge.java:112)
               at org.jboss.ejb3.interceptors.metadata.AdditiveBeanInterceptorMetaDataBridge.<init>(AdditiveBeanInterceptorMetaDataBridge.java:48)
               at org.jboss.ejb3.aop.BeanContainer.initialize(BeanContainer.java:193)
               at org.jboss.ejb3.EJBContainer.<init>(EJBContainer.java:240)
               ... 83 more
              Caused by: java.lang.NullPointerException
               at org.jboss.ejb3.interceptors.metadata.BeanInterceptorMetaDataBridge.setupMetaDataLists(BeanInterceptorMetaDataBridge.java:219)
               ... 88 more


              If I add "jboss-client.xml", the error is gone, but my EJB variable is always null.
              I tried to add a "jndi.properties" file, but this did not make any change.

              By declaring an environment reference and performing a JNDI lookup, I can access the bean.

              Thanks

              Wolfgang

              • 4. Re: @EJB injection in JBoss 5 application clients?
                jaikiran

                As far as i know, you have to have the application-client.xml in your appclient (StatelessClient.jar) for it to be recognized as a appclient. When you introduce the appication-client.xml and the jboss-client.xml, you will see this in the logs:

                15:04:10,279 INFO [ClientENCInjectionContainer] STARTED CLIENT ENC CONTAINER: StatelessClient


                Then to run the appclient, i think you require a appclient launcher. I don't have much information about how to use the appclient launcher, but based on what i have seen in the forums here, the jboss-client.jar does have a AppClientLauncher which does the job.


                • 5. Re: @EJB injection in JBoss 5 application clients?
                  wolfgangknauf

                  I tried to start the app through the "AppClientMain" with this commandline (unzipped client and ejb jar from sample EAR), but it did not help:

                  java -cp C:\temp\jboss-5.0.0.CR2\client\jbossall-client.jar;StatelessEJB.jar;StatelessClient.jar org.jboss.client.AppClientMain -jbossclient de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelApplicationClient

                  The EJB was not injected, the variable was still null.

                  Updated sample (with deployment descriptors for client): http://www.informatik.fh-wiesbaden.de/~knauf/private/Stateless_BrokenAppClient2.ear

                  Any further ideas?

                  Wolfgang

                  • 6. Re: @EJB injection in JBoss 5 application clients?
                    jaikiran

                    I haven't tried this on my local setup. Let me give it a try and see how it goes.

                    • 7. Re: @EJB injection in JBoss 5 application clients?
                      jaikiran

                      I haven't yet got a chance to give this a try. Maybe i will get some time during this weekend.

                      "Wolfgang Knauf" wrote:
                      Any further ideas?


                      There's a test case in the JBoss AS trunk, which you could have a look at http://anonsvn.jboss.org/repos/jbossas/trunk/testsuite/src/main/org/jboss/test/client/test/AppClientUnitTestCase.java

                      • 8. Re: @EJB injection in JBoss 5 application clients?
                        jaikiran

                         

                        "jaikiran" wrote:
                        Maybe i will get some time during this weekend.



                        Got it working. Have created a wiki with the details about how to use the application client container https://www.jboss.org/community/docs/DOC-12835.

                        P.S: I took the liberty of attaching your sample application to that wiki. If you don't want it to be available on the wiki then feel free to remove it from there.


                        • 9. Re: @EJB injection in JBoss 5 application clients?
                          wolfgangknauf

                          Whow, great! Thanks a lot! As this sample is required for an EJB course at the University of Applied Science in Wiesbaden, Germany, your knowledge will be spread to a group of 15 students on thursday. Your help was just in time ;-).

                          I will update my sample (with proper EAR name and maybe code cleanup) tomorrow.

                          Thanks

                          Wolfgang

                          • 10. Re: @EJB injection in JBoss 5 application clients?
                            wolfgangknauf

                            Updated your wiki entry with a properly named EAR file without web client and updated the doc to reflect those changes.

                            • 11. Re: @EJB injection in JBoss 5 application clients?
                              bcn

                              Hello,

                              two more questions:
                              1. Can you really use the EJB annotation only in the main class (and only for static fields)? In real-world application that would make it almost useless.

                              2. Can you use in the same way a stateful session bean? E. g. to handle the client authentication and session.

                              Thanks in advance!

                              • 12. Re: @EJB injection in JBoss 5 application clients?
                                jaikiran

                                 

                                "bcn" wrote:

                                1. Can you really use the EJB annotation only in the main class (and only for static fields)?


                                That's what the spec says.

                                "bcn" wrote:

                                In real-world application that would make it almost useless.



                                Why do you think so?

                                From what i understand, they do have a valid reason for making this restriction. Consider you have a Main class into which you have to inject the bean. Remember that when you use 'java' to run this class, it invokes the static main method. So if you want to access the injected EJB, that member too should be static. In some of the examples, users usually create an object of the same class in the static main method and then use the instance variables:
                                public class MyClass {
                                
                                 @EJB
                                 private MyEJB bean;
                                
                                 public static void main(String args[])
                                 {
                                 MyClass obj = new MyClass();
                                 obj.callMyMethod();
                                 }
                                
                                 public void callMyMethod()
                                 {
                                 bean.xxxMethod();
                                 }
                                }


                                Consider this scenario shown above. A new object of the class was created and then used to access the bean. The application client container has no way to inject the @EJB for this newly created object (since it has no control on it).

                                That's the reason (in my opinion) why the field has to be static.


                                • 13. Re: @EJB injection in JBoss 5 application clients?
                                  wolfgangknauf

                                  In addition: spec chapter 9.4 says this:

                                  Injection is also supported for the application client main class. Because the application client container does not create instances of the application client main class, but merely loads the class and invokes the static main method, injection into the application client class uses static fields and methods, unlike other Java EE components. Injection occurs before the main method is called.


                                  Stateful session beans should work as well as Stateless beans or any other injection type.

                                  Wolfgang

                                  • 14. Re: @EJB injection in JBoss 5 application clients?
                                    bcn

                                    Thank you both for the answers.

                                    So stateful beans should work, okay, great.

                                    I understand that the field with the EJB annotation unfortunately has to be static. That could make it harder to use the same code in an app client and in an J2EE server. Okay, maybe you can use always static fields.

                                    What I am still not sure about is whether you can use an EJB annotation in classes others than the main class. That's what I meant with real-world application: the main class creates another class that creates another class etc. that contains a (static) EJB field. You never have all EJB fields in your main class! I guess that if the class loader only loads the main class, and injection works only before program start, it cannot work.

                                    Regards

                                    1 2 Previous Next