[jboss-user] [EJB 3.0] - Re: MDB cannot loads enitities if more than 10 concurrent me

sekhrivijay do-not-reply at jboss.com
Mon Oct 20 11:42:55 EDT 2008


Hi
Here is some more information about the problem along with some code snapshots. Note that the code is trimmed for clarity purposes.
Request is a simple entity (e as mentioned in the problem before) that is persisted in session bean  . Here is a trimmed snapshot
Request.java

package gov.fnal.ms.dm.entity;
  | 
  | import java.io.Serializable;
  | 
  | import javax.persistence.Column;
  | import javax.persistence.Entity;
  | .....
  | @Entity
  | 
  | @NamedQueries({@NamedQuery(name = "Request.findById", query = "SELECT r FROM Request r WHERE r.id = :id"),
  | @NamedQuery(name = "Request.findAll", query = "SELECT r FROM Request r"),
  | })
  | @Table(name = "cms_dbs_migration.Request")
  | @SequenceGenerator(name="seq", sequenceName="cms_dbs_migration.SEQ_REQUEST")
  | public class Request implements Serializable {
  |     private String detail;
  |     @Id
  |     @GeneratedValue(strategy = GenerationType.AUTO, generator="seq")
  |     @Column(nullable = false)
  |     private Long id;
  |     private String notify;
  | .....
  | 

The session bean is MSSessionEJBBean.
MSSessionEJBBean.java

@Stateless(name="MSSessionEJB")
  | @WebService(endpointInterface = "gov.fnal.ms.dm.session.MSSessionEJBWS")
  | public class MSSessionEJBBean implements MSSessionEJB, MSSessionEJBLocal, MSSessionEJBWS {
  |     @PersistenceContext(unitName="dm")
  |     private EntityManager em;
  | .......

The methods that is called concurrently in this bean is
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  |  public Request addRequest(String srcUrl, String dstUrl, String path,
  |                              String dn, String withParents, String withForce, String notify) throws Exception {
  |             Request r = addRequestUnit(srcUrl, dstUrl, path, dn, withParents, withForce, notify);
  |             if (r != null) sendToQueue(r.getId());
  |             return r;
  |     }


It first adds the request entity and then sends a message to the queue in separate methods each using TransactionAttributeType.REQUIRES_NEW (I don't think this TransactionAttributeType is needed . I was just playing to see if this resolves the problem)
Here is the method that actually persist the entity
 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  |     public Request addRequestUnit(String srcUrl, String dstUrl, String path,
  |                              String dn, String withParents, String withForce, String notify) throws Exception {
  |               ....// Does something before persisting
  |              Request r = new Request();
  |              r.setNotify(notify);
  |             r.setPath(path);
  |             r.setPerson(p);
  |             r.setWithForce(withForce);
  |             r.setWithParents(withParents);
  |             r.setProgress(new Integer(0));
  |             r.setStatus("Queued");
  |             r.setDetail("Waiting to be Picked up");
  |             em.persist(r);
  |             System.out.println("Request Entity persisted");
  |             System.out.println("ID is " + r.getId());
  |              return r;
  | }
  | 

I can see that the log files has messages anonymous wrote : "Request Entity persisted" "ID is " 12 (or some other number) . So it is safe to assume that the request entity is persisted properly before the message is sent to the queue. Here is how the message is sent to the queue
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  |     private void sendToQueue(long rId) throws Exception {
  |             QueueSession session = null;
  |             QueueConnection conn = null;
  |             try {
  |                 conn = factory.createQueueConnection();
  |                 session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
  |                 MapMessage mapMsg = session.createMapMessage();
  |                 mapMsg.setLong("request", rId);
  |                 session.createSender(queueRequest).send(mapMsg);
  |             } finally {
  |                     if (session != null) session.close();
  |                     if(conn != null) try {
  |                             conn.close();
  |                     }catch(Exception e) {e.printStackTrace();}
  |             }
  | 
  |             System.out.println("Message sent to queue");
  |     }
  | 


I can see the message anonymous wrote : "Message sent to queue" in the log file right after I see the anonymous wrote : "Request Entity persisted" message. So it correct to assume that the message is infact sent to the queue.
Here is the md bean that gets the message from the queue and process it

  | @MessageDriven(activationConfig =
  |  {
  |    @ActivationConfigProperty(propertyName="destinationType",
  |      propertyValue="javax.jms.Queue"),
  |    @ActivationConfigProperty(propertyName="destination",
  |      propertyValue="queue/requestmdb")
  |  })
  | public class RequestMessageDrivenBean implements MessageListener {
  |         @EJB
  |     private MSSessionEJBLocal ejbObj;
  | 
  |     public void onMessage(Message message) {
  | 
  |         try{
  |             System.out.println("Message recived ");
  |         if(message instanceof MapMessage) {
  |                 System.out.println("This is a instance of MapMessage");
  |                 MapMessage mMsg = (MapMessage) message;
  |                 long rId = mMsg.getLong("request");
  |                 List<Request> rList = ejbObj.getRequestById(new Long(rId));
  |                 System.out.println("rList size is " +  rList.size());
  |                 for(Request r: rList) {
  |                       //Does something and print something in logs
  |                 }
  | 
  |             }
  |             System.out.println("Finsihed onMessage");
  |         }catch(Exception e) {
  |             System.out.println(e.getMessage());
  |         }
  |     }
  | }
One thing to note here is that getRequestById is another method in the same session bean MSSessionEJB. Can that be the reason for not loading the request from the database when many concurrent request are present? Here is what it does
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  |     public List<Request> getRequestById(Long id) throws Exception {
  |             System.out.println("Inside getRequestById id is " + id);
  |         return em.createNamedQuery("Request.findById")
  |             .setParameter("id", id)
  |             .getResultList();
  |     }




In the logs I do see anonymous wrote : "This is a instance of MapMessage"  and I do see the correct Rid that was persisted before in the log anonymous wrote : "inside getRequestById id is 12" . Finally I do see anonymous wrote : "Finsihed onMessage" for all the request no matter how many are sent concurrently.
Here is where the problem is . rList size is 1 for most of the cases but it returns 0 when the number of concurrent message exceeds 10.

So you see there is no exception per se, just that entity does not get loaded from the database. I would like to mention this again, it does work properly when the number of concurrent request are less than 10. All the invocation of onMessage in MB are able to load the entity properly in that case. Its only when the number of concurrent request increases more than 10, the onMessage is unable to load the entity and the rList is 0.
FYI I am using jboss-4.2.2.GA on RedHat enterprise linux 4 with jdk1.6.0_04

Please let me know if there is more information required on this.
Thank you












View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4183284#4183284

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4183284



More information about the jboss-user mailing list