From 0ed3ba765757444221880c8424ccfa50ae1ed9a9 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 24 Sep 2008 00:00:55 +0000 Subject: [PATCH] Refactored CharacterStreamOutboundChannelAdapter to CharacterStreamWritingMessageConsumer and simplified the abstract method for AbstractOutboundChannelAdapter so that only a bean definition is returned (the base class now handles registration). --- .../FileOutboundChannelAdapterParser.java | 7 +-- .../FtpOutboundChannelAdapterParser.java | 7 +-- .../MailOutboundChannelAdapterParser.java | 7 +-- ...haracterStreamWritingMessageConsumer.java} | 35 ++++++------ .../ConsoleOutboundChannelAdapterParser.java | 53 +++--------------- ...terStreamWritingMessageConsumerTests.java} | 56 +++++++++---------- ...soleOutboundChannelAdapterParserTests.java | 38 +++++++------ .../AbstractOutboundChannelAdapterParser.java | 24 +++++++- ...dInvokingOutboundChannelAdapterParser.java | 20 ++++--- 9 files changed, 116 insertions(+), 131 deletions(-) rename org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/{CharacterStreamOutboundChannelAdapter.java => CharacterStreamWritingMessageConsumer.java} (74%) rename org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/{CharacterStreamOutboundChannelAdapterTests.java => CharacterStreamWritingMessageConsumerTests.java} (71%) diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java index 60134ea868..c7901108f6 100644 --- a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java +++ b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java @@ -18,8 +18,8 @@ package org.springframework.integration.file.config; import org.w3c.dom.Element; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.AbstractOutboundChannelAdapterParser; import org.springframework.integration.file.FileWritingMessageConsumer; @@ -34,7 +34,7 @@ import org.springframework.util.StringUtils; public class FileOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { @Override - protected String parseConsumer(Element element, ParserContext parserContext) { + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { String directory = element.getAttribute("directory"); Assert.hasText(directory, "directory is required"); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FileWritingMessageConsumer.class); @@ -43,8 +43,7 @@ public class FileOutboundChannelAdapterParser extends AbstractOutboundChannelAda if (StringUtils.hasText(fileNameGenerator)) { builder.addPropertyReference("fileNameGenerator", fileNameGenerator); } - return BeanDefinitionReaderUtils.registerWithGeneratedName( - builder.getBeanDefinition(), parserContext.getRegistry()); + return builder.getBeanDefinition(); } } diff --git a/org.springframework.integration.ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java b/org.springframework.integration.ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java index 6ac3993d0b..c9d4c762c3 100644 --- a/org.springframework.integration.ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java +++ b/org.springframework.integration.ftp/src/main/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParser.java @@ -18,8 +18,8 @@ package org.springframework.integration.ftp.config; import org.w3c.dom.Element; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.AbstractOutboundChannelAdapterParser; import org.springframework.integration.ftp.FtpSendingMessageConsumer; @@ -34,7 +34,7 @@ import org.springframework.integration.ftp.QueuedFTPClientPool; public class FtpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { @Override - protected String parseConsumer(Element element, ParserContext parserContext) { + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpSendingMessageConsumer.class); String username = element.getAttribute("username"); String password = element.getAttribute("password"); @@ -48,8 +48,7 @@ public class FtpOutboundChannelAdapterParser extends AbstractOutboundChannelAdap queuedFTPClientPool.setPort(Integer.parseInt(port)); queuedFTPClientPool.setRemoteWorkingDirectory(remoteWorkingDirectory); builder.addConstructorArgValue(queuedFTPClientPool); - return BeanDefinitionReaderUtils.registerWithGeneratedName( - builder.getBeanDefinition(), parserContext.getRegistry()); + return builder.getBeanDefinition(); } } diff --git a/org.springframework.integration.mail/src/main/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParser.java b/org.springframework.integration.mail/src/main/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParser.java index d728fd9ab0..1d7c6eb99f 100644 --- a/org.springframework.integration.mail/src/main/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParser.java +++ b/org.springframework.integration.mail/src/main/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParser.java @@ -18,8 +18,8 @@ package org.springframework.integration.mail.config; import org.w3c.dom.Element; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.ConfigurationException; import org.springframework.integration.config.AbstractOutboundChannelAdapterParser; @@ -39,7 +39,7 @@ public class MailOutboundChannelAdapterParser extends AbstractOutboundChannelAda } @Override - protected String parseConsumer(Element element, ParserContext parserContext) { + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MailSendingMessageConsumer.class); String mailSenderRef = element.getAttribute("mail-sender"); String host = element.getAttribute("host"); @@ -70,8 +70,7 @@ public class MailOutboundChannelAdapterParser extends AbstractOutboundChannelAda if (StringUtils.hasText(headerGeneratorRef)) { builder.addPropertyReference("headerGenerator", headerGeneratorRef); } - return BeanDefinitionReaderUtils.registerWithGeneratedName( - builder.getBeanDefinition(), parserContext.getRegistry()); + return builder.getBeanDefinition(); } } diff --git a/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/CharacterStreamOutboundChannelAdapter.java b/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/CharacterStreamWritingMessageConsumer.java similarity index 74% rename from org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/CharacterStreamOutboundChannelAdapter.java rename to org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/CharacterStreamWritingMessageConsumer.java index 9ab3620832..6568237436 100644 --- a/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/CharacterStreamOutboundChannelAdapter.java +++ b/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/CharacterStreamWritingMessageConsumer.java @@ -27,21 +27,21 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.integration.ConfigurationException; -import org.springframework.integration.endpoint.AbstractMessageConsumingEndpoint; import org.springframework.integration.message.Message; +import org.springframework.integration.message.MessageConsumer; import org.springframework.integration.message.MessagingException; import org.springframework.util.Assert; /** - * An outbound Channel Adapter that writes to a {@link Writer}. String-based objects - * will be written directly, but if the object is not itself a {@link String}, the - * target will write the result of the object's {@link #toString()} method. To - * append a new-line after each write, set the {@link #shouldAppendNewLine} flag to - * true. It is false by default. + * A {@link MessageConsumer} that writes characters to a {@link Writer}. + * String, character array, and byte array payloads will be written directly, + * but for other payload types, the result of the object's {@link #toString()} + * method will be written. To append a new-line after each write, set the + * {@link #shouldAppendNewLine} flag to 'true'. It is 'false' by default. * * @author Mark Fisher */ -public class CharacterStreamOutboundChannelAdapter extends AbstractMessageConsumingEndpoint { +public class CharacterStreamWritingMessageConsumer implements MessageConsumer { private final Log logger = LogFactory.getLog(this.getClass()); @@ -50,11 +50,11 @@ public class CharacterStreamOutboundChannelAdapter extends AbstractMessageConsum private volatile boolean shouldAppendNewLine = false; - public CharacterStreamOutboundChannelAdapter(Writer writer) { + public CharacterStreamWritingMessageConsumer(Writer writer) { this(writer, -1); } - public CharacterStreamOutboundChannelAdapter(Writer writer, int bufferSize) { + public CharacterStreamWritingMessageConsumer(Writer writer, int bufferSize) { Assert.notNull(writer, "writer must not be null"); if (writer instanceof BufferedWriter) { this.writer = (BufferedWriter) writer; @@ -72,7 +72,7 @@ public class CharacterStreamOutboundChannelAdapter extends AbstractMessageConsum * Factory method that creates a target for stdout (System.out) with the * default charset encoding. */ - public static CharacterStreamOutboundChannelAdapter stdout() { + public static CharacterStreamWritingMessageConsumer stdout() { return stdout(null); } @@ -80,7 +80,7 @@ public class CharacterStreamOutboundChannelAdapter extends AbstractMessageConsum * Factory method that creates a target for stdout (System.out) with the * specified charset encoding. */ - public static CharacterStreamOutboundChannelAdapter stdout(String charsetName) { + public static CharacterStreamWritingMessageConsumer stdout(String charsetName) { return createTargetForStream(System.out, charsetName); } @@ -88,7 +88,7 @@ public class CharacterStreamOutboundChannelAdapter extends AbstractMessageConsum * Factory method that creates a target for stderr (System.err) with the * default charset encoding. */ - public static CharacterStreamOutboundChannelAdapter stderr() { + public static CharacterStreamWritingMessageConsumer stderr() { return stderr(null); } @@ -96,16 +96,16 @@ public class CharacterStreamOutboundChannelAdapter extends AbstractMessageConsum * Factory method that creates a target for stderr (System.err) with the * specified charset encoding. */ - public static CharacterStreamOutboundChannelAdapter stderr(String charsetName) { + public static CharacterStreamWritingMessageConsumer stderr(String charsetName) { return createTargetForStream(System.err, charsetName); } - private static CharacterStreamOutboundChannelAdapter createTargetForStream(OutputStream stream, String charsetName) { + private static CharacterStreamWritingMessageConsumer createTargetForStream(OutputStream stream, String charsetName) { if (charsetName == null) { - return new CharacterStreamOutboundChannelAdapter(new OutputStreamWriter(stream)); + return new CharacterStreamWritingMessageConsumer(new OutputStreamWriter(stream)); } try { - return new CharacterStreamOutboundChannelAdapter(new OutputStreamWriter(stream, charsetName)); + return new CharacterStreamWritingMessageConsumer(new OutputStreamWriter(stream, charsetName)); } catch (UnsupportedEncodingException e) { throw new ConfigurationException("unsupported encoding: " + charsetName, e); @@ -117,8 +117,7 @@ public class CharacterStreamOutboundChannelAdapter extends AbstractMessageConsum this.shouldAppendNewLine = shouldAppendNewLine; } - @Override - public void onMessageInternal(Message message) { + public void onMessage(Message message) { Object payload = message.getPayload(); if (payload == null) { if (logger.isWarnEnabled()) { diff --git a/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java b/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java index 5260c2cc3f..c05c16daf1 100644 --- a/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java +++ b/org.springframework.integration.stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java @@ -18,16 +18,11 @@ package org.springframework.integration.stream.config; import org.w3c.dom.Element; -import org.springframework.beans.factory.BeanDefinitionStoreException; -import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -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.ConfigurationException; -import org.springframework.integration.channel.DirectChannel; -import org.springframework.integration.stream.CharacterStreamOutboundChannelAdapter; +import org.springframework.integration.config.AbstractOutboundChannelAdapterParser; +import org.springframework.integration.stream.CharacterStreamWritingMessageConsumer; import org.springframework.util.StringUtils; /** @@ -35,28 +30,12 @@ import org.springframework.util.StringUtils; * * @author Mark Fisher */ -public class ConsoleOutboundChannelAdapterParser extends AbstractSingleBeanDefinitionParser { +public class ConsoleOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { @Override - protected Class getBeanClass(Element element) { - return CharacterStreamOutboundChannelAdapter.class; - } - - @Override - protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException { - String id = element.getAttribute("id"); - if (!element.hasAttribute("channel")) { - // the created channel will get the 'id', so the adapter's bean name includes a suffix - id = id + ".adapter"; - } - else if (!StringUtils.hasText(id)) { - id = parserContext.getReaderContext().generateBeanName(definition); - } - return id; - } - - @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + CharacterStreamWritingMessageConsumer.class); if (element.getLocalName().startsWith("stderr")) { builder.setFactoryMethod("stderr"); } @@ -70,25 +49,7 @@ public class ConsoleOutboundChannelAdapterParser extends AbstractSingleBeanDefin if ("true".equals(element.getAttribute("append-newline"))) { builder.addPropertyValue("shouldAppendNewLine", Boolean.TRUE); } - String channelName = element.getAttribute("channel"); - if (StringUtils.hasText(channelName)) { - builder.addPropertyReference("inputChannel", channelName); - } - else { - builder.addPropertyReference("inputChannel", this.createDirectChannel(element, parserContext)); - } - } - - private String createDirectChannel(Element element, ParserContext parserContext) { - String channelId = element.getAttribute("id"); - if (!StringUtils.hasText(channelId)) { - throw new ConfigurationException("The channel-adapter's 'id' attribute is required when no 'channel' " - + "reference has been provided, because that 'id' would be used for the created channel."); - } - BeanDefinitionBuilder channelBuilder = BeanDefinitionBuilder.genericBeanDefinition(DirectChannel.class); - BeanDefinitionHolder holder = new BeanDefinitionHolder(channelBuilder.getBeanDefinition(), channelId); - BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry()); - return channelId; + return builder.getBeanDefinition(); } } diff --git a/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/CharacterStreamOutboundChannelAdapterTests.java b/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/CharacterStreamWritingMessageConsumerTests.java similarity index 71% rename from org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/CharacterStreamOutboundChannelAdapterTests.java rename to org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/CharacterStreamWritingMessageConsumerTests.java index 6ed3378c7a..4544878bb2 100644 --- a/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/CharacterStreamOutboundChannelAdapterTests.java +++ b/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/CharacterStreamWritingMessageConsumerTests.java @@ -32,7 +32,7 @@ import org.springframework.integration.scheduling.PollingSchedule; /** * @author Mark Fisher */ -public class CharacterStreamOutboundChannelAdapterTests { +public class CharacterStreamWritingMessageConsumerTests { private QueueChannel channel; @@ -47,18 +47,18 @@ public class CharacterStreamOutboundChannelAdapterTests { @Test - public void testSingleString() { + public void singleString() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); - target.onMessage(new StringMessage("foo")); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); + consumer.onMessage(new StringMessage("foo")); assertEquals("foo", writer.toString()); } @Test - public void testTwoStringsAndNoNewLinesByDefault() { + public void twoStringsAndNoNewLinesByDefault() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); - poller.subscribe(target); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); + poller.subscribe(consumer); poller.setMaxMessagesPerPoll(1); channel.send(new StringMessage("foo"), 0); channel.send(new StringMessage("bar"), 0); @@ -69,11 +69,11 @@ public class CharacterStreamOutboundChannelAdapterTests { } @Test - public void testTwoStringsWithNewLines() { + public void twoStringsWithNewLines() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); - target.setShouldAppendNewLine(true); - poller.subscribe(target); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); + consumer.setShouldAppendNewLine(true); + poller.subscribe(consumer); poller.setMaxMessagesPerPoll(1); channel.send(new StringMessage("foo"), 0); channel.send(new StringMessage("bar"), 0); @@ -85,11 +85,11 @@ public class CharacterStreamOutboundChannelAdapterTests { } @Test - public void testMaxMessagesPerTaskSameAsMessageCount() { + public void maxMessagesPerTaskSameAsMessageCount() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); poller.setMaxMessagesPerPoll(2); - poller.subscribe(target); + poller.subscribe(consumer); channel.send(new StringMessage("foo"), 0); channel.send(new StringMessage("bar"), 0); poller.run(); @@ -97,13 +97,13 @@ public class CharacterStreamOutboundChannelAdapterTests { } @Test - public void testMaxMessagesPerTaskExceedsMessageCountWithAppendedNewLines() { + public void maxMessagesPerTaskExceedsMessageCountWithAppendedNewLines() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); poller.setMaxMessagesPerPoll(10); poller.setReceiveTimeout(0); - poller.subscribe(target); - target.setShouldAppendNewLine(true); + poller.subscribe(consumer); + consumer.setShouldAppendNewLine(true); channel.send(new StringMessage("foo"), 0); channel.send(new StringMessage("bar"), 0); poller.run(); @@ -112,10 +112,10 @@ public class CharacterStreamOutboundChannelAdapterTests { } @Test - public void testSingleNonStringObject() { + public void singleNonStringObject() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); - poller.subscribe(target); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); + poller.subscribe(consumer); poller.setMaxMessagesPerPoll(1); TestObject testObject = new TestObject("foo"); channel.send(new GenericMessage(testObject)); @@ -124,12 +124,12 @@ public class CharacterStreamOutboundChannelAdapterTests { } @Test - public void testTwoNonStringObjectWithOutNewLines() { + public void twoNonStringObjectWithOutNewLines() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); poller.setReceiveTimeout(0); poller.setMaxMessagesPerPoll(2); - poller.subscribe(target); + poller.subscribe(consumer); TestObject testObject1 = new TestObject("foo"); TestObject testObject2 = new TestObject("bar"); channel.send(new GenericMessage(testObject1), 0); @@ -139,13 +139,13 @@ public class CharacterStreamOutboundChannelAdapterTests { } @Test - public void testTwoNonStringObjectWithNewLines() { + public void twoNonStringObjectWithNewLines() { StringWriter writer = new StringWriter(); - CharacterStreamOutboundChannelAdapter target = new CharacterStreamOutboundChannelAdapter(writer); - target.setShouldAppendNewLine(true); + CharacterStreamWritingMessageConsumer consumer = new CharacterStreamWritingMessageConsumer(writer); + consumer.setShouldAppendNewLine(true); poller.setReceiveTimeout(0); poller.setMaxMessagesPerPoll(2); - poller.subscribe(target); + poller.subscribe(consumer); TestObject testObject1 = new TestObject("foo"); TestObject testObject2 = new TestObject("bar"); channel.send(new GenericMessage(testObject1), 0); diff --git a/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParserTests.java b/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParserTests.java index 4433f539ac..f27bff18b0 100644 --- a/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParserTests.java +++ b/org.springframework.integration.stream/src/test/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParserTests.java @@ -34,7 +34,7 @@ import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.ConfigurationException; import org.springframework.integration.message.StringMessage; -import org.springframework.integration.stream.CharacterStreamOutboundChannelAdapter; +import org.springframework.integration.stream.CharacterStreamWritingMessageConsumer; /** * @author Mark Fisher @@ -61,9 +61,10 @@ public class ConsoleOutboundChannelAdapterParserTests { public void stdoutAdapterWithDefaultCharset() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "consoleOutboundChannelAdapterParserTests.xml", ConsoleOutboundChannelAdapterParserTests.class); - CharacterStreamOutboundChannelAdapter adapter = - (CharacterStreamOutboundChannelAdapter) context.getBean("stdoutAdapterWithDefaultCharset"); - DirectFieldAccessor accessor = new DirectFieldAccessor(adapter); + Object adapter = context.getBean("stdoutAdapterWithDefaultCharset"); + CharacterStreamWritingMessageConsumer consumer = (CharacterStreamWritingMessageConsumer) + new DirectFieldAccessor(adapter).getPropertyValue("consumer"); + DirectFieldAccessor accessor = new DirectFieldAccessor(consumer); Writer bufferedWriter = (Writer) accessor.getPropertyValue("writer"); assertEquals(BufferedWriter.class, bufferedWriter.getClass()); DirectFieldAccessor bufferedWriterAccessor = new DirectFieldAccessor(bufferedWriter); @@ -72,7 +73,7 @@ public class ConsoleOutboundChannelAdapterParserTests { Charset writerCharset = Charset.forName(((OutputStreamWriter) writer).getEncoding()); assertEquals(Charset.defaultCharset(), writerCharset); this.resetStreams(); - adapter.onMessage(new StringMessage("foo")); + consumer.onMessage(new StringMessage("foo")); assertEquals("foo", out.toString()); assertEquals("", err.toString()); } @@ -81,9 +82,10 @@ public class ConsoleOutboundChannelAdapterParserTests { public void stdoutAdapterWithProvidedCharset() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "consoleOutboundChannelAdapterParserTests.xml", ConsoleOutboundChannelAdapterParserTests.class); - CharacterStreamOutboundChannelAdapter adapter = - (CharacterStreamOutboundChannelAdapter) context.getBean("stdoutAdapterWithProvidedCharset"); - DirectFieldAccessor accessor = new DirectFieldAccessor(adapter); + Object adapter = context.getBean("stdoutAdapterWithProvidedCharset"); + CharacterStreamWritingMessageConsumer consumer = (CharacterStreamWritingMessageConsumer) + new DirectFieldAccessor(adapter).getPropertyValue("consumer"); + DirectFieldAccessor accessor = new DirectFieldAccessor(consumer); Writer bufferedWriter = (Writer) accessor.getPropertyValue("writer"); assertEquals(BufferedWriter.class, bufferedWriter.getClass()); DirectFieldAccessor bufferedWriterAccessor = new DirectFieldAccessor(bufferedWriter); @@ -92,7 +94,7 @@ public class ConsoleOutboundChannelAdapterParserTests { Charset writerCharset = Charset.forName(((OutputStreamWriter) writer).getEncoding()); assertEquals(Charset.forName("UTF-8"), writerCharset); this.resetStreams(); - adapter.onMessage(new StringMessage("bar")); + consumer.onMessage(new StringMessage("bar")); assertEquals("bar", out.toString()); assertEquals("", err.toString()); } @@ -117,9 +119,10 @@ public class ConsoleOutboundChannelAdapterParserTests { public void stderrAdapter() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "consoleOutboundChannelAdapterParserTests.xml", ConsoleOutboundChannelAdapterParserTests.class); - CharacterStreamOutboundChannelAdapter adapter = - (CharacterStreamOutboundChannelAdapter) context.getBean("stderrAdapter"); - DirectFieldAccessor accessor = new DirectFieldAccessor(adapter); + Object adapter = context.getBean("stderrAdapter"); + CharacterStreamWritingMessageConsumer consumer = (CharacterStreamWritingMessageConsumer) + new DirectFieldAccessor(adapter).getPropertyValue("consumer"); + DirectFieldAccessor accessor = new DirectFieldAccessor(consumer); Writer bufferedWriter = (Writer) accessor.getPropertyValue("writer"); assertEquals(BufferedWriter.class, bufferedWriter.getClass()); DirectFieldAccessor bufferedWriterAccessor = new DirectFieldAccessor(bufferedWriter); @@ -128,7 +131,7 @@ public class ConsoleOutboundChannelAdapterParserTests { Charset writerCharset = Charset.forName(((OutputStreamWriter) writer).getEncoding()); assertEquals(Charset.defaultCharset(), writerCharset); this.resetStreams(); - adapter.onMessage(new StringMessage("bad")); + consumer.onMessage(new StringMessage("bad")); assertEquals("", out.toString()); assertEquals("bad", err.toString()); } @@ -137,9 +140,10 @@ public class ConsoleOutboundChannelAdapterParserTests { public void stdoutAdatperWithAppendNewLine() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "consoleOutboundChannelAdapterParserTests.xml", ConsoleOutboundChannelAdapterParserTests.class); - CharacterStreamOutboundChannelAdapter adapter = - (CharacterStreamOutboundChannelAdapter) context.getBean("newlineAdapter"); - DirectFieldAccessor accessor = new DirectFieldAccessor(adapter); + Object adapter = context.getBean("newlineAdapter"); + CharacterStreamWritingMessageConsumer consumer = (CharacterStreamWritingMessageConsumer) + new DirectFieldAccessor(adapter).getPropertyValue("consumer"); + DirectFieldAccessor accessor = new DirectFieldAccessor(consumer); Writer bufferedWriter = (Writer) accessor.getPropertyValue("writer"); assertEquals(BufferedWriter.class, bufferedWriter.getClass()); DirectFieldAccessor bufferedWriterAccessor = new DirectFieldAccessor(bufferedWriter); @@ -148,7 +152,7 @@ public class ConsoleOutboundChannelAdapterParserTests { Charset writerCharset = Charset.forName(((OutputStreamWriter) writer).getEncoding()); assertEquals(Charset.defaultCharset(), writerCharset); this.resetStreams(); - adapter.onMessage(new StringMessage("foo")); + consumer.onMessage(new StringMessage("foo")); assertEquals("foo\n", out.toString()); } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/AbstractOutboundChannelAdapterParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/AbstractOutboundChannelAdapterParser.java index 096da973b7..1e49819765 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/AbstractOutboundChannelAdapterParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/AbstractOutboundChannelAdapterParser.java @@ -20,9 +20,11 @@ import org.w3c.dom.Element; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.ConfigurationException; import org.springframework.integration.endpoint.OutboundChannelAdapter; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; @@ -38,7 +40,10 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann Element pollerElement = DomUtils.getChildElementByTagName(element, "poller"); BeanDefinitionBuilder adapterBuilder = null; adapterBuilder = BeanDefinitionBuilder.genericBeanDefinition(OutboundChannelAdapter.class); - adapterBuilder.addConstructorArgReference(this.parseConsumer(element, parserContext)); + AbstractBeanDefinition consumerBeanDefinition = this.parseConsumer(element, parserContext); + String consumerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName( + consumerBeanDefinition, parserContext.getRegistry()); + adapterBuilder.addConstructorArgReference(consumerBeanName); if (pollerElement != null) { if (!StringUtils.hasText(channelName)) { throw new ConfigurationException("outbound channel adapter with a 'poller' requires a 'channel' to poll"); @@ -54,8 +59,21 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann } /** - * Subclasses must implement this method and return the bean name of the MessageConsumer. + * Override this method to control the registration process and return the bean name. + * If parsing a bean definition whose name can be auto-generated, consider using + * {@link #parseConsumer(Element, ParserContext)} instead. */ - protected abstract String parseConsumer(Element element, ParserContext parserContext); + protected String parseAndRegisterConsumer(Element element, ParserContext parserContext) { + AbstractBeanDefinition definition = this.parseConsumer(element, parserContext); + Assert.notNull(definition, "Consumer parsing must return a BeanDefinition."); + return BeanDefinitionReaderUtils.registerWithGeneratedName( + definition, parserContext.getRegistry()); + } + + /** + * Override this method to return the BeanDefinition for the MessageConsumer. It will + * be registered with a generated name. + */ + protected abstract AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext); } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/MethodInvokingOutboundChannelAdapterParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/MethodInvokingOutboundChannelAdapterParser.java index a1706fb5e7..16a2ebfebc 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/MethodInvokingOutboundChannelAdapterParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/MethodInvokingOutboundChannelAdapterParser.java @@ -18,6 +18,7 @@ package org.springframework.integration.config; import org.w3c.dom.Element; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; @@ -33,17 +34,22 @@ import org.springframework.util.StringUtils; public class MethodInvokingOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { @Override - protected String parseConsumer(Element element, ParserContext parserContext) { + protected String parseAndRegisterConsumer(Element element, ParserContext parserContext) { String target = element.getAttribute("target"); Assert.isTrue(StringUtils.hasText(target), "target is required"); - String methodName = element.getAttribute("method"); - if (StringUtils.hasText(methodName)) { - BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingConsumer.class); - invokerBuilder.addConstructorArgReference(target); - invokerBuilder.addConstructorArgValue(methodName); - target = BeanDefinitionReaderUtils.registerWithGeneratedName(invokerBuilder.getBeanDefinition(), parserContext.getRegistry()); + if (element.hasAttribute("method")) { + target = BeanDefinitionReaderUtils.registerWithGeneratedName( + this.parseConsumer(element, parserContext), parserContext.getRegistry()); } return target; } + @Override + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { + BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingConsumer.class); + invokerBuilder.addConstructorArgReference(element.getAttribute("target")); + invokerBuilder.addConstructorArgValue(element.getAttribute("method")); + return invokerBuilder.getBeanDefinition(); + } + }