Why doesn’t Maven execute my unit tests?

If you have been using Maven for some time, you might have noticed that Maven will automatically find and execute your unit tests when they are present in your project, even without any additional configuration.

This is because it is using the Surefire Plugin with a default configuration (that can be overridden of course). However, for this to execute your tests, you need to place your test classes in the proper place and you need to name them appropriately.

Location of test classes

Your test classes need to be placed under the src/test/java folder, otherwise it won’t be picked up.

Naming of test classes

By default, the Surefire Plugin will automatically include all test classes that where the name matches one of the following patterns:

  • Test*.java
  • *Test.java
  • *TestCase.java

Example

We have the following test classes:

And the result is:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.jtuts.MyTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.039 sec
Running com.jtuts.MyTestCase
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec
Running com.jtuts.TestMyCode
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.jtuts.TestsForMyCode
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

You can see that 3 of the above classes are skipped, because they do not match the naming convention.

How to set up remote debugging in IntelliJ IDEA for a Java web application that is run by Tomcat Maven plugin

In this tutorial I show you a quick and easy way to debug your Java web application that is run by the Tomcat Maven plugin. There are just two short steps to this. Let’s see them.

Set up debugging options for Maven

You have to supply the required properties to Maven, so IDEA can connect to you app white it is running. This can be done by setting the MAVEN_OPTS environment property to

-Xdebug -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=n -Xmx4g -Xms4g -XX:MaxPermSize=1g

Be sure to keep it in one line, I just broke it to two lines for readability.

Note here, the value 4000. This is the port that we are using for remove debugging. When you start your app with the Maven Tomcat plugin, you should see something like this, that means, the app is listening for remote debugging connections:

...
Listening for transport dt_socket at address: 4000
...

Configuring remote debugging in IDEA

For this you have to add a new Debug configuration that can be done by selecting the Run -> Edit configurations menu item. Here click the plus sign, to add a new configuration and select Remote.

The new Remote debugging configuration is immediately created. You can give it a name, and set the port to 4000. Here is an image about how I set it up:

remote-debugging-idea

 

After you configured it, click OK, select the created configuration and start debugging with the green button that resembles a bug.

remote-debugging-idea2

You are all set. You can add breakpoints and debug your running app remotely.

What’s with the -Xnoagent -Djava.compiler=NONE options?

You may see that in some places the remote debugging configuration contains the

-Xnoagent -Djava.compiler=NONE

options as well. These options were only required for very old JVMs so you can forget about them now.

 

How to list the effective settings of Maven

When you are using Maven, sometimes you need custom configuration in your Maven settings.xml file. However, if you are using multiple versions of Maven, or there are multiple settings.xml files existing at the same time, it can be hard to track down which settings file is actually used.

To help with this issue, there is the following command:

mvn help:effective-settings

It results in an XML displayed on the console. That XML contains the settings that are used by Maven.

 

Tomcat Maven plugin does not use the configured context path

When you use the Tomcat Maven Plugin to deploy your application, you can specify the context path under which you want your application to be accessible. An example of the configuration of this plugin looks like this:

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <path>/jtuts</path>
    </configuration>
</plugin>

This way you application will be accessible under the /jtuts path. Depending on you port setting it can be for example localhost:8080/jtuts.

Sometimes you can run into an issue where no matter what you configure in the <path> element, you always end up with a context path that is equal to your artifactId. For example:

http://localhost:8080/using-spring-type-conversion-20140208

In my case the problem was the way I referenced the tomcat plugin in my mvn command. To use the Tomcat 7 plugin that you configured in your pom.xml (like I showed you above) you have to use the plugin name “tomcat7“. So you would build and deploy you app for example with the following Maven command:

mvn clean install tomcat7:run

This starts an embedded Tomcat using the plugin you have configured and uses the context path you have set.

The problem comes when you accidentally leave out the “7” at the end of the plugin name. If you deploy you app using:

mvn clean install tomcat:run

Maven will see that there are no plugins configured that has the name “tomcat“, but the build won’t fail because Maven has some conventions for finding plugins that you have not declared in your POM. In this case maven will find the org.codehaus.mojo:tomcat-maven-plugin and use it with default configuration. The default configuration means that the context path will be equal to the artifactId.

