10 Replies Latest reply on Jul 12, 2008 2:13 AM by jaikiran pai

    Can you Inject Local EJB from separate ear file?

    jfrankman Novice

      I have two session beans each deployed in a different ear's on the same JBoss server. Can i successfully inject Session bean A into Session bean B if each one is deployed in a different ear? I keep getting this error and everything looks ok so I assume that they must both be within the same ear for @EJB injection to work. Can anyone tell me this is correct?

      here is the error I get upon deployment:

      " Reason: java.lang.RuntimeException: could not resolve global JNDI name for @EJB for container KeyBankCheckImagesMessageHandler: reference class: com.idfbins.nexusevents.services.NexusEventsService ejbLink: not used by any EJBs"

      Here is my how I inject it:

      public class KeyBankCheckImagesMessageHandler implements MessageListener{
      
       @PersistenceContext(unitName = "KeyBankChecksDB")
       private EntityManager em;
      
       @In(create=true) KeyBankServices keybankServices;
      
       @EJB(name="NexusEvents/NexusEventsServiceImpl/local")
       NexusEventsService nexusEventsService;


        • 1. Re: Can you Inject Local EJB from separate ear file?
          jaikiran pai Master

           

          @EJB(name="NexusEvents/NexusEventsServiceImpl/local")
          NexusEventsService nexusEventsService;


          Is NexusEvents/NexusEventsServiceImpl/local, the JNDI name of your NexusEventsService? If yes, then try this:

          @EJB(mappedName="NexusEvents/NexusEventsServiceImpl/local")
           NexusEventsService nexusEventsService;


          Note the use of mappedName in the injection.



          • 2. Re: Can you Inject Local EJB from separate ear file?
            jfrankman Novice

            Thanks for the tip. Your suggestion solved my problem. I also found that I had to change the jboss config to use callbyvalue per this article:

            http://wiki.jboss.org/wiki/ClassLoadingConfiguration

            Now I am almost there. I can inject the session bean and call a method, but now the object returned by the session beans method cannot be cast into my class:

            NexusEventDefinition def= nexusEventsService.findNexusEventDefinitionByName("Synchronous event that does neat things.");


            I get a class cast exception:


            java.lang.ClassCastException: com.idfbins.nexusevents.vo.NexusEventDefinition
            at $Proxy175.findNexusEventDefinitionByName(Unknown Source)
            at com.idfbins.keybank.KeyBankCheckImagesMessageHandler.onMessage(KeyBankCheckImagesMessageHandler.java:76)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:585)
            at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
            at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
            at org.jboss.seam.intercept.EJBInvocationContext.proceed(EJBInvocationContext.java:44)
            at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
            at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:31)
            at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
            at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:46)
            at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
            at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:42)
            at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
            at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:118)
            at org.jboss.seam.intercept.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:50)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:585)
            at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:118)
            at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
            at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
            at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
            at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
            at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
            at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
            at org.jboss.aspects.tx.TxPolicy.invokeInNoTx(TxPolicy.java:66)
            at org.jboss.aspects.tx.TxInterceptor$NotSupported.invoke(TxInterceptor.java:112)
            at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
            at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
            at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
            at org.jboss.ejb3.mdb.MessagingContainer.localInvoke(MessagingContainer.java:249)
            at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.delivery(MessageInflowLocalProxy.java:268)
            at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.invoke(MessageInflowLocalProxy.java:138)
            at $Proxy103.onMessage(Unknown Source)
            at org.jboss.resource.adapter.jms.inflow.JmsServerSession.onMessage(JmsServerSession.java:178)
            at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:891)
            at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:170)
            at org.jboss.mq.SpySession.run(SpySession.java:323)
            at org.jboss.resource.adapter.jms.inflow.JmsServerSession.run(JmsServerSession.java:237)
            at org.jboss.resource.work.WorkWrapper.execute(WorkWrapper.java:204)
            at org.jboss.util.threadpool.BasicTaskWrapper.run(BasicTaskWrapper.java:275)
            at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:756)
            at java.lang.Thread.run(Thread.java:595)


            Any idea why I am getting the class cast exception?

            • 3. Re: Can you Inject Local EJB from separate ear file?
              jaikiran pai Master

              Looks like a classloader issue. Have you configured your applications for classloader scoping (using jboss-app.xml)? Can you provide more details about the packaging of both your application? Specifically, is that NexusEventDefinition interface (and other bean interfaces) packaged in both the EARs?

              • 4. Re: Can you Inject Local EJB from separate ear file?
                jaikiran pai Master

                The jmx-console method mentioned here http://wiki.jboss.org/wiki/ClassCastExceptions might help you in debugging this issue.

                • 5. Re: Can you Inject Local EJB from separate ear file?
                  jfrankman Novice

                  "Have you configured your applications for classloader scoping (using jboss-app.xml)? "

                  According to the wiki I thought all I had to do was to turn on the callByValue setting in the jboss-service.xml. Do I also need to make the suggested changes to the jboss-app.xml?


                  Can you provide more details about the packaging of both your application? Specifically, is that NexusEventDefinition interface (and other bean interfaces) packaged in both the EARs?

                  NexusEventDefinition is a POJO with and @Entity annotation. The method on my session bean returns this pojo. I do not have an interface for it. Should I create an interface and modify the Session bean to return the interface instead of the class?

                  The packaging is as follows.
                  1. I have two ear projects: NexusEvents.ear and KeyB.ear.
                  2. I have a message driven bean in the KeyB.ear that I want to be able to call a session bean deployed in the NexusEvents.ear to return an instance of NexusEventDefinition.
                  3. I have exported the session bean interface and the NexusEventDefinition class out of my NexusEvents project into a jar named nexusevents.jar and have deployed it with the KeyB.ear.

                  • 6. Re: Can you Inject Local EJB from separate ear file?
                    jaikiran pai Master

                     

                    NexusEventDefinition is a POJO with and @Entity annotation. The method on my session bean returns this pojo. I do not have an interface for it. Should I create an interface and modify the Session bean to return the interface instead of the class?


                    I had (incorrectly) assumed that nexusEventsService.findNexusEventDefinitionByName returns an bean interface. If its a POJO then you need not create an interface.


                    The packaging is as follows.
                    1. I have two ear projects: NexusEvents.ear and KeyB.ear.
                    2. I have a message driven bean in the KeyB.ear that I want to be able to call a session bean deployed in the NexusEvents.ear to return an instance of NexusEventDefinition.
                    3. I have exported the session bean interface and the NexusEventDefinition class out of my NexusEvents project into a jar named nexusevents.jar and have deployed it with the KeyB.ear.


                    Does the NexusEvents.ear too have the NexusEventDefinition class?

                    Also did the jmx-console method in that wiki help in identifying the jar which was being used to pick up this class? The other way to figure out which jar is being used to load this NexusEventDefinition class, is to add the -verbose:class option to the run.bat and pass it as a JVM option. This will print to STDOUT (i would recommend redirecting it too a file since the output will be a lot) the classes that are being loaded in the JVM and also the jars that are being used to load these classes. In that output, search for this NexusEventDefinition class and see which jar(s) are being used.


                    • 7. Re: Can you Inject Local EJB from separate ear file?
                      jfrankman Novice

                      Yes, the NexusEventDefinition class exists in both Jars.


                      I did try to use the jmx console, but when I invoked the listClasses method I got an error saying:

                      "Information
                      Not loaded in repository cache"

                      I could use the verbose setting, but do I really need to? I already know I have the same class deployed in two separate projects. I just need to know what I can do about it.

                      My research thus far shows that other people when confronted with this situation, removed the classes from both ear projects and packaged them into a separate jar file and deployed it on the jboss lib directory. I would prefer if there was a better way to to handle this than by splitting it.

                      I tried some suggestions on the wiki that said to use the jboss-app.xml file, but I could not add the changes because these files are alread configured for jboss seam:


                      <jboss-app>
                       <loader-repository>
                       seam.jboss.org:loader=NexusEvents
                       </loader-repository>
                      
                      </jboss-app>


                      How can I tell JBoss to load a single NexusEventDefinition class but have it referenced from two different ears?



                      • 8. Re: Can you Inject Local EJB from separate ear file?
                        jaikiran pai Master

                        For classloading configurations, i use the jboss-app.xml approach. Haven't tried the callByValue. You mentioned that the jboss-app.xml is already present. You even posted the one from NexusEvents.ear (i guess). Can you post the other one from KeyB.ear? Just wanted to make sure that you are not using the same loader repository name in both these jboss-app.xml files.

                        • 9. Re: Can you Inject Local EJB from separate ear file?
                          jfrankman Novice

                          I don't quite get the concept of scope classloaders yet. Wouldn't you want both ear's to use the same classloader so you don't get the classCastException?

                          Here are the jboss-app.xml files.

                          NexusEvents.ear:

                          <jboss-app>
                           <loader-repository>
                           seam.jboss.org:loader=NexusEvents
                           </loader-repository>
                          
                          </jboss-app>


                          And the KeyB.ear:
                          <jboss-app>
                           <loader-repository>
                           seam.jboss.org:loader=KeyBankChecksJEE2
                           </loader-repository>
                          </jboss-app>


                          Originally I tried to set both loaders equal to NexusEvents (identical- seam.jboss.org:loader=NexusEvents
                          in each config file) but this caused the KeyB.ear deployment to fail.

                          • 10. Re: Can you Inject Local EJB from separate ear file?
                            jaikiran pai Master

                            jfrankman,

                            I would now suggest that you use the -verbose:class to check the jar files being used for loading your applications. Sometimes the class being reported in the classcastexception may not be the actual culprit. It may also be some class being used in the NexusEventDefinition which might be causing this issue.

                            I don't quite get the concept of scope classloaders yet.


                            This might help http://wiki.jboss.org/wiki/JBossClassLoadingUseCases