Details

  • User impact:
    Low
  • Similar Issues:
    None

Description

When an exception is thrown inside a sync outbound endpoint (for example, in a transformer), the exception is handled by both the connector-exception-strategy and the service-exception-strategy (when in this case it should only be handled by the connector-exception-strategy since it happens in the transformer inside the outbound-endpoint). This works fine when the outbound-endpoint is async.

At the end of AbstractMessageDispatcher.send(MuleEvent event) there is this code:

catch (DispatchException e)
{
    handleException(e);
    throw e;
}
catch (Exception e)
{
    handleException(e);
    throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
}

This means that, whatever the handleException(e) method does, the exception is rethrown. If the dispatching is done on the same thread as the service (which is what happens when the outbound-endpoint is sync) then that exception will reach the service-exception-strategy, allowing it to handle it despite the fact that it might have already been handled but the connector-exception-strategy.

Changing this behavior could make things to break so I will have to analyze it deeper.

Issue Links

Activity

Hide
Edu Pereda added a comment -

This issue was detected on EE-1968

Show
Edu Pereda added a comment - This issue was detected on EE-1968
Hide
Edu Pereda added a comment -

This is the stack call when the outbound endpoint is async:

MuleServer - EE-1968 - async outbound [Java Application]	
	org.mule.MuleServer at localhost:2023	
		Thread [MuleServer.1] (Running)	
		Daemon Thread [Thread-3] (Running)	
		Thread [http1.receiver.1] (Running)	
		Thread [SandboxGateway.1] (Running)	
		Thread [SystemStreamConnector.scheduler.1] (Running)	
		Thread [SuccessService.1] (Running)	
		Thread [ErrorService2.1] (Running)	
		Thread [ErrorService1.1] (Running)	
		Thread [LogService.1] (Running)	
		Thread [DestroyJavaVM] (Running)	
		Thread [SystemStreamConnector.receiver.1] (Running)	
		Thread [SystemStreamConnector.scheduler.2] (Running)	
		Thread [SystemStreamConnector.scheduler.3] (Running)	
		Thread [SystemStreamConnector.scheduler.4] (Running)	
		Thread [vm2.dispatcher.1] (Suspended (breakpoint at line 14 in TestTransformer))	
			TestTransformer.transform(MuleMessage, String) line: 14	
			TestTransformer(AbstractMessageAwareTransformer).doTransform(Object, String) line: 68	
			TestTransformer(AbstractTransformer).transform(Object) line: 254	
			DefaultMuleMessage.applyAllTransformers(List) line: 645	
			DefaultMuleMessage.applyTransformers(List, Class) line: 606	
			DefaultMuleMessage.applyTransformers(List) line: 599	
			DefaultMuleEvent.transformMessage(Class) line: 328	
			DefaultMuleEvent.transformMessage() line: 323	
			VMMessageDispatcher.doDispatch(MuleEvent) line: 47	
			VMMessageDispatcher(AbstractMessageDispatcher).dispatch(MuleEvent) line: 104	       THIS ONE HANDLES EXCEPTION AND THAT'S IT
			AbstractConnector$DispatchWorker.doRun() line: 2510	
			AbstractConnector$DispatchWorker(AbstractMuleEventWork).run() line: 41	
			WorkerContext.run() line: 310	
			ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1061	
			ThreadPoolExecutor$Worker.run() line: 575	
			Thread.run() line: 619

This is the stack call when the outbound endpoint is sync:

