DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Deploy Spring Boot Apps From Jar to War
  • Creating Application using Spring Roo and Deploying on Google App Engine
  • Develop Web Apps in F# with WebSharper
  • 4 Major Steps Of Web Application Penetration Testing

Trending

  • Agentic AI for Automated Application Security and Vulnerability Management
  • How Trustworthy Is Big Data?
  • Doris: Unifying SQL Dialects for a Seamless Data Query Ecosystem
  • Stateless vs Stateful Stream Processing With Kafka Streams and Apache Flink
  1. DZone
  2. Coding
  3. Frameworks
  4. Deploying Spring Apps to Tomcat (Without web.xml)

Deploying Spring Apps to Tomcat (Without web.xml)

For those out there who haven't made the jump to Servlet's annotations, see how to deploy a simple sample Spring app to Tomcat without a web.xml file.

By 
Mohamed Sanaulla user avatar
Mohamed Sanaulla
·
Nov. 21, 17 · Tutorial
Likes (10)
Comment
Save
Tweet
Share
61.9K Views

Join the DZone community and get the full member experience.

Join For Free

Since the Servlet 3 specification, web.xml is no longer needed for configuring your web application and has been replaced by annotations. In this article, we will look at how to deploy a simple Spring-based application without web.xml to Tomcat 8.5.x.

Creating an Empty Application

Use the following command to create an empty web application using the Maven webapp archetype:

mvn archetype:generate -DgroupId=info.sanaulla -DartifactId=spring-tomcat-sample 
   -Dversion=1.0 -DarchetypeArtifactId=maven-archetype-webapp


Delete the web.xml created in src\main\webapp\WEB-INF. Then, we need to update the maven-war-plugin not to fail if web.xml is missing. This can be done by updating the plugin information in the build tag as shown below:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
        <execution>
            <id>default-war</id>
            <phase>prepare-package</phase>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </execution>
    </executions>
</plugin>


Setting Up Dependencies

We would need the following dependencies added to the pom.xml:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>${thymeleaf.version}</version>
</dependency>
<dependency>
    <groupId>nz.net.ultraq.thymeleaf</groupId>
    <artifactId>thymeleaf-layout-dialect</artifactId>
    <version>${thymeleaf-layout-dialect.version}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>${h2.version}</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    <version>${lombok.version}</version>
</dependency>


And their corresponding version properties are given below:

<properties>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <java.version>1.8</java.version>
    <apache.commons.version>3.6</apache.commons.version>
    <h2.version>1.4.196</h2.version>
    <jackson.version>2.9.2</jackson.version>
    <lombok.version>1.16.18</lombok.version>
    <spring.version>5.0.0.RELEASE</spring.version>
    <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.2.1</thymeleaf-layout-dialect.version>
</properties>


Configuring Our H2 Embedded DB

Let us create a configuration bean for configuring our DataSource, which is an Embedded H2, and create a Bean of type NamedParameterJdbcTemplate:

@Configuration
public class DBConfiguration {

    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .generateUniqueName(false)
            .setName("testdb")
            .setType(EmbeddedDatabaseType.H2)
            .addDefaultScripts()
            .setScriptEncoding("UTF-8")
            .ignoreFailedDrops(true)
            .build();
    }

    @Bean
    public NamedParameterJdbcTemplate namedParamJdbcTemplate() {
        NamedParameterJdbcTemplate namedParamJdbcTemplate =
            new NamedParameterJdbcTemplate(dataSource());
        return namedParamJdbcTemplate;
    }
}


Then we need a SQL script schema.sql that will set up the tables while data.sql will seed them with data each time the application is run. Let us create the corresponding files in src/main/resources:

-- schema.sql
DROP TABLE IF EXISTS person;

CREATE TABLE person(
  id NUMERIC IDENTITY PRIMARY KEY,
  first_name VARCHAR(512) NOT NULL,
  last_name VARCHAR(512) NOT NULL,
  date_of_birth TIMESTAMP NOT NULL,
  place_of_birth VARCHAR(512)
);

-- data.sql
INSERT INTO person(first_name, last_name, date_of_birth, place_of_birth) 
VALUES ('First', 'Last', DATE '1990-02-21', 'Bangalore');
INSERT INTO person(first_name, last_name, date_of_birth, place_of_birth) 
VALUES ('First2', 'Last2', DATE '1987-02-21', 'Mumbai');
INSERT INTO person(first_name, last_name, date_of_birth, place_of_birth) 
VALUES ('First3', 'Last3', DATE '1996-02-21', 'Chennai');
INSERT INTO person(first_name, last_name, date_of_birth, place_of_birth) 
VALUES ('First4', 'Last4', DATE '1978-02-21', 'Delhi');


