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.

Cross Site Request Forgery (CSRF) Protection in Spring 3.1

Eyal Lupu has written an excellent article in his blog about mitigating Cross Site Request Forgery (CSRF) attack.

CSRF allows an attacker to create a fake form / link posting to a secured website. It exploits the fact you might have an active session from a secured website. For example, an attacker can create a fake form / link with all the data required to transfer money to his / her account without you realizing it.

This CSRF prevention techniques involes two components:

  1. Rendering a hidden form field with randomly generated token stored in session
  2. Ensuring the next post request came with matching token

The sample source code of this solution can be obtained from:

git clone https://github.com/eyal-lupu/eyallupu-blog.git

Spring MVC File Upload Form

Objective : Setup a form with file upload field

Environment

  • Spring MVC 3.2.3.RELEASE
  • Commons Fileupload 1.3

First let’s code the JSP view of the form. Note below enctype=”multipart/form-data” setting is important, it tells the browser to post the form data as multipart.

<form method="post" enctype="multipart/form-data">
  File: <input type="file" name="myfile"/><br/>
  <button type="submit">Upload</button>
</form>

Above JSP will result in a simple file upload form like this:

fileuploadform

Then add commons-fileupload 1.3 maven dependency to your pom.xml:

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3</version>
</dependency>

And configure CommonsMultipartResolver on your spring context. The bean id name is important. Also below I configured it to have maximum file size of 1 mb (1000000 bytes)

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <property name="maxUploadSize" value="1000000"/>
</bean>

Now we’re ready to code the controller handler method. The uploaded file is automatically bound into a MultiPart object from which you can obtain input stream.

@RequestMapping(value = "/", method = RequestMethod.POST)
public String upload(@RequestParam("myfile") MultipartFile myFile) {
  logger.info("Received file of size " + myFile.getSize() + " bytes");
  InputStream inputStream = myFile.getInputStream();
  // .. do something with inputStream
  inputStream.close();
  return "home";
}

Hibernate One To Many Relationship

Continuing from my post Spring MVC + Hibernate + MySQL Quick Start From Scratch, here is how to setup one to many relationship on Hibernate.

Let’s assume you want to add a new table called topping, each pizza can have several toppings (one to many relationship).

Pizza table
pizzatable

Topping table
topping table

First code the Topping entity class:

@Entity
@Table(name = "topping")
public class Topping {
  @Id
  @GeneratedValue
  private long id;
  
  private String name;
  
  @ManyToOne
  @JoinColumn(name = "pizza_id", referencedColumnName = "id")
  private Pizza pizza;

  // getters & setters..
}

Notice the usage of @ManyToOne and @JoinColumn annotation. This allows the owning Pizza to be queried from the Topping. This also says “in order to find pizza that owns this topping, have a look at pizza_id column on topping table, match it with id column on pizza table”

And let’s have a look at our modified Pizza entity class:

@Entity
@Table(name = "pizza")
public class Pizza {
  @Id @GeneratedValue private long id;
  private String name;
  private double price;
  
  @OneToMany(mappedBy = "pizza", fetch = FetchType.LAZY)
  private List<Topping> toppings;

  // getters & setters
}

This setups a bi-directional relationship where you can obtain list of toppings from a Pizza object, and the owning Pizza from a Topping object.

The FetchType.LAZY setting tells Hibernate not to bother populating the toppings unless we ask it to (this is handy to conserve memory if you have a long chains of relationships with thousands of objects on it).

Next if I want to list my pizzas with its topping, I can write following method on my DAO class:

@Transactional
public List<Pizza> findAllWithToppings() {
  Session session = sessionFactory.getCurrentSession();
  List pizzas = session.createQuery("select distinct p from Pizza as p left join fetch p.toppings").list();
  return pizzas;
}

The above hibernate query will roughly translate into following SQL:

select * from pizza p left outer join topping t on p.id = t.pizza_id;

Download the source code

git clone https://gerrytan@bitbucket.org/gerrytan/pizzashop.git -b one_to_many

Installing Spring Security On Spring MVC Project

These are steps required to install Spring Security for a form authentication implementation on a Spring MVC project.

  1. Maven Dependencies.

    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-core</artifactId>
    	<version>3.1.4.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-config</artifactId>
    	<version>3.1.4.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-web</artifactId>
    	<version>3.1.4.RELEASE</version>
    </dependency>
    
  2. Add Spring Security filter to web.xml
    <!-- Spring Security Filter -->
    <filter>
    	<filter-name>springSecurityFilterChain</filter-name>
    	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    
    <filter-mapping>
    	<filter-name>springSecurityFilterChain</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    
  3. Add a security-context.xml spring beans config file. You can place all your security config on root application context xml but separating it would produce clearer code without namespace prefix clutter
    <!-- On root-context.xml -->
    <import resource="security-context.xml"/>
    
    <!-- On security-context.xml" -->
    <beans:beans xmlns="http://www.springframework.org/schema/security"
    	xmlns:beans="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    </beans:beans>
    
  4. Add basic HTTP form authentication and provider as seen on Spring reference manual
    <http auto-config='true'>
    	<intercept-url pattern="/**" access="ROLE_USER" />
    </http>
    
    <authentication-manager>
    	<authentication-provider>
    	  <user-service>
    	    <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
    	    <user name="bob" password="bobspassword" authorities="ROLE_USER" />
    	  </user-service>
    	</authentication-provider>
    </authentication-manager>