Reputation: 701
I am modifying and old project that uses Spring 3.1.4.
I am trying to use a StartupListener to configure Logback:
public class LoggingStartupListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingStartupListener.class.getName());
@Override
public void contextInitialized(final ServletContextEvent sce) {
final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
context.reset();
final JoranConfigurator configurator = new JoranConfigurator();
final ServletContext servletContext = sce.getServletContext();
final StringBuilder filePath = new StringBuilder(100);
filePath.append(servletContext.getRealPath("/"));
filePath.append(servletContext.getInitParameter("logFileName"));
InputStream configStream = null;
try {
configStream = FileUtils.openInputStream(new File(filePath.toString()));
...
It is reading a file path from the web.xml:
<context-param>
<param-name>logFileName</param-name>
<param-value>/WEB-INF/config/${spring.profiles.active}/logback.xml</param-value>
</context-param>
Now, when I run a JUnit test I always run into the exception:
java.io.FileNotFoundException: File '/var/folders/v7/1r3m8y8j487dqj7vmvb4n4kxcw70fj/T/tomcat-embedded-77438108580291256392.tmp/webapps/myproject/WEB-INF/config/${spring.profiles.active}/logback.xml' does not exist
at org.apache.commons.io.FileUtils.openInputStream(FileUtils.java:136)
Which means, that the property spring.profiles.active is never resolved.
I tried all kind of things:
1) I tried setting the property before the test:
@BeforeClass
public static void setSystemProperty() {
System.out.println("---------------------BeforeClass--------------------");
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("local");
ctx.refresh();
System.setProperty("spring.profiles.active", "local");
}
But it did not work, because this method is called way after the error is thrown. ("----------BeforeClass--------------" appears much after the error in the log.)
2) I tried using an annotation before the test class:
@ActiveProfiles(profiles = "local")
3) I tried setting the property with a spring-test.properties file:
spring.profile.active=local
and include it in the test-context:
<context:property-placeholder location="classpath:spring-test.properties"/>
-> no effect whatsoever
4) I even tried to set the property directly IN the ServletContextListener:
@Override
public void contextInitialized(final ServletContextEvent sce) {
System.setProperty("spring.profiles.active", "local");
...
And this really surprised me, because this should have worked, shouldn't it?
Do I encounter these problems because I am using an old Spring version? I never had these problems in other projects with higher Spring versions. Or what am I missing?
Can I configure the listener to startup later? Or can I configure the unit tests to set the system property before the ServletContextListener is started?
Or will it be better to initialise logback in a different way to avoid these problems - but why don't they appear in other projects then?
I found this but I don't know whether that applies to my case: Spring-test and ServletContextListener in web.xml
It says there is no way to configure ServletContextListener using Spring MVC Test. It says I can try to overwrite the context-param with
wac.getServletContext().setInitParameter(name, value);
But I wouldn't know when/ where to do it because the web.xml is obviously read before the test classes are initialised.
Thanks a lot in advance for any hint
Upvotes: 1
Views: 2686
Reputation: 701
I used logback spring extensions instead of our own implementation and with that the problem disappears!
I used this documentation: https://github.com/qos-ch/logback-extensions/wiki/Spring
One of the features is: - "Specify the logback.xml location using a Spring resource path and system property placeholders."
Exactly what I needed. I used logback-ext-spring with version 0.1.4.
Upvotes: 1