Creating an API Controller

Lets us create a model class Person:

@Data
public class Person {
    private Integer id;
    private String firstName;
    private String lastName;
    private Date dateOfBirth;
    private String placeOfBirth;
}


And a corresponding DAO class PersonDAO:

@Service
public class PersonDAO {

    @Autowired NamedParameterJdbcTemplate jdbcTemplate;

    public List < Person > getPersons() {
        return jdbcTemplate.query("SELECT * FROM person",
            (ResultSet rs, int rowNum) - > {
                Person p = new Person();
                p.setId(rs.getInt("id"));
                p.setFirstName(rs.getString("first_name"));
                p.setLastName(rs.getString("last_name"));
                p.setDateOfBirth(rs.getDate("date_of_birth"));
                p.setPlaceOfBirth(rs.getString("place_of_birth"));
                return p;
            });
    }
}


The API controller is as shown below:

@RestController
@RequestMapping("/api/persons")
public class ApiController {

    @Autowired PersonDAO personDao;

    @GetMapping
    public ResponseEntity << ? > getPersons() {
        return ResponseEntity.ok(personDao.getPersons());
    }
}


Deploying Our App to Tomcat

I assume that you have downloaded Tomcat and extracted it to your file system. For development purposes, I prefer to update server.xml to configure the context and point to the exploded WAR directory as shown below:

<Context path="/sample" reloadable="true" docBase="G:\samples\spring-tomcat-sample\target\spring-tomcat-sample" />


For production-related deployments, you can upload the WAR to the server.

So once you start the server, you can verify if the app has been deployed correctly by visiting the API URL http://localhost:8080/sample/api/persons in the browser to get the data as shown below:

Configuring Thymeleaf

Let us now configure Thymeleaf as our templating engine to serve the UI for our application. Configuring it requires the following bean definitions:

  • Technique for resolving the templates. There are many possibilities, and we will use Classpath based template resolver

  • Create an instance of SpringTemplateEngine and set the template resolver technique

  • Setup Spring’s ViewResolver to use the SpringTemplateEngine

@Configuration
public class ViewConfiguration {

    @Bean
    public ClassLoaderTemplateResolver templateResolver() {
        ClassLoaderTemplateResolver templateResolver =
            new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCacheable(false);
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine =
            new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.addDialect(new LayoutDialect());
        return templateEngine;
    }

    @Bean
    public ViewResolver viewResolver() {
        ThymeleafViewResolver viewResolver =
            new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        viewResolver.setCharacterEncoding("UTF-8");
        return viewResolver;
    }

}


Creating a View Controller

Let us create a simple controller that will serve our UI templates:

@Controller
@RequestMapping("/")
public class ViewController {

    @Autowired PersonDAO personDao;

    @GetMapping
    public String index(Model model) {
        model.addAttribute("persons", personDao.getPersons());
        return "index";
    }
}


Creating a Thymeleaf Based Template

We need to create a template index.html, which is returned from the above controller:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
        <link rel="stylesheet" href="https://bootswatch.com/4/cerulean/bootstrap.min.css" />
    </head>
    <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
            <a class="navbar-brand" href="#">Spring on Tomcat</a>
        </nav>
        <div class="container">
            <div class="page-header">
                <h1>Spring on Tomcat</h1>
            </div>
            <div class="row">
                <div class="col">
                    <ul class="list-group">
                        <li class="list-group-item" th:each="p : ${persons}">
            [[${p.firstName}]] [[${p.lastName}]], 
            Date Of Birth: [[${#dates.format(p.dateOfBirth, 'dd/MMM/yyyy')}]]
            Place: [[${p.placeOfBirth}]]
            </li>
                    </ul>
                </div>
            </div>
        </div>
        <script src="https://bootswatch.com/_vendor/jquery/dist/jquery.min.js"></script>
        <script src="https://bootswatch.com/_vendor/popper.js/dist/umd/popper.min.js"></script>
        <script src="https://bootswatch.com/_vendor/bootstrap/dist/js/bootstrap.min.js"></script>
    </body>
</html>


Conclusion

In this article, we looked at configuring a simple Spring MVC-based application without web.xml (without using Spring Boot) and deploying it to Tomcat. We also configured Thymeleaf to render our UI templates. The complete code for this can be found here.

Apache Tomcat Spring Framework app Web application

Published at DZone with permission of Mohamed Sanaulla, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Deploy Spring Boot Apps From Jar to War
  • Creating Application using Spring Roo and Deploying on Google App Engine
  • Develop Web Apps in F# with WebSharper
  • 4 Major Steps Of Web Application Penetration Testing

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!