2 Replies Latest reply: Oct 6, 2011 5:43 AM by Robert.Patrick-Oracle RSS

    MDB - how to force retry

      I am new to JMS and MDBs using Weblogic 9.2 and want to know how to handle errors while processing the message? Here is the behavior I would like to have:

      1. Message comes in to Queue MsgQ
      2. MDB's onMessage is triggered
      3. MDB processes the message
      4a) On Success -> MDB returns normally
      4b) On backend connection error -> the message is returned to MsgQ for retry at a later point
      4c) On processing error -> the message is added to ErrorQ and depending on the review I want to move the messages back to the MsgQ or throw them away

      How would I go about setting this up? What would be better to use here, MDB or SpringFramework's MDP to get the above done?

      Appreciate all comments, suggestions and information.
        • 1. Re: MDB - how to force retry
          René van Wijk
          "How would I go about setting this up? What would be better to use here, MDB or SpringFramework's MDP to get the above done?"

          Message-driven beans are more integrated than Spring's MDPs. Note that MDP consumer are unmanaged in a WebLogic environment, i.e.,
          the listener thread is unmanaged. WebLogic commonj work managers to handle threading. In the case when using MDPs it is wise
          to let a work manager handle the threading - an example is given here: http://middlewaremagic.com/weblogic/?p=5569

          To enable the steps you want, you can
          - Set up a normal JMS environment (JMS Server, Persistent store (if you want the message to be persisted), JMS Module (that contains
          a connection factory and two queues one normal and one when error occur)

          - For the normal queue you can configure a delivery failure (the delivery failure, configuration tab (note that this is in 10 but 9.2 has probably something similar)).
          - In the delivery failure environment you can set the redelivery delay, redilivery limit and set the error destination

          - Additionally, you can also set the time-to-live on a connection factory. In this case when a certain consumer is down for a long time
          it gets discarded from the queue. In the delivery failure environment you can set the expiration policy to redirect in which case
          it gets redirected to the configured error queue.

          - The error queue can be consumed by a separate consumer (message-driven bean) when this is necessary.

          Seminar on Cloud Computing - http://middlewaremagic.com/weblogic/?p=7387
          • 2. Re: MDB - how to force retry
            The best way to do this is as follows:

            public void onMessage(Message msg) {
            if (processingError) {
            // manually put the message into the Error Q
            else if (backendError) {
            // if receiving the message transactionally, call setRollbackOnly() instead of throwing the runtime exception...
            throw new weblogic.ejb.NonDestructiveRuntimeException("backend error occurred");

            While you could also just use the backend error logic for all errors and rely on the WLS-defined Error Q and redelivery count to eventually move the messages off to an Error Q, the problem with this approach is:

            1.) You may end up with a mixute of messages on the Error Q, those that failed because of a processing error and those that failed due to backend connectivity issues. Basically, you just move the complexity from the MDB to whatever code is processing the messages in the Error Q.

            2.) Repeatedly throwing the same exception from an MDB can cause the MDB to be suspended temporarily (based on the init-suspend-seconds and max-suspend seconds settings). Suspending the EJB because of backend connectivity errors is exactly what you want but suspending it because of processing errors (e.g., from invalid messages) is not typically what you want.

            My suggestion that I make in Professional Oracle WebLogic Server is to actually use two different error queues, one for technical errors (e.g., backend connectivity issues) and one for business errors (e.g., processing errors). For the technical errors queue, you can just use the normal WLS Error Q/redelivery limit mechanism to make sure that the messages get moved to the Error Q automatically. Once the technical issues are resolved, you can simply move the messages from the Error Q back to the original queue for processing. For business errors, you should create a different JMS queue and explicitly enqueue the message that failed due to business errors (e.g., invalid message format, insufficient credit, etc.) to this other JMS queue. By doing this, you know that all of the messages in the business error queue are ones that will never be able to be successfully processed without correcting whatever caused the business logic processing failure.

            Hope this helps,