• Post Reply Bookmark Topic Watch Topic
  • New Topic

MDB cannot loads enitities if more than 10 concurrent messages are sent together

 
Vijay Sekhri
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,
I have seen a weird behavior of the MDB in Jboss or perhaps in transaction management.
Here is a my scenario
I have a session bean sb, an entity bean e and a message driven bean mb
When a request comes to sb , it persists a new entity e and send a message (primary key) to mb
mb then loads e from the database using one of the findByXX method and does something else.

If 10 concurrent request comes to sb, 10 different entities are persisted and 10 different messages are sent to mb
mb are able to load 10 different e from the database

Everything works fine as long as there are 10 concurrent request. If there are 13 concurrent request, then one or two mb
cannot load e from the database. It seems that the session bean has persisted the entities but some of them are still unload able from mb. They have been persisted , (I saw in the logs), but mb cannot load them.

Initially I thought that a transaction mishap might be happening, so instead of persisting the entity and sending the message in one method in sb , I separated these two tasks in two methods a and b, in which both a and b uses RequiresNew transaction attribute. But the problem still remains. Please note if the number of parallel request are less than 10 then everything works fine. Is there something I am missing or is Jboss doing something buggy?
The above situation is reproducible .


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





The session bean is MSSessionEJBBean.
MSSessionEJBBean.java


The methods that is called concurrently in this bean is



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



I can see that the log files has messages

"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



I can see the message

"Message sent to queue"

in the log file right after I see the

"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



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





In the logs I do see

"This is a instance of MapMessage"

and I do see the correct Rid that was persisted before in the log
"inside getRequestById id is 12"

. Finally I do see
"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
 
Afzal Hossain
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Vijay Sekhri ,
I think it is NOT safe to assume that the request entity is persisted properly before the message is sent to the queue because entity manager will persist the entity when the request method is return. So i would suggest to use the flush method after persisting.

thanks
 
Vijay Sekhri
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Afzal,
Thank you for your reply. It indeed resolved the problem however now I am more confused perhaps because of my insufficient knowledge about entity manager.
I want to know why is flush necessary in a method that has TransactionAttributeType.REQUIRES_NEW as the transaction type. I persist the request in a separate method and send the message to the queue in a separate method, both using a different transactions. Doesn't it mean that the method (which is executed first)that persist the request , commits the transaction right after returning from the method.

Apparently flushing the entity manager (as you recommended) seems to have committed the transaction and not the return of the method itself.

I don't persist the request and send the message to the queue in single method. They are in two different methods. So the return of first method should persist without flushing the em right? Can you enlighten me some more.
Thank you once again.
 
Afzal Hossain
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Vijay,
First of all If persist() is called within transaction, the insert may happen immediately or it may be queued until the end of the transaction, depending on the flush mode. You can always force the insertion manually within a transaction by calling the flush( chapter 5 page 76 enterprise javabeans 3 o'reilly).

From your code: in public Request addRequest(..... ) method

Here you are calling sendToQueue(r.getId()); method while you are still in the transaction and the transaction will end after the addRequest(.... ) method returns. As because you are still in the transaction method the some entities might not be inserted immediately and the message driven bean will not able to find some entity. That is why you need to call manual flush method.


OR you could try by omitting the the line @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
from public Request addRequest(... ) method.

It seems redundant to use @TransactionAttribute in both methods addRequest(... ) and ddRequestUnit(....) . you should not use it in addRequest(.. ) method.

Your addRequestUnit(....) is fine and you are using @TransactionAttribute thats good.

Finally when we are dealing with concurrency i think it is a good idea to use flush method manually and we will be certain that the entity will persist.

These are all my understanding ... and sorry in advance if my guess is wrong..
Hope this info will help you
thanks
 
Vijay Sekhri
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Afzal,
I guess it make some more sense now. Thank you for your time and effort.
regards
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!