3 Replies Latest reply on Jul 26, 2005 1:30 PM by dookie23

    JBoss problem?  Or Entity Bean's problem?

    dookie23

      Hi I have been trying to solve this issue for a while but I still can't. I have tried this on JBoss 4.0.1sp1 and 4.0.2. Both give me the same result.

      Ok, here is the scenario: I have the following bean calling sequence (servlet calling session bean, then MDB.. so on):

      Servlet --> Session Bean --> MDB (of course, asynchronous)

      So theoretically, The Session Bean should run concurrently with the MDB.

      The problem that I am having is, before Session Bean's testSession() can finish (it has a while loop running for some time, code shown below), the MDB is stuck at the database fetch. It seems that the MDB cannot fetch the same row from the database. If the MDB fetches a different row from the database, the MDB runs fine even when the Session Bean is stuck in a loop.

      My question is, why? Is there some kind of locking mechanism where the Session Bean has to release? Can anybody help?

      Here are the code snipplets:

      I have 4 classes:

      A Servlet:

       protected void service(HttpServletRequest req, HttpServletResponse resp)
       {
       ...
       InitialContext context = new InitialContext();
       Object ref = context.lookup("ejb/QuestionSession");
       QuestionSessionHome home =
       (QuestionSessionHome) javax.rmi.PortableRemoteObject.narrow(
       ref, QuestionSessionHome.class);
      
       QuestionSession session = home.create();
       session.testSession(); // calling Session Bean's testSession method...
       }
      



      A Stateless Session Bean:
       public void testSession() {
      
       log.info("At testSession()");
      
      
       DestinationLookupData data = testNumberOfContection(0, null); // fetching row 0 from database
       log.info("######## BEFORE READ ########");
       log.info("QueueFilter: " + data.getQueue_filter());
       log.info("######## AFTER READ ########");
      
       sendToTopic("TRANSACTION_START"); // send asynchronously to MDB
      
       int counter = 0;
       while (true) // Some long long process....
       {
       try
       {
       Thread.sleep(2000);
       }
       catch (InterruptedException e)
       {
       e.printStackTrace();
       }
       if (counter > 20)
       break;
      
       counter++;
       }
      
       log.info("#####################################");
       log.info("######## FINISHED WHILE LOOP ########");
       log.info("#####################################");
      
       }
      



      A Message Driven Bean:

      public void onMessage(Message message) {
      
       log.info("At onMessage()");
      
       DestinationLookupData data = testNumberOfContection(0, null); // fetching row 0 from database
       log.info("######## BEFORE READ ########");
       log.info("QueueFilter: " + data.getQueue_filter());
       log.info("######## AFTER READ ########");
      
      
       }
      




      An Entity Bean:
      With a finder method searching for a specific row in the database. The key is passed in by testNumberOfContection (the first parameter, both the SessionBean and MDB are running invoking that). Therefore, the MDB and SessionBean are looking for the same row in the database.


      Thanks!!

      Brian

        • 1. Re: JBoss problem?  Or Entity Bean's problem?
          jamesstrachan

          Brian,

          Surely the problem has very little to do with JBoss or EJB's.

          Both Entity Beans and Message Driven Beans operate in a transaction context set by the EJB server.

          So, when your entity bean reads row #0 (or whichever), it takes a database lock on this row in case the entity bean intends to update the row,

          Your MDB cannot then read the same row as it is already locked.

          This diagnosis may be wrong. You do not supply enough information on your implementation of persistence or the database that you are using. Some databases do not take locks on a read.

          But it does match the problems that you report.

          James Strachan

          • 2. Re: JBoss problem?  Or Entity Bean's problem?
            dookie23

            Hi, thanks for your reply.

            Here is the Session Facade which talks to the entity bean:

             /**
             * Business method
             *
             * @ejb.interface-method view-type = "local"
             */
             public DestinationLookupData findByStageAndFilter(int stage,
             java.lang.String filter)
             {
             if (null == destinationLookupHome)
             {
             log.error("destinationLookupHome is NULL!");
             return null;
             }
            
             Collection lookup = null;
             Integer stageInteger = new Integer(stage);
             DestinationLookup row;
            
             try
             {
             // Lookup entry from database by stage & filter or only by stage.
             if (filter != null)
             {
             lookup = destinationLookupHome.findByStageAndFilter(stageInteger, filter);
             }
             else
             {
             lookup = destinationLookupHome.findByStage(stageInteger);
             }
             }
             catch (RemoteException e)
             {
             e.printStackTrace();
             }
             catch (FinderException e)
             {
             e.printStackTrace();
             }
            
             // if lookup is not null and only 1 record found...
             if ((lookup != null) && (lookup.size() == 1))
             {
             Object[] objArray = lookup.toArray();
             row = (DestinationLookup) objArray[0];
             return copyDestinationLookup(row);
             }
            
             log.error("Error fetching data from storage. " + "Stage = " + stage
             + " filter = " + filter);
             return null;
             }
            


            This is where it's stuck:

             /**
             * @param lookup
             * @return
             */
             private static DestinationLookupData copyDestinationLookup(
             DestinationLookup lookup)
             {
             try
             {
             log.info("######## before #########");
             log.info("QueueFilter = " + lookup.getQueue_filter());
             log.info("######## after #########");
            
            
             DestinationLookupData lookupData = new DestinationLookupData(lookup
             .getStage().intValue(), lookup.getQueue_filter(), lookup
             .getFilter(), lookup.getNext_stage().intValue(), lookup
             .getId().intValue());
            
             return lookupData;
             }
             catch (Exception e)
             {
             e.printStackTrace();
             return null;
             }
             }
            



            Here is the finder method in the entity bean:

             <!-- Entity Beans -->
             <entity >
             <description>[CDATA[Description for DestinationLookup]]</description>
             <display-name>Name for DestinationLookup</display-name>
            
             <ejb-name>DestinationLookup</ejb-name>
            
             <home>com.shaw.eng.rsc.epe.transaction.framework.interfaces.DestinationLookupHome</home>
             <remote>com.shaw.eng.rsc.epe.transaction.framework.interfaces.DestinationLookup</remote>
            
             <ejb-class>com.shaw.eng.rsc.epe.transaction.framework.ejb.DestinationLookupCMP</ejb-class>
             <persistence-type>Container</persistence-type>
             <prim-key-class>com.shaw.eng.rsc.epe.transaction.framework.interfaces.DestinationLookupPK</prim-key-class>
             <reentrant>True</reentrant>
             <cmp-version>2.x</cmp-version>
             <abstract-schema-name>DestinationLookup</abstract-schema-name>
             <cmp-field >
             <description>[CDATA[Getter for CMP Field id]]</description>
             <field-name>id</field-name>
             </cmp-field>
             <cmp-field >
             <description>[CDATA[Getter for CMP Field stage]]</description>
             <field-name>stage</field-name>
             </cmp-field>
             <cmp-field >
             <description>[CDATA[Getter for CMP Field next_stage]]</description>
             <field-name>next_stage</field-name>
             </cmp-field>
             <cmp-field >
             <description>[CDATA[Getter for CMP Field queue_filter]]</description>
             <field-name>queue_filter</field-name>
             </cmp-field>
             <cmp-field >
             <description>[CDATA[Getter for CMP Field filter]]</description>
             <field-name>filter</field-name>
             </cmp-field>
            
             <query>
             <query-method>
             <method-name>findByStageAndFilter</method-name>
             <method-params>
             <method-param>java.lang.Integer</method-param>
             <method-param>java.lang.String</method-param>
             </method-params>
             </query-method>
             <ejb-ql>[CDATA[SELECT object(o) FROM DestinationLookup o WHERE o.stage = ?1 AND o.filter = ?2]]</ejb-ql>
             </query>
             <query>
             <query-method>
             <method-name>findByStage</method-name>
             <method-params>
             <method-param>java.lang.Integer</method-param>
             </method-params>
             </query-method>
             <ejb-ql>[CDATA[SELECT object(o) FROM DestinationLookup o WHERE o.stage = ?1]]</ejb-ql>
             </query>
             <!-- Write a file named ejb-finders-DestinationLookupBean.xml if you want to define extra finders. -->
             </entity>
            


            Is there anyway I can get around this issue? Do you need more info?

            • 3. Re: JBoss problem?  Or Entity Bean's problem?
              dookie23

              I forgot to mention, I am using MySQL as my database. However, I have tested this with Hypersonic as well. Same issue.