If you would like to read more about how Maven finds plugins that you have not configured, read the accepted answer in this Stackoverflow question.

So to sum it up, if you misspell the plugin name and use “tomcat” instead of “tomcat7“, Maven will not use the plugin that you configured, but another one with a default configuration. This could be the reason why your context path setting is not taken into account.

Of course, there can be other reasons for this kind of issue, but I have ran into this a couple of times and this was the solution for me.

 

Creating a Spring MVC Maven web application from scratch

This tutorial describes how to create a simple Spring MVC web application statring from a basic Maven project. We set up the required directories and files by hand, almost nothing will be pre-generated.

Tools I used for this tutorial:

Creating the Maven project

  1. In STS press Ctrl + N, this brings up the New wizard where you select what kind of project or file you would like to create. In the search box enter maven. From the filtered list select Maven Project.
  2. Click Next.
  3. Check the Create a simple project (skip archetype selection) checkbox.
  4. Click Next.
  5. Set the following properties:
    • Group Id: com.jtuts
    • Artifact Id: spring-mvc-maven-webapp-from-scratch
    • Packaging: war
    • Name: spring-mvc-maven-webapp-from-scratch
  6. Click Finish.

Of course the Group Id, Artifact Id and Name properties can be set to anything else, these are just example values. However the war value for the Packaging is mandatory, because we are creating a web application and the server which will run it (in our case Tomcat) expects a .war file.

The directory structure

STS will automatically create the basic directory structure for our application. This conforms to the basic structure that Maven expects. You can find more information about it on Maven’s Introduction to the Standard Directory Layout page.

The most important directories for us are:

  • src/main/java: Java source files.
  • src/main/resources: Other resources like property files and xml files.
  • src/main/webapp: Web application source files (e.g. JPSs, images, CSS files).
  • src/test/java: Test source files.
  • src/test/resources: Resources for tests.

By default, Maven expects you to have the above mentioned files in these directories. You can change this in Maven’s pom.xml but you should avoid it not to create confusion when other developers look at your project.

The pom.xml

The pom.xml file is added automatically by STS when you create the Maven project. However, we made some additions that are needed for our webapp to work. This is what the final pom.xml looks like:

<?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.jtuts</groupId>
    <artifactId>spring-mvc-maven-webapp-from-scratch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>spring-mvc-maven-webapp-from-scratch</name>

    <properties>
        <spring.version>4.1.0.RELEASE</spring.version>
        <servlet.api.version>3.0.1</servlet.api.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.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>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.api.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>spring-mvc-maven-webapp-from-scratch</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/${project.build.finalName}</path>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

In this file we include all the dependencies that are required by our example project. We also have a tag which configures the build process of Maven.

The finalName will be the name of the .war file that is created.

Then, we have two plugins:

  1. The tomcat7-maven-plugin can be used to enable Maven to start an embedded Tomcat server and run our app inside it. It also specifies that the context path under which our app will be available (in this case we use the value of the finalName): /spring-mvc-maven-webapp-from-scratch.
  2. With the maven-compiler-plugin we configure the compilation process of Maven. In this case we set that our source code must be compatible with at least Java 1.7, and we want our compiled program to be executable with Java 1.7 and above.

Creating the web.xml file

The web.xml file must be placed in the /src/main/webapp/WEB-INF/ folder is the Web Application Deployment Descriptor of your application. So you have to create the WEB-INF directory in the /src/main/webapp/ directory and inside it create a file named web.xml. This file is an XML document that defines everything about your application that a server needs to know: servlets and other components like filters or listeners, initialization parameters, container-managed security constraints, resources, welcome pages, etc.

The full path for this file is: /src/main/webapp/WEB-INF/web.xml

In this project we will use the following web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">

    <display-name>Spring MVC application from scratch</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
        </init-param>
        <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>
            classpath:spring/application-context.xml
        </param-value>
    </context-param>

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

</web-app>

The <web-app> element

This is the root element of you web.xml file.

The attributes inside the <web-app> tag mean that the file uses the 3.0 version of the Servlet Specification.

Defining the DispatcherServlet

The job of the DispatcherServlet is to take an incoming URI and find the right combination of handlers (generally methods on Controller classes) and views (generally JSPs) that combine to form the page or resource that’s supposed to be found at that location.

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Let’s see the definition of the servlet step by step.

