Thiago Negri
Thiago Negri

Reputation: 5351

Preventing a message-driven bean from consuming messages [or] handling database connection failures in Java EE

Scenario

We deliver a Java EE application as a layer between a legacy database-oriented application and a real-time Java SE application that manages physical devices to block or to grant access (like eletronic doors).

The Java EE application is local to the customer. He manages the application server in his local network.

Everything the Java SE do is based on it's internal memory. This memory is updated by the Java EE application thru JMS Messages.

The Java EE application receives messages from the Java SE applications, these messages are mission-critical, i.e. they can not be lost.

Once the Java EE receives these messages it persists it to the database.

The major slice of our customers have a single database machine (not clustered, not HA, etc.).

Our application should handle database connection failures gracefully, and it does. But this is becoming a really burden to our design.

Every new thread (MDB, EJB Timer or WebService) starts by invoking a database check in an ad-hoc Singleton (i.e. not a @Singleton as we are using EJB 3.0). If database connection is down, the Singleton locks up (so all other threads waits until the lock is released), stops all timers running, and keep trying a database connection every five seconds. If a JMS message is delivered during this process, the MDB will be held to the Singleton's lock, so the message will not be consumed nor lost.

Once the database connection is back up, the lock is released and the timers are started again. The MDBs are free to continue processing their messages.

The architecture of the solutions looks like that [sorry for the poor mspaint drawing]:

Solution's Architecture

Why?

We are doing this lock-based approach because on every tests we did, throwing an exception or rolling back the transaction at the MDB causes the message to be redelivered immediately. The redelivery count sums up really quick and the message ends up in the dead-message queue (DMQ).

We need this message to be processed as soon as the database connection is up, so it can not be redirected to the DMQ.

Dream

We dream a world where it is possible to stop consuming messages or processing any other requests until the database connection is up.

Once we detect the database failure, the entire application shutdown and focus in one little thing: to get to know when the database is back up. Once we have this information, we get the entire application to work again.

Question

Is it possible to have more control over the Java EE container? Like stopping or starting an annotated MDB at will.

Or, is it possible to be database-failure-proof in a more elegant way? (Considering the JMS Messages are mission-critical.)

Upvotes: 1

Views: 1298

Answers (1)

mcfinnigan
mcfinnigan

Reputation: 11638

How long is your database typically down?

Can you not use some sort of signalling system inside the MDB? Synchronize on some external object, and only process the current message if that object clears you to do so?

The simplest example I can think of for this is a Monitor, against which your MDBs synchronize. The Monitor monitors the Database, and sets PERMIT_PROCESSING false as soon as it loses the ability to contact the database.

It's not elegant though.

Upvotes: 0

Related Questions