Create Spring Web MVC Project from Maven Archetype in Eclipse Neon

This post describes how to use Maven in Eclipse Neon for creating a new Spring Web MVC project from a Maven archetype. The spring-mvc-archetype developed by Frédéric Fondement from ENSISA is used here. This archetype creates a new Java web project and adds the following framework components:

Summary

  1. Configuring the Embedded Maven 3 Distribution in Eclipse Neon
  2. Creating a new Spring Web MVC Project from Maven Archetype
  3. Running the Spring Web Web Project with Maven

Related Posts

1  Configuring the Embedded Maven 3 Distribution in Eclipse Neon

For this example, the Eclipse Java EE IDE (Neon version 3) is used. If needed, refer to the post below on how to setup an integrated development environment with Eclipse Neon and Apache Tomcat.

Launch the Eclipse Neon IDE and use the main menu to navigate to Eclipse > Preferences > Maven > Installations to confirm that the EMBEDDED distribution is available and checked as shown below.

Eclipse Neon - Preferences - View Available Maven Installations

Maven will use a file called settings.xml which by default it tries to locate at %Home%/.m2.

Eclipse Neon - Preferences - View Maven User Settings and Local Repository Location

For example, on a Linux OS, for a user named george, the default location would be:

/Users/george/.m2/setting.xml

If the file does not exist, Maven will use default settings. Below is a basic sample settings.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 
                     https://maven.apache.org/xsd/settings-1.0.0.xsd">

  <!-- 
   | The default local repository is set to %HOME%\.m2\repository.
   -->
  <localRepository>/Users/george/.m2/repository</localRepository>

  <!--
   | Maven prompts you when it needs input. If false, Maven will use sensible defaults.
   -->
  <interactiveMode>true</interactiveMode>
  
  <proxies>
    <proxy>
      <id>myCompany</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>domain\username</username>
      <password>Password123</password>
      <host>proxy.mycompany.com</host>
      <port>8080</port>
      <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
  </proxies>
</settings>

If needed, use the proxy setting to specify a proxy server and authentication credentials that will be used by Maven when creating new projects from archetypes and during dependency resolution.

If behind a proxy, it may also be necessary to configure proxy settings for Eclipse using Preferences > General > Network Connections. These proxy settings are used by Eclipse –not Maven– when e.g. installing and updating plugins from the Eclipse Marketplace or when downloading Maven archetypes during project setup.

Eclipse Neon - Preferences - View Network Proxy Settings

If proxy related issues with Maven or Eclipse persist, please see stackoverflow.com/questions/25760961 for additional information on this topic.

2  Creating a new Spring Web MVC Project from Maven Archetype

In Eclipse Neon, navigate to File > New > Maven Project to create a new project from a Maven Archetype.

Eclipse Neon - File Menu - Create New Maven Project

Click on Next on the first step in the New Maven Project wizard screen. Make sure that the option Create a simple project (skip archetype selection) is NOT checked.

Eclipse Neon - New Maven Project - Select Project Name and Location

The Select an Archetype step is the most important one here, as it allows the selection of an existing archetype for the creation of a new Maven project. The archetype will automatically configure the project so that it supports the Spring MVC framework. Change the Catalog dropdown to All Catalogs. The archetype that is used here is called spring-mvc-archetype. Enter the name into the Filter box.

Eclipse Neon - New Maven Project - Select an Archetype

If the archetype does not show up in the list, click on the Add Archetype button. Archetype information can be found on the Maven Central Repository.

Maven Central Repository - spring-mvc-archetype Artifact Information

On the Add Archetype screen, enter the archetype information as per the Maven Central Repository:

  • Archetype Group Id: fr.uha.ensisa.ff
  • Archetype Artifact Id: spring-mvc-archetype
  • Archetype Version: 1.0.3
Eclipse Neon - New Maven Project - Add a New Archetype

Click on OK to continue. It should then show up in the list of selectable archetypes.

Eclipse Neon - New Maven Project - Select spring-mvc-archetype Archetype

Select the archetype artifact from the list and click on Next. On the Specify Archetype parameters screen, enter the Artificat Id of the new project Maven should create based on the archetype. Here, the project name is SimpleSpringMVCProject.

Then click on Finish. Maven will now run and setup the Spring Web MVC project according to the specified archetype. This process includes downloading all dependencies and adding them to the local Maven repository.

Eclipse Neon - New Maven Project - Specify Archetype Parameters

The output in the Maven console should be similar to what is shown in the screen shot below.

