Monday, May 28, 2018

Spring MVC maven tomcat

In this tutorial, we will show you how to create a Java web project (Spring MVC) with Maven.
Technologies used :
  1. Maven 3.1.1
  2. Eclipse 4.2
  3. JDK 7
  4. Spring 4.1.1.RELEASED
  5. Tomcat 7
  6. Logback 1.0.13

1. Create Web Project from Maven Template

You can create a quick start Java web application project by using the Maven maven-archetype-webapp template. In a terminal (*uix or Mac) or command prompt (Windows), navigate to the folder you want to create the project.
Type this command :
$ mvn archetype:generate -DgroupId={project-packaging} 
-DartifactId={project-name}
-DarchetypeArtifactId=maven-archetype-webapp
-DinteractiveMode=false

//for example
$ mvn archetype:generate -DgroupId=com.mkyong
-DartifactId=CounterWebApp
-DarchetypeArtifactId=maven-archetype-webapp
-DinteractiveMode=false

For example :
$ pwd
/Users/mkyong/Documents/workspace

$ mvn archetype:generate -DgroupId=com.mkyong -DartifactId=CounterWebApp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-webapp:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.mkyong
[INFO] Parameter: packageName, Value: com.mkyong
[INFO] Parameter: package, Value: com.mkyong
[INFO] Parameter: artifactId, Value: CounterWebApp
[INFO] Parameter: basedir, Value: /Users/mkyong/Documents/workspace
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/mkyong/Documents/workspace/CounterWebApp
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.147s
[INFO] Finished at: Thu Dec 20 20:35:19 MYT 2012
[INFO] Final Memory: 12M/128M
[INFO] ------------------------------------------------------------------------

A new web project named “CounterWebApp“, and some of the standard web directory structure is created automatically.

2. Project Directory Layout

Review the generated project layout :
.
|____CounterWebApp
| |____pom.xml
| |____src
| | |____main
| | | |____resources
| | | |____webapp
| | | | |____index.jsp
| | | | |____WEB-INF
| | | | | |____web.xml

Maven generated some folders, a deployment descriptor web.xml, pom.xml and index.jsp.
Note
Please check this official Maven standard directory layout guide to understand more.
pom.xml
<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/maven-v4_0_0.xsd"
>

<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>CounterWebApp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>CounterWebApp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>CounterWebApp</finalName>
</build>
</project>

web.xml – Servlet 2.3 is too old, consider upgrade to 2.5
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >


<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>

index.jsp – A simple hello world html file
<html>
<body>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
style
="display:block"

data-ad-client="ca-pub-2836379775501347"
data-ad-slot="8821506761"
data-ad-format="auto"
data-ad-region="mkyongregion">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script><h2>Hello World!</h2>
</body>
</html>

3. Eclipse IDE Support

To import this project into Eclipse, you need to generate some Eclipse project configuration files :
3.1 In terminal, navigate to “CounterWebApp” folder, type this command :
mvn eclipse:eclipse -Dwtpversion=2.0

Note
This option -Dwtpversion=2.0 tells Maven to convert the project into an Eclipse web project (WAR), not the default Java project (JAR). For convenience, later we will show you how to configure this WTP option in pom.xml.
3.2 Imports it into Eclipse IDE – File -> Import… -> General -> Existing Projects into workspace.
project structure
Figure : In Eclipse, if you see a globe icon on top of the project, means this is a web project.

4. Update POM

In Maven, the web project settings are configure via this single pom.xml file.
  1. Add project dependencies – Spring, logback and junit
  2. Add plugins to configure this project
Read comments for self-explanatory.
pom.xml
<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/maven-v4_0_0.xsd"
>

<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>CounterWebApp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>CounterWebApp Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<jdk.version>1.7</jdk.version>
<spring.version>4.1.1.RELEASE</spring.version>
<jstl.version>1.2</jstl.version>
<junit.version>4.11</junit.version>
<logback.version>1.0.13</logback.version>
<jcl-over-slf4j.version>1.7.5</jcl-over-slf4j.version>
</properties>

<dependencies>

<!-- Unit Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>

<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${jcl-over-slf4j.version}</version>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>

</dependencies>

<build>
<finalName>CounterWebApp</finalName>