MuleServer - EE-1968 - sync outbound [Java Application]	
	org.mule.MuleServer at localhost:2019	
		Thread [MuleServer.1] (Running)	
		Daemon Thread [Thread-3] (Running)	
		Thread [http1.receiver.1] (Running)	
		Thread [SandboxGateway.1] (Running)	
		Thread [SystemStreamConnector.scheduler.1] (Running)	
		Thread [SuccessService.1] (Running)	
		Thread [ErrorService1.1] (Running)	
		Thread [ErrorService2.1] (Running)	
		Thread [LogService.1] (Running)	
		Thread [DestroyJavaVM] (Running)	
		Thread [SystemStreamConnector.receiver.1] (Running)	
		Thread [SystemStreamConnector.scheduler.2] (Running)	
		Thread [SystemStreamConnector.scheduler.3] (Running)	
		Thread [SystemStreamConnector.scheduler.4] (Running)	
		Thread [SandboxGateway.2] (Suspended (breakpoint at line 14 in TestTransformer))	
			TestTransformer.transform(MuleMessage, String) line: 14	
			TestTransformer(AbstractMessageAwareTransformer).doTransform(Object, String) line: 68	
			TestTransformer(AbstractTransformer).transform(Object) line: 254	
			DefaultMuleMessage.applyAllTransformers(List) line: 645	
			DefaultMuleMessage.applyTransformers(List, Class) line: 606	
			DefaultMuleMessage.applyTransformers(List) line: 599	
			DefaultMuleEvent.transformMessage(Class) line: 328	
			DefaultMuleEvent.transformMessage() line: 323	
			VMMessageDispatcher.doSend(MuleEvent) line: 101	
			VMMessageDispatcher(AbstractMessageDispatcher).send(MuleEvent) line: 165	THIS ONE HANDLES THE EXCEPTION AND RE THROWS IT
			VMConnector(AbstractConnector).send(OutboundEndpoint, MuleEvent) line: 2136	
			DefaultOutboundEndpoint.send(MuleEvent) line: 97	
			DefaultMuleSession.sendEvent(MuleEvent) line: 332	
			DefaultMuleSession.sendEvent(MuleMessage, OutboundEndpoint) line: 216	
			AbstractOutboundRouter$2.doInTransaction() line: 152	
			TransactionTemplate.execute(TransactionCallback) line: 114	
			FilteringOutboundRouter(AbstractOutboundRouter).send(MuleSession, MuleMessage, OutboundEndpoint) line: 159	
			FilteringOutboundRouter.route(MuleMessage, MuleSession) line: 79	
			DefaultOutboundRouterCollection$1.doInTransaction() line: 86	
			TransactionTemplate.execute(TransactionCallback) line: 47	
			DefaultOutboundRouterCollection.route(MuleMessage, MuleSession) line: 91	
			SedaService(AbstractService).dispatchToOutboundRouter(MuleEvent, MuleMessage) line: 863	
			SedaService.dispatchToOutboundRouter(MuleEvent, MuleMessage) line: 554	
			SedaService$ComponentStageWorker.doRun() line: 576	
			SedaService$ComponentStageWorker(AbstractMuleEventWork).run() line: 41	
			WorkerContext.run() line: 310	
			ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1061	
			ThreadPoolExecutor$Worker.run() line: 575	
			Thread.run() line: 619

Note that the difference starts here:

  • async
    • VMMessageDispatcher(AbstractMessageDispatcher).dispatch(MuleEvent) line: 104 THIS ONE HANDLES EXCEPTION AND THAT'S IT
  • sync
    • VMMessageDispatcher(AbstractMessageDispatcher).send(MuleEvent) line: 165 THIS ONE HANDLES THE EXCEPTION AND RE THROWS IT
Show
Edu Pereda added a comment - This is the stack call when the outbound endpoint is async:
MuleServer - EE-1968 - async outbound [Java Application]	
	org.mule.MuleServer at localhost:2023	
		Thread [MuleServer.1] (Running)	
		Daemon Thread [Thread-3] (Running)	
		Thread [http1.receiver.1] (Running)	
		Thread [SandboxGateway.1] (Running)	
		Thread [SystemStreamConnector.scheduler.1] (Running)	
		Thread [SuccessService.1] (Running)	
		Thread [ErrorService2.1] (Running)	
		Thread [ErrorService1.1] (Running)	
		Thread [LogService.1] (Running)	
		Thread [DestroyJavaVM] (Running)	
		Thread [SystemStreamConnector.receiver.1] (Running)	
		Thread [SystemStreamConnector.scheduler.2] (Running)	
		Thread [SystemStreamConnector.scheduler.3] (Running)	
		Thread [SystemStreamConnector.scheduler.4] (Running)	
		Thread [vm2.dispatcher.1] (Suspended (breakpoint at line 14 in TestTransformer))	
			TestTransformer.transform(MuleMessage, String) line: 14	
			TestTransformer(AbstractMessageAwareTransformer).doTransform(Object, String) line: 68	
			TestTransformer(AbstractTransformer).transform(Object) line: 254	
			DefaultMuleMessage.applyAllTransformers(List) line: 645	
			DefaultMuleMessage.applyTransformers(List, Class) line: 606	
			DefaultMuleMessage.applyTransformers(List) line: 599	
			DefaultMuleEvent.transformMessage(Class) line: 328	
			DefaultMuleEvent.transformMessage() line: 323	
			VMMessageDispatcher.doDispatch(MuleEvent) line: 47	
			VMMessageDispatcher(AbstractMessageDispatcher).dispatch(MuleEvent) line: 104	       THIS ONE HANDLES EXCEPTION AND THAT'S IT
			AbstractConnector$DispatchWorker.doRun() line: 2510	
			AbstractConnector$DispatchWorker(AbstractMuleEventWork).run() line: 41	
			WorkerContext.run() line: 310	
			ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1061	
			ThreadPoolExecutor$Worker.run() line: 575	
			Thread.run() line: 619
This is the stack call when the outbound endpoint is sync:
MuleServer - EE-1968 - sync outbound [Java Application]	
	org.mule.MuleServer at localhost:2019	
		Thread [MuleServer.1] (Running)	
		Daemon Thread [Thread-3] (Running)	
		Thread [http1.receiver.1] (Running)	
		Thread [SandboxGateway.1] (Running)	
		Thread [SystemStreamConnector.scheduler.1] (Running)	
		Thread [SuccessService.1] (Running)	
		Thread [ErrorService1.1] (Running)	
		Thread [ErrorService2.1] (Running)	
		Thread [LogService.1] (Running)	
		Thread [DestroyJavaVM] (Running)	
		Thread [SystemStreamConnector.receiver.1] (Running)	
		Thread [SystemStreamConnector.scheduler.2] (Running)	
		Thread [SystemStreamConnector.scheduler.3] (Running)	
		Thread [SystemStreamConnector.scheduler.4] (Running)	
		Thread [SandboxGateway.2] (Suspended (breakpoint at line 14 in TestTransformer))	
			TestTransformer.transform(MuleMessage, String) line: 14	
			TestTransformer(AbstractMessageAwareTransformer).doTransform(Object, String) line: 68	
			TestTransformer(AbstractTransformer).transform(Object) line: 254	
			DefaultMuleMessage.applyAllTransformers(List) line: 645	
			DefaultMuleMessage.applyTransformers(List, Class) line: 606	
			DefaultMuleMessage.applyTransformers(List) line: 599	
			DefaultMuleEvent.transformMessage(Class) line: 328	
			DefaultMuleEvent.transformMessage() line: 323	
			VMMessageDispatcher.doSend(MuleEvent) line: 101	
			VMMessageDispatcher(AbstractMessageDispatcher).send(MuleEvent) line: 165	THIS ONE HANDLES THE EXCEPTION AND RE THROWS IT
			VMConnector(AbstractConnector).send(OutboundEndpoint, MuleEvent) line: 2136	
			DefaultOutboundEndpoint.send(MuleEvent) line: 97	
			DefaultMuleSession.sendEvent(MuleEvent) line: 332	
			DefaultMuleSession.sendEvent(MuleMessage, OutboundEndpoint) line: 216	
			AbstractOutboundRouter$2.doInTransaction() line: 152	
			TransactionTemplate.execute(TransactionCallback) line: 114	
			FilteringOutboundRouter(AbstractOutboundRouter).send(MuleSession, MuleMessage, OutboundEndpoint) line: 159	
			FilteringOutboundRouter.route(MuleMessage, MuleSession) line: 79	
			DefaultOutboundRouterCollection$1.doInTransaction() line: 86	
			TransactionTemplate.execute(TransactionCallback) line: 47	
			DefaultOutboundRouterCollection.route(MuleMessage, MuleSession) line: 91	
			SedaService(AbstractService).dispatchToOutboundRouter(MuleEvent, MuleMessage) line: 863	
			SedaService.dispatchToOutboundRouter(MuleEvent, MuleMessage) line: 554	
			SedaService$ComponentStageWorker.doRun() line: 576	
			SedaService$ComponentStageWorker(AbstractMuleEventWork).run() line: 41	
			WorkerContext.run() line: 310	
			ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1061	
			ThreadPoolExecutor$Worker.run() line: 575	
			Thread.run() line: 619