Eclipse Neon - New Maven Project - View Maven Console Output in Eclipse

After Maven has created the project, its structure and files can be viewed in the Eclipse Project Explorer.

Eclipse Neon - Maven Project - View Structure of Spring Web MVC Project in Project Explorer

Expand the node Libraries > Maven Dependencies to view the Spring 5 and other JAR files that have been downloaded and added to the local repository. The location of a JAR in the repository is determined by its group Id, artifact Id and version.

Maven - View Local Repository Contents in Finder on Mac OS X

Open the pom.xml file that was created as per the Maven archetype. This file specifies a project’s dependencies and what plugins Maven executes during a build. See Maven’s plugin architecture for more information. The archetype that was used in this example adds the following features to a new Maven project:

<?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.pgx.web.spring</groupId>
    <artifactId>SimpleSpringMVCProject</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>SimpleSpringMVCProject</name>
    <url>http://maven.apache.org</url>

    <properties>
        <java.version>1.8</java.version>
        <servlet.port>8080</servlet.port>
        <spring.version>5.0.0.RELEASE</spring.version>
        <cglib.version>2.2.2</cglib.version>
        <maven.compiler.target></maven.compiler.target>
        <maven.compiler.source></maven.compiler.source>
    </properties>

    <dependencies>
        <!-- Spring core & MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version></version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version></version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version></version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version></version>
            <type>jar</type>
            <scope>test</scope>
        </dependency>

        <!-- CGLib for @Configuration -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version></version>
            <scope>runtime</scope>
        </dependency>

        <!-- Servlet Specification -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.4</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- Tag Libraries -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- Logging -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
            <scope>runtime</scope>
        </dependency>

        <!-- JSR-330 for @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

        <!-- Commons Upload for File upload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.2</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>springsource-milestones</id>
            <name>SpringSource Milestones Proxy</name>
            <url>https://oss.sonatype.org/content/repositories/springsource-milestones</url>
        </repository>
    </repositories>

    <build>
        <finalName></finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source></source>
                    <target></target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port></port>
                    <contextReloadable>true</contextReloadable>
                </configuration>
                <executions>
                    <execution>
                        <id>start-tomcat</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <fork>true</fork>
                        </configuration>
                    </execution>
                    <execution>
                        <id>stop-tomcat</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>shutdown</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <executions>
                    <execution>
                        <id>perform-it</id>
                        <goals>
                            <goal>integration-test</goal>
                        </goals>
                        <configuration>
                            <systemProperties>
                                <property>
                                    <name>servlet.port</name>
                                    <value></value>
                                </property>
                                <property>
                                    <name>name</name>
                                    <value></value>
                                </property>
                            </systemProperties>
                        </configuration>
                    </execution>
                    <execution>
                        <id>verify-it</id>
                        <goals>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

At this point, the Spring Web MVC project can be built with Maven. To run a Maven build from within Eclipse Neon, right-click on the project and select Run As > Maven build.

Eclipse Neon - Project Context Menu - Run Maven Build

Enter the Maven build goals, here clean install and click on Run.

Eclipse Neon - Maven Launch Configuration - Run Clean Build

After a successful build, Maven will copy the generated WAR file into the local repository. The location is based on the group Id, artifact Id and version. The output from the Maven build is shown in the Eclipse console.

Eclipse Neon - View Maven Build Output in Console

Here, the WAR file SimpleSpringMVCProject-0.0.1-SNAPSHOT.war is located in the local repository at:

/Users/george/.m2/repository/com/pgx/web/spring/SimpleSpringMVCProject/0.0.1-SNAPSHOT

During the Maven build –after successful compilation– test cases are executed. This archetype includes one integration test case that validates a Servlet by making an HTTP request. The code of HelloIT.java is shown below.

package com.pgx.web.spring.SimpleSpringMVCProject.it;

import org.junit.*;
import java.io.*;
import java.net.*;
import org.apache.commons.io.IOUtils;

public class HelloIT{
  
  private static String port, name;
  
  @Before
  public void setup() {
    port = System.getProperty("servlet.port", "8080");
    name = System.getProperty("artifactId", "SimpleSpringMVCProject");
  }

  @Test
  public void hello() throws IOException {
    String testName = "testname";

    HttpURLConnection connection = 
        (HttpURLConnection)new URL("http://localhost:" + port  + '/' + 
            name +"/hello?name=" + testName).openConnection();

    connection.connect();
    Assert.assertEquals(200, connection.getResponseCode());
    
    try (InputStream in = connection.getInputStream()) {
      String output = IOUtils.toString(in);
      Assert.assertTrue("Name not found in page - source: \n" + output, 
          output.contains(testName));
    }
  }
}

