Spring Boot Web as Standalone App

By | October 8, 2023

I created a very simple starter project for create web app with embedded Tomcat. This project is supposed to be runnable with just the war file. If you want to create it from scratch here are the steps.

Step 0. Requirements

I’m using the following:

  • Java 21
  • Maven 3.9.5

Step 1. Project/Code Structure

Create the following code structure. I’m using IntelliJ Idea to code, so this screenshot is taken from there. Essential directories are:

  • src/main/java/ – main source directory
  • src/test/java/ – unit test directory
  • src/main/resources/static/ – for static files
  • src/test/resources/ – unit test resources
  • src/main/webapp/WEB-INF/jsp/ – this is where JSP files reside

Essential files are:

  • pom.xml – Maven build file
  • src/main/resources/application.properties – configuration file under main resources
  • src/main/java/com/pssoft7/web/Application.java – main Spring Boot application entry point
  • src/main/java/com/pssoft7/web/controller/HomeController.java – the “Hello, World” controller
  • src/main/resources/static/css/style.css – sample static CSS
  • src/main/webapp/WEB-INF/jsp/index.jsp – the “Hello, World” view (JSP)

Step 2. Codes

Edit pom.xml and here is my content:

<?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.pssoft7</groupId>
   <artifactId>web-starting</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>web-standalone-application</name>
   <description>Spring Boot Standalone Web application</description>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>3.1.4</version>
      <relativePath />
      <!-- lookup parent from repository -->
   </parent>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <!-- This is a web application -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.apache.tomcat.embed</groupId>
         <artifactId>tomcat-embed-jasper</artifactId>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>javax.servlet.jsp.jstl</groupId>
         <artifactId>jstl-api</artifactId>
         <version>1.2</version>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

Application.java

package com.pssoft7.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

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

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

}

HomeController.java

package com.pssoft7.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {
    @RequestMapping("/")
    public String goToHome() {
        return "index";
    }

}

style.css:

body {
  background-color: lightblue;
}

h1 {
  color: navy;
  margin-left: 20px;
}

application.properties

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

# logging settings
logging.level.root=INFO
logging.level.com.pssoft7=TRACE

# server error settings
server.error.whitelabel.enabled=true
server.error.include-exception=true
server.error.include-message=always
server.error.include-stacktrace=always

index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<link rel="stylesheet" href="css/style.css">
<title>Hello, World</title>
</head>
<body>
<h1>Hello, World! This is our first JSP page.</h1>
<p>
You have successfully run a sample page.
</p>
</body>
</html>

Step 3. Build and Run

at the root directory of the project where pom.xml resides, run mvn -U clean package to build a war file. Once it’s successfully build, run the war file with java just like how you run a runnable jar: java -jar target/web-starting-0.0.1-SNAPSHOT.war. Once started, you can navigate to http://localhost:8080/ using your web browser.

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< com.pssoft7:web-starting >----------------------
[INFO] Building web-standalone-application 0.0.1-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ war ]---------------------------------
[INFO] 
[INFO] --- clean:3.2.0:clean (default-clean) @ web-starting ---
[INFO] Deleting /home/poh/Documents/workspace/spring-boot-web-starting-project/target
[INFO] 
[INFO] --- resources:3.3.1:resources (default-resources) @ web-starting ---
[INFO] Copying 1 resource from src/main/resources to target/classes
[INFO] Copying 1 resource from src/main/resources to target/classes
[INFO] 
[INFO] --- compiler:3.11.0:compile (default-compile) @ web-starting ---
[INFO] Changes detected - recompiling the module! :source
[INFO] Compiling 2 source files with javac [debug release 17] to target/classes
[INFO] 
[INFO] --- resources:3.3.1:testResources (default-testResources) @ web-starting ---
[INFO] Copying 0 resource from src/test/resources to target/test-classes
[INFO] 
[INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ web-starting ---
[INFO] Changes detected - recompiling the module! :dependency
[INFO] 
[INFO] --- surefire:3.0.0:test (default-test) @ web-starting ---
[INFO] 
[INFO] --- war:3.3.2:war (default-war) @ web-starting ---
[INFO] Packaging webapp
[INFO] Assembling webapp [web-starting] in [/home/poh/Documents/workspace/spring-boot-web-starting-project/target/web-starting-0.0.1-SNAPSHOT]
[INFO] Processing war project
[INFO] Copying webapp resources [/home/poh/Documents/workspace/spring-boot-web-starting-project/src/main/webapp]
[INFO] Building war: /home/poh/Documents/workspace/spring-boot-web-starting-project/target/web-starting-0.0.1-SNAPSHOT.war
[INFO] 
[INFO] --- spring-boot:3.1.4:repackage (repackage) @ web-starting ---
[INFO] Replacing main artifact /home/poh/Documents/workspace/spring-boot-web-starting-project/target/web-starting-0.0.1-SNAPSHOT.war with repackaged archive, adding nested dependencies in BOOT-INF/.
[INFO] The original artifact has been renamed to /home/poh/Documents/workspace/spring-boot-web-starting-project/target/web-starting-0.0.1-SNAPSHOT.war.original
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.416 s
[INFO] Finished at: 2023-10-08T09:50:11+08:00
[INFO] ------------------------------------------------------------------------
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.1.4)

2023-10-08T09:50:13.613+08:00  INFO 5399 --- [           main] com.pssoft7.web.Application              : Starting Application v0.0.1-SNAPSHOT using Java 21 with PID 5399 (/home/poh/Documents/workspace/spring-boot-web-starting-project/target/web-starting-0.0.1-SNAPSHOT.war started by poh in /home/poh/Documents/workspace/spring-boot-web-starting-project)
2023-10-08T09:50:13.618+08:00 DEBUG 5399 --- [           main] com.pssoft7.web.Application              : Running with Spring Boot v3.1.4, Spring v6.0.12
2023-10-08T09:50:13.621+08:00  INFO 5399 --- [           main] com.pssoft7.web.Application              : No active profile set, falling back to 1 default profile: "default"
2023-10-08T09:50:15.363+08:00  INFO 5399 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-10-08T09:50:15.383+08:00  INFO 5399 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-10-08T09:50:15.383+08:00  INFO 5399 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.13]
2023-10-08T09:50:15.942+08:00  INFO 5399 --- [           main] org.apache.jasper.servlet.TldScanner     : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
2023-10-08T09:50:16.007+08:00  INFO 5399 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-10-08T09:50:16.009+08:00  INFO 5399 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2291 ms
2023-10-08T09:50:16.398+08:00  INFO 5399 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2023-10-08T09:50:16.713+08:00  INFO 5399 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-10-08T09:50:16.771+08:00  INFO 5399 --- [           main] com.pssoft7.web.Application              : Started Application in 4.066 seconds (process running for 5.489)


And there you go, the basic runnable web application using Spring Boot.

What’s Next

I am planning to keep this starting template updated with other features such as examples for:

  • Internationalization and Localization (i18n/l10n)
  • Externalized configurations
  • Templating for multi-page app
  • Single page support
  • Security and OAuth2
  • Session
  • Reactive Web support

So that people can quickly grab a starter project and actually start.

I also may want to look at making a template like this for older Java (and Maven).

References

The whole starter project on github.

Reference:

~Poh

Leave a Reply

Your email address will not be published. Required fields are marked *