Added Target interface and split DefaultMessageEndpoint into TargetEndpoint and HandlerEndpoint. All "one-way" adapters now implement Target instead of MessageHandler, the ConcurrentHandler is now ConcurrentTarget, and the MessageDispatcher also operates on Targets rather than MessageHandlers.

This commit is contained in:
Mark Fisher
2008-04-17 17:25:56 +00:00
parent e9673586c4
commit 0f6bd60ee0
69 changed files with 930 additions and 1008 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -16,35 +16,33 @@
package org.springframework.integration.adapter.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.integration.adapter.AbstractTargetAdapter;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.Target;
/**
* A target adapter for publishing {@link MessagingEvent MessagingEvents}. The
* {@link MessagingEvent} is a subclass of Spring's {@link ApplicationEvent}
* used by this adapter to wrap any {@link Message} received on its channel.
* used by this adapter to wrap any {@link Message} sent to this target.
*
* @author Mark Fisher
*/
public class ApplicationEventTargetAdapter extends AbstractTargetAdapter<MessagingEvent> implements
ApplicationEventPublisherAware {
public class ApplicationEventTargetAdapter<T> implements Target, ApplicationEventPublisherAware {
private final MessageMapper<T, MessagingEvent<T>> mapper = new MessagingEventMapper<T>();
private ApplicationEventPublisher applicationEventPublisher;
public ApplicationEventTargetAdapter() {
this.setMessageMapper(new MessagingEventMapper());
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@Override
protected boolean sendToTarget(MessagingEvent event) {
this.applicationEventPublisher.publishEvent(event);
public boolean send(Message<?> message) {
this.applicationEventPublisher.publishEvent(this.mapper.mapMessage((Message<T>) message));
return true;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -17,22 +17,22 @@
package org.springframework.integration.adapter.event;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageCreator;
import org.springframework.integration.message.MessageMapper;
/**
* A {@link MessageMapper} implementation for mapping to and from
* {@link MessagingEvent MessagingEvents}.
* Maps between {@link Message Messages} and {@link MessagingEvent MessagingEvents}.
*
* @author Mark Fisher
*/
public class MessagingEventMapper<T> implements MessageMapper<T, MessagingEvent<T>> {
public class MessagingEventMapper<T> implements MessageCreator<MessagingEvent<T>, T>, MessageMapper<T, MessagingEvent<T>> {
public MessagingEvent<T> fromMessage(Message<T> message) {
return new MessagingEvent<T>(message);
}
public Message<T> toMessage(MessagingEvent<T> event) {
public Message<T> createMessage(MessagingEvent<T> event) {
return event.getMessage();
}
public MessagingEvent<T> mapMessage(Message<T> message) {
return new MessagingEvent<T>(message);
}
}

View File

@@ -23,10 +23,11 @@ import java.io.FileWriter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.message.AbstractMessageMapper;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageCreator;
import org.springframework.integration.message.MessageHandlingException;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.MessagingException;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
@@ -36,7 +37,7 @@ import org.springframework.util.FileCopyUtils;
*
* @author Mark Fisher
*/
public abstract class AbstractFileMapper<T> extends AbstractMessageMapper<T, File> {
public abstract class AbstractFileMapper<T> implements MessageCreator<File, T>, MessageMapper<T, File> {
protected Log logger = LogFactory.getLog(this.getClass());
@@ -60,7 +61,7 @@ public abstract class AbstractFileMapper<T> extends AbstractMessageMapper<T, Fil
this.fileNameGenerator = fileNameGenerator;
}
public File fromMessage(Message<T> message) {
public File mapMessage(Message<T> message) {
try {
File file = new File(parentDirectory, this.fileNameGenerator.generateFileName(message));
this.writeToFile(file, message.getPayload());
@@ -71,7 +72,7 @@ public abstract class AbstractFileMapper<T> extends AbstractMessageMapper<T, Fil
}
}
public Message<T> toMessage(File file) {
public Message<T> createMessage(File file) {
try {
T payload = this.readMessagePayload(file);
if (payload == null) {

View File

@@ -37,7 +37,7 @@ public class FileSource implements PollableSource<Object>, InitializingBean {
private volatile boolean textBased = true;
private volatile AbstractFileMapper mapper;
private volatile AbstractFileMapper<?> mapper;
private volatile FileNameGenerator fileNameGenerator;
@@ -84,7 +84,7 @@ public class FileSource implements PollableSource<Object>, InitializingBean {
}
}
public Message<Object> poll() {
public Message poll() {
File[] files = null;
if (this.fileFilter != null) {
files = this.directory.listFiles(this.fileFilter);
@@ -101,7 +101,7 @@ public class FileSource implements PollableSource<Object>, InitializingBean {
}
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
return this.mapper.toMessage(files[i]);
return this.mapper.createMessage(files[i]);
}
}
return null;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -18,8 +18,8 @@ package org.springframework.integration.adapter.file;
import java.io.File;
import org.springframework.integration.adapter.AbstractTargetAdapter;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.Target;
import org.springframework.util.Assert;
/**
@@ -28,7 +28,10 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public class FileTargetAdapter extends AbstractTargetAdapter<File> {
public class FileTargetAdapter implements Target {
private AbstractFileMapper<?> mapper;
public FileTargetAdapter(File directory) {
this(directory, true);
@@ -36,23 +39,22 @@ public class FileTargetAdapter extends AbstractTargetAdapter<File> {
public FileTargetAdapter(File directory, boolean isTextBased) {
if (isTextBased) {
this.setMessageMapper(new TextFileMapper(directory));
this.mapper = new TextFileMapper(directory);
}
else {
this.setMessageMapper(new ByteArrayFileMapper(directory));
this.mapper = new ByteArrayFileMapper(directory);
}
}
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
Assert.notNull(fileNameGenerator, "'fileNameGenerator' must not be null");
MessageMapper<?,?> mapper = this.getMessageMapper();
if (mapper instanceof AbstractFileMapper<?>) {
((AbstractFileMapper<?>) mapper).setFileNameGenerator(fileNameGenerator);
}
}
@Override
protected boolean sendToTarget(File file) {
public boolean send(Message message) {
File file = this.mapper.mapMessage(message);
return file.exists();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -24,7 +24,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.adapter.file.FileTargetAdapter;
import org.springframework.integration.endpoint.DefaultMessageEndpoint;
import org.springframework.integration.endpoint.TargetEndpoint;
import org.springframework.integration.scheduling.Subscription;
/**
@@ -35,7 +35,7 @@ import org.springframework.integration.scheduling.Subscription;
public class FileTargetAdapterParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return DefaultMessageEndpoint.class;
return TargetEndpoint.class;
}
protected boolean shouldGenerateId() {

View File

@@ -32,8 +32,8 @@ import org.springframework.integration.adapter.file.ByteArrayFileMapper;
import org.springframework.integration.adapter.file.FileNameGenerator;
import org.springframework.integration.adapter.file.TextFileMapper;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageCreator;
import org.springframework.integration.message.MessageDeliveryAware;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.MessagingException;
import org.springframework.integration.message.PollableSource;
import org.springframework.util.Assert;
@@ -70,7 +70,7 @@ public class FtpSource implements PollableSource<Object>, MessageDeliveryAware {
private volatile boolean textBased = true;
private volatile MessageMapper mapper;
private volatile MessageCreator<File, ?> messageCreator;
private final DirectoryContentManager directoryContentManager = new DirectoryContentManager();
@@ -113,14 +113,14 @@ public class FtpSource implements PollableSource<Object>, MessageDeliveryAware {
public void afterPropertiesSet() {
if (this.isTextBased()) {
this.mapper = new TextFileMapper(this.localWorkingDirectory);
this.messageCreator = new TextFileMapper(this.localWorkingDirectory);
}
else {
this.mapper = new ByteArrayFileMapper(this.localWorkingDirectory);
this.messageCreator = new ByteArrayFileMapper(this.localWorkingDirectory);
}
}
public final Message<Object> poll() {
public final Message poll() {
try {
this.establishConnection();
FTPFile[] fileList = this.client.listFiles();
@@ -143,7 +143,7 @@ public class FtpSource implements PollableSource<Object>, MessageDeliveryAware {
FileOutputStream fileOutputStream = new FileOutputStream(file);
this.client.retrieveFile(fileName, fileOutputStream);
fileOutputStream.close();
return this.mapper.toMessage(file);
return this.messageCreator.createMessage(file);
}
catch (Exception e) {
try {

View File

@@ -25,7 +25,7 @@ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.adapter.httpinvoker.HttpInvokerTargetAdapter;
import org.springframework.integration.endpoint.DefaultMessageEndpoint;
import org.springframework.integration.endpoint.HandlerEndpoint;
import org.springframework.integration.scheduling.Subscription;
import org.springframework.util.StringUtils;
@@ -37,7 +37,7 @@ import org.springframework.util.StringUtils;
public class HttpInvokerTargetAdapterParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return DefaultMessageEndpoint.class;
return HandlerEndpoint.class;
}
protected boolean shouldGenerateId() {

View File

@@ -19,8 +19,8 @@ package org.springframework.integration.adapter.jms;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import org.springframework.integration.handler.MessageHandler;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.Target;
import org.springframework.jms.core.JmsTemplate;
/**
@@ -28,7 +28,7 @@ import org.springframework.jms.core.JmsTemplate;
*
* @author Mark Fisher
*/
public class JmsTargetAdapter extends AbstractJmsTemplateBasedAdapter implements MessageHandler {
public class JmsTargetAdapter extends AbstractJmsTemplateBasedAdapter implements Target {
public JmsTargetAdapter(JmsTemplate jmsTemplate) {
super(jmsTemplate);
@@ -47,11 +47,12 @@ public class JmsTargetAdapter extends AbstractJmsTemplateBasedAdapter implements
}
public final Message<?> handle(final Message<?> message) {
if (message != null) {
this.getJmsTemplate().convertAndSend(message);
public final boolean send(final Message<?> message) {
if (message == null) {
throw new IllegalArgumentException("message must not be null");
}
return null;
this.getJmsTemplate().convertAndSend(message);
return true;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -26,7 +26,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.adapter.jms.JmsTargetAdapter;
import org.springframework.integration.endpoint.DefaultMessageEndpoint;
import org.springframework.integration.endpoint.TargetEndpoint;
import org.springframework.integration.scheduling.Subscription;
import org.springframework.util.StringUtils;
@@ -41,7 +41,7 @@ public class JmsTargetAdapterParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return DefaultMessageEndpoint.class;
return TargetEndpoint.class;
}
protected boolean shouldGenerateId() {

View File

@@ -21,8 +21,8 @@ import javax.mail.internet.MimeMessage;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.integration.adapter.MessageMappingException;
import org.springframework.integration.message.AbstractMessageMapper;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageMapper;
import org.springframework.mail.MailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMailMessage;
@@ -36,7 +36,7 @@ import org.springframework.util.Assert;
*
* @author Marius Bogoevici
*/
public class ByteArrayMailMessageMapper extends AbstractMessageMapper<byte[], MailMessage> {
public class ByteArrayMailMessageMapper implements MessageMapper<byte[], MailMessage> {
private final JavaMailSender mailSender;
@@ -63,7 +63,7 @@ public class ByteArrayMailMessageMapper extends AbstractMessageMapper<byte[], Ma
throw new UnsupportedOperationException("mapping from MailMessage to byte array not supported");
}
public MailMessage fromMessage(Message<byte[]> message) {
public MailMessage mapMessage(Message<byte[]> message) {
try {
MimeMessage mimeMessage = this.mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, this.multipartMode);

View File

@@ -17,10 +17,9 @@
package org.springframework.integration.adapter.mail;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.handler.MessageHandler;
import org.springframework.integration.message.AbstractMessageMapper;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.Target;
import org.springframework.mail.MailMessage;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
@@ -33,7 +32,7 @@ import org.springframework.util.Assert;
* @author Marius Bogoevici
* @author Mark Fisher
*/
public class MailTargetAdapter implements MessageHandler, InitializingBean {
public class MailTargetAdapter implements Target, InitializingBean {
private final JavaMailSender mailSender;
@@ -84,22 +83,22 @@ public class MailTargetAdapter implements MessageHandler, InitializingBean {
this.objectMessageMapper = objectMessageMapper;
}
public Message<?> handle(Message<?> message) {
public final boolean send(Message<?> message) {
MailMessage mailMessage = this.convertMessageToMailMessage(message);
this.mailHeaderGenerator.populateMailMessageHeader(mailMessage, message);
this.sendMailMessage(mailMessage);
return null;
return true;
}
@SuppressWarnings("unchecked")
private MailMessage convertMessageToMailMessage(Message<?> message) {
if (message.getPayload() instanceof String) {
return this.textMessageMapper.fromMessage((Message<String>) message);
return this.textMessageMapper.mapMessage((Message<String>) message);
}
else if (message.getPayload() instanceof byte[]) {
return this.byteArrayMessageMapper.fromMessage((Message<byte[]>) message);
return this.byteArrayMessageMapper.mapMessage((Message<byte[]>) message);
}
return this.objectMessageMapper.fromMessage((Message<Object>) message);
return this.objectMessageMapper.mapMessage((Message<Object>) message);
}
private void sendMailMessage(MailMessage mailMessage) {
@@ -116,17 +115,18 @@ public class MailTargetAdapter implements MessageHandler, InitializingBean {
}
private static class DefaultObjectMailMessageMapper extends AbstractMessageMapper<Object, MailMessage> {
private static class DefaultObjectMailMessageMapper implements MessageMapper<Object, MailMessage> {
public Message<Object> toMessage(MailMessage source) {
throw new UnsupportedOperationException("mapping from MailMessage to Object not supported");
}
public MailMessage fromMessage(Message<Object> objectMessage) {
public MailMessage mapMessage(Message<Object> objectMessage) {
SimpleMailMessage message = new SimpleMailMessage();
message.setText(objectMessage.getPayload().toString());
return message;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -16,8 +16,8 @@
package org.springframework.integration.adapter.mail;
import org.springframework.integration.message.AbstractMessageMapper;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.StringMessage;
import org.springframework.mail.MailMessage;
import org.springframework.mail.SimpleMailMessage;
@@ -30,14 +30,14 @@ import org.springframework.util.Assert;
*
* @author Marius Bogoevici
*/
public class TextMailMessageMapper extends AbstractMessageMapper<String, MailMessage> {
public class TextMailMessageMapper implements MessageMapper<String, MailMessage> {
public Message<String> toMessage(MailMessage source) {
Assert.isInstanceOf(SimpleMailMessage.class, source, "source must be a SimpleMailMessage");
return new StringMessage(((SimpleMailMessage) source).getText());
}
public MailMessage fromMessage(Message<String> stringMessage) {
public MailMessage mapMessage(Message<String> stringMessage) {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setText(stringMessage.getPayload());
return mailMessage;

View File

@@ -26,7 +26,7 @@ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.adapter.mail.MailTargetAdapter;
import org.springframework.integration.endpoint.DefaultMessageEndpoint;
import org.springframework.integration.endpoint.TargetEndpoint;
import org.springframework.integration.scheduling.Subscription;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.util.StringUtils;
@@ -39,7 +39,7 @@ import org.springframework.util.StringUtils;
public class MailTargetAdapterParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return DefaultMessageEndpoint.class;
return TargetEndpoint.class;
}
protected boolean shouldGenerateId() {

View File

@@ -26,7 +26,7 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.adapter.rmi.RmiSourceAdapter;
import org.springframework.integration.adapter.rmi.RmiTargetAdapter;
import org.springframework.integration.endpoint.DefaultMessageEndpoint;
import org.springframework.integration.endpoint.HandlerEndpoint;
import org.springframework.integration.scheduling.Subscription;
import org.springframework.util.StringUtils;
@@ -38,7 +38,7 @@ import org.springframework.util.StringUtils;
public class RmiTargetAdapterParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
return DefaultMessageEndpoint.class;
return HandlerEndpoint.class;
}
protected boolean shouldGenerateId() {

View File

@@ -20,15 +20,21 @@ import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.springframework.integration.adapter.AbstractTargetAdapter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessagingException;
import org.springframework.integration.message.Target;
/**
* A target adapter that writes a byte array to an {@link OutputStream}.
*
* @author Mark Fisher
*/
public class ByteStreamTargetAdapter extends AbstractTargetAdapter {
public class ByteStreamTargetAdapter implements Target {
private final Log logger = LogFactory.getLog(this.getClass());
private BufferedOutputStream stream;
@@ -46,21 +52,20 @@ public class ByteStreamTargetAdapter extends AbstractTargetAdapter {
}
}
@Override
protected boolean sendToTarget(Object object) {
if (object == null) {
public boolean send(Message message) {
Object payload = message.getPayload();
if (payload == null) {
if (logger.isWarnEnabled()) {
logger.warn(this.getClass().getSimpleName() + " received null object");
}
return false;
}
try {
if (object instanceof String) {
this.stream.write(((String) object).getBytes());
if (payload instanceof String) {
this.stream.write(((String) payload).getBytes());
}
else if (object instanceof byte[]){
this.stream.write((byte[]) object);
else if (payload instanceof byte[]){
this.stream.write((byte[]) payload);
}
else {
throw new MessagingException(this.getClass().getSimpleName() +

View File

@@ -23,9 +23,13 @@ import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.adapter.AbstractTargetAdapter;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessagingException;
import org.springframework.integration.message.Target;
import org.springframework.util.Assert;
/**
@@ -38,7 +42,9 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public class CharacterStreamTargetAdapter extends AbstractTargetAdapter {
public class CharacterStreamTargetAdapter implements Target {
private final Log logger = LogFactory.getLog(this.getClass());
private final BufferedWriter writer;
@@ -112,26 +118,26 @@ public class CharacterStreamTargetAdapter extends AbstractTargetAdapter {
this.shouldAppendNewLine = shouldAppendNewLine;
}
@Override
protected boolean sendToTarget(Object object) {
if (object == null) {
public boolean send(Message message) {
Object payload = message.getPayload();
if (payload == null) {
if (logger.isWarnEnabled()) {
logger.warn("target adapter received null object");
logger.warn("target adapter received null payload");
}
return false;
}
try {
if (object instanceof String) {
writer.write((String) object);
if (payload instanceof String) {
writer.write((String) payload);
}
else if (object instanceof char[]) {
this.writer.write((char[]) object);
else if (payload instanceof char[]) {
this.writer.write((char[]) payload);
}
else if (object instanceof byte[]) {
this.writer.write(new String((byte[]) object));
else if (payload instanceof byte[]) {
this.writer.write(new String((byte[]) payload));
}
else {
writer.write(object.toString());
writer.write(payload.toString());
}
if (this.shouldAppendNewLine) {
writer.newLine();