DSL: Add enrichHeaders(Map) EIP-method

* Introduce `MapBuilder` and its custom inheritor - `MailHeadersBuilder`
* Add `HeaderEnricherSpec.headers(MapBuilder)` and `.headers(Map)`
* Change `MailTests` to use new `Mail.headers()` and new `IntegrationFlowDefinition.enrichHeaders(MapBuilder)`
* Change `mailapi` dependency to the IO's `javax.mail`

Polishing - Add headerExpressions()

More Polishing - Add Configurer

Polishing - PR Comments

- Move MapBuilderConfigurer to superclass.
- Move PropertiesBuilderConfigurer into PropertiesBuilder.
This commit is contained in:
Artem Bilan
2014-08-27 14:08:37 +03:00
committed by Gary Russell
parent 238c1f06b9
commit 4b5bbb6412
12 changed files with 270 additions and 18 deletions

View File

@@ -18,11 +18,16 @@ package org.springframework.integration.dsl;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.dsl.core.IntegrationComponentSpec;
import org.springframework.integration.dsl.support.BeanNameMessageProcessor;
import org.springframework.integration.dsl.support.MapBuilder;
import org.springframework.integration.dsl.support.MapBuilder.MapBuilderConfigurer;
import org.springframework.integration.dsl.support.StringStringMapBuilder;
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
import org.springframework.integration.handler.MessageProcessor;
import org.springframework.integration.transformer.HeaderEnricher;
@@ -34,6 +39,7 @@ import org.springframework.util.Assert;
/**
* @author Artem Bilan
* @author Gary Russell
*/
public class HeaderEnricherSpec extends IntegrationComponentSpec<HeaderEnricherSpec, HeaderEnricher> {
@@ -70,6 +76,43 @@ public class HeaderEnricherSpec extends IntegrationComponentSpec<HeaderEnricherS
return this.messageProcessor(new BeanNameMessageProcessor<Object>(beanName, methodName));
}
public HeaderEnricherSpec headers(MapBuilder<?, String, Object> headers) {
return headers(headers.get());
}
public HeaderEnricherSpec headers(Map<String, Object> headers) {
Assert.notNull(headers);
for (Entry<String, Object> entry : headers.entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
if (value instanceof Expression) {
header(name, new ExpressionEvaluatingHeaderValueMessageProcessor<Object>((Expression) value, null));
}
else {
header(name, value);
}
}
return this;
}
public HeaderEnricherSpec headerExpressions(MapBuilder<?, String, String> headers) {
return headerExpressions(headers.get());
}
public HeaderEnricherSpec headerExpressions(MapBuilderConfigurer<StringStringMapBuilder, String, String> configurer) {
StringStringMapBuilder builder = new StringStringMapBuilder();
configurer.configure(builder);
return headerExpressions(builder.get());
}
public HeaderEnricherSpec headerExpressions(Map<String, String> headers) {
Assert.notNull(headers);
for (Entry<String, String> entry : headers.entrySet()) {
header(entry.getKey(), new ExpressionEvaluatingHeaderValueMessageProcessor<Object>(entry.getValue(), null));
}
return this;
}
public <V> HeaderEnricherSpec header(String name, V value) {
return this.header(name, value, null);
}

View File

@@ -18,6 +18,7 @@ package org.springframework.integration.dsl;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.BeanCreationException;
@@ -40,6 +41,7 @@ import org.springframework.integration.dsl.support.FixedSubscriberChannelPrototy
import org.springframework.integration.dsl.support.GenericHandler;
import org.springframework.integration.dsl.support.GenericRouter;
import org.springframework.integration.dsl.support.GenericSplitter;
import org.springframework.integration.dsl.support.MapBuilder;
import org.springframework.integration.dsl.support.MessageChannelReference;
import org.springframework.integration.expression.ControlBusMethodFilter;
import org.springframework.integration.filter.ExpressionEvaluatingSelector;
@@ -76,6 +78,7 @@ import org.springframework.util.StringUtils;
/**
* @author Artem Bilan
* @author Gary Russell
*/
public abstract class IntegrationFlowDefinition<B extends IntegrationFlowDefinition<B>> {
@@ -286,6 +289,37 @@ public abstract class IntegrationFlowDefinition<B extends IntegrationFlowDefinit
return this.handle(enricherSpec.get(), endpointConfigurer);
}
public B enrichHeaders(MapBuilder<?, String, Object> headers) {
return enrichHeaders(headers, null);
}
public B enrichHeaders(MapBuilder<?, String, Object> headers,
EndpointConfigurer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) {
return enrichHeaders(headers.get(), endpointConfigurer);
}
/**
* Accept a {@link Map} of values to be used for the
* {@link org.springframework.messaging.Message} header enrichment.
* {@code values} can apply an {@link org.springframework.expression.Expression}
* to be evaluated against a request {@link org.springframework.messaging.Message}.
* @param headers the Map of headers to enrich.
* @return this.
*/
public B enrichHeaders(Map<String, Object> headers) {
return enrichHeaders(headers, null);
}
public B enrichHeaders(final Map<String, Object> headers,
EndpointConfigurer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) {
return enrichHeaders(new ComponentConfigurer<HeaderEnricherSpec>() {
@Override
public void configure(HeaderEnricherSpec spec) {
spec.headers(headers);
}
}, endpointConfigurer);
}
public B enrichHeaders(ComponentConfigurer<HeaderEnricherSpec> headerEnricherConfigurer) {
return this.enrichHeaders(headerEnricherConfigurer, null);
}

