INT-3115 Fix EvaluationContext Initialization

There were several "helper" classes where the context was initialized
in the constructor, before the BeanFactory was passed in.

Generally fixed by adding the BeanFactory to the constructor args.

Other cases where the container-managed bean instantiated a helper
and never passed in the BeanFactory.

Finally, a fix to ExpressionUtils where the caller had a BeanFactory
but the BF did not contain an EvaluationContext factory bean, the
BeanResolver was not set up. This is unlikely in a Spring Integration
application, but added for completeness.

INT-3115 Add a BeanFactory to Test Cases

Change the WARN log in ExpressionUtils to a fatal exception to detect
cases where an EvaluationContext was created without a BeanFactory.

While this was generally in test cases, it also exposed some cases
in code where the context was initialized without a BF.

polishing on merge
This commit is contained in:
Gary Russell
2013-08-26 20:45:48 -04:00
committed by Mark Fisher
parent 06b06b1c8f
commit 52b340956f
55 changed files with 531 additions and 119 deletions

View File

@@ -26,6 +26,7 @@ import java.nio.charset.Charset;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.expression.Expression;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -82,6 +83,8 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
private volatile FileNameGenerator fileNameGenerator = new DefaultFileNameGenerator();
private volatile boolean fileNameGeneratorSet;
private volatile StandardEvaluationContext evaluationContext;
private final Expression destinationDirectoryExpression;
@@ -190,6 +193,7 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
Assert.notNull(fileNameGenerator, "FileNameGenerator must not be null");
this.fileNameGenerator = fileNameGenerator;
this.fileNameGeneratorSet = true;
}
/**
@@ -226,6 +230,9 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
validateDestinationDirectory(directory, this.autoCreateDirectory);
}
if (!this.fileNameGeneratorSet && this.fileNameGenerator instanceof BeanFactoryAware) {
((BeanFactoryAware) this.fileNameGenerator).setBeanFactory(this.getBeanFactory());
}
}
private void validateDestinationDirectory(File destinationDirectory, boolean autoCreateDirectory) {

View File

@@ -285,6 +285,7 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
}
if (this.getBeanFactory() != null) {
this.fileNameProcessor.setBeanFactory(this.getBeanFactory());
this.renameProcessor.setBeanFactory(this.getBeanFactory());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2013 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,16 +16,20 @@
package org.springframework.integration.file;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import java.io.File;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import static org.junit.Assert.assertTrue;
import org.springframework.beans.factory.BeanFactory;
/**
* @author Mark Fisher
* @author Gary Russell
* @since 1.0.3
*/
public class AutoCreateDirectoryTests {
@@ -58,6 +62,7 @@ public class AutoCreateDirectoryTests {
public void autoCreateForInboundEnabledByDefault() {
FileReadingMessageSource source = new FileReadingMessageSource();
source.setDirectory(new File(INBOUND_PATH));
source.setBeanFactory(mock(BeanFactory.class));
source.afterPropertiesSet();
assertTrue(new File(INBOUND_PATH).exists());
}
@@ -67,6 +72,7 @@ public class AutoCreateDirectoryTests {
FileReadingMessageSource source = new FileReadingMessageSource();
source.setDirectory(new File(INBOUND_PATH));
source.setAutoCreateDirectory(false);
source.setBeanFactory(mock(BeanFactory.class));
source.afterPropertiesSet();
}
@@ -74,6 +80,7 @@ public class AutoCreateDirectoryTests {
public void autoCreateForOutboundEnabledByDefault() {
FileWritingMessageHandler handler = new FileWritingMessageHandler(
new File(OUTBOUND_PATH));
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
assertTrue(new File(OUTBOUND_PATH).exists());
}
@@ -82,6 +89,7 @@ public class AutoCreateDirectoryTests {
public void autoCreateForOutboundDisabled() {
FileWritingMessageHandler handler = new FileWritingMessageHandler(
new File(OUTBOUND_PATH));
handler.setBeanFactory(mock(BeanFactory.class));
handler.setAutoCreateDirectory(false);
handler.afterPropertiesSet();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2013 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,24 +17,27 @@
package org.springframework.integration.file;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import java.io.File;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.support.MessageBuilder;
/**
* @author Mark Fisher
* @author Gary Russell
*/
public class DefaultFileNameGeneratorTests {
@Test
public void defaultHeaderNamePresent() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
Message<?> message = MessageBuilder.withPayload("test")
.setHeader(FileHeaders.FILENAME, "foo").build();
generator.setBeanFactory(mock(BeanFactory.class));
Message<?> message = MessageBuilder.withPayload("test").setHeader(FileHeaders.FILENAME, "foo").build();
String filename = generator.generateFileName(message);
assertEquals("foo", filename);
}
@@ -42,6 +45,7 @@ public class DefaultFileNameGeneratorTests {
@Test
public void defaultHeaderNameNotPresent() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
Message<?> message = MessageBuilder.withPayload("test").build();
String filename = generator.generateFileName(message);
assertEquals(message.getHeaders().getId() + ".msg", filename);
@@ -50,8 +54,9 @@ public class DefaultFileNameGeneratorTests {
@Test
public void defaultHeaderNameNotString() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
Message<?> message = MessageBuilder.withPayload("test")
.setHeader(FileHeaders.FILENAME, new Integer(123)).build();
generator.setBeanFactory(mock(BeanFactory.class));
Message<?> message = MessageBuilder.withPayload("test").setHeader(FileHeaders.FILENAME, new Integer(123))
.build();
String filename = generator.generateFileName(message);
assertEquals(message.getHeaders().getId() + ".msg", filename);
}
@@ -59,9 +64,9 @@ public class DefaultFileNameGeneratorTests {
@Test
public void customHeaderNamePresent() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
generator.setHeaderName("foo");
Message<?> message = MessageBuilder.withPayload("test")
.setHeader("foo", "bar").build();
Message<?> message = MessageBuilder.withPayload("test").setHeader("foo", "bar").build();
String filename = generator.generateFileName(message);
assertEquals("bar", filename);
}
@@ -69,6 +74,7 @@ public class DefaultFileNameGeneratorTests {
@Test
public void customHeaderNameNotPresent() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
generator.setHeaderName("foo");
Message<?> message = MessageBuilder.withPayload("test").build();
String filename = generator.generateFileName(message);
@@ -78,9 +84,9 @@ public class DefaultFileNameGeneratorTests {
@Test
public void customHeaderNameNotString() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
generator.setHeaderName("foo");
Message<?> message = MessageBuilder.withPayload("test")
.setHeader("foo", new Integer(123)).build();
Message<?> message = MessageBuilder.withPayload("test").setHeader("foo", new Integer(123)).build();
String filename = generator.generateFileName(message);
assertEquals(message.getHeaders().getId() + ".msg", filename);
}
@@ -88,18 +94,19 @@ public class DefaultFileNameGeneratorTests {
@Test
public void filePayloadPresent() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
File payload = new File("/some/path/foo");
Message<?> message = MessageBuilder.withPayload(payload).build();
String filename = generator.generateFileName(message);
assertEquals("foo", filename);
assertEquals("foo", filename);
}
@Test
public void defaultHeaderNameTakesPrecedenceOverFilePayload() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
File payload = new File("/some/path/ignore");
Message<?> message = MessageBuilder.withPayload(payload)
.setHeader(FileHeaders.FILENAME, "foo").build();
Message<?> message = MessageBuilder.withPayload(payload).setHeader(FileHeaders.FILENAME, "foo").build();
String filename = generator.generateFileName(message);
assertEquals("foo", filename);
}
@@ -107,10 +114,10 @@ public class DefaultFileNameGeneratorTests {
@Test
public void customHeaderNameTakesPrecedenceOverFilePayload() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
generator.setHeaderName("foo");
File payload = new File("/some/path/ignore");
Message<?> message = MessageBuilder.withPayload(payload)
.setHeader("foo", "bar").build();
Message<?> message = MessageBuilder.withPayload(payload).setHeader("foo", "bar").build();
String filename = generator.generateFileName(message);
assertEquals("bar", filename);
}
@@ -118,9 +125,9 @@ public class DefaultFileNameGeneratorTests {
@Test
public void customHeaderNameTakesPrecedenceOverDefault() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
generator.setHeaderName("foo");
Message<?> message = MessageBuilder.withPayload("test")
.setHeader(FileHeaders.FILENAME, "ignore")
Message<?> message = MessageBuilder.withPayload("test").setHeader(FileHeaders.FILENAME, "ignore")
.setHeader("foo", "bar").build();
String filename = generator.generateFileName(message);
assertEquals("bar", filename);
@@ -129,10 +136,10 @@ public class DefaultFileNameGeneratorTests {
@Test
public void customHeaderNameTakesPrecedenceOverFilePayloadAndDefault() {
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
generator.setBeanFactory(mock(BeanFactory.class));
generator.setHeaderName("foo");
File payload = new File("/some/path/ignore1");
Message<?> message = MessageBuilder.withPayload(payload)
.setHeader(FileHeaders.FILENAME, "ignore2")
Message<?> message = MessageBuilder.withPayload(payload).setHeader(FileHeaders.FILENAME, "ignore2")
.setHeader("foo", "bar").build();
String filename = generator.generateFileName(message);
assertEquals("bar", filename);

View File

@@ -19,12 +19,12 @@ package org.springframework.integration.file;
import java.io.File;
import java.io.FileOutputStream;
import org.junit.Assert;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
@@ -38,6 +38,7 @@ import org.springframework.util.FileCopyUtils;
/**
* @author Gunnar Hillert
* @author Artem Bilan
* @author Gary Russell
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)

View File

@@ -24,6 +24,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.io.FileOutputStream;
@@ -35,6 +36,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.channel.NullChannel;
@@ -66,6 +68,8 @@ public class FileWritingMessageHandlerTests {
super.create();
outputDirectory = temp.newFolder("outputDirectory");
handler = new FileWritingMessageHandler(outputDirectory);
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
sourceFile = temp.newFile("sourceFile");
FileCopyUtils.copy(SAMPLE_CONTENT.getBytes(DEFAULT_ENCODING),
new FileOutputStream(sourceFile, false));

View File

@@ -39,6 +39,8 @@ import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.file.FileHeaders;
@@ -120,6 +122,7 @@ public class RemoteFileOutboundGatewayTests {
Session session = mock(Session.class);
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/x/")).thenReturn(files);
@@ -303,6 +306,7 @@ public class RemoteFileOutboundGatewayTests {
SessionFactory sessionFactory = mock(SessionFactory.class);
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "mv", "payload");
gw.afterPropertiesSet();
Session<?> session = mock(Session.class);
final AtomicReference<String> args = new AtomicReference<String>();
doAnswer(new Answer<Object>() {
@@ -329,6 +333,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "mv", "payload");
gw.setRenameExpression("payload.substring(1)");
gw.afterPropertiesSet();
Session<?> session = mock(Session.class);
final AtomicReference<String> args = new AtomicReference<String>();
doAnswer(new Answer<Object>() {
@@ -353,6 +358,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "mv", "payload");
gw.setRenameExpression("'foo/bar/baz'");
gw.afterPropertiesSet();
Session<?> session = mock(Session.class);
final AtomicReference<String> args = new AtomicReference<String>();
doAnswer(new Answer<Object>() {
@@ -404,6 +410,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.setOptions("-f");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/x/")).thenReturn(files);
@@ -423,6 +430,7 @@ public class RemoteFileOutboundGatewayTests {
Session session = mock(Session.class);
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = new TestLsEntry[0];
when(session.list("testremote/")).thenReturn(files);
@@ -439,6 +447,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.setOptions("-1");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/")).thenReturn(files);
@@ -457,6 +466,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.setOptions("-1 -f");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/")).thenReturn(files);
@@ -475,6 +485,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.setOptions("-1 -dirs");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/")).thenReturn(files);
@@ -494,6 +505,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.setOptions("-1 -dirs -links");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/")).thenReturn(files);
@@ -514,6 +526,7 @@ public class RemoteFileOutboundGatewayTests {
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "ls", "payload");
gw.setOptions("-1 -a -f -dirs -links");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/")).thenReturn(files);
@@ -537,6 +550,7 @@ public class RemoteFileOutboundGatewayTests {
(sessionFactory, "ls", "payload");
gw.setOptions("-1 -a -f -dirs -links");
gw.setFilter(new TestPatternFilter("*4"));
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
TestLsEntry[] files = fileList();
when(session.list("testremote/")).thenReturn(files);
@@ -721,6 +735,7 @@ public class RemoteFileOutboundGatewayTests {
Session session = mock(Session.class);
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway
(sessionFactory, "rm", "payload");
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
when(session.remove("testremote/x/f1")).thenReturn(Boolean.TRUE);
@SuppressWarnings("unchecked")
@@ -742,6 +757,7 @@ class TestRemoteFileOutboundGateway extends AbstractRemoteFileOutboundGateway<Te
public TestRemoteFileOutboundGateway(SessionFactory sessionFactory,
String command, String expression) {
super(sessionFactory, Command.toCommand(command), expression);
this.setBeanFactory(mock(BeanFactory.class));
}
@Override

View File

@@ -38,6 +38,7 @@ import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -74,6 +75,7 @@ public class FileTransferringMessageHandlerTests {
ExpressionParser parser = new SpelExpressionParser();
FileTransferringMessageHandler<F> handler = new FileTransferringMessageHandler<F>(sf);
handler.setRemoteDirectoryExpression(parser.parseExpression("''"));
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
handler.handleMessage(new GenericMessage<String>("hello"));
verify(session, times(1)).write(Mockito.any(InputStream.class), Mockito.anyString());
@@ -98,6 +100,7 @@ public class FileTransferringMessageHandlerTests {
FileTransferringMessageHandler<F> handler = new FileTransferringMessageHandler<F>(sf);
handler.setRemoteDirectoryExpression(new LiteralExpression("foo"));
handler.setTemporaryRemoteDirectoryExpression(new LiteralExpression("bar"));
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
handler.handleMessage(new GenericMessage<String>("hello"));
verify(session, times(1)).write(Mockito.any(InputStream.class), Mockito.anyString());
@@ -122,6 +125,7 @@ public class FileTransferringMessageHandlerTests {
ExpressionParser parser = new SpelExpressionParser();
FileTransferringMessageHandler<F> handler = new FileTransferringMessageHandler<F>(sf);
handler.setRemoteDirectoryExpression(parser.parseExpression("headers['path']"));
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
Message<?> message = MessageBuilder.withPayload("hello").setHeader("path", null).build();
handler.handleMessage(message);
@@ -136,6 +140,7 @@ public class FileTransferringMessageHandlerTests {
when(sf.getSession()).thenReturn(session);
ExpressionParser parser = new SpelExpressionParser();
FileTransferringMessageHandler<F> handler = new FileTransferringMessageHandler<F>(sf);
handler.setBeanFactory(mock(BeanFactory.class));
handler.setRemoteDirectoryExpression(parser.parseExpression("headers['path']"));
handler.setTemporaryFileSuffix(null);
handler.onInit();
@@ -153,6 +158,7 @@ public class FileTransferringMessageHandlerTests {
FileTransferringMessageHandler<F> handler = new FileTransferringMessageHandler<F>(sf);
handler.setRemoteDirectoryExpression(parser.parseExpression("headers['path']"));
handler.setUseTemporaryFileName(false);
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
Message<?> message = MessageBuilder.withPayload("hello").setHeader("path", null).build();
handler.handleMessage(message);
@@ -166,6 +172,7 @@ public class FileTransferringMessageHandlerTests {
SessionFactory<F> sf = mock(SessionFactory.class);
CachingSessionFactory<F> csf = new CachingSessionFactory<F>(sf, 2);
FileTransferringMessageHandler<F> handler = new FileTransferringMessageHandler<F>(csf);
handler.setBeanFactory(mock(BeanFactory.class));
Session<F> session1 = newSession();
Session<F> session2 = newSession();
Session<F> session3 = newSession();