Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 24

Thread: error-channel on JMS adaptor

  1. #11
    Join Date
    Feb 2009
    Location
    London
    Posts
    128

    Default

    Yes, in theory error-channel should do the stuff as mentioned by you but sadly it is not doing for me.

    As soon as I turn the transacted ack on the mesasge gets retried infinitely as it is not removed/deleted.

    I am surprised that it has message like "no ErrorHandler has been set". Though the ERROR message do get routed to error-channel( may be it is crying for unmarshalling chani) but eventually finds one on MDAdaptor.

    Also, I added few logging statements in catch(Throwable) of the ErrorHandler class to ensure that I come to know of any failure in the ErrorHandler.
    Just to add the error it encounters before propagating the exception to error-handler.

    Code:
    Execution of JMS message listener failed, and no ErrorHandler has been set. 
    org.springframework.integration.MessagingException: failed to send message
    	at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:193)
    	at org.springframework.integration.jms.ChannelPublishingJmsMessageListener.onMessage(ChannelPublishingJmsMessageListener.java:225)
    	at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:535)
    	at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:495)
    	at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467)
    	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)
    	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)
    	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058)
    	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:952)
    	at java.lang.Thread.run(Thread.java:619)
    Caused by: org.springframework.integration.transformer.MessageTransformationException: failed to transform message
    	at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:44)
    	at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:67)
    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:98)
    	at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
    	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:110)
    	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:44)
    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
    	at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
    	at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
    	at org.springframework.integration.core.MessagingTemplate.convertAndSend(MessagingTemplate.java:189)
    	at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:184)
    	... 9 more
    Caused by: java.lang.NullPointerException
    	at com.abc.request.transformer.MessageUnMarshallingTransformer.doTransform(MessageUnMarshallingTransformer.java:111)
    	at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:33)
    	... 20 more

  2. #12
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    Can you try to bypass SI and simply register a listener with try/catch Throwable, force new RuntimeException in the try, handle it in the catch and see if the message is still on the destination.
    It might also be Tibco specific configurations with regard to acknowledging transactions.

  3. #13
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,840

    Default

    Is the stack trace you posted above revealing that an Exception is being thrown from your error-handling flow?, specifically:
    Code:
    Caused by: java.lang.NullPointerException
    	at com.abc.request.transformer.MessageUnMarshallingTransformer.doTransform(
    If an Exception is thrown after sending to the error-channel, it *will* propagate and roll back the transaction. Think of the error-handling flow as your "last chance" to create a successful response Message.

  4. #14
    Join Date
    Feb 2009
    Location
    London
    Posts
    128

    Default

    Hi Mark, the null pointer one was not from error-handling flow. I thought(wished was the case) the same earlier when Oleg answered few.

    Ok, here i made a sample class(attached).

    Behavior:
    • AUTO ack: Message gets removed whether session.commit gets called or not

    • CLIENT_ACK*/TRANSACTED acknowledge will require explicit commit call on the session for failure/success to have the message removed from the queue. Otherwise message will remain on queue.


    Mark/Oleg,
    After error handling flow, can we call the commit or it should have been called automatically. I am looking through DefaultMessageListenerContainer and AbstractMessageListenerContainer but have not reached to any good stage.

    Thanks.
    Attached Files Attached Files

  5. #15
    Join Date
    Feb 2009
    Location
    London
    Posts
    128

    Default

    I think doExecuteListener will never commit if there was a runtimeException as I dont see handleListenerException(ex) ding anything.

    I am assuming it is a RUnTimeException thrown when my system does not recognize a request message and as per code below commit will never happen.

    I could be wrong but this is what I can figure out in AbstractMessageListenerContainer class. May be time to debug this one.

    Code:
    /**
    	 * Execute the specified listener,
    	 * committing or rolling back the transaction afterwards (if necessary).
    	 * @param session the JMS Session to operate on
    	 * @param message the received JMS Message
    	 * @see #invokeListener
    	 * @see #commitIfNecessary
    	 * @see #rollbackOnExceptionIfNecessary
    	 * @see #handleListenerException
    	 */
    	protected void executeListener(Session session, Message message) {
    		try {
    			doExecuteListener(session, message);
    		}
    		catch (Throwable ex) {
    			handleListenerException(ex);
    		}
    	}
    
    	/**
    	 * Execute the specified listener,
    	 * committing or rolling back the transaction afterwards (if necessary).
    	 * @param session the JMS Session to operate on
    	 * @param message the received JMS Message
    	 * @throws JMSException if thrown by JMS API methods
    	 * @see #invokeListener
    	 * @see #commitIfNecessary
    	 * @see #rollbackOnExceptionIfNecessary
    	 * @see #convertJmsAccessException
    	 */
    	protected void doExecuteListener(Session session, Message message) throws JMSException {
    		if (!isAcceptMessagesWhileStopping() && !isRunning()) {
    			if (logger.isWarnEnabled()) {
    				logger.warn("Rejecting received message because of the listener container " +
    						"having been stopped in the meantime: " + message);
    			}
    			rollbackIfNecessary(session);
    			throw new MessageRejectedWhileStoppingException();
    		}
    		try {
    			invokeListener(session, message);
    		}
    		catch (JMSException ex) {
    			rollbackOnExceptionIfNecessary(session, ex);
    			throw ex;
    		}
    		catch (RuntimeException ex) {
    			rollbackOnExceptionIfNecessary(session, ex);
    			throw ex;
    		}
    		catch (Error err) {
    			rollbackOnExceptionIfNecessary(session, err);
    			throw err;
    		}
    		commitIfNecessary(session, message);
    	}

  6. #16
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,840

    Default

    What you are describing is correct and is the intended behavior. If a RuntimeException propagates, then the transaction will not commit. That is exactly how rollbacks work. If you want to have a transaction commit, then you must ensure that no Exception propagates. In the case of the JMS gateway, if you have an error handling messaging flow that does not itself throw an Exception, then the transaction will commit.

  7. #17
    Join Date
    Feb 2009
    Location
    London
    Posts
    128

    Default

    Quote Originally Posted by Mark Fisher View Post
    What you are describing is correct and is the intended behavior. If a RuntimeException propagates, then the transaction will not commit. That is exactly how rollbacks work. If you want to have a transaction commit, then you must ensure that no Exception propagates. In the case of the JMS gateway, if you have an error handling messaging flow that does not itself throw an Exception, then the transaction will commit.

    Agreed, but ERROR handling in my case do not throw any kind of Throwable/Error/Exception but still the message is not committed/removed from the input queue.

    And, after looking at the code above- how will transaction commit when there is no call to commit. I am confused.

    As per my earlier message, Tib message will not get moved/removed from queue unless there is commit. And, I do not see any commit when message is handled by Errorhandler.
    Last edited by rock_star; Feb 17th, 2011 at 12:11 PM.

  8. #18
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,840

    Default

    In the code excerpt you pasted above, commitIfNecessary() is called as long as no exception has been thrown. If your transactions are not committing, that means an exception is triggering a rollback.

  9. #19
    Join Date
    Feb 2009
    Location
    London
    Posts
    128

    Default

    Mark,

    I understand that but unfortuntaley----

    The exception is being thrown only in the exceution path/flow where a request comes and Unmarshaller tries to unmarshall the XML. This results in exception message which gets routed to error-channel.

    And, ErrorHandler listening on error-channel there, creates a custom response and puts on the responseTopic. The message is delivered to response topic( verified by listening to topic ).

    ISSUE: The input request message still stays on the input request queue. To me this is because, there was no explicit commit during the whole chain. And as per my message number 14 in this post( with sample)- TIB EMS expects the explicit commit.

    What I am pointing is that, there is no place in the ErrorHandler chain which will issue commit call to remove the message from request queue.

    Please respond if this is not clear and apologies for bad English.

    Expectations:

    Is there a way that I can call commit in ErrorHandler? Because unless commit is called in ErrorHandler the message in Tib queue will not be removed/deleted.

    Flow Diagram, which works in excellent manner when no exception.
    Code:
    Tibco EMS Queue---> Message Driven Adaptor( with Error-Channel atrribute)---->Unmarshaller--> Service Activator---> ResponseChannel---> JMS outbound message adaptor---> Tib Topic.
    Last edited by rock_star; Feb 17th, 2011 at 03:14 PM.

  10. #20
    Join Date
    Feb 2009
    Location
    London
    Posts
    128

    Default

    Guys,

    any response would be helpful for me.

    I had used similar framework in past and this is how it worked there.

    When there is a exception anywhere in the flow, the exception flows back to starting point( in this case Message Driven Adaptor) and then the error terminal( error-channel in SIntegartion ) had access to that partofucalr flowcontext, giving handle to context which was used to commit or rollback in ErrorHandler.

    I think similar stuff should be provided in Spring Integration, otherwise error-channel is not that useful in this scenario as there is no way to commot the original transaction( intotiating transaction) in the ErrorHandler.

    Example case:

    JMS Adaptor--SA1---> SA2-->SA3-->JMS Outbound

    Suppose all SA(s) do some DB operations then in case of exceptions I would really like rollback all DB transactions except the JMS start-transaction( which started at begining of flow) to get rid of message after I have tried maximum number of tries.

    Mark/Oleg,

    To me ErrorHandler feature is bug if it does not provide something to commit.

    Thanks for patience and I look forward to hear from you. Please read my previous message in this post as well.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •