diff --git a/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java b/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java index f2458e0295..b1e924bbd6 100644 --- a/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java +++ b/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java @@ -161,7 +161,6 @@ public class JmsMessageDrivenEndpointParser extends AbstractSingleBeanDefinition IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-request-payload"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-reply-payload"); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-channel"); int defaults = 0; if (StringUtils.hasText(element.getAttribute(DEFAULT_REPLY_DESTINATION_ATTRIB))) { defaults++; @@ -191,6 +190,7 @@ public class JmsMessageDrivenEndpointParser extends AbstractSingleBeanDefinition IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout", "requestTimeout"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload", "extractRequestPayload"); } + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-channel"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-converter"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "header-mapper"); BeanDefinition beanDefinition = builder.getBeanDefinition(); diff --git a/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.0.xsd b/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.0.xsd index cefd7dcd02..2979cb4711 100644 --- a/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.0.xsd +++ b/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.0.xsd @@ -389,6 +389,15 @@ + + + + + + + + + diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/InboundOneWayErrorTests-context.xml b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/InboundOneWayErrorTests-context.xml new file mode 100644 index 0000000000..6f9e3b5681 --- /dev/null +++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/InboundOneWayErrorTests-context.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/InboundOneWayErrorTests.java b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/InboundOneWayErrorTests.java new file mode 100644 index 0000000000..9fd9544a3d --- /dev/null +++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/InboundOneWayErrorTests.java @@ -0,0 +1,118 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.jms.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.jms.ConnectionFactory; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Session; + +import org.junit.Test; + +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.Message; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.core.PollableChannel; +import org.springframework.jms.core.JmsTemplate; +import org.springframework.jms.core.MessageCreator; +import org.springframework.util.ErrorHandler; + +/** + * @author Mark Fisher + */ +public class InboundOneWayErrorTests { + + @Test + public void noErrorChannel() throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("InboundOneWayErrorTests-context.xml", getClass()); + JmsTemplate jmsTemplate = new JmsTemplate(context.getBean("connectionFactory", ConnectionFactory.class)); + Destination queue = context.getBean("queueA", Destination.class); + jmsTemplate.send(queue, new MessageCreator() { + public javax.jms.Message createMessage(Session session) throws JMSException { + return session.createTextMessage("test-A"); + } + }); + TestErrorHandler errorHandler = context.getBean("testErrorHandler", TestErrorHandler.class); + errorHandler.latch.await(3000, TimeUnit.MILLISECONDS); + assertNotNull(errorHandler.lastError); + assertNotNull(errorHandler.lastError.getCause()); + assertEquals("failed to process: test-A", errorHandler.lastError.getCause().getMessage()); + PollableChannel testErrorChannel = context.getBean("testErrorChannel", PollableChannel.class); + assertNull(testErrorChannel.receive(0)); + context.close(); + } + + @Test + public void errorChannel() throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("InboundOneWayErrorTests-context.xml", getClass()); + JmsTemplate jmsTemplate = new JmsTemplate(context.getBean("connectionFactory", ConnectionFactory.class)); + Destination queue = context.getBean("queueB", Destination.class); + jmsTemplate.send(queue, new MessageCreator() { + public javax.jms.Message createMessage(Session session) throws JMSException { + return session.createTextMessage("test-B"); + } + }); + PollableChannel errorChannel = context.getBean("testErrorChannel", PollableChannel.class); + Message errorMessage = errorChannel.receive(3000); + assertNotNull(errorMessage); + assertEquals(MessageHandlingException.class, errorMessage.getPayload().getClass()); + MessageHandlingException exception = (MessageHandlingException) errorMessage.getPayload(); + assertNotNull(exception.getCause()); + assertEquals(TestException.class, exception.getCause().getClass()); + assertEquals("failed to process: test-B", exception.getCause().getMessage()); + TestErrorHandler errorHandler = context.getBean("testErrorHandler", TestErrorHandler.class); + assertNull(errorHandler.lastError); + context.close(); + } + + + public static class TestService { + public void process(Object o) { + throw new TestException("failed to process: " + o); + } + } + + + @SuppressWarnings("serial") + private static class TestException extends RuntimeException { + public TestException(String message) { + super(message); + } + } + + + @SuppressWarnings("unused") + private static class TestErrorHandler implements ErrorHandler { + + private final CountDownLatch latch = new CountDownLatch(1); + + private volatile Throwable lastError; + + public void handleError(Throwable t) { + this.lastError = t; + this.latch.countDown(); + } + } + +}