<servlet-name>mvc-dispatcher</servlet-name>

Defines the name by which we can reference the servlet.

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

The class that contains the servlet’s code.

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
</init-param>

The contextConfigLocation parameter tells the DispatcherServlet which xml to use for setting up the WebApplicationContext. This will be a child to the root WebApplicationContext defined by ContextLoaderListener and can access every bean in it.

<load-on-startup>1</load-on-startup>

For load-on-startup a value of >=0 means that the servlet is loaded when the web-app is deployed or when the server starts. A value < 0 means that the servlet is loaded whenever the container feels like. Also, the container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-startup value.

The ContextLoaderListener

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath:spring/application-context.xml
    </param-value>
</context-param>

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

The ContextLoaderListener creates the root WebApplicationContext for your application. This application context contains all the beans defined in the xml specified as the value of the contextConfigLocation parameter. Also, the beans from this context are available in any child contexts (such as the one we created with the DispatcherServlet).

The dispatcher-servlet.xml file

Create a file named dispatcher-servlet.xml in the src/main/resources/spring directory. It could be anywhere else, but it is good practice to group spring context xml files in a common directory.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">

    <context:component-scan base-package="com.jtuts.spring.mvc.webapp.controller" />
    <mvc:annotation-driven />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

</beans>

This first line tells spring to go over the classes in the com.jtuts.spring.mvc.webapp.controller package and register them as spring beans if they have the appropriate annotation. In our case we have only one such class which is a controller and this is signified by putting a @Controller annotation on the class.

The <mvc:annotation-driven> tag enables a couple of spring features like mapping requests to controllers, validating form data with the @Valid annotation, using the ConversionService and so on.

The viewResolver bean will handle the resolving of our views (in this case jsp files). The prefix property’s value will be prepended to the name of every view we request and the suffix property’s value will be appended to the requested view name. So, for example if we request the view “home” then the viewResolver will modify this to /WEB-INF/views/home.jsp. This bean enables Spring to find our views, and also lets us write shorter view names because we can omit the common parts from path.

The application-context.xml file

Create file named application-context.xml  in the src/main/resources/spring directory. It should contain the following:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">

</beans>

For this basic application this file does not define or configure anything, but when extending our application with additional functionality we can define the beans for our root application context here in the same manner we did in the dispatcher-servlet.xml. So this file currently is just an empty placeholder for future bean definitions and configuration.

The controller

We need a controller to provide a response when the user requests a specific URL. Create a class called HomeController in the com.jtuts.spring.mvc.webapp.controller package, and put the following code in it:

package com.jtuts.spring.mvc.webapp.controller;

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

@Controller
public class HomeController {

    @RequestMapping("home")
    public ModelAndView home2() {
        return new ModelAndView("home");
    }
}

In Spring MVC each controller is a class ann otated with the @Controller annotation. These classes handle incoming requests. A controller can handle multiple requests with multiple methods. The @RequestMapping annotation means that in case of which request urls should spring invoke this method. The method returns a ModelAndView object which contains the view we would like to display and also the model (the data to be displayed in the view). In this case we use the

public ModelAndView(String viewName)

constructor of the ModelAndView class which expects the name of the view to be displayed. Additional model parameters are not retured in this simple example.

The view (jsp) file

We also need a simple jsp file in the project which we will show to the user if they request /home. In this example the full URL, where this page is available is: http://localhost:8080/spring-mvc-maven-webapp-from-scratch/home

Create a views directory in the WEB-INF folder, and inside it create a home.jsp file with the following content:

<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Spring MVC web application from scratch</title>
</head>
<body>
    <h1>Welcome to the home page.</h1>
</body>
</html>

The concrete file will be found by the viewResolver bean we defined earlier. It uses the prefix, the view name we returned from the controller, and the suffix. These concatenated will form the correct path to the home.jsp file.

Starting the web application

In the command line navigate to the root directory of the application and execute the command mvn clean install tomcat7:run. This compiles the project, packages into a .war file, starts an embedded tomcat server and deploys the war file in it.

After the process is completed we can access the app at http://localhost:8080/spring-mvc-maven-webapp-from-scratch/home

Download

You can download the complete source files for this project here.