1

I have a working Spring application that contains a embedded Tomcat. As a executable war, it works fine. As I'm going to use AngularJ for the front end, it isn't very practical to have the Spring project in an executable jar, as I will do debugging in the browser and want to be able to quickly edit the js source files. If they are saved in an archive, this is annoying.

That's why I want to make it deployable, so it would get unpacked on a tomcat. It seems to be that easy, but I can't get it to work.

The context always gets loaded twice apparently. Because of that first I get an exception of the repository (@Repository) I use (already blocked) and another exception from spring "Cannot initialize context because there is already a root application context present".

I confused as I already read, that is quite normal that Spring creates 2 contexts, especially with MVC. But why the exceptions then?

My SpringApp class looks like this

@EnableWebMvc
@ComponentScan
@EnableAutoConfiguration
public class LAuthServerApplication extends WebMvcConfigurerAdapter {

    @Autowired
    Environment env;

    public static void main(String[] args) {
    System.out.println("#################### Startup parameters ##############");
    for (String s : args) {
        System.out.println("Parameter: " + s);
    }
    System.out.println("######################################################");
    SpringApplication.run(LAuthServerApplication.class, args);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
    }

    @Bean
    public InternalResourceViewResolver viewResolver() {
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setPrefix("/WEB-INF/pages/");
    viewResolver.setSuffix(".jsp");
    return viewResolver;
    }

To make it deployable I added this class to my project:

@Configuration
public class AppServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
}

POM:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ch.comlab.comweb</groupId>
    <artifactId>LAuth</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>
    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>

    </properties>
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.5.RELEASE</version>
    </parent>

    <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.comlab.comweb</groupId>
        <artifactId>Infrastructure</artifactId>
        <version>1.2.6</version>
    </dependency>

    </dependencies>
    <build>
    <plugins>
        <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
            <webResources>
            <resource>
                <directory>src/main/webapp</directory>
                <filtering>true</filtering>
            </resource> 
            </webResources>
        </configuration>
        </plugin>
        <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <resources>
            <resource>
                <filtering>true</filtering>
                <directory>src/main/resources/</directory>
            </resource>
            </resources>
        </configuration>
        </plugin>
    </plugins>
    </build>
    <repositories>
    <repository>
        <id>spring-releases</id>
        <url>https://repo.spring.io/libs-release</url>
    </repository>
    </repositories>
    <pluginRepositories>
    <pluginRepository>
        <id>spring-releases</id>
        <url>https://repo.spring.io/libs-release</url>
    </pluginRepository>
    </pluginRepositories>
    <name>LAuth</name>
</project>
Herr Derb
  • 4,977
  • 5
  • 34
  • 62
  • 1
    Have you seen [Spring Boot Devtools](http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html)? Allows you to debug and edit files like js files on the fly when debugging your app in an IDE (when not packaged in a jar). No need to deploy it in Tomcat for debugging. – Jesper Jun 20 '16 at 10:02
  • @Herr could you show your pom file? I already did a project with a war configuration to be deployed into tomcat. I can share with you – cralfaro Jun 20 '16 at 10:26
  • Possible duplicate of [Spring Boot War deployed to Tomcat](http://stackoverflow.com/questions/27904594/spring-boot-war-deployed-to-tomcat) – Mudassar Jun 20 '16 at 10:27
  • @Mudassar I exactly tried this. It did not work, that's why I'm asking here – Herr Derb Jun 20 '16 at 10:29
  • @Jesper Does this also work for executable wars? – Herr Derb Jun 20 '16 at 10:29
  • Devtools work when you run or debug your Spring Boot app from your IDE, in expanded form. When you run it from a packaged jar or war, the devtools are automatically disabled. Read [the documentation](http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html) on how to use devtools. – Jesper Jun 20 '16 at 10:31
  • Repalce return application.sources(Application.class); by return application.sources(LAuthServerApplication .class); – naddame Jan 16 '17 at 09:56

4 Answers4

4

I believe its due to the embedded server which comes from spring-boot-tomcat.

Can you exclude embedded tomcat and try? Eg:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

also remove your tomcat dependency which you gave next to spring-boot-starter-web.

Dhanabalan
  • 572
  • 5
  • 19
3

Your configuration is a bit confusing and verbose if you use Spring Boot.

You should remove the maven-war-plugin from your list of plugins. As the spring-boot-maven-plugin takes care of those things already (and the parent is also).

Next your configuration remove some of the code and merge the LAuthServerApplication and your starter into one. And use @SpringBootApplication instead of single annotations (saves you code).

@SpringBootApplication
public class LAuthServerApplication extends SpringBootServletInitializer {

    @Autowired
    Environment env;

    public static void main(String[] args) {
        System.out.println("#################### Startup parameters ##############");
        for (String s : args) {
            System.out.println("Parameter: " + s);
        }
        System.out.println("######################################################");
        SpringApplication.run(LAuthServerApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(LAuthServerApplication.class);
    }

}

In your application.properties add

spring.mvc.view.prefix=/WEB-INF/pages/
spring.mvc.view.suffix=.jsp

Spring Boot already configures Spring MVC for you and yours interferes with that. Don't override the defaults unless you have very specific needs.

Now rebuild and restart your application.

Note: IMHO it is a very bad idea to edit the unpacked files directly into tomcat, as you really want to edit the source files. Instead of hacking your way around you might want to take a look at the JHipster project, which unifies JS and Spring Boot development.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Thanks, I tried your suggested changes. I'm still getting "Cannot initialize context because there is already a root application context present". Why is it a bad idea to edit js files directly in tomcat? It saves a lot of time as I see it. – Herr Derb Jun 20 '16 at 12:36
  • Because you re editing deployed files, which you need to copy back to your workspace to have the final artifact prepared. This is going to bite you at some point in the future. Do you have a `web.xml` or another `WebApplicationInitializer` in your classpath? – M. Deinum Jun 20 '16 at 12:41
0

I finally got it to run, with the following POM and the suggested Code change from M.Denium and Dhanabalan:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ch.comlab.comweb</groupId>
<artifactId>LAuth</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>

</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
</parent>

<dependencies>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
    <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-el</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
    <groupId>ch.comlab.comweb</groupId>
    <artifactId>Infrastructure</artifactId>
    <version>1.2.6</version>
</dependency>

</dependencies>
<build>
<plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <resources>
        <resource>
            <filtering>true</filtering>
            <directory>src/main/resources/</directory>
        </resource>
        </resources>
    </configuration>
    </plugin>
</plugins>
</build>
<repositories>
<repository>
    <id>spring-releases</id>
    <url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
    <id>spring-releases</id>
    <url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
<name>LAuth</name>

Herr Derb
  • 4,977
  • 5
  • 34
  • 62
0

If you have used spring initializer online by default pom file comes like this for version 2.3.1.RELEASE

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-starter</artifactId>
        </dependency>
....

Change it to

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
...

Clearing the cache didn't worked for me. Only thing worked was this.

Krishnadas PC
  • 5,981
  • 2
  • 53
  • 54