Note that the difference starts here:
  • async
    • VMMessageDispatcher(AbstractMessageDispatcher).dispatch(MuleEvent) line: 104 THIS ONE HANDLES EXCEPTION AND THAT'S IT
  • sync
    • VMMessageDispatcher(AbstractMessageDispatcher).send(MuleEvent) line: 165 THIS ONE HANDLES THE EXCEPTION AND RE THROWS IT
Hide
Edu Pereda added a comment -

I am attaching a proposed patch. I am testing it locally right now. It fixes the issue but I want to make sure it does not break anything.

This is the main modification:

Index: core/src/main/java/org/mule/service/AbstractService.java
===================================================================
--- core/src/main/java/org/mule/service/AbstractService.java	(revision 17810)
+++ core/src/main/java/org/mule/service/AbstractService.java	(working copy)
@@ -855,12 +858,24 @@
         {
             if (getOutboundRouter().hasEndpoints())
             {
-                // Here we can use the same message instance because there is no inbound response.
+                // Here we can use the same message instance because there is no
+                // inbound response.
                 if (stats.isEnabled())
                 {
                     stats.incSentEventASync();
                 }
-                getOutboundRouter().route(result, event.getSession());
+                try
+                {
+                    getOutboundRouter().route(result, event.getSession());
+                }
+                catch (MessagingException e)
+                {
+                    if (!ExceptionUtils.containsType(e, DispatchException.class))
+                    {
+                        // DispatchExceptions are handled in the dispatcher.
+                        throw e;
+                    }
+                }
             }
         }
     }
Show
Edu Pereda added a comment - I am attaching a proposed patch. I am testing it locally right now. It fixes the issue but I want to make sure it does not break anything. This is the main modification:
Index: core/src/main/java/org/mule/service/AbstractService.java
===================================================================
--- core/src/main/java/org/mule/service/AbstractService.java	(revision 17810)
+++ core/src/main/java/org/mule/service/AbstractService.java	(working copy)
@@ -855,12 +858,24 @@
         {
             if (getOutboundRouter().hasEndpoints())
             {
-                // Here we can use the same message instance because there is no inbound response.
+                // Here we can use the same message instance because there is no
+                // inbound response.
                 if (stats.isEnabled())
                 {
                     stats.incSentEventASync();
                 }
-                getOutboundRouter().route(result, event.getSession());
+                try
+                {
+                    getOutboundRouter().route(result, event.getSession());
+                }
+                catch (MessagingException e)
+                {
+                    if (!ExceptionUtils.containsType(e, DispatchException.class))
+                    {
+                        // DispatchExceptions are handled in the dispatcher.
+                        throw e;
+                    }
+                }
             }
         }
     }
Hide
Edu Pereda added a comment -

Some of the changes from this bug were reverted in http://fisheye.codehaus.org/changelog/mule/?cs=19198 for issue MULE-4955. That issue is more general than this one.
It was done for 2.2.x.

Show
Edu Pereda added a comment - Some of the changes from this bug were reverted in http://fisheye.codehaus.org/changelog/mule/?cs=19198 for issue MULE-4955. That issue is more general than this one. It was done for 2.2.x.
Hide
Edu Pereda added a comment -

This issue is fixed for 2.2.x (it will be out on 2.2.6).

I am not closing it until we merge it with 3.x

Show
Edu Pereda added a comment - This issue is fixed for 2.2.x (it will be out on 2.2.6). I am not closing it until we merge it with 3.x
Hide
Mateo Almenta Reca added a comment - - edited

This should not been an issue anymore in 3.0 since there is no more connector exception strategy. Can you please confirm all this is good with the new model?
Need to make sure that the underling cases are handled by the new architecture

Show
Mateo Almenta Reca added a comment - - edited This should not been an issue anymore in 3.0 since there is no more connector exception strategy. Can you please confirm all this is good with the new model? Need to make sure that the underling cases are handled by the new architecture
Hide
Edu Pereda added a comment -
Show
Edu Pereda added a comment - Merged by Travis on 3.x: http://fisheye.codehaus.org/changelog/mule/?cs=19000

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: