12 Replies Latest reply on Nov 29, 2010 8:06 AM by sergiu_pienar

    How do I enable pass-by-reference for EJB3 in JBoss AS container?

    jlsimone

      I am converting a somewhat large application from EJB2/WebSphere to EJB3/JBoss. In EJB2/WebSphere,I am able to configure the WebSphere container to use pass-by-reference between EJBs that coexist in the same JVM. I would like to do the same with the JBoss AS. I have done some research and saw some documentation that says you can use the <container-invoker-conf> tag in the jboss.xml file to optimize the calls within the container JVM. But I get the feeling that this is old, outdated information. So far, I have not been able to verify this with any information that I have found on the "current" (JBoss AS 5.1) jboss.xml file.

       

      Can some one point me to an article or the documentation that might clarify this for me?

       

      Thanks

       

      *** 7/30/13 update: The"correct answer" below is not the whole story. My March 23, 2010 post (below) on initializing a stateful EJB with pass-by-reference is closer to the answer I was looking for and close to the implementation I used. - JLS

        • 1. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
          jaikiran

          jlsimone wrote:

           

          I have done some research and saw some documentation that says you can use the <container-invoker-conf> tag in the jboss.xml file to optimize the calls within the container JVM. But I get the feeling that this is old, outdated information.


           

          Thanks

          Yes, that's old and is for EJB2.x.

           

          Are you using remote business interfaces or local business interfaces for the beans?

          • 2. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
            jlsimone

            I am using remote interfaces. Generally, the client looks up and gets a remote interface to, say, EJB1. When the client requests additional functionality from the server, it makes a call to EJB1 which looks up EJB2 and EJB1 passes the remote interface for EJB2 back to the client. The client can now invoke the methods of EJB2 using the remote interface provided by EJB1.

            • 3. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
              jlsimone

              Here is some new/additional information and a more concrete example.

               

              I wrote a small, simple-minded application to test solutions to these types of problems. Please excuse the silly names. I have a stateful EJB named HatBean. The HatBean has a getHatCleaner()method that it uses to get a reference to (the remote interface for) the stateful HatCleanerBean. The last line of the stack trace below shows the call to the HatBean method getHatCleaner(). Once the HatBean has the remote interface for the HatCleanerBean, the HatBean uses that remote interface to initialize the state of the HatCleanerBean by calling the initialize() method on the HatCleanerBean, passing it objects that will be retained in the state of the HatCleanerBean. (This initialize() method is my own hack that I use, having only recently learned about the @Init annotation for the EJB3 beans.) Anyway, this stack trace seems to indicate that the container is serializing the objects that are being passed to the HatCleanerBean. One of the objects passed to the HatCleanerBean.initialize() method is the HatCleanerProcessor. I deliberately did not make the HatCleanerProcessor serializable because I want the HatCleanerProcessor to be passed by reference to the HatCleanerBean, bypassing serialization for calls within the same JVM. I see interesting things in the stack trace like MarshalledObjectForLocalCalls which makes me think that the container recognizes the local nature of the call. But further up in the stack trace is a reference to a StatefulRemoteInvocation which suggests remote rather than local interactions. The question remains, that is, is there a way to get the JBoss 5.1 EJB container to quit trying to serialize objects across a local call to an EJB?

               

              Caused by: java.io.NotSerializableException: com.swa.hat.server.domain.HatCleanerProcessor
              at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
              at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1338)
              at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1146)
              at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
              at java.rmi.MarshalledObject.<init>(MarshalledObject.java:101)
              at org.jboss.aop.joinpoint.MethodInvocation.writeExternal(MethodInvocation.java:373)
              at org.jboss.ejb3.proxy.impl.invocation.StatefulRemoteInvocation.writeExternal(StatefulRemoteInvocation.java:78)
              at org.jboss.serial.persister.ExternalizePersister.writeData(ExternalizePersister.java:58)
              at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.describeObject(ObjectDescriptorFactory.java:276)
              at org.jboss.serial.objectmetamodel.DataContainer$DataContainerOutput.writeObject(DataContainer.java:390)
              at org.jboss.serial.io.MarshalledObjectForLocalCalls.<init>(MarshalledObjectForLocalCalls.java:38)
              at org.jboss.ejb3.remoting.IsLocalInterceptor.invokeLocal(IsLocalInterceptor.java:79)
              at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:72)
              at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
              at org.jboss.aspects.remoting.PojiProxy.invoke(PojiProxy.java:62)
              at $Proxy268.invoke(Unknown Source)
              at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java:207)
              at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java:164)
              at $Proxy255.initialize(Unknown Source)
              at com.swa.hat.ejb.HatBean.getHatCleaner(HatBean.java:45)

              • 4. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                jlsimone

                ... Only slightly more information, not all that helpful.

                I have not been completely sure about whether or not this really was a case of pass-by-reference vs. pass-by-value within the container. When I run my JBoss tests, I notice some strange behavior in the application as well as the NotSerializableException mentioned above. Well, by coincedence, someone was running our WebSphere-based version of the same application the other day and the WebSphere app was showing the same strange behavior and the same NotSerializableException for the same class. The solution in this case was to go to Admin console to the ORB Service configuration for the app and to turn on pass-by-reference (it had gotten turned off somehow). After restarting the app server, the WebSphere app started working normally again. Now I am thinking that this really is a problem with pass-by-value/reference in JBoss.

                 

                I have read that JBoss is supposed to, by default, use pass-by-reference for method calls between EJBs  within the container. I looked at the org.jboss.invocation.InvokerInterceptor (I cannot remember what led me there) and I saw that it looks like it is trying to do the right thing with a local call. I am wondering what I might have done (or not done) to cause JBoss to not use pass-by-reference in this case. I am still looking for the solution. Please let me know if someone needs more information from me or examples of my code or configuration.

                 

                Thanks all.

                • 5. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                  jaikiran

                  EJB3 spec mandates that the invocations on remote business interfaces be passed-by-value, which means that the object that you are passing around, needs to be serializable. If you don't have any remote invocations, then you can switch to use local interfaces instead.

                  • 6. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                    jlsimone

                    Hmmm, I am so new to JBoss that I am not in the position to question the knowledge and experience of those who have been around and involved much longer than I. Never the less, I have a couple more questions. I am hoping against hope that I can get JBoss to do what WebSphere is doing for me.

                     

                    I read a post at this link http://www.theserverside.com/discussions/thread.tss?thread_id=24905 that said, "JBoss automatically knows when you are accessing an EJB in the same container, even if you use Remote interfaces. Thus, it passes by reference instead of by value, offering the performance advantage of Local interfaces." Now, it is important to point out that this post was from April, 2004, a long time ago. Was this statement ever true, and if so, is it still true?

                     

                    In addition, somehow I found my way to the org.jboss.invocation.InvokerInterceptor class. This class strongly suggests that the quote from the post, above, may be true. I have been trying to figure out if or how or when this InvokerInterceptor might be used and how it might behave in my circumstances. Is the InvokerInterceptor ever used at all in JBoss? Does JBoss need to be configured in order to use it?

                    • 7. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                      jlsimone

                      Here is some more information. I apologize for continuing to reference old documentation, but I am still searching and will eventually find my way to the current JBoss 5.1 docs. Anyway, I did some more searching on "JBoss call by value" and found this link:

                      http://docs.jboss.org/jbossas/whatsnew40/html_single/

                       

                      which talks about what's new in JBoss AS 4.0.1. In paragraph 2.1, it talks about optimizing performance for components deployed in the same JVM and goes on to say, "As a result, this configuration is not fully J2EE 1.4 compliant", which agrees with jaikiran's comments in an earlier post on this thread.

                       

                      One thing that I find interesting, though, and something that keeps nagging at me, is the fact that there are three xml/configuration files in JBoss that I have found so far that all contain "call-by-value" semantics and they all are setting call-by-value to FALSE, which to me means call-by-reference is TRUE which is what I need. But I am not getting call by reference in the container. I am running a non-clustered JBoss 5.1.0 default server. These are the files that I have found so far that all have some form of "call by value = false".

                       

                      server\default\deployers\ear-deployer-jboss-beans.xml

                      server\default\conf\jboss-service.xml

                      server\default\conf\standardjboss.xml

                      • 8. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                        jaikiran

                        jlsimone wrote:

                         

                        Hmmm, I am so new to JBoss that I am not in the position to question the knowledge and experience of those who have been around and involved much longer than I. Never the less, I have a couple more questions. I am hoping against hope that I can get JBoss to do what WebSphere is doing for me.

                        In short, it's not possible with EJB3 in JBoss AS-5

                         

                        jlsimone wrote:

                         

                         

                         

                        I read a post at this link http://www.theserverside.com/discussions/thread.tss?thread_id=24905 that said, "JBoss automatically knows when you are accessing an EJB in the same container, even if you use Remote interfaces. Thus, it passes by reference instead of by value, offering the performance advantage of Local interfaces." Now, it is important to point out that this post was from April, 2004, a long time ago. Was this statement ever true, and if so, is it still true?

                         

                         

                        Yes, it was true and would still apply for EJB2.x.

                         

                        jlsimone wrote:

                         


                         

                        In addition, somehow I found my way to the org.jboss.invocation.InvokerInterceptor class. This class strongly suggests that the quote from the post, above, may be true. I have been trying to figure out if or how or when this InvokerInterceptor might be used and how it might behave in my circumstances. Is the InvokerInterceptor ever used at all in JBoss? Does JBoss need to be configured in order to use it?

                        It's not used in EJB3 for JBoss. It's (probably is still) used for EJB2.x. The EJB3 interceptors are all present in ejb3-interceptors-aop.xml in the deploy folder.

                         

                        In JBoss AS-5, for EJB3 remote interfaces, the interceptors are smart enough to figure out whether the client lies in the same VM and if it does, then the call is *not* routed through any network layer. However the call for EJB3 remote interfaces, *is* still serialized/de-serialized (since the spec mandates it).  Currently there's no way to disable this.

                         

                        I guess, you could probably add a feature request https://jira.jboss.org/jira/browse/EJBTHREE to allow something along those lines.

                        • 9. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                          jlsimone
                          Well, I guess I am "stuck with" EJB 2.x for now. I modified my small PoC test application to use EJB 2.x and it works as jaikiran described it. My serialization errors have disappeared. Thanks for your help and patience, jaikiran.
                          • 10. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                            jlsimone

                            I  just now discovered that there might be an alternate solution to my particular problem, that is passing the initialization state to an EJB in the same JVM using pass by reference instead of pass by value. On another discussion thread, I was asking about initializing the state of of a stateful EJB. I was given an example solution/alternative which I have modified. The modified example is shown below.

                             

                            interface MyLocal {
                               MyRemote create(String state);
                            }

                            interface MyRemote{
                               void doWork();

                            class MyBean implement MyRemote, MyLocal {
                               MyRemote create(String state) {
                                  this.state = state;
                                  return ctx.getBusinessObject(MyRemote.class);
                               }
                              
                               void doWork(){
                                  // do something
                               }
                            }

                             

                            This example allows me to use EJBx to create EJBy in the same JVM. I use the local interface, initialize the state of EJBy, passing the state by reference. The create method of EJBy creates the remote interface which is ultimately passed back to the remote client.

                            • 11. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                              dbschofield

                              In JBoss AS-5, for EJB3 remote interfaces, the interceptors are smart enough to figure out whether the client lies in the same VM and if it does, then the call is *not* routed through any network layer. However the call for EJB3 remote interfaces, *is* still serialized/de-serialized (since the spec mandates it).  Currently there's no way to disable this.

                               

                              I guess, you could probably add a feature request https://jira.jboss.org/jira/browse/EJBTHREE to allow something along those lines.

                               

                              I need this feature for performance reasons but didn't see that anyone had opened it so I took the liberty.

                              https://jira.jboss.org/browse/EJBTHREE-2110

                              • 12. Re: How do I enable pass-by-reference for EJB3 in JBoss AS container?
                                sergiu_pienar

                                How can you apply the patch to JBoss 5.1.0 GA ?