3 Replies Latest reply on Apr 18, 2006 3:18 AM by Jacob Boje

    Slow performance releasing stateless session bean!

    Jacob Boje Newbie

      HI

      This issue is about performance when releasing a stateless session bean on JBOSS 4.0.1SP1. The performance problem occurs when
      returning from an method in a stateless session bean after selecting a large number of objects from the database. Actually the
      same problem is happening after inserting a large number of objects into the database.

      In our scenario we've a stateless session bean with a method to return branches for a given company. A company is an
      objectwith an one-to-many relationship to branches. See sample code below

      To retrieve the branchlist from a specifik company, the first step in the method (A) is to query the company and then
      execute the method getBranches() on the company object. In our scenario the branchlist for the company
      contains 1000 objects. Getting the branch list and building dto's is done in no time.
      But, when the method returns the branchlist (or even just the number of branches) back to the client, then the
      container (java.exe) process will take up 100% cpu-time for maybe a minut or more. It seems like the container is
      doing some heavy calculations before control is passed back to the client.

      If I change the way the method (B) retrieves the branches to an EJB query, then the problem is gone. The query will
      still return the same list of 1000 objects and we'll still transform them into dto's. When changing the way to retrieve
      the branches, the control is passed back to the client much more efficient - why that?

      The main question is - why does the release of a stateless session beans perform very bad when using
      one-to-many relations to retrive a large number of objects?

      And question number 2. I we create a new CompanyPO and assosiating 1000 branches, then persisting of the CompanyPO
      will take up a lot of time and cpu-power, before the control is passed back to the client. Why?

      The client is part of the same ear-file and used local interfaces. The java-client is looking up the
      stateless session bean like this:

       InitialContext ctx = new InitialContext();
       CompanyManagementLocal bean = (CompanyManagementLocal)ctx.lookup(CompanyManagementLocal.class.getName());
      


      SAMPLE CODE!

      Method A below has very bad performance. It retrieves branches through the getBranches() method on the company
      object.
       public List<IBranch> getCompanyBranchList(ICompanySimple companyTO) throws HvidvaskException {
       CompanyDAO dao = new CompanyDAO(em);
       List<IBranch> resultsList = null;
       try {
       CompanyPO company = dao.FindCompanyByCvrNo(companyTO.getCvrNo());
       Collection<BranchPO> branches = company.getBranches();
       resultsList = DTOBuilder.createBranchList(branches);
       }
       catch (DaoException daoEx) {
       throw new HvidvaskException("Unable to return branch list");
       }
       return resultsList;
       }
      


      Method B below has very good performance. It retrives branches through a EJB query.
       public List<IBranch> getSignedBranchList(ICompanySimple companyTO) throws HvidvaskException {
       List<IBranch> branchList = null;
       try {
       CompanyPO company = em.find(CompanyPO.class, companyTO.getId());
       Query q = QueryFactory.createSignedBranchQuery(em, company);
       Collection<BranchPO> resultList = q.getResultList();
       if (resultList != null) {
       branchList = DTOBuilder.createBranchList(resultList);
       }
       }
       catch (Exception daoEx) {
       throw new HvidvaskException("Unable to return branch list");
       }
       return branchList;
       }
      


      CompanyPO and BranchPO persistence objects
      @Entity(access=AccessType.FIELD)
      public class CompanyPO implements Serializable {
      
       @Id private int;
       private String cvrNo;
       @OneToMany(mappedBy = "company"
       ,fetch=FetchType.LAZY
       ,cascade = {CascadeType.PERSIST, CascadeType.MERGE})
       private Collection<BranchPO> branches;
      
       public CompanyPO() {
       }
       ...
      }
      
      public class BranchPO implements StateObject, Serializable {
      
       @Id
       private int id;
       private String pNo;
       private String name;
       @ManyToOne(optional = false
       ,cascade = {CascadeType.PERSIST, CascadeType.MERGE}
       ,fetch=FetchType.LAZY)
       private CompanyPO company;
      
       @OneToOne(optional=false, fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.MERGE})
       @JoinColumn(name="ADDR_ID", unique=false, nullable=false)
       private AddressPO address;
      
       @OneToOne(optional=true, cascade={CascadeType.PERSIST, CascadeType.MERGE})
       @JoinColumn(name="MANAGER_ID", unique=false)
       private BranchManagerPO manager;
      
       @Column(name="currency_exchange")
       private boolean currencyExchange;
       ...
      }
      


        • 1. Re: Slow performance releasing stateless session bean!
          asd dsda Newbie

          Hi I've got the same problem. Did you find answers for your questions?

          • 2. Re: Slow performance releasing stateless session bean!
            Bill Burke Master

            ARe you sure this is a Stateless Session Bean problem and not a Hibernate/EM problem?

            to me this:

            CompanyPO company = dao.FindCompanyByCvrNo(companyTO.getCvrNo());
            Collection branches = company.getBranches();


            looks different than this:

            CompanyPO company = em.find(CompanyPO.class, companyTO.getId());
            Query q = QueryFactory.createSignedBranchQuery(em, company);
            Collection resultList = q.getResultList();


            is dao.FindCompanyByCvrNo() simply doing em.find()? and that's it? The examples are different as in the 1st you are lazily fetching the branches via the getBranches() method while in the second you are fetching queries via EJBQL

            ARe you sure this is a Stateless Session Bean problem and not a Hibernate/EM problem?

            inline dao.FINDCompnayByCvrNo and tell me if you have the same performance problems.

            • 3. Re: Slow performance releasing stateless session bean!
              Jacob Boje Newbie

              HI

              I've pasted in the method findCompanyByCvrNo below. The method uses a query to fetch the company by cvrNo. The query is also pastes below.

              Yes I'm completly sure that my session beans are using the Stateless annotation. I don't know if this is a stateless session bena problem or a hibernate/EM problem. I'm just using EJB3 and doesn't care about the JBOSS EJB3 implementation.

              Yes the two scenarios are different. Scenario A is fetching branches through the oneToMany relationship between company and branches. Scenario B is fetching branches using a query. Scenario B has far better performance than A - that is a problem, because I'll have to change all our OneToMany fetches to queries (specially when we fetch more than 100 rows).


              I've tried out the scenarios on Oracles OC4J and here is the performance not a problem, so I think it's a problem in Hibernate or the EJB container.

               public CompanyPO FindCompanyByCvrNo(String cvrNo) throws DaoException {
               CompanyPO c = null;
              
               try {
               c = (CompanyPO)em.createNamedQuery("findCompanyByCvrNo").setParameter("cvrNo", cvrNo).getSingleResult();
               }
               catch (EntityNotFoundException notFound) {
               // create new company by calling CVR
               c = CvrDAO.getCVRInfo(cvrNo);
               }
               catch (Exception e) {
               throw new DaoException(e);
               }
              
               return c;
               }
              


              EJB Query
              @NamedQuery(name = "findCompanyByCvrNo",
               queryString = "SELECT c FROM CompanyPO c WHERE c.cvrNo = :cvrNo")