Debugging Maven Unit Test in Eclipse / STS

Maven unit tests (run by surefire plugin) can be debugged with eclipse. Firstly check you’re using surefire plugin version 2.16 or newer. Observe / add following in your pom.xml

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.16</version>
</plugin>

Ensure you’ve set some breakpoints to debug the faulty codes. Then on your run configuration, add -Dmaven.surefire.debug=true parameter:

maven-debug1

When this run configuration is executed, maven will wait for you to attach the remote debugger instead of launching the tests:

maven-debug2

Now open eclipse debug configuration, create a Remote Java Application config with your source code and set the port to 5005:

maven-debug3

When the debugger attaches the unit test will proceed and when any breakpoints hit you can debug it like a normal java/eclipse application

Advertisements

Java and XML Injectable Properties on Spring

Here’s how you can create a property file which can be injected on Java classes as well as on bean XML configuration file.

Firstly ensure annotation config is switched on:

<context:annotation-config/>

Create your properties file, in this case I create config.properties on my classpath root (src/main/resources/config.properties on Maven-compliant project)

name=Gerry

Register this property file on your spring context using <util:properties> tag. The file will be registered as a bean class with name config

<util:properties id="config" location="classpath:/config.properties"/>

Whenever you want to inject the value into a Java class, you can use @value annotation

@Component
public class Person {

  @Value("#{config.name}")
  private String name;

  //...
}

Similarly you can do the same to xml bean config file

<bean class="my.app.Person">
  <property name="name" value="#{config.name}"/>
</bean>

Note that if you config has dots on it, you need to use the square bracket syntax or Spring will confuse the dot as property access

@Value("#{config['first.name']}")
private String name;

Multiple Environment Trick

Another trick I love is specifying multiple environment config, eg: one for prod and dev. This is common when dealing with datasource properties:

dbhost=localhost
dbhost.dev=192.168.0.20

On dev environment, I then supply -Denv=dev system property to my VM args, and do this when looking up the property:

@Value("#{systemProperties['env'] == 'dev' ? config['dbhost.dev'] : config['dbhost']}")
private String databaseHost;

Putting String List on Properties

Property files can also hold simple string list:

emails=gerry@test.com,tom@wohoo.com

When injecting this, use the split() method. Becareful with whitespaces you placed as it will be carried over

@Value(#{config['emails'].split(',')})
List<String> emails;

Returning JSON View on Spring MVC

Another simple way to return JSON object is by using jackson-mapper-asl. Similar to how we can map server-bound post, this method can also be used to write response.

Firstly, on your Spring MVC enabled project, add following maven dependency:

<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-mapper-asl</artifactId>
  <version>1.9.12</version>
</dependency>

Spring can automatically convert your POJO into a json string. So say we have this data object we want to return:

public class Customer {
  private String name = "";
  private String email = "";
  // getters & setters...
}

And this is the controller request mapping method. Important bits here is the method returns a POJO object directly, and it is annotated with @ResponseBody annotation.

@RequestMapping("/customer/{id}")
@ResponseBody
public Customer getCustomer(@PathVariable("id") long id) {
  Customer customer = // Search customer by given id through repository..
  return customer;
}

On the client side the returned JSON will be something like this:

{
  name = "Tom",
  email = "tom@someprovider.com"
}

Injecting Properties to Spring MVC JSP View

Spring MVC internationalization (i18n) message support can be used for a simple config / property file. Add following bean definition on your container xml config file:

<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" 
  id="messageSource"
  p:basenames="WEB-INF/i18n/site"
  p:fallbackToSystemLocale="false"/>

The bean above will read properties key-value pairs from WEB-INF/i18n/site.properties. Make sure you create this file with standard java-style properties:

site.name=Cool\ Bananas

Then in your JSP views, without any further intervention you can inject the values. Use spring message tag to achieve this

<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<html>
  <head>
    <title><spring:message code="site.name"/></title>
  </head>
  <body>
  </body>
</html>

Binding a List Request Parameter on Spring MVC

Here’s another handy stuff I found on Spring MVC, if you have an unknown number of elements on your form (say a fruit basket), you can bind them into a List with @RequestParam annotation.

Let’s say this is our form:
spring-bind-list

Each text input has the same name fruits:

<form method="post">
  Fruit 1: <input type="text" name="fruits"/><br/>
  Fruit 2: <input type="text" name="fruits"/><br/>
  Fruit 3: <input type="text" name="fruits"/><br/>
  <input type="submit"/>
</form>

On your controller’s handler method, you can obtain the list of all fruit names by binding it like this:

@RequestMapping(value = "/", method = RequestMethod.POST)
public String addFruits(@RequestParam("fruits") List<String> fruits) {
  // ...
}

The order of fruit names added to the list will be the same as the order of your form text inputs.

Spring Basic Concept: Inversion of Control and Dependency Injection

If you’re a newbie just starting to learn Spring, or even if you’ve heard a lot about Spring but not sure what it was, Martin Fowler has an excellent article about this: Inversion of Control and Dependency Injection pattern.

It was a bit old (written in 2004) but every single conceptual discussion still applies today.

If any of the following keyword doesn’t make any sense to you, then I beg you spare 20 minutes of your time to read this excellent article:

  • Inversion of Control
  • Dependency Injection
  • Service Locator

Posting JSON to Spring MVC Controller

Spring MVC can be setup to automatically bind incoming JSON string into a Java object. Firstly, ensure you have jackson-mapper-asl included on the classpath:

<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-mapper-asl</artifactId>
  <version>1.9.13</version>
</dependency>

Assuming the JSON string we want to bind represent a person object like this:

{
  name: "Gerry",
  age: 20,
  city: "Sydney"
}

Which will be bound into following Java class:

public class Person {
  private String name;
  private int age;
  private String city;
  // getters & setters ...
}

Declare the Spring MVC controller handler method like below. The handler method is mapped into path “addPerson” with method POST.

@RequestMapping(value = "/addPerson", method = RequestMethod.POST, headers = {"Content-type=application/json"})
public String addPerson(@RequestBody Person person) {
  logger.debug(person.toString());
  return "person";
}

Below is an example jQuery based javascript handler that posts into the above Spring MVC handler.

$.ajax({
  type: "POST",
  url: "addPerson",
  data: JSON.stringify({ name: "Gerry", age: 20, city: "Sydney" }),
  contentType: 'application/json',
  success: function(html) {
    alert(html);
  }
});