8 Replies Latest reply on Oct 15, 2012 3:10 PM by Carlo de Wolf

    Singleton EJBs not working as expected

    Mylos Kathos Master

      Hi all!

      I have developed a Singleton EJB which caches some data for an application. I'm using container managed concurrency and setting READ locks on the get method, and WRITE locks on the set method.

         @Lock(READ)

      public Object get(String name) {

          // Collect Data from DB

          return cache.get(name);

          }

       

          @Lock(WRITE) 

          public void set(String name, Object value) {

              // Set Data on DB as well   

              cache.put(name, value);

             

          }

      Now, what I'm observing is that the get method cannot be accessed concurrently by its clients (as I would). It can be easily tested with a dummy wait Thread.sleep

      @Lock(READ) // non cambia niente se metto READ !

      public Object get(String name) {

              try {

                  Thread.sleep(10000);

              } catch (InterruptedException e) {

                  // TODO Auto-generated catch block

                  e.printStackTrace();

              }

              return cache.get(name);

          }

       

      Is it my misunderstanding of how @Lock(WRITE)  and @Lock(READ) work ? It seems to me that it does not change anything if I choose one Lock type or another in Container Managed Concurrency......

      Thanks

      Mylos

        • 1. Re: Singleton EJBs not working as expected
          Stephen Coy Master

          The lock semantics are applied to the bean instance, not the method call.

           

          The spec (§4.8.5.1) says (emphasis mine):

          If the container invokes a method associated with a Read lock, any number of other concurrent invocations on Read methods are allowed to access the bean instance simultaneously.

          That *could* be interpreted to mean "calls of other methods". If you had another getter method that is also marked with @Lock(READ), then it should be allowed to proceed.

           

          I'm not sure if that is what's happening though. It would be interesting to get some comments from the implementor.

          • 2. Re: Singleton EJBs not working as expected
            jaikiran pai Master

            It doesn't matter which method is being called as long as it is a READ and there's no WRITE in progress. We have  testcase here for Singleton concurrency semantics https://github.com/jbossas/jboss-as/blob/master/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/ejb/singleton/concurrency/SingletonBeanTestCase.java

             

            Mylos, what exact issue are you running into?

             

            I suspect that you might be using the "new()" keyword to instantiate a EJB instead of using either JNDI lookup or injection. Is that right?

            • 3. Re: Singleton EJBs not working as expected
              Mylos Kathos Master

              Hello Jaikiran,

              thanks for your reply. No the EJB is instantiated in a Servlet using:

               

              @EJB SimpleSingleton singleton;

               

              My concern is that, since the get method will contain as well access to EIS, I'm afraid that it can become an application bottleneck, if it allows just one client until the method is returned.

               

              This is the full EJB singleton code ( Using Thread.sleep() to simulate access to EIS)

               

               

               

               

              import static javax.ejb.LockType.*;

               

              import javax.ejb.Lock;

              import javax.ejb.Singleton;

              import javax.ejb.Startup;

              import org.jboss.logging.Logger;

              import java.util.*;

               

              @Singleton

              @Startup

               

              public class SimpleSingleton {

               

              private HashMap cache;

               

              private static final Logger logger =

                        Logger.getLogger(SimpleSingleton.class);

               

              @PostConstruct

              public void initCache(){

                   this.cache = new HashMap();

              }

               

              @Lock(READ)

              public Object get(String name) {

                   logger.info("Getting data");

                   try {

                          Thread.sleep(10000);

                      } catch (InterruptedException e) {

                          e.printStackTrace();

                      }

                      return cache.get(name);

                  }

               

                  @Lock(WRITE)

                  public void set(String name, Object value) {

               

                      cache.put(name, value);

               

                  }

               

              }

              Now if I invoke the EJB from a Servlet, the singleton.get(key) won't allow concurrent access to this method.

               

              @EJB SimpleSingleton singleton;

              . . . . .

              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

                  String key = request.getParameter("key");

                  String value = request.getParameter("value");

                  singleton.set(key, value);

                  // NO CONCURRENT ACCESS TO THIS METHOD

                  String retVal = (String)singleton.get(key);

               

              }

              Hope somebody can shed some light on it....

              Thanks

              Mylos

              • 4. Re: Singleton EJBs not working as expected
                jaikiran pai Master

                Are you sure it's the READ which isn't allowed. Your servlet invocation also has a WRITE in the same method (doGet) which will block for multiple requests and a READ too will block as a result. If you really want to test to see if multiple simultaneous reads are allowed, then you have to leave out the write from the equation.

                • 5. Re: Singleton EJBs not working as expected
                  Mylos Kathos Master

                  Hello,

                  yes I've tested as well removing the call to the put method which has WRITE lock.

                  I'm attaching the Project test case (it's just an Eclipse project made up of an EJB and a Servlet). You will see that by issuing multiple Servlet requests:

                   

                  http://localhost:8080/SingletonExample/SingletonClient

                   

                  Just one, at the time, is allowed to enter the get method:

                   

                  16:02:15,206 INFO  [ejb.SimpleSingleton] (http--127.0.0.1-8080-1) Getting data

                  . . . . . wait 10 secs

                  16:02:25,206 INFO  [ejb.SimpleSingleton] (http--127.0.0.1-8080-1) Getting data

                   

                  Thanks for your time

                  Mylos

                  • 6. Re: Singleton EJBs not working as expected
                    jaikiran pai Master

                    How are you triggering that servlet client? From that log, it looks like there aren't multiple threads involved.

                    • 7. Re: Singleton EJBs not working as expected
                      Mylos Kathos Master

                      Yes, true sorry I didn't pay attention to it. Now I have tested using JMeter and it produces the correct behaviour:

                      17:30:55,563 INFO  [ejb.SimpleSingleton] (http--127.0.0.1-8280-1) Getting data

                      17:30:58,014 INFO  [ejb.SimpleSingleton] (http--127.0.0.1-8280-2) Getting data [no wait time]

                      17:31:04,398 INFO  [ejb.SimpleSingleton] (http--127.0.0.1-8280-3) Getting data [no wait time]

                      . . . . .

                      I don't know why if I issue several HTTP calls from the *same* browser, using multiple Tabs, then calls are enqueued using always the same thread. I guess it's a matter of Servlet Session...maybe the Web server detects that calls are coming from the same Session.......

                      Thanks for your help

                      • 8. Re: Singleton EJBs not working as expected
                        Carlo de Wolf Master

                        @Lock(READ) or @Lock(WRITE) have nothing to do with the state changes you are enacting in your bean.

                         

                        It only has to do with the level of concurrency. It ensures that there are either multiple readers or 1 writer (thread) on your bean.