4 Replies Latest reply on Jan 24, 2011 1:23 PM by piotrekde

    Number of stateless beans

    piotrekde

      Hello,

       

      I have a couple of questions related to the number of stateless beans created by JBoss. First please take a look at the following code:

       

      @Remote
      public interface ComputerRemote {
          void startComputations();
      }
      

       

       

       

      @Stateful
      public class ComputerBean implements ComputerRemote {
      
          @EJB
          private ProcessorLocal processor;
      
          public void startComputations() {
              Random r = new Random();
              while(true) {
                  processor.compute(r.nextInt());
              }
          }
      }
      
      

       

       

       

      @Local
      public interface ProcessorLocal {
          void compute(int i);
      }
      

       

       

       

      @Stateless
      public class ProcessorBean implements ProcessorLocal {
      
          private static int COUNTER = 0;
      
          public ProcessorBean() {
              COUNTER ++;
          }
      
          public void compute(int i) {
              System.out.println("----------------> " + COUNTER);
      
              // some dummy computations - it's here only in order to take some time
              double d = 0.3;
              for (int j=0; j<100; j++) {
                  d+= 0.2 % 4 + i;
              }
          }
      }
      

       

       

      So, we got stateful ComputerBean (along with its remote interface) which holds a reference to (local) stateless ProcessorBean.

      ComputerBean draws some random number and passes it into processor which do some dummy computations (just to take some time).

      There is also a COUNTER integer which is expected to count the number of stateless ProcessorBeans.

       

      If I execute it as below:

       

       

              Object obj = jndiContext.lookup("app/ComputerBean/remote");
              ComputerRemote computer = (ComputerRemote) obj;
              computer.startComputations();
      

       

       

      Computations are started, but on JBoss console there is still printed COUNTER=1.

       

      So my questions are:

       

      1. Why COUNTER is equal 1 all the time? Shouldn't it be more stateless beans? (I know that server manages them, but I thought that if stateless bean do some work for a some amount of time, and another call comes in, then server would create another instance of thise bean and processing both of them would take place simultaneously).

       

      2. Is COUNTER=1 all the time because ComputerBean waits for ProcessorBean to end its current computations, and then call another one passing the next random number? I mean - it is blocking operation, running in one thread? Is there any way to run this computations in multiple threads and do not wait for the end of the first one in order to call second?

       

      3. (this question is probably related to 2nd question) Is there any way to run ComputerBean in a "daemon" mode? I mean, if I execute computer.starComputations() by JNDI from the remote client it stops and waits for the return from startComputations method. It would never happen, because it runs in while(true) loop. But I'd like to call this method and process next client's instructions. E.g. ProcessorBean was a kind of CRON service / FTP server (running in background all the time, waiting for incoming requests, not blocking the rest of execution).

       

      Thanks in advance for all hints!

       

      Piotr

        • 1. Number of stateless beans
          wdfink

          Stateless beans are managed by the container. I suppose you run the test is a single thread client.

          In this case you have only one request at a time to the SLSB and the container reuse it.

           

          1)

          reused by container, call multithreaded and you will see that the number of beans are increases.

          You might also watch it by using the jmx- or admin console.

           

          2)

          No SLSB are created on demand, it depends to the container configuration whether it will be destroyed or pool for reuse.

          The SFSB reference is a proxy and the container will conect this reference on demand, you can not sure that two calls to a SLSB reach the same instance

           

          3)

          EJB 3.1 future objects might be an option for you.

          Also such kind of parallel (async) access can be handled by JMS (possible fire and forget or have a temporary back channel)

          Or you start threads at client side, which is IMHO not a good idea, the other are more JEE ;-)

          1 of 1 people found this helpful
          • 2. Number of stateless beans
            piotrekde

            Thanks for the anwer,

             

            So it's all because one single thread and execution order. You are right - when I call SLSB from multithreaded client, container creates more instances.

             

            Unfortunately I have to use EJB 3.0 spec. Is JMS the only way for me to implement parallel processing in JEE-appropriate way ?

            • 3. Number of stateless beans
              wdfink

              I think yes,

              we hide JMS internal in this case. Calling a SLSB to prepare the work and fil the JMS queue.

               

              Problem is if you want to have an answer. One option is to poll with a SLSB and check whether the job is finished.

              Other is to send a JMS message if the job is finished.

              • 4. Re: Number of stateless beans
                piotrekde

                I found that I can use org.jboss.ejb3.common.proxy.plugins.async.AsyncUtils in the following way:

                 

                 

                @Stateful
                public class ComputerBean implements ComputerRemote {
                
                    @EJB
                    private ProcessorLocal processor;
                
                    public void startComputations() {
                        Random r = new Random();
                        while(true) {
                            AsyncUtils.mixinAsync(processor).compute(r.nextInt());
                        }
                    }
                }
                

                 

                 

                Then it is possible to use Future interface to get result (when it will be ready). I tested it - works, but I have also noticed something strange. Let's consider following code:

                 

                 

                @Stateless
                public class ProcessorBean implements ProcessorLocal {
                
                    private static int COUNTER = 0;
                
                    @PostConstruct
                    public void init() {
                        System.out.println("constructing");
                        COUNTER++;
                    }
                
                    @PreDestroy
                    public void destroy() {
                        System.out.println("destroying");
                        COUNTER--;
                    } 
                
                    public void compute(int i) {
                        System.out.println("----------------> " + COUNTER);
                
                        // some dummy computations - it's here only in order to take some time
                        double d = 0.3;
                        for (int j=0; j<100; j++) {
                            d+= 0.2 % 4 + i;
                        }
                    }
                }
                

                 

                 

                Counter is increased and printed to the console - it looks as SLSB are pooled and their number is increased when needed.
                However, counter is _never_ decremented - even if I stop computations for 15 minutes and then restart it.

                I would say that I expected that after some downtime number of pooled SLSB will go to some small number.

                 

                Is this something wrong with my code (some hold references etc.) ?

                 

                Thanks,
                Piotr