This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes EJB and other Java EE Technologies and the fly likes Why am I getting two instances of my Singleton EJB? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » EJB and other Java EE Technologies
Bookmark "Why am I getting two instances of my Singleton EJB?" Watch "Why am I getting two instances of my Singleton EJB?" New topic
Author

Why am I getting two instances of my Singleton EJB?

Scott Gifford
Greenhorn

Joined: Mar 26, 2013
Posts: 9
I'm doing some experiments to help solidify my understanding of @Singleton EJBs.

I have implemented an EJB called TotalBean like this:


I have it injected into a message-driven bean like this:


And also into a Servlet like this:


The EJB and message-driven bean are deployed in one application, and the servlet in another application.

My expectation is that my GlassFish log will contain the same bean name every time the singleton bean is used, since just one singleton will be created across my entire domain. Instead, though, the logs indicate there are at least two instances of my "singleton" bean:

  • INFO: In servlet, totalBean is TotalBean@1b8e347
  • INFO: In message-driven bean, totalBean is TotalBean@1b8e347
  • INFO: In servlet, totalBean is TotalBean@1b8e347
  • INFO: In message-driven bean, totalBean is TotalBean@16ba6b2
  • INFO: In servlet, totalBean is TotalBean@1b8e347
  • INFO: In message-driven bean, totalBean is TotalBean@1b8e347
  • INFO: In servlet, totalBean is TotalBean@1b8e347

  • Can anybody help me understand the fault in my understanding of @Singleton EJBs?

    Thanks!

    -----Scott.
    Lucas Smith
    Ranch Hand

    Joined: Apr 20, 2009
    Posts: 804
        
        1

    Scott Gifford wrote:
    The EJB and message-driven bean are deployed in one application, and the servlet in another application.


    Different applications mean different classloaders. Singleton bean is one and only one but per classloader.

    Try it with two invocations of:


    One in MDB (first app) and one is servlet (second app).


    SCJP6, SCWCD5, OCE:EJBD6.
    BLOG: http://leakfromjavaheap.blogspot.com
    Scott Gifford
    Greenhorn

    Joined: Mar 26, 2013
    Posts: 9
    OK, I changed my code to:

    This is what I see:

    • INFO: In servlet, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In servlet, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In message-driven bean, totalBean is TotalBean@1d13d6a class class com.sun.proxy.$Proxy278 loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@942215
      static loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@942215
    • INFO: In servlet, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In message-driven bean, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In servlet, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In message-driven bean, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In servlet, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In message-driven bean, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In servlet, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In message-driven bean, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In servlet, totalBean is TotalBean@e704a0 class class com.sun.proxy.$Proxy283 loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) static loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    • INFO: In message-driven bean, totalBean is TotalBean@1d13d6a class class com.sun.proxy.$Proxy278 loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@942215
      static loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@942215


    So I'm pretty baffled by this honestly. Why does the same MDB sometimes use different classloaders? And the MDB and servlet sometimes use the same classloader?

    Maybe my fundamental understanding of EJBs is incorrect. I thought that with local EJBs, the application server (in my case GlassFish) created a pool of EJB objects, then handed them out to different applications in the same domain as needed. With a singleton, I thought it created one instance for the entire domain, and when it was injected handed out the exact same singleton EJB to every consumer.

    But apparently, this is not what is happening. There are at least two copies of this singleton EJB, both of which are sometimes handed out to the MDB. Is this a quirk of MDBs, or would I see this behavior anywhere I injected a singleton EJB?

    Can you help me see where my misunderstanding is? And what would be a good application of a semi-singleton of this sort?

    Thanks for any guidance,

    -----Scott.

    Update: Trimmed class names, improved formatting.
    Lucas Smith
    Ranch Hand

    Joined: Apr 20, 2009
    Posts: 804
        
        1

    Please look at: https://community.jboss.org/thread/165926 .

    I can propose you a little experiment. Add method annotated with @PostConstruct to your singleton bean and log from that method. Moreover you can add a counter field in the singleton bean and invoke a method which increment that counter and return the actual result from servlet and MDB. Please post the results.
    Scott Gifford
    Greenhorn

    Joined: Mar 26, 2013
    Posts: 9
    Sure, I added this both EJBs:

    My TotalBean already had a count it was maintaining, and the MDB calls a method that increments it each time it receives a message. I modified TotalBean.getName() to print this count. I also moved the code to print the class name and class loader into that class; I think the experiment I did above was printing the loader for the proxy class, not for the underlying EJB class. TotalBean.getName() looks like this:

    Here is the log, with interesting parts in bold:

    • INFO: Created EJB TotalBean@363549
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 0
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 0
    • INFO: Created EJB TotalMessageBean@f5d656
    • INFO: In message-driven bean, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 1
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 1
    • INFO: In message-driven bean, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 2
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 2
    • INFO: In message-driven bean, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 3
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 3
    • INFO: Created EJB TotalMessageBean@925975
    • INFO: Created EJB TotalBean@4766d2
    • INFO: In message-driven bean, totalBean is TotalBean@4766d2 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@53580c
      count 1
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 3
    • INFO: In message-driven bean, totalBean is TotalBean@4766d2 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@53580c
      count 2
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 3
    • INFO: In message-driven bean, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 4
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 4
    • INFO: In message-driven bean, totalBean is TotalBean@4766d2 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@53580c
      count 3
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 4
    • INFO: In message-driven bean, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 5
    • INFO: In servlet, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 5
    • INFO: In message-driven bean, totalBean is TotalBean@363549 class class TotalBean loader WebappClassLoader (delegate=true; repositories=WEB-INF/classes/) count 6

    Here's what it looks like to me: It starts by creating the TotalBean EJB and TotalMessageBean MDB as expecte. They are injected properly and used, then after a while, a new TotalBean and TotalMessageBean are created. After this I start TotalMessageBean start logging different TotalBean objects, even though it is a singleton; you can see at the end it is using the original TotalBean again.

    This does give me more insight into what's happening, thanks! I still don't understand why it would be creating and then using a second singleton EJB though, or why the MDB would be using different classloaders at different times.

    ------Scott.
    Lucas Smith
    Ranch Hand

    Joined: Apr 20, 2009
    Posts: 804
        
        1

    As far as I can see the behaviour of Singleton bean is wrong. @PostConstruct method should be called once in the case of Singleton bean.

    Please read:
    http://piotrnowicki.com/2012/11/communication-between-ejb-modules-in-the-same-application-server/

    Especially:
    "EJB specification doesn’t guarantee any behaviour when you use the local business interfaces for inter-modules communication even if those modules are part of the same Application Server / JVM."

    Let's try Remote interface for Singleton bean. You may not be able to inject such a bean (with remote interface) with @EJB. In case of that you can use JNDI lookup.

    Please post the results.
    Scott Gifford
    Greenhorn

    Joined: Mar 26, 2013
    Posts: 9
    Lucas Smith wrote:
    ...

    Please read:
    http://piotrnowicki.com/2012/11/communication-between-ejb-modules-in-the-same-application-server/

    Especially:
    "EJB specification doesn’t guarantee any behaviour when you use the local business interfaces for inter-modules communication even if those modules are part of the same Application Server / JVM."


    You know, I had just read that yesterday. It actually threw me for a bit of a loop; I had thought the advantage of using a local EJB over just using something like a static method was that you could have one EJB application servicing multiple applications, and could update the EJB to affect all applications at once. If you can't do that, I don't know the reason for using a stateless local EJB instead of a static method. But, that's probably a question for another post.

    My TotalBean and TotalMessageBean are in the same application JAR file. If I remove all references to them from my WAR file, and just have it send JMS messages to be processed by TotalMessageBean, I still see the same behavior. Even with only one application using my singleton TotalBean, I still see multiple instances of it created and used interchangeably. So inappropriate local communication does not explain the entire problem.

    Let me try it next with a remote interface.
    Scott Gifford
    Greenhorn

    Joined: Mar 26, 2013
    Posts: 9
    Lucas Smith wrote:As far as I can see the behaviour of Singleton bean is wrong. @PostConstruct method should be called once in the case of Singleton bean.
    ...

    Let's try Remote interface for Singleton bean. You may not be able to inject such a bean (with remote interface) with @EJB. In case of that you can use JNDI lookup.

    Please post the results.


    Results are as expected with a remote interface!

    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 0
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 0
    • INFO: Created EJB TotalMessageBean@36e92b
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 1
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 1
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 2
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 2
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 3
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 3
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 4
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 4
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 5
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 5
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 6
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 6
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 7
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 8
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 8
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 8
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 9
    • INFO: In servlet, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 9
    • INFO: In message-driven bean, totalBean is TotalBean@1a13f57 class class TotalBean loader ASURLClassLoader :
      urlSet = [URLEntry : file:/Users/sgifford/NetBeansProjects/Lab8Beans/build/classes/, URLEntry : file:/Applications/NetBeans/glassfish-3.1.1/glassfish/domains/domain1/generated/ejb/Lab8Beans]
      doneCalled = false
      Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a94e97
      count 10

    So, I'm not sure what that tells us. Is the singleton's behavior supposed to depend on whether it is invoked locally or remotely? Is a singleton accessed through a remote interface a domain-wide singleton, or is it only guaranteed to be single inside each application? What is the purpose or goal of singletons behaving this way?

    Thanks!

    ------Scott.
    Lucas Smith
    Ranch Hand

    Joined: Apr 20, 2009
    Posts: 804
        
        1

    Please, post the structure of your archive(s) in the form of:

    webapp.war
    |-- images/
    | `-- banner.jpg
    |-- index.html
    |-- jsps/
    | |-- public/
    | | `-- login.jsp
    | `-- private/
    | |-- application.jsp
    | `-- settings.jsp
    `-- WEB-INF/
    |-- lib/
    | `-- some-library.jar
    |-- classes/
    | `-- compiled.class
    `-- web.xml

    Mark servlet and MDB.

    P.S.:
    EJBs are much more than static methods. The instances of stateless session beans are pooled so that they can be picked up from the pool to handle incoming requests. When one instance is busy - another one is chosen to handle the request and it is all done in thread safe manner.
    Please read:
    http://leakfromjavaheap.blogspot.com/2013/03/are-interceptors-similar-to-ejbs.html
    Moreover EJBs provide transactions which are crucial for enterprise systems.
    Scott Gifford
    Greenhorn

    Joined: Mar 26, 2013
    Posts: 9
    Lucas Smith wrote:Please, post the structure of your archive(s) in the form of:

    webapp.war
    |-- images/
    ...

    Mark servlet and MDB.

    Not sure how to get it in quite that format, but here is the output from "jar tf":

    I have simplified the code to isolate the problem and get it into a state where I can share the whole project (including the source code if that would be helpful), and it still exhibits the same problem.

    Lucas Smith wrote:
    P.S.:
    EJBs are much more than static methods. The instances of stateless session beans are pooled so that they can be picked up from the pool to handle incoming requests. When one instance is busy - another one is chosen to handle the request and it is all done in thread safe manner.
    Please read:
    http://leakfromjavaheap.blogspot.com/2013/03/are-interceptors-similar-to-ejbs.html
    Moreover EJBs provide transactions which are crucial for enterprise systems.

    Thanks for the interesting link! Maybe EJB's advantage with concurrency is mostly with instance variables; non-instance variables gain no additional thread safety from EJBs AFAIK, and local variables are thread safe even in static methods. Since resources can be injected into instance variables, I see where this can be useful for thread safe access to those resources. Transactions are a useful feature too, I probably need to experiment with this a bit more to understand how it interacts with other sorts of transactions.

    Do you happen to have any suggestions for good resources to deepen my understanding of Java EE? I have read through a few books and am at the point where I can usually get Java EE to do what I want given enough fidgeting, but I still don't feel like I have a good "big picture" sense of how everything fits together, and without that understanding everything seems very fragile.

    Thanks for your help!
    Lucas Smith
    Ranch Hand

    Joined: Apr 20, 2009
    Posts: 804
        
        1

    Firstly, I believe that improper behavior of Your singleton bean comes from the fact that you called that singleton through @Local interface from outer module. You can give a try and define everything within WAR - since JEE6 it is perfectly OK.

    When it comes to JEE, I suggest you to pick a book about servlets, one about EJBs and one about JPA.
    Scott Gifford
    Greenhorn

    Joined: Mar 26, 2013
    Posts: 9
    Lucas Smith wrote:Firstly, I believe that improper behavior of Your singleton bean comes from the fact that you called that singleton through @Local interface from outer module. You can give a try and define everything within WAR - since JEE6 it is perfectly OK.

    OK, thanks for the help! I am surprised that GlassFish allows me to do this and then behaves incorrectly, instead of giving an error, but it does seem to work with a @Remote interface so it seems to be right.
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
     
    subject: Why am I getting two instances of my Singleton EJB?
     
    Similar Threads
    MDB in EJB 3.0 and JBOSS AS 6.1 final
    @MessageDriven messageListener Interface
    How to use MessageDrivenBean Interface without implementing javax.ejb.MessageDriven-Bean interface.
    Associate Same Mdb file to multiple queue in Ejb3 jboss 5.x server
    accessing local session bean from a message driven bean