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:
- Spring Web Application references.
- Spring Boot common application properties.
- Baeldung’s Spring Boot internationalization.
~Poh