Devops

Build Spring Boot Helloapp in simple steps

2022-01-1010 min read

Build Spring Boot Helloapp in simple steps

This blog is part of the series, which needs a Helloapp to demonstrate the workflow and the tools features. I have built this app with Java using Spring Boot to build the MVC framework. This blog demonstrate the steps to build a standard Java app with view model to expose URI paths to external users.

Setup app environment

Planned to use the personal macos laptop as the build environment. Following tools have been installed and configured for the app development.

Install Java 17 and Maven to the workstation

I have used Homebrew to install maven. Maven can be installed with brew install maven. Java17 has been installed usng the binary from the Eclipse Temurin™ project.

$ brew install --cask temurin
 
$ brew info temurin
temurin: 17.0.1,12
https://adoptium.net/
/usr/local/Caskroom/temurin/17,35 (183.9MB)
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/temurin.rb
==> Name
Eclipse Temurin Java Development Kit
==> Description
JDK from the Eclipse Foundation (Adoptium)
==> Artifacts
OpenJDK17U-jdk_x64_mac_hotspot_17.0.1_12.pkg (Pkg)
==> Analytics
install: 4,442 (30 days), 11,831 (90 days), 14,567 (365 days)
 
$ java -version
openjdk version "17" 2021-09-14
OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode, sharing)

We have to setup the JAVA_HOME environment variable to enable java and maven globally on the workstation.

export JAVA_HOME="/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home"
export CPPFLAGS="-I/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/include"

Visual Studio Code with extensions to support Java app development.

Install other Java and value added extensions along with Spring Boot extension in VSCode.

Build Spring Boot project

We can use the Spring Initializr to create the project blueprint and add the required dependencies to get them added to the pom.xml file.

Spring Boot Dependencies added to the project :
Spring Web: Build web, including RESTful, applications using Spring MVC. Uses Apache Tomcat as the default embedded container.
Spring Boot DevTools: Provides fast application restarts, LiveReload, and configurations for enhanced development experience.
Thymeleaf: A modern server-side Java template engine for both web and standalone environments. Allows HTML to be correctly displayed in browsers and as static prototypes.

pom file

 
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.txconsole</groupId>
	<artifactId>helloappjava</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>helloappjava</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
 
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
 
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
	</dependencies>
 
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
 
</project>

Project structure

In this project, build the src folder structure as below :

$ tree helloappjava/src/main/java
helloappjava/src/main/java
└── com
    └── txconsole
        └── helloappjava
            ├── HelloappjavaApplication.java
            └── controllers
                ├── GreetingController.java
                └── HelloController.java

Build the controller

Since the usecase is to just build the Helloapp, thus we would not add the models, services and repository sections, as it’s not needed for this project. The controller would be built to expose the methods to model the view template with the content and control the view layer.

 
package com.txconsole.helloappjava.controllers;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
 
@Controller
public class GreetingController {
 
    @Value("${greet.user}")
    private String greetuser;
 
    @Value("${greet.msg}")
    private String greetmsg;
 
    @Value("${app.version}")
    private String appversion;
 
    @GetMapping("/")
	public String greeting( @RequestParam(name="greet", required=false) String greet,
    @RequestParam(name="name", required=false) String name, Model model) {
        if (greet != null) {
            model.addAttribute("greet", greet);
        } else {
            model.addAttribute("greet", greetmsg);
        }
 
        if (name != null) {
            model.addAttribute("name", name);
        } else {
            model.addAttribute("name", greetuser);
        }
        model.addAttribute("appversion", appversion);
		return "index";
	}
 
    @GetMapping("about")
	public String about(  Model model) {
        model.addAttribute("appversion", appversion);
		return "about";
	}
}

This is the controller.java file, which we use to create 2 methods for index and the about page. We expose the greeting and the username on the index.html page, via 2 sources – (1) from application.properties as the default value and (2) request-params which can be used to override the default is required. We read the greet and user from properties file via @value annotation into the variable which gets passed to the model.

The controller is built to also access the app version from the properties file and display on the index and the about page of the application.

Properties file

The properties can be used further to expose other project related variables. As of now, we have exposed server port, logging level and the app related custom variables.

server.port=8080
logging.level.web=info
greet.user=KingKong
greet.msg=Hello
app.version=v1.0.0

View layer

I have used the Materialize framework to build the web frontend pages. To expose the web pages, we would add the index.html and about.html pages to the helloappjava/src/main/resources/templates path of the project. The project template files can be found here.

Static files

Since the usecase is to build a Helloapp which can be used for various poc purpose thus there might be a need to use this application offline (without internet). To address this point, we have maintained all the static assets (i.e. css, js, img and fonts) at helloappjava/src/main/resources/static. My efforts have been to keep this app as light as possible, but still have all the raw materials for extending this project, if needed in future.

We can visualize the static files in the tree structure below:

$ tree helloappjava/src/main/resources/static
helloappjava/src/main/resources/static
├── css
   ├── font-awesome.min.css
   ├── materialize.min.css
   └── style.css
├── fonts
   ├── FontAwesome.otf
   ├── fontawesome-webfont.eot
   ├── fontawesome-webfont.svg
   ├── fontawesome-webfont.ttf
   ├── fontawesome-webfont.woff
   └── fontawesome-webfont.woff2
├── img
   └── stars_black_24dp.svg
└── js
    ├── init.js
    └── materialize.min.js

As we can see, I have used the fontawesome (The iconic font and CSS toolkit) css and fonts in the project.

Build and run app

We can test the application with the run/debug extension in VSCode or in command prompt as below.

Build and package the java application with mvn clean package into JAR file and launch the application locally exposed on port 8080 as below :

 
$ java -jar target/helloappjava-0.0.1-SNAPSHOT.jar
 
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.2)
 
2021-12-26 00:34:58.167  INFO 44252 --- [           main] c.t.h.HelloappjavaApplication            : Starting HelloappjavaApplication v0.0.1-SNAPSHOT using Java 17 on srajeshkuma-a01.vmware.com with PID 44252 (/Users/srajeshkumar/myprojects/myapps/helloappjava/target/helloappjava-0.0.1-SNAPSHOT.jar started by srajeshkumar in /Users/srajeshkumar/myprojects/myapps/helloappjava)
2021-12-26 00:34:58.169  INFO 44252 --- [           main] c.t.h.HelloappjavaApplication            : No active profile set, falling back to default profiles: default
2021-12-26 00:34:58.898  INFO 44252 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-12-26 00:34:58.908  INFO 44252 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-12-26 00:34:58.909  INFO 44252 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2021-12-26 00:34:58.955  INFO 44252 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-12-26 00:34:58.955  INFO 44252 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 739 ms
2021-12-26 00:34:59.155  INFO 44252 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2021-12-26 00:34:59.246  INFO 44252 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-12-26 00:34:59.253  INFO 44252 --- [           main] c.t.h.HelloappjavaApplication            : Started HelloappjavaApplication in 1.429 seconds (JVM running for 1.837)
2021-12-26 00:35:04.625  INFO 44252 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-12-26 00:35:04.625  INFO 44252 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-12-26 00:35:04.626  INFO 44252 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms

Wrapping Up

With the above changes and configurations, the application is ready to be used for various use cases.

helloapp-site.jpg

This is an ongoing project and more enhancements (eg. Spring Boot Actuator for monitoring and swagger for APIs) would be added later. I would update the github project accordingly.

The Helloapp project is maintained at github - https://github.com/rajks24/helloappjava.git and available for the Community members.