Search code examples
javaspringtomcatwar

tomcat does not start the war application


The intention is to convert a vanilla java application to a spring web app that will run on a tomcat server (war packaging). Constraints are that spring boot can not be used and that the configuration must be of xml type (not a java configuration). app should serve a static page saying "hello world" for example, but it should also process files that reside in some folder (not of relevance at this time).

pom.xml:

<?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>com.example</groupId>
<artifactId>file-handler</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.4.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-inline</artifactId>
        <version>3.11.1</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>3.11.1</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.12.3</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.12.3</version>
    </dependency>

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.200</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.28</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.8</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.8</version>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M5</version>
        </plugin>

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
                <mainClass>com.example.Main</mainClass>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.3.1</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>

    </plugins>
</build>

Tomcat can serve static pages (if in .jsp format) without having to write an explicit internalViewResolver; so in webapp folder there is a single index.jsp file. (rendering of static page works fine)

In src/main/resources there is a beans.xml file where all beans are declared and it looks like this:

<?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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:log4j.properties, classpath:application.properties"/>

    <bean id="jdbcFileRepository" class="com.example.data.JdbcFileRepository">
        <constructor-arg index="0" value="File_Handler_Table"/>
        <constructor-arg index="1" value="jdbc:h2:/home/user/repo/file-handler"/>
    </bean>

    <bean id = "fileHandler" class = "com.example.service.FileHandler">
        <constructor-arg index="0" ref="jdbcFileRepository"/>
    </bean>
</beans>

Main method should create an instance of FileHandler class and call run() on it that should process the files:

public class Main {
    public static void main(String[] args) {
        var applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        var fileHandler = applicationContext.getBean(XmlHandler.class);
        fileHandler.run();
    }
}

Now, if we run this main method locally everything is in order... we can observe that the files are being processed and info about those files is stored to database. However, if we were to create a war package of the app and deploy it on tomcat server; the static page will be displayed but the fileHandler.run() will never be called. Can someone explain what is happening here? I have tried to find similar questions but I guess no one encountered this kind of issue before.


Solution

  • the issue was in the fact that no dispatcher servlet was defined for the app. after adding this to the web.xml, the app runs fine on tomcat:

    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4">
        <servlet>
            <servlet-name>dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:beans.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>