If there are test case failures, the Maven Failsafe Plugin generates a report at target/failsafe-reports.

Maven Failsafe Plugin - View Integration Test Case Execution Reports

The text files in the list contain error information such as logs and stack traces for debugging test case failures.

3  Running the Spring Web MVC Project with Maven

For this example, Maven is used to deploy and run the WAR file on an embedded Tomcat 7 instance. The tomcat7-maven-plugin (see line 43 in pom.xml file) is part of the archetype definition and allows Maven to run web applications on Tomcat. See the plugin’s support page for more information.

In the Goals field, on the Maven launch configuration, enter tomcat7:run to use the plugin for running the generated WAR file:

Eclipse Neon - Maven Launch Configuration - Run WAR File on Embedded Tomcat 7 Servlet Container

Maven will start Tomcat 7 and deploy the generated WAR file. The Maven console will show that the embedded Tomcat 7 instance has been started. It also shows the Spring Web MVC view- and resource mappings.

Eclipse Neon - Run WAR File on Embedded Tomcat 7 Servlet Container - Console Output of Spring Web MVC Project Startup

In this example, the web application’s context path is the artifact Id which is SimpleSpringMVCProject. See line 10 in the pom.xml file. So, the URL for accessing the Hello World view from a web browser is:

http://localhost:8080/SimpleSpringMVCProject/hello

This mapping will use the home.jsp file located under WEB-INF/views to generate the below HTML page:

Eclipse Neon - Run WAR File on Embedded Tomcat 7 Servlet Container - Access Spring Web MVC Project Application from Browser

The home.jsp is part of the archetype definition. This file is located at WEB-INF/views of the Eclipse project.

<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<tags:template>
  <jsp:attribute name="head">  
    <script type="text/javascript">
      // inline JavaScript here 
    </script>
    </jsp:attribute>  
  <jsp:body>
    <h1>Hello <c:out value="${name}" /></h1>
    <p>This is just an example page.</p>
  </jsp:body>
</tags:template>

The JSP file uses a template that is based on the file template.tag which is located at WEB-INF/tags.

<?xml version="1.0" encoding="UTF-8" ?>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<jsp:directive.attribute name="head" required="false" fragment="true"/>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title> SimpleSpringMVCProject </title>

    <c:url value="/" var="baseUrl" />
    <c:set value="${fn:length(baseUrl)}" var="baseUrlLen" />
    <c:set var="baseUrl" value="${fn:substring(baseUrl, 0, baseUrlLen - 1)}"/>
    
    <link rel="stylesheet" type="text/css" media="all" 
             href="/resources/bootstrap/css/bootstrap.css"/>
    <link rel="stylesheet" type="text/css" media="all" 
             href="/resources/bootstrap/css/bootstrap-responsive.css"/>
    <link rel="stylesheet" type="text/css" media="all" href="/resources/style.css"/>
    <script type="text/javascript" src="/resources/project.js" ></script>
    <jsp:invoke fragment="head"/>
  </head>
  <body>
    <jsp:doBody />
  </body>
</html>

The view controller Java class HomeController is shown below. It is located in the com.pxg.web.spring package which was specified during the Maven project setup. It adds a String parameter called name to the model. If the parameter is not present in the query string of the request, it defaults to "World". See line 12 in the source code below.

package com.pgx.web.spring.SimpleSpringMVCProject.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HomeController {

  @RequestMapping(value="/hello")
  public ModelAndView hello(@RequestParam(required=false, defaultValue="World") String name) {
    ModelAndView ret = new ModelAndView("home");
    // Adds an object to be used in home.jsp
    ret.addObject("name", name);
    return ret;
  }
}

This example does not rely on XML configuration files for Spring MVC. It uses a Java class and annotations:

package com.pgx.web.spring.SimpleSpringMVCProject.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan(basePackages="com.pgx.web.spring.SimpleSpringMVCProject")
@EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{

  @Bean
  public ViewResolver getViewResolver(){
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
  }
  
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
  }

  @Bean
  public MultipartResolver multipartResolver(){
    return new CommonsMultipartResolver();
  }
}

Refer to the Spring Web MVC documentation for details on the annotations in this class and for XML configuration equivalents.

Leave a Reply