Minimizing class loading in parsers and using the parser context error handling capabilities rather than throwing Exceptions or using assertions. This facilitates proper tooling support (INT-114).
This commit is contained in:
@@ -16,11 +16,9 @@
|
||||
|
||||
package org.springframework.integration.jms.config;
|
||||
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -28,7 +26,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class JmsAdapterParserUtils {
|
||||
abstract class JmsAdapterParserUtils {
|
||||
|
||||
static final String JMS_TEMPLATE_ATTRIBUTE = "jms-template";
|
||||
|
||||
@@ -50,35 +48,48 @@ public abstract class JmsAdapterParserUtils {
|
||||
|
||||
static final String HEADER_MAPPER_PROPERTY = "headerMapper";
|
||||
|
||||
/*
|
||||
* The following constants match those of javax.jms.Session.
|
||||
* They are duplicated here to avoid a dependency in tooling.
|
||||
*/
|
||||
|
||||
public static String determineConnectionFactoryBeanName(Element element) {
|
||||
static final int SESSION_TRANSACTED = 0;
|
||||
|
||||
private static final int AUTO_ACKNOWLEDGE = 1;
|
||||
|
||||
private static final int CLIENT_ACKNOWLEDGE = 2;
|
||||
|
||||
private static final int DUPS_OK_ACKNOWLEDGE = 3;
|
||||
|
||||
|
||||
static String determineConnectionFactoryBeanName(Element element, ParserContext parserContext) {
|
||||
String connectionFactoryBeanName = "connectionFactory";
|
||||
if (element.hasAttribute(CONNECTION_FACTORY_ATTRIBUTE)) {
|
||||
connectionFactoryBeanName = element.getAttribute(CONNECTION_FACTORY_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(connectionFactoryBeanName)) {
|
||||
throw new BeanCreationException(
|
||||
"JMS adapter 'connection-factory' attribute must not be empty");
|
||||
parserContext.getReaderContext().error(
|
||||
"JMS adapter 'connection-factory' attribute must not be empty", element);
|
||||
}
|
||||
}
|
||||
return connectionFactoryBeanName;
|
||||
}
|
||||
|
||||
public static Integer parseAcknowledgeMode(Element element) {
|
||||
static Integer parseAcknowledgeMode(Element element, ParserContext parserContext) {
|
||||
String acknowledge = element.getAttribute("acknowledge");
|
||||
if (StringUtils.hasText(acknowledge)) {
|
||||
int acknowledgeMode = Session.AUTO_ACKNOWLEDGE;
|
||||
int acknowledgeMode = AUTO_ACKNOWLEDGE;
|
||||
if ("transacted".equals(acknowledge)) {
|
||||
acknowledgeMode = Session.SESSION_TRANSACTED;
|
||||
acknowledgeMode = SESSION_TRANSACTED;
|
||||
}
|
||||
else if ("dups-ok".equals(acknowledge)) {
|
||||
acknowledgeMode = Session.DUPS_OK_ACKNOWLEDGE;
|
||||
acknowledgeMode = DUPS_OK_ACKNOWLEDGE;
|
||||
}
|
||||
else if ("client".equals(acknowledge)) {
|
||||
acknowledgeMode = Session.CLIENT_ACKNOWLEDGE;
|
||||
acknowledgeMode = CLIENT_ACKNOWLEDGE;
|
||||
}
|
||||
else if (!"auto".equals(acknowledge)) {
|
||||
throw new BeanCreationException("Invalid JMS 'acknowledge' setting: " +
|
||||
"only \"auto\", \"client\", \"dups-ok\" and \"transacted\" supported.");
|
||||
parserContext.getReaderContext().error("Invalid JMS 'acknowledge' setting: " +
|
||||
"only \"auto\", \"client\", \"dups-ok\" and \"transacted\" supported.", element);
|
||||
}
|
||||
return acknowledgeMode;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.jms.JmsDestinationPollingSource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -44,7 +43,8 @@ public class JmsInboundChannelAdapterParser extends AbstractPollingInboundChanne
|
||||
|
||||
@Override
|
||||
protected String parseSource(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(JmsDestinationPollingSource.class);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.jms.JmsDestinationPollingSource");
|
||||
String jmsTemplate = element.getAttribute(JmsAdapterParserUtils.JMS_TEMPLATE_ATTRIBUTE);
|
||||
String destination = element.getAttribute(JmsAdapterParserUtils.DESTINATION_ATTRIBUTE);
|
||||
String destinationName = element.getAttribute(JmsAdapterParserUtils.DESTINATION_NAME_ATTRIBUTE);
|
||||
@@ -62,7 +62,7 @@ public class JmsInboundChannelAdapterParser extends AbstractPollingInboundChanne
|
||||
builder.addConstructorArgReference(jmsTemplate);
|
||||
}
|
||||
else if (StringUtils.hasText(destination) || StringUtils.hasText(destinationName)) {
|
||||
builder.addConstructorArgReference(JmsAdapterParserUtils.determineConnectionFactoryBeanName(element));
|
||||
builder.addConstructorArgReference(JmsAdapterParserUtils.determineConnectionFactoryBeanName(element, parserContext));
|
||||
if (StringUtils.hasText(destination)) {
|
||||
builder.addConstructorArgReference(destination);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.integration.jms.config;
|
||||
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -25,10 +23,6 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.jms.ChannelPublishingJmsMessageListener;
|
||||
import org.springframework.integration.jms.JmsMessageDrivenEndpoint;
|
||||
import org.springframework.jms.listener.DefaultMessageListenerContainer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -58,8 +52,8 @@ public class JmsMessageDrivenEndpointParser extends AbstractSingleBeanDefinition
|
||||
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return JmsMessageDrivenEndpoint.class;
|
||||
protected String getBeanClassName(Element element) {
|
||||
return "org.springframework.integration.jms.JmsMessageDrivenEndpoint";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,30 +78,35 @@ public class JmsMessageDrivenEndpointParser extends AbstractSingleBeanDefinition
|
||||
private String parseMessageListenerContainer(Element element, ParserContext parserContext) {
|
||||
if (element.hasAttribute("container")) {
|
||||
for (String containerAttribute : containerAttributes) {
|
||||
Assert.isTrue(!element.hasAttribute(containerAttribute), "The '" + containerAttribute +
|
||||
"' attribute should not be provided when specifying a 'container' reference.");
|
||||
if (element.hasAttribute(containerAttribute)) {
|
||||
parserContext.getReaderContext().error("The '" + containerAttribute +
|
||||
"' attribute should not be provided when specifying a 'container' reference.", element);
|
||||
}
|
||||
}
|
||||
return element.getAttribute("container");
|
||||
}
|
||||
// otherwise, we build a DefaultMessageListenerContainer instance
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(DefaultMessageListenerContainer.class);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.jms.listener.DefaultMessageListenerContainer");
|
||||
String destinationAttribute = this.expectReply ? "request-destination" : "destination";
|
||||
String destinationNameAttribute = this.expectReply ? "request-destination-name" : "destination-name";
|
||||
String destination = element.getAttribute(destinationAttribute);
|
||||
String destinationName = element.getAttribute(destinationNameAttribute);
|
||||
Assert.isTrue(StringUtils.hasText(destination) ^ StringUtils.hasText(destinationName),
|
||||
"Exactly one of '" + destinationAttribute + "' or '" + destinationNameAttribute + "' is required.");
|
||||
if (!(StringUtils.hasText(destination) ^ StringUtils.hasText(destinationName))) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Exactly one of '" + destinationAttribute + "' or '" + destinationNameAttribute + "' is required.", element);
|
||||
}
|
||||
builder.addPropertyReference(JmsAdapterParserUtils.CONNECTION_FACTORY_PROPERTY,
|
||||
JmsAdapterParserUtils.determineConnectionFactoryBeanName(element));
|
||||
JmsAdapterParserUtils.determineConnectionFactoryBeanName(element, parserContext));
|
||||
if (StringUtils.hasText(destination)) {
|
||||
builder.addPropertyReference("destination", destination);
|
||||
}
|
||||
else {
|
||||
builder.addPropertyValue("destinationName", destinationName);
|
||||
}
|
||||
Integer acknowledgeMode = JmsAdapterParserUtils.parseAcknowledgeMode(element);
|
||||
Integer acknowledgeMode = JmsAdapterParserUtils.parseAcknowledgeMode(element, parserContext);
|
||||
if (acknowledgeMode != null) {
|
||||
if (acknowledgeMode.intValue() == Session.SESSION_TRANSACTED) {
|
||||
if (acknowledgeMode.intValue() == JmsAdapterParserUtils.SESSION_TRANSACTED) {
|
||||
builder.addPropertyValue("sessionTransacted", Boolean.TRUE);
|
||||
}
|
||||
else {
|
||||
@@ -126,7 +125,8 @@ public class JmsMessageDrivenEndpointParser extends AbstractSingleBeanDefinition
|
||||
}
|
||||
|
||||
private String parseMessageListener(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ChannelPublishingJmsMessageListener.class);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.jms.ChannelPublishingJmsMessageListener");
|
||||
builder.addPropertyValue("expectReply", this.expectReply);
|
||||
if (this.expectReply) {
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "request-channel");
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.jms.JmsSendingMessageHandler;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -36,7 +35,8 @@ public class JmsOutboundChannelAdapterParser extends AbstractOutboundChannelAdap
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(JmsSendingMessageHandler.class);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.jms.JmsSendingMessageHandler");
|
||||
String jmsTemplate = element.getAttribute(JmsAdapterParserUtils.JMS_TEMPLATE_ATTRIBUTE);
|
||||
String destination = element.getAttribute(JmsAdapterParserUtils.DESTINATION_ATTRIBUTE);
|
||||
String destinationName = element.getAttribute(JmsAdapterParserUtils.DESTINATION_NAME_ATTRIBUTE);
|
||||
@@ -52,7 +52,7 @@ public class JmsOutboundChannelAdapterParser extends AbstractOutboundChannelAdap
|
||||
}
|
||||
else if (StringUtils.hasText(destination) ^ StringUtils.hasText(destinationName)) {
|
||||
builder.addPropertyReference(JmsAdapterParserUtils.CONNECTION_FACTORY_PROPERTY,
|
||||
JmsAdapterParserUtils.determineConnectionFactoryBeanName(element));
|
||||
JmsAdapterParserUtils.determineConnectionFactoryBeanName(element, parserContext));
|
||||
if (StringUtils.hasText(destination)) {
|
||||
builder.addPropertyReference(JmsAdapterParserUtils.DESTINATION_PROPERTY, destination);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.jms.JmsOutboundGateway;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -40,12 +38,15 @@ public class JmsOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(JmsOutboundGateway.class);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.jms.JmsOutboundGateway");
|
||||
builder.addPropertyReference("connectionFactory", element.getAttribute("connection-factory"));
|
||||
String requestDestination = element.getAttribute("request-destination");
|
||||
String requestDestinationName = element.getAttribute("request-destination-name");
|
||||
Assert.isTrue(StringUtils.hasText(requestDestination) ^ StringUtils.hasText(requestDestinationName),
|
||||
"Exactly one of the 'request-destination' or 'request-destination-name' attributes is required.");
|
||||
if (!(StringUtils.hasText(requestDestination) ^ StringUtils.hasText(requestDestinationName))) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Exactly one of the 'request-destination' or 'request-destination-name' attributes is required.", element);
|
||||
}
|
||||
if (StringUtils.hasText(requestDestination)) {
|
||||
builder.addPropertyReference("requestDestination", requestDestination);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ 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 static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.channel.PollableChannel;
|
||||
@@ -134,8 +134,9 @@ public class JmsInboundGatewayParserTests {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("jmsGatewayWithConnectionFactoryOnly.xml", this.getClass());
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
assertEquals(IllegalArgumentException.class, e.getCause().getClass());
|
||||
catch (BeanDefinitionStoreException e) {
|
||||
assertTrue(e.getMessage().contains("request-destination"));
|
||||
assertTrue(e.getMessage().contains("request-destination-name"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -145,8 +146,8 @@ public class JmsInboundGatewayParserTests {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("jmsGatewayWithEmptyConnectionFactory.xml", this.getClass());
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
assertEquals(BeanCreationException.class, e.getCause().getClass());
|
||||
catch (BeanDefinitionStoreException e) {
|
||||
assertTrue(e.getMessage().contains("connection-factory"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ package org.springframework.integration.jms.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
@@ -80,8 +80,8 @@ public class JmsOutboundChannelAdapterParserTests {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("jmsOutboundWithEmptyConnectionFactory.xml", this.getClass());
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
assertEquals(BeanCreationException.class, e.getCause().getClass());
|
||||
catch (BeanDefinitionStoreException e) {
|
||||
assertTrue(e.getMessage().contains("connection-factory"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user