View File

@@ -29,7 +29,7 @@ import org.aopalliance.aop.Advice;
import org.springframework.integration.dsl.core.ComponentsRegistration;
import org.springframework.integration.dsl.core.MessageProducerSpec;
import org.springframework.integration.dsl.support.PropertiesBuilder;
import org.springframework.integration.dsl.support.PropertiesConfigurer;
import org.springframework.integration.dsl.support.PropertiesBuilder.PropertiesConfigurer;
import org.springframework.integration.mail.ImapIdleChannelAdapter;
import org.springframework.integration.mail.ImapMailReceiver;
import org.springframework.integration.mail.SearchTermStrategy;

View File

@@ -19,7 +19,7 @@ import org.springframework.integration.mail.ImapMailReceiver;
/**
* @author Gary Russell
*
* @author Artem Bilan
*/
public class Mail {
@@ -56,6 +56,10 @@ public class Mail {
return imapIdleAdapter(new ImapMailReceiver(url));
}
public static MailHeadersBuilder headers() {
return new MailHeadersBuilder();
}
private static ImapIdleChannelAdapterSpec imapIdleAdapter(ImapMailReceiver imapMailReceiver) {
return new ImapIdleChannelAdapterSpec(imapMailReceiver);
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2014 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.dsl.mail;
import org.springframework.integration.dsl.support.MapBuilder;
import org.springframework.integration.mail.MailHeaders;
/**
* @author Artem Bilan
* @author Gary Russell
*/
public class MailHeadersBuilder extends MapBuilder<MailHeadersBuilder, String, Object> {
MailHeadersBuilder() {
}
public MailHeadersBuilder subject(String subject) {
return put(MailHeaders.SUBJECT, subject);
}
public MailHeadersBuilder subjectExpression(String subject) {
return putExpression(MailHeaders.SUBJECT, subject);
}
public MailHeadersBuilder to(String to) {
return put(MailHeaders.TO, to);
}
public MailHeadersBuilder toExpression(String to) {
return putExpression(MailHeaders.TO, to);
}
public MailHeadersBuilder cc(String cc) {
return put(MailHeaders.CC, cc);
}
public MailHeadersBuilder ccExpression(String cc) {
return putExpression(MailHeaders.CC, cc);
}
public MailHeadersBuilder bcc(String bcc) {
return put(MailHeaders.BCC, bcc);
}
public MailHeadersBuilder bccExpression(String bcc) {
return putExpression(MailHeaders.BCC, bcc);
}
public MailHeadersBuilder from(String from) {
return put(MailHeaders.FROM, from);
}
public MailHeadersBuilder fromExpression(String from) {
return putExpression(MailHeaders.FROM, from);
}
public MailHeadersBuilder replyTo(String replyTo) {
return put(MailHeaders.REPLY_TO, replyTo);
}
public MailHeadersBuilder replyToExpression(String replyTo) {
return putExpression(MailHeaders.REPLY_TO, replyTo);
}
/**
* @param multipartMode header value
* @return this
* @see org.springframework.mail.javamail.MimeMessageHelper
*/
public MailHeadersBuilder multipartMode(int multipartMode) {
return put(MailHeaders.MULTIPART_MODE, multipartMode);
}
public MailHeadersBuilder multipartModeExpression(String multipartMode) {
return putExpression(MailHeaders.MULTIPART_MODE, multipartMode);
}
public MailHeadersBuilder attachmentFilename(String attachmentFilename) {
return put(MailHeaders.ATTACHMENT_FILENAME, attachmentFilename);
}
public MailHeadersBuilder attachmentFilenameExpression(String attachmentFilename) {
return putExpression(MailHeaders.ATTACHMENT_FILENAME, attachmentFilename);
}
public MailHeadersBuilder contentType(String contentType) {
return put(MailHeaders.CONTENT_TYPE, contentType);
}
public MailHeadersBuilder contentTypeExpression(String contentType) {
return putExpression(MailHeaders.CONTENT_TYPE, contentType);
}
private MailHeadersBuilder putExpression(String key, String expression) {
return put(key, PARSER.parseExpression(expression));
}
}

View File

@@ -25,7 +25,7 @@ import javax.mail.Session;
import org.springframework.integration.dsl.core.ComponentsRegistration;
import org.springframework.integration.dsl.core.MessageSourceSpec;
import org.springframework.integration.dsl.support.PropertiesBuilder;
import org.springframework.integration.dsl.support.PropertiesConfigurer;
import org.springframework.integration.dsl.support.PropertiesBuilder.PropertiesConfigurer;
import org.springframework.integration.mail.AbstractMailReceiver;
import org.springframework.integration.mail.MailReceivingMessageSource;

View File

@@ -21,7 +21,7 @@ import javax.activation.FileTypeMap;
import org.springframework.integration.dsl.core.MessageHandlerSpec;
import org.springframework.integration.dsl.support.PropertiesBuilder;
import org.springframework.integration.dsl.support.PropertiesConfigurer;
import org.springframework.integration.dsl.support.PropertiesBuilder.PropertiesConfigurer;
import org.springframework.integration.mail.MailSendingMessageHandler;
import org.springframework.mail.javamail.JavaMailSenderImpl;

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2014 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.dsl.support;
import java.util.HashMap;
import java.util.Map;
import org.springframework.expression.spel.standard.SpelExpressionParser;
/**
* @author Artem Bilan
*/
public class MapBuilder<B extends MapBuilder<B, K, V>, K, V> {
protected final static SpelExpressionParser PARSER = new SpelExpressionParser();
private final Map<K, V> map = new HashMap<K, V>();
public B put(K key, V value) {
this.map.put(key, value);
return _this();
}
public Map<K, V> get() {
return this.map;
}
@SuppressWarnings("unchecked")
protected final B _this() {
return (B) this;
}
public interface MapBuilderConfigurer<B extends MapBuilder<B, K, V>, K, V> {
void configure(MapBuilder<B, K, V> builder);
}
}

View File

@@ -20,6 +20,7 @@ import java.util.Properties;
/**
* @author Gary Russell
* @author Artem Bilan
*
*/
public class PropertiesBuilder {
@@ -35,4 +36,10 @@ public class PropertiesBuilder {
return this.properties;
}
public interface PropertiesConfigurer {
void configure(PropertiesBuilder propertiesBuilder);
}
}

View File

@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.dsl.support;
/**
* @author Artem Bilan
* A map builder creating a map with String keys and values.
*
* @author Gary Russell
*
*/
public interface PropertiesConfigurer {
void configure(PropertiesBuilder propertiesBuilder);
public class StringStringMapBuilder extends MapBuilder<StringStringMapBuilder, String, String> {
}

View File

@@ -129,18 +129,14 @@ public class MailTests {
private ImapIdleChannelAdapter imapIdleAdapter;
@Test
public void testOutbound() throws Exception {
public void testSmtp() throws Exception {
assertEquals("localhost", TestUtils.getPropertyValue(this.sendMailHandler, "mailSender.host"));
Properties javaMailProperties = TestUtils.getPropertyValue(this.sendMailHandler,
"mailSender.javaMailProperties", Properties.class);
assertEquals("true", javaMailProperties.getProperty("mail.debug"));
this.sendMailChannel.send(MessageBuilder.withPayload("foo")
.setHeader(MailHeaders.SUBJECT, "foo")
.setHeader(MailHeaders.FROM, "foo@bar")
.setHeader(MailHeaders.TO, "bar@baz")
.build());
this.sendMailChannel.send(MessageBuilder.withPayload("foo").build());
int n = 0;
while (n++ < 100 && smtpServer.getMessages().size() == 0) {
@@ -163,8 +159,8 @@ public class MailTests {
assertNotNull(message);
MimeMessage mm = (MimeMessage) message.getPayload();
assertEquals("foo@bar", mm.getRecipients(RecipientType.TO)[0].toString());
assertEquals("bar@baz", mm.getFrom()[0].toString());
assertEquals("Test Email", mm.getSubject());
assertEquals("bar@baz", message.getHeaders().get(MailHeaders.FROM));
assertEquals("Test Email", message.getHeaders().get(MailHeaders.SUBJECT));
assertEquals("foo\r\n", mm.getContent());
}
@@ -199,6 +195,7 @@ public class MailTests {
@Bean
public IntegrationFlow sendMailFlow() {
return IntegrationFlows.from("sendMailChannel")
.enrichHeaders(Mail.headers().subject("foo").from("foo@bar").to("bar@baz"))
.handle(Mail.outboundAdapter("localhost")
.port(smtpPort)
.credentials("user", "pw")
@@ -215,6 +212,8 @@ public class MailTests {
.javaMailProperties(p -> p.put("mail.debug", "true")),
e -> e.autoStartup(true)
.poller(Pollers.fixedDelay(1000)))
.enrichHeaders(s -> s.headerExpressions(c -> c.put(MailHeaders.SUBJECT, "payload.subject")
.put(MailHeaders.FROM, "payload.from[0].toString()")))
.channel(MessageChannels.queue("pop3Channel"))
.get();
}