tonix
tonix

Reputation: 6939

"Cannot initialize context because there is already a root app..." when a Jetty auto-restart occurs after a change in the code Spring Vaadin?

I am experiencing the following issue on a Spring application with Vaadin when I run it with Jetty:

I have Jetty configured in a way that it scans the project working directory and if it sees changes made in the code, it restarts the server automatically (like Tomcat does too).

What I noticed is that if I make even a small change in the code and then Jetty fires automatically a restart, the following exception is thrown:

java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!

I know that this exception is thrown when there is more than one ContextLoaderListener as both ContextLoaderListeners try to load the same root ApplicationContext (therefore causing the exception), as explained here, also:

Why this Spring application with java-based configuration don't work properly

The point is that I do not have another ContextLoaderListener registered (or at least, I think so, as I cannot be sure cause I am using Spring together with Vaadin via the Vaadin Spring addon -> https://vaadin.com/directory#addon/vaadin-spring as a Maven dependency, and the addon is not yet officially STABLE).

One thing I am sure of is that the only listener I have in my code is the following:

package com.app.config;

import javax.servlet.annotation.WebListener;

import org.springframework.web.context.ContextLoaderListener;

@WebListener
public class AppContextLoaderListener extends ContextLoaderListener {
}

So I thought "Maybe there's a problem with the addon?". But then I tried to reproduce the issue using Tomcat instead of Jetty (started Tomcat, ran the application on Tomcat with Run on Server, modified some arbitrary code, waited that Tomcat republished the changes automatically) but the exception is never thrown with Tomcat.

So it might be Jetty related? Does anyone experienced something similar too?

Where is the issue?

This is the applicationContext.xml file I use (I post it for completeness):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

    <bean class="com.app.config.AppConfig" />
    <context:component-scan base-package="com.app" />
</beans>

EDIT: here is the full stacktrace of the exception:

java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:277)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:764)
    at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:406)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:756)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:242)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1221)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:699)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:454)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
    at runjettyrun.scanner.RJRFileChangeListener.filesChanged(RJRFileChangeListener.java:155)
    at org.eclipse.jetty.util.Scanner.reportBulkChanges(Scanner.java:680)
    at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:546)
    at org.eclipse.jetty.util.Scanner.scan(Scanner.java:398)
    at org.eclipse.jetty.util.Scanner$1.run(Scanner.java:348)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)

Upvotes: 1

Views: 3470

Answers (1)

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49462

You are using run-jetty-run, that doesn't do reload/restart the same way as you are expecting.

Note: run-jetty-run is not a jetty tool or project, its a 3rd party tool with no committers in common with core jetty.

Either use the jetty-distribution, or jetty-maven-plugin, or jetty-runner and you'll have better luck, mostly because the context reload is done properly, through the DeploymentManager (which run-jetty-run doesn't use).

Upvotes: 2

Related Questions