<plugins>
<!-- Eclipse project -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<!-- Always download and attach dependencies source code -->
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<!-- Avoid type mvn eclipse:eclipse -Dwtpversion=2.0 -->
<wtpversion>2.0</wtpversion>
</configuration>
</plugin>

<!-- Set JDK Compiler Level -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>

<!-- For Maven Tomcat Plugin -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/CounterWebApp</path>
</configuration>
</plugin>

</plugins>

</build>
</project>

Note
For convenience, declares maven-eclipse-plugin and configure wtpversion to avoid typing the parameter -Dwtpversion=2.0. Now, each time you use mvn eclipse:eclipse, Maven will convert this project into Eclipse web project.
#Before 
mvn eclipse:eclipse --> Eclipse Java project (JAR)
mvn eclipse:eclipse -Dwtpversion=2.0 --> Eclipse Java web project (WAR)

#Now
mvn eclipse:eclipse --> Eclipse Java web project (WAR)

5. Update Source Code

In this step, we will create a few files and folders for Spring MVC and logback logging framework, the final project structure will look like this :
.
|____pom.xml
|____src
| |____main
| | |____java
| | | |____com
| | | | |____mkyong
| | | | | |____controller
| | | | | | |____BaseController.java
| | |____resources
| | | |____logback.xml
| | |____webapp
| | | |____WEB-INF
| | | | |____mvc-dispatcher-servlet.xml
| | | | |____pages
| | | | | |____index.jsp
| | | | |____web.xml

maven-web-project-directory
Note
Create the folder manually if it doesn’t exist.
5.1 Create a Spring MVC controller class.
/src/main/java/com/mkyong/controller/BaseController.java
package com.mkyong.controller;

import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class BaseController {

private static int counter = 0;
private static final String VIEW_INDEX = "index";
private final static org.slf4j.Logger logger = LoggerFactory.getLogger(BaseController.class);

@RequestMapping(value = "/", method = RequestMethod.GET)
public String welcome(ModelMap model) {

model.addAttribute("message", "Welcome");
model.addAttribute("counter", ++counter);
logger.debug("[welcome] counter : {}", counter);

// Spring uses InternalResourceViewResolver and return back index.jsp
return VIEW_INDEX;

}

@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public String welcomeName(@PathVariable String name, ModelMap model) {

model.addAttribute("message", "Welcome " + name);
model.addAttribute("counter", ++counter);
logger.debug("[welcomeName] counter : {}", counter);
return VIEW_INDEX;

}

}

5.2 Create a Spring configuration file.
/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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:component-scan base-package="com.mkyong.controller" />

<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>

</beans>

5.3 Update existing web.xml to support Servlet 2.5 (the default Servlet 2.3 is too old), and also integrates Spring framework via Spring’s listener ContextLoaderListener.
/src/main/webapp/WEB-INF/web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

version="2.5">


<display-name>Counter Web Application</display-name>

<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>

5.4 Moves index.jsp to folder WEB-INF/pages, in order to protect direct access. And updates the content :
/src/main/webapp/WEB-INF/pages/index.jsp
<html>
<body>
<h1>Maven + Spring MVC Web Project Example</h1>

<h2>Message : ${message}</h2>
<h2>Counter : ${counter}</h2>
</body>
</html>

5.5 Create a logback.xml file and puts in resources folder.
/src/main/resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">

<Pattern>
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
</Pattern>

</layout>
</appender>

<logger name="com.mkyong.controller" level="debug"
additivity="false">

<appender-ref ref="STDOUT" />
</logger>

<root level="error">
<appender-ref ref="STDOUT" />
</root>

</configuration>

6. Eclipse + Tomcat

Here are few ways to deploy and test the web project.
6.1 To compile, test and package the project into a WAR file, type this :
mvn package

A new WAR file will be generated at project/target/CounterWebApp.war, just copy and deploy to your Tomcat.
6.2 If you want to debug this project via Eclipse server plugin (Tomcat or other containers), type this again :
mvn eclipse:eclipse

If everything is fine, the project dependencies will be attached to the project web deployment assembly.
eclipse-web-deployment-assembly
Figure : Right clicks on the project -> Properties -> Deployment Assembly
6.3 Since the Maven Tomcat plugin is declared :
pom.xml
 <!-- For Maven Tomcat Plugin -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/CounterWebApp</path>
</configuration>
</plugin>

Type this command :
mvn tomcat:run

