Stéphane
Stéphane

Reputation: 524

EJB with spring : transaction issue in JPA flush

I have an issue with an injected EntityManager in my MessageDriven Bean that use spring bean as services (the bootstrap is done with the SpringBeanAutowiringInterceptor.

Here is the code :

@MessageDriven(name = "ProcessMDB")
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class ProcessMDB implements MessageListener {

    @Autowired
    private ProcessService processService;

    @Override
    public void onMessage(Message message) {
        try {
            id = message.getLongProperty("ID");
            processService.process(id);
        } catch (Exception e) {
            // Handle error.
        }
    }

The process service has a DAO where the EntityManager is injected with the annotation @PersistentContext...

The problem is that if a JPA error occurs in the processService, it may occur during the entityManager.flush() call... so the try catch block is gone and the //Handle error stuff is not done.

So I tried to add manually the flush.

@MessageDriven(name = "ProcessMDB")
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class ProcessMDB implements MessageListener {

    @Autowired
    private ProcessService processService;

    @PersistenceContext
    private EntityManager em;

    @Override
    public void onMessage(Message message) {
        try {
            id = message.getLongProperty("ID");
            processService.process(id);
            em.flush();
        } catch (Exception e) {
            // Handle error.
        }
    }

But it seems that the flush has no effect.

I've try to add the em.flush in the underlying DAO (just after the persist for instance) and it works! The exception is well raised and the catch block is executed. But it doesn't work if I put the em.flush() at the MessageDrivenBean level.

I think that it's transaction manager problem... The entitymanager in spring beans is not in the same tx than the injected entity manager in my ejb.

If I make em.find in the onMessage() method, the fetched object holds old values (the one in the database), not values that are changed in the service method.

I've configured my database as followed :

<jee:jndi-lookup id="emf" jndi-name="persistence/PUnit" />

and my tx manager as followed :

<tx:annotation-driven/>

<tx:jta-transaction-manager />

What do I wrong?

Can someonee help me?

Thanks

Stéphane

Upvotes: 1

Views: 491

Answers (1)

Nayan Wadekar
Nayan Wadekar

Reputation: 11622

You have injected EntityManager in ProcessMDB, but the object is being persisted in ProcessService.

Now, how can any operation in ProcessMDB can affect ProcessService, both will have probably their own individual EntityManager.

Scope of PersistenceContext is upto associated EntityManager. The object will be in the context of ProcessService & not in ProcessMDB, therefore calling flush on later will have no effect & this is expected behaviour.

Upvotes: 0

Related Questions