Why do I get an unexpected RuntimeException warn in the logs when using RemoteFileTemplate?
Asked Answered
D

1

7

I'm using Spring-integration 4.1.1.RELEASE and have code that uploads files in message payloads to a remote sFtp share. I'm using an sFtpRemoteFileTemplate initialized like this:

Expression remoteDirectoryExpression = new  LiteralExpression("si.sftp.sample");
SpelExpressionParser parser = new SpelExpressionParser();
Expression fileNameExpression = parser.parseExpression("payload.name");

template = new SftpRemoteFileTemplate(sessionFactory);
template.setCharset("UTF-8");
template.setBeanFactory(beanFactory);
template.setAutoCreateDirectory(true);
template.setRemoteDirectoryExpression(remoteDirectoryExpression);
template.setFileNameExpression(fileNameExpression);
template.setTemporaryFileSuffix(".writing");
template.setUseTemporaryFileName(true);

However when running the code, this warning appears in my log files - once for each expression in the template:

WARN   - o.s.i.e.ExpressionUtils: Creating EvaluationContext with no beanFactory
java.lang.RuntimeException: No beanfactory
at org.springframework.integration.expression.ExpressionUtils.createStandardEvaluationContext(ExpressionUtils.java:79) [spring-integration-core-4.1.1.RELEASE.jar:na]
at org.springframework.integration.util.AbstractExpressionEvaluator.getEvaluationContext(AbstractExpressionEvaluator.java:114) [spring-integration-core-4.1.1.RELEASE.jar:na]
at org.springframework.integration.util.AbstractExpressionEvaluator.getEvaluationContext(AbstractExpressionEvaluator.java:100) [spring-integration-core-4.1.1.RELEASE.jar:na]
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:164) [spring-integration-core-4.1.1.RELEASE.jar:na]
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:123) [spring-integration-core-4.1.1.RELEASE.jar:na]
at org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor.processMessage(ExpressionEvaluatingMessageProcessor.java:72) [spring-integration-core-4.1.1.RELEASE.jar:na]

Why is that? I haven't managed to get rid of it, and my suspicion is that the Bean Factory instance is not delegated to the ExpressionEvaluatingMessageProcessor inside RemoteFileTemplate (The calling class has implemented BeanFactoryAware and I've verified the beanFactory field is populated properly). I've created a test case for it, where I've managed to reproduce it.

@Test
public void shouldUploadFile() throws Exception
{
  Message<File> msg = MessageBuilder
    .withPayload(Fixture.getFile())
    .build();

  final String remoteDir = template.send(msg);
  org.junit.Assert.assertNotNull("remote file must exist", remoteDir);
  logger.info("uploaded file: \'{}\'", remoteDir);
  SftpTestUtils.cleanUp(template, Fixture.getFileName());
}

It shouldn't be a problem with the ExpressionEvaluatingMessageProcessor, as this test case passes without warnings under the same context:

@Test
public void shouldTestProcessor()
{
  SpelExpressionParser parser = new SpelExpressionParser();
  Expression fileNameExpression = parser.parseExpression("payload.name");
  ExpressionEvaluatingMessageProcessor<String> fileNameProcessor = new ExpressionEvaluatingMessageProcessor<String>(
      fileNameExpression, String.class);
  fileNameProcessor.setBeanFactory(beanFactory);
  Message<File> message = MessageBuilder.withPayload(Fixture.getFile()).build();
  String fileName = fileNameProcessor.processMessage(message);
  org.junit.Assert.assertEquals("filename is not as expected", Fixture.getFileName(), fileName);
  logger.info("generated fileName: \'{}\'", fileName);
}

Any clues?

Domination answered 14/4, 2015 at 10:16 Comment(0)
V
5

You need to invoke afterPropertiesSet() to finalize the initialization of the RFT when constructing it outside of a Spring ApplicationContext.

This is true for many Spring Integration components.

Those that implement Lifecycle (not RFT) may also need to be start()ed.

Vazquez answered 14/4, 2015 at 10:33 Comment(3)
Thanks for your answer Gary - it was so obvious!Domination
Can you explain a little bit where should I call afterPropertiesSet(), please?Delegate
Does "after the properties are set" seem reasonable? In this case, after template.setUseTemporaryFileName(true);. However, it's generally better to let Spring mange your beans for you and you don't have to deal with stuff like that.Vazquez

© 2022 - 2024 — McMap. All rights reserved.