It will start Tomcat and deploy your project default to port 8080.

7. Demo

Deploy the WAR file on Tomcat :
7.1 http://localhost:8080/CounterWebApp/
maven-web-project-demo1
7.2 http://localhost:8080/CounterWebApp/mkyong
maven-web-project-demo2
7.3 http://localhost:8080/CounterWebApp/android
maven-web-project-demo3

Download Source Code

Download it – Maven-WebProject-CounterWebApp.zip (9 KB)

Spring Boot Maven Tomcat

You got Started with Apache Maven and you got Started with Spring Boot. Now you’re ready for the next step, so let’s build a complete front to back website with Maven and Spring.



Create Maven Web App

From the command-line you can generate a new project with Maven Archetypes. Archetypes are skeleton applications that you can build from. In our case I want to create a Web Application, so I can use the ‘maven-archetype-webapp’ archetype.
$ mvn archetype:generate -DgroupId=com.remkohde.hello -DartifactId=hello -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
$ cd hello
Open the ‘hello’ web app in your favorite IDE. Edit the ‘pom.xml’,
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.remkohde.hello</groupId>
<artifactId>hello</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Hello Webapp</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
  <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
  <build>
<finalName>hello</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration></configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<server>mytomcat7</server>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
This adds the ‘tomcat7-maven-plugin’ to run in an embedded Tomcat7 server. Run the webapp with ‘mvn tomcat7:run’ and open the webapp in ‘http://localhost:8080/’.
$ mvn tomcat7:run

Add a Servlet

Edit the pom.xml to add a dependency to support for HttpServlet in the ‘javax.servlet’ package of J2EE.
<dependencies>
<!--
https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Create a new file ‘~/src/main/java/com/remkohde/hello/HelloServlet.java’, which creates a ‘HelloServlet.java’ class in the ‘com.remkohde.hello’ package in the default Java sources folder ‘~/src/main/java’ in your web server. Edit the ‘HelloServlet.java’ class.
package com.remkohde.hello;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, 
HttpServletResponse response)
throws ServletException, IOException {

PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Hello Servlet</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("Hello Servlet");
out.println("</BODY>");
out.println("</HTML>");
}
}
Lastly, configure Tomcat to map to our HelloServlet. Edit the ‘~/src/main/webapp/WEB-INF/web.xml’.
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Hello World</display-name>
  <servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
  <servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
Restart Tomcat with ‘mvn tomcat7:run’ and open the Servlet in ‘http://localhost:8080/hello’.

Add Spring

We did a lot of basic J2EE work in a very short time, but let’s step it up. The real way to build a J2EE Web Application is with Spring. So let’s convert our web application into a Spring Boot web application. In Spring, HTTP requests are handled by a controller. So-called annotation replaces the ‘web.xml’ servlet definition and mapping, and Spring boots the servlets by inspecting your classes and looking for this annotation.
Edit your ‘pom.xml’ to support Spring.
<dependencies>
...
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
...
</dependencies>
...
<build>
<plugins>
...
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.0.RELEASE</version>
</plugin>
</plugins>
</build>
Add 2 Java classes: ‘~/src/main/java/com/remkohde/hello/Application.java’ and ‘~/src/main/java/com/remkohde/hello/HelloController.java’.
Add the entry point or the default main class for our Spring Application.
package com.remkohde.hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The HelloController is in Spring land what our HelloServlet was in a pure J2EE Servlet world.
package com.remkohde.hello;
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 HelloController {
@GetMapping("/hello")
public String hello(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "hello";
}
}
The ‘return “hello”;’ line returns a view called ‘hello’ which refers to a file ‘hello.html’ in the ‘~/src/main/resources/templates/’ folder. The view template style I am using here is Thymeleaf, which is a dependency in the ‘pom.xml’. Other view templates you can use are JSP/JSTL, Tiles or Velocity.
Create the view template ‘~/src/main/resources/templates/hello.html’.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Hello ' + ${name} + '!'" />
</body>
</html>
Wow! Done! You did it. Let’s run your Tomcat Web App with Maven and Spring!
$ mvn spring-boot:run
Open the application in ‘http://127.0.0.1:8080/hello’. You should see ‘Hello World!’. Let’s try to say hi to yourself: ‘http://127.0.0.1:8080/hello?name=Remko’.