Web services with JAX-WS, JAXB and Spring

I’ve recently been working a lot with Java web services, most of these were greenfield projects where we were able to choose the architecture. I decided to use JAX-WS to create the web services but was unsure initially of the best way to go about this. In general there are two approaches to writing web services (contract first or code first).

Contract first
Contract first requires a wsdl to be written first and then JAX-WS can be used to generate matching code. This approach has its place if you already have a wsdl but they’re not the easiest of things to work with and maintenance quickly becomes messy.

Code first
Code first is much easier as you simply write the code using a handful of basic annotations and let JAX-WS generate the wsdl for you at run time. The downside to this approach is that you have to write the code before you have a wsdl or schema available. This may not be an issue but if you need to write a specification first then it’s handy to have some kind of schema to define how the inputs and outputs are going to look.

Also, in some cases you may be able to express more in a schema than you can with just Java code. For instance you might want to set a restriction in the schema (like a string max length), or perhaps you want a particular nested structure of elements. You could do this yourself with JAXB annotations but it’s easier to write a schema and generate the required classes.

Combined approach using JAXB
I asked this as a question on stackoverflow and one of the answers provided inspiration for a kind of best of both worlds approach. This has now been implemented for several different projects and overall it’s been a pleasure to work with. The basic idea is that development follow something like the following process.

  1. Write a basic schema that defines the request and response types (this can be included in specifications and is easier to maintain than a full wsdl)
  2. Use JAXB/XJC to generate the request and response types
  3. Write a JAX-WS endpoint using the generated types as inputs and outputs
  4. Let JAX-WS generate the full wsdl at runtime

Spring integration
In addition to this I wanted to use spring for managing services, dependency injection and loading properties files. This requires setting up JAX-WS slightly differently so that spring can load the endpoints and inject dependencies. If you don’t do this then you’ll end up with a JAX-WS version of the endpoint with none of its dependencies injected while spring will have its own instance complete with injected dependencies but not handling any requests.

Maven build and dependencies
I’m using maven to manage the build and dependencies. You don’t have to use maven but it really does make life much easier. These are the required dependencies you’ll need in your pom.xml file.

		<!-- JAXWS web services -->
      	<dependency>
        	<groupId>com.sun.xml.ws</groupId>
        	<artifactId>jaxws-rt</artifactId>
        	<version>2.2.7</version>
      	</dependency>

      	<!-- Spring DI -->
        <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.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <!-- JAX-WS/Spring integration -->
      	<dependency>
			<groupId>org.jvnet.jax-ws-commons.spring</groupId>
			<artifactId>jaxws-spring</artifactId>
			<version>1.8</version>
            <exclusions>
         	  <exclusion>
            	<groupId>org.springframework</groupId>
            	<artifactId>spring</artifactId>
         	  </exclusion>
        	</exclusions>
		</dependency>

In the build section of the pom you’ll also need to configure the JAXB plugin to auto-generate code from your schemas. The way it’s setup here it will look for any schema in the directory /src/main/resources/xsd and then generate code and put it in a source folder called /target/generated-sources/src/main/java. If you’re using eclipse you’ll want to right click this folder and take the option Build path > Use as source folder. If you don’t do this you’ll still be able to run a build using maven but you’ll probably see compile errors in eclipse.

  <build>
        <plugins>
            <!-- Generate JAXB Java source files from an XSD file -->
            <plugin>
            	<groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!-- Don't set package name here as we want different packages for each schema.
                         Instead we set in each schema separately. -->
                    <!-- <packageName></packageName>  -->
                    <outputDirectory>${basedir}/target/generated-sources/src/main/java</outputDirectory>
                    <schemaDirectory>${basedir}/src/main/resources/xsd</schemaDirectory>
                </configuration>
            </plugin>
        </plugins>
  </build>

Web app config files
Next we need to add some configuration files to setup our web application. First is the web.xml deployment descriptor. Here we define the standard spring listener to load our spring configuration and we also setup a servlet to listen for our web service requests. Rather than use the JAX-WS servlet we’ve used a spring wrapper which will later allow us to use dependency injection in our endpoint classes.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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">

  <display-name>TestServices</display-name>

  <!-- Load spring configuration -->
  <context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/application-context.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- Servlet to handle all jax-ws requests -->
  <servlet>
    <servlet-name>jaxws-servlet</servlet-name>
    <servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>jaxws-servlet</servlet-name>
    <url-pattern>/service/*</url-pattern>
  </servlet-mapping>

  <!-- There didn't ought to be any sessions created but it's good practice to define a
  timeout as it varies for different containers. -->
  <session-config>
    <session-timeout>40</session-timeout>
  </session-config>

</web-app>

The spring config is minimal in this basic example. It’s just turning on classpath scanning for the package in our test project and enabling auto-wiring of scanned dependencies. We also need to setup which urls map to which endpoint classes but this has been moved to a separate file which we import at the bottom.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-3.2.xsd

       " >

    <context:component-scan base-package="com.testservices"/>
    <context:annotation-config/>

 	<!-- Define the jaxws endpoint -->
 	<import resource="jaxws-context.xml"/>

</beans>

Usually with JAX-WS you need a config file called sun-jaxws.xml where you define which urls map to which endpoints. In this case we’re using a spring JAX-WS servlet so instead we add our mappings here. This simple mapping is saying all web service requests to /service/test1 will go to the spring bean with an ID of test1Services. We shall see this bean shortly.

<?xml version="1.0" encoding="UTF-8"?>
<beans 	xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:ws="http://jax-ws.dev.java.net/spring/core"
		xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
		xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd


http://jax-ws.dev.java.net/spring/core


http://jax-ws.dev.java.net/spring/core.xsd


http://jax-ws.dev.java.net/spring/servlet


http://jax-ws.dev.java.net/spring/servlet.xsd">

 	<!-- Define our jaxws endpoint (replaces sun-jaxws.xml) -->
    <wss:binding url="/service/test1">
        <wss:service>
            <ws:service bean="#test1Services" />
        </wss:service>
    </wss:binding>   

</beans>

Schema to define request/response types
In this simple example we could get away with one simple schema but in a real world example you’ll probably end up with many. The way I’ve been organizing this is to have a base shared schema which defines common types. For example you might want all requests to include a username, password and environment and maybe the response should always have a boolean element to indicate success. Then you can write a schema for each endpoint defining the request and response types for all operations on that wsdl.

Here is the example base schema shared.xsd.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema 	xmlns:xs="http://www.w3.org/2001/XMLSchema"
			xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
			jaxb:version="2.0"
			targetNamespace="http://shared.testservices.com/"
			xmlns:tns="http://shared.testservices.com/"
			elementFormDefault="qualified">

  <!-- Settings for the JAXB code generation -->
  <xs:annotation>
    <xs:appinfo>
      <!-- Set the package name for the generated classes -->
      <jaxb:schemaBindings>
        <jaxb:package name="com.testservices.generated.shared" />
      </jaxb:schemaBindings>
    </xs:appinfo>
  </xs:annotation>			

  <!-- Begin Types/Classes to be generated -->
  <xs:group name="baseRequest">
    <xs:sequence>
      <xs:element name="user" type="xs:string"/>
      <xs:element name="apikey" type="xs:string"/>
    </xs:sequence>
  </xs:group>    

  <xs:group name="baseResponse">
    <xs:sequence>
      <xs:element name="success" type="xs:boolean"/>
    </xs:sequence>
  </xs:group>   

</xs:schema>

This schema then imports the shared types and defines a simple request and response type for our example web service. Note that we can define which package the generated code belongs to by using the jaxb namespace extensions. There are a number of other customizations you can do like mapping xml types to Java types.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema 	xmlns:xs="http://www.w3.org/2001/XMLSchema"
			xmlns:sh="http://shared.testservices.com/"
			xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
			jaxb:version="2.0"
			targetNamespace="http://test1.testservices.com/"
			xmlns:tns="http://test1.testservices.com/"
			elementFormDefault="qualified">

  <!-- Settings for the JAXB code generation -->
  <xs:annotation>
    <xs:appinfo>
      <!-- Set the package name for the generated classes -->
      <jaxb:schemaBindings>
        <jaxb:package name="com.testservices.generated.test1" />
      </jaxb:schemaBindings>
    </xs:appinfo>
  </xs:annotation>

  <xs:import namespace="http://shared.testservices.com/" schemaLocation="shared.xsd" />

  <xs:complexType name="test1Request">
    <xs:sequence>
      <xs:group ref="sh:baseRequest"/>
      <xs:element name="id" type="xs:int" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="test1Response">
    <xs:sequence>
      <xs:group ref="sh:baseResponse"/>
      <xs:element name="field1" type="xs:string" />
      <xs:element name="field2" type="xs:string" />
    </xs:sequence>
  </xs:complexType>

</xs:schema>

Finally add the endpoint interface/class
Having saved those schemas there should now be a generated class called Test1Request and another called Test1Response. We’re now ready to start piecing things together. The final stage is to define the JAX-WS handler and add a web method that uses these classes as inputs and outputs.

@WebService
public interface Test1
{
	Test1Response test1(Test1Request request);
}

So we have a very simple interface which we annotate with the JAX-WS @WebService annotation. There is one method which uses our generated classes. When this code is deployed JAX-WS will do the legwork and generate the WSDL with this one method on it. We just need to implement this interface now.

@Component("test1Services")
@WebService(endpointInterface = "com.testservices.endpoint.Test1")
public class Test1Impl implements Test1
{

	ObjectFactory	fact	= new ObjectFactory();

	@Override
	public Test1Response test1(Test1Request request)
	{
		System.out.println("User: " + request.getUser());
		System.out.println("ID: " + request.getId());

		Test1Response response = fact.createTest1Response();

		response.setSuccess(true);
		response.setField1("Value 1");
		response.setField2("Value 2");

		return response;
	}

}

The implementation uses the JAXB object factory, which was generated for us, to create a response object. We then hardcode some values just to see if it works. In practice you’ll be able to inject a spring service here and go off and do whatever business logic is required. The class has been annotated as a spring component called test1Services. It’s important that this matches the bean name given in the spring config file for JAX-WS. The @WebService annotation names the interface that we’ve implemented.

You should now be able to fire up your test server and see this running. If you go to http://localhost:PORT/ProjectName/service/test1 you should see a page confirming the web service has been deployed with a link to the wsdl (just append ?wsdl).

, , , ,

Leave a comment

Calling RPG on the AS400 from Java

RPG is the native language on the IBM as400 midrange server (aka iSeries, system i and now just “i”). In a recent project I had to find a way to call a number of RPG programs from a Java application. If you’re in this situation then there are a few options available.

  • PCML (the subject of this article)
  • SQL Stored procedure
  • Integrated web services server (IWS)

Stored procedure
One possibility is to write a SQL stored procedure using RPG which could be called from Java using JDBC. This option may not be viable depending on the parameters your program needs. A stored procedure is good for returning result sets of records but you can only return one and you can’t pass one in.

Integrated web services server (IWS)
If you want to quickly expose an RPG program as a web service then you might want to look at IWS. This is a quick way to get up and running but there are a number of limitations.

  • If you want multiple operations on the same wsdl you have to write them all as procedures in the same service program
  • If using a service program IWS only supports up to 7 parameters including both inputs and outputs
  • IWS only supports contract last development. In other words you have to write the code first to get the wsdl.
  • The generated wsdl has a number of duplicated elements which you have to manually remove to tidy the appearance.
  • If you change the parameters or operations you have to go through the whole wizard again on each machine you deploy to.
  • Arrays are fixed size in RPG so IWS always returns all elements, even if some are simply blanks.

PCML
The most flexible method is Program Call Markup Language (PCML). This is an API that IBM provided for just this scenario. PCML is an XML language for defining the parameter list for an RPG program. This can then be used from a Java application.

Generating the PCML
You could write the pcml file by hand but a better way is to get the RPG compiler to generate it for you. First lets write a simple RPG program that we want to call.

D CONVTEMP        PR                  Extpgm('CONVTEMP') 
D  iCelsius                      9  3 Const                   
D  oFahrenheit                   9  3                    
D CONVTEMP        PI                                     
D  iCelsius                      9  3 Const                   
D  oFahrenheit                   9  3                    
 /free                                                   
   // We could get an API to return whatever we like here
   oFahrenheit = ((iCelsius * 9) / 5) + 32;              
   Return;                                               
 /end-free                                               

Yes it’s the cliche web service example to convert temperature from Celsius into Fahrenheit. It’s a good one to start with though because it is has both an input and an output but is still fairly simple. Note that the input parameter has been defined as a const, this is significant when we generate the PCML.

To generate the PCML from here you need to prompt compile and set the following options. Set PGMINFO to *PCML and INFOSTMF to a path on the ifs where you want your generated file to go e.g. /mylib/CONVTEMP.pcml. Doing so gives the following PCML.

<pcml version="4.0">
   <program name="CONVTEMP" path="/QSYS.LIB/PCMLTEST.LIB/CONVTEMP.PGM">
      <data name="ICELSIUS" type="packed" length="9" precision="3" usage="input" />
      <data name="OFAHRENHEIT" type="packed" length="9" precision="3" usage="inputoutput" />
   </program>
</pcml>                                              

We now have an XML file that describes how to call this program. Notice that the iCelsius parameter has been set to input but oFahrenheit is inputoutput. This is a result of setting iCelsius to a const parameter. When making a PCML call you must set a value for all input parameters. The default is inputoutput which can go both ways but is inconvenient if you don’t have an input value to set. Unfortunately there’s no language feature in RPG to set a parameter to output only so you have to adjust these manually.

      <data name="OFAHRENHEIT" type="packed" length="9" precision="3" usage="output" />                                            

Java dependencies
To make a PCML program call you just need the jt400 jar on your classpath. You can either use the IBM version that comes bundled with the AS400 or the open source JTOpen version.

If you use maven then you can simply declare it as a dependency like this.

<dependency>
   	<groupId>net.sf.jt400</groupId>
	<artifactId>jt400</artifactId>
	<version>6.7</version>
</dependency>                                       

This works fine but sadly the JTOpen developers stopped publishing to maven central at version 6.7 (current version is 7.10 at time of writing).

Calling the program
This is everything you need to make the program call. The Java class below is a simple test that opens a connection, calls the program and returns the result.

import java.math.BigDecimal;

import com.ibm.as400.access.AS400;
import com.ibm.as400.data.PcmlException;
import com.ibm.as400.data.ProgramCallDocument;

public class ConvertTemperature
{

	private AS400	as400;

	public ConvertTemperature()
	{
		as400 = new AS400("SYSTEM", "USERNAME", "PASSWORD");
	}

	public BigDecimal celsiusToFahrenheit(BigDecimal celsius)
	{
		BigDecimal fahrenheit = null;

		try
		{
			ProgramCallDocument pcml = new ProgramCallDocument(as400, "CONVTEMP");

			pcml.setValue("CONVTEMP.ICELSIUS", celsius);
			boolean rc = pcml.callProgram("CONVTEMP");
			if(rc)
			{
				fahrenheit = (BigDecimal) pcml.getValue("CONVTEMP.OFAHRENHEIT");
			}
		}
		catch(PcmlException e)
		{
			e.printStackTrace();
		}

		return fahrenheit;
	}

	public static void main(String[] args)
	{
		ConvertTemperature ct = new ConvertTemperature();
		ct.celsiusToFahrenheit(new BigDecimal(25.2));
	}

}

The second parameter to the ProgramCallDocument constructor is the path on the classpath to the PCML xml document. I created a file called CONVTEMP.pcml and put it in the src/main/resources folder. To keep things simple this is the root classpath folder, the .pcml suffix is not required as it is implied.

The PCML API will automatically handle converting Java types to AS400 types and back again. In this example the packed decimal from the AS400 becomes a BigDecimal in Java.

This is obviously a basic example that works as a proof of concept but there are a few additions worth mentioning if you want to use this in a production environment.

Adding connection pooling
Each time you create an AS400 object you’re opening a physical connection to the AS400. Each new connection creates a new job on the AS400. It’s obviously a bit wasteful to then throw this away and start with a fresh connection on the next call. A much better solution is to create a connection pool.

First you need to create the connection pool object. This code should live in it’s own class so the pool can be shared by different parts of the application. You could also load a properties file from the classpath to set the connection pool properties.

AS400ConnectionPool pool = new AS400ConnectionPool();

Now each time you want a connection you simply ask the pool. If no connections exist then one will be created.

AS400 as400 = pool.getConnection("SYSTEM", "USERNAME", "PASSWORD");

Remember to always return the connection back to the pool once you’re finished with it. This should be done in the finally section of the try/catch block to ensure the connection is returned if an exception is thrown.

pool.returnConnectionToPool(as400);

Setting a library list
The PCML file generated had a fixed path to a specific library. In practice you may find the program exists in different libraries and you want to use the one at the top of the library list. To do this we must first change the PCML file to not hardcode the library.

Change this:

<program name="CONVTEMP" path="/QSYS.LIB/PCMLTEST.LIB/CONVTEMP.PGM">

To this:

<program name="CONVTEMP" path="/QSYS.LIB/%LIBL%.LIB/CONVTEMP.PGM">

Next we need an event listener that will set the library list when a new connection is opened.

import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400Message;
import com.ibm.as400.access.CommandCall;
import com.ibm.as400.access.ConnectionListener;
import com.ibm.as400.access.ConnectionPoolEvent;
import com.ibm.as400.access.ConnectionPoolListener;

public class AS400ConnectionPoolListener implements ConnectionPoolListener
{
    @Override
    public void connectionCreated(ConnectionPoolEvent event)
	{
		AS400 as400 = (AS400) event.getSource();
		CommandCall command = new CommandCall(as400);
		try
		{
            String liblCommand = "CHGLIBL(QTEMP PCMLTEST QGPL)";
			if(command.run(liblCommand) != true)
			{
				// Show the messages (returned whether or not there was an
				// error.)
				AS400Message[] messagelist = command.getMessageList();
				for(int count = 0; count < messagelist.length; count++)
				{
					// Show each message.
					System.out.println("System message: " + messagelist[count].getText());
				}
			}
        }

	@Override
	public void connectionExpired(ConnectionPoolEvent event)
	{
		// Not currently overriden
	}

	@Override
	public void connectionPoolClosed(ConnectionPoolEvent event)
	{
		// Not currently overriden
	}

	@Override
	public void connectionReleased(ConnectionPoolEvent event)
	{
		// Not currently overriden
	}

	@Override
	public void connectionReturned(ConnectionPoolEvent event)
	{
		// Not currently overriden
	}

	@Override
	public void maintenanceThreadRun(ConnectionPoolEvent event)
	{
		// Not currently overriden
	}
}

Finally the event listener needs to be registered as an observer of the connection pool.

pool.addConnectionPoolListener(new AS400ConnectionPoolListener());

Summary
This is a basic example that shows how to call an RPG program from Java. To brush this up a bit for production you only really need a few classes to wrap the connection pool and loading of properties. This would allow you to set the library list on different servers with a simple properties file. I would use spring to load the properties and register a bean that holds the connection pool. If you have to support multiple environments then you could set the library list each time you get a connection. Alternatively it might be more efficient to pass the environment to the RPG program and handle it on the AS400.

, , ,

Leave a comment

A first knockout custom binding to display twitter bootstrap alerts

Just had a go at my first knockout custom binding. I wanted to be able to bind an observableArray to a div and for that div to display as a twitter bootstrap alert with each array item on a separate line.

If you want to get TB working with knockout quickly then you may want to check out this library.

http://billpull.github.io/knockout-bootstrap/

I decided not to use it for my alerts because I wanted my errors to be in a single dismissable alert. It would be a pain for the user to have to dismiss all the alerts separately. Also, I’m trying to learn knockout so writing my own is all part of the fun. :)

So with that out of the way this is what I came up with.
First in my html I have this very simple markup.

<div data-bind="alertList: errors, priority: 'error'"></div>

I’m using my new binding called alertList to bind an array to this div. The priority option will allow me to choose an error, warning, info or success alert.

This is what the JSON looks like coming back from the server. The main things to note are that it’s an array of errors and each error has a message attribute.

[{"message":"Password may not be null","messageTemplate":"{javax.validation.constraints.NotNull.message}","path":"User.createUser.arg0.password","invalidValue":null},
{"message":"Language may not be null","messageTemplate":"{javax.validation.constraints.NotNull.message}","path":"User.createUser.arg0.supportedLanguage","invalidValue":null},
{"message":"Username may not be null","messageTemplate":"{javax.validation.constraints.NotNull.message}","path":"User.createUser.arg0.username","invalidValue":null}]

In the view model we’ll typically have an ajax request to get a rest resource. If that results in an error then we can populate the observable errors array with the response from the server. The custom binding will then magically render these in the div with the correct styling. This is a stripped down example just to give the idea.

define(["jquery", "knockout", "mapping"], function($, ko, mapping)
{
"use strict";
var FormVM = function FormVM()
{
  var self = this;
  self.errors = ko.observableArray();
  self.submit = function()
  {
    $.ajax( {
      url: "test",
      type: "post",
      error: function(data)
      {
        self.errors(data.responseJSON);
      }
    } );
  };
};
return FormVM;
});

Finally we just need the custom binding to glue it all together.

define(["jquery", "knockout"], function($, ko)
{
"use strict";
/**
* Binds an observable array to a dismissable alert box
*/
ko.bindingHandlers.alertList =
{
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext)
{
  var data = valueAccessor();
  var priority = allBindingsAccessor().priority;

  var alertClass = "alert-danger";
  if(priority === "info")
  {
    alertClass = "alert-info";
  }else if(priority === "warning")
  {
    alertClass = "alert-warning";
  }else if(priority === "success")
  {
    alertClass = "alert-success";
  }

  element.style.display = "none";
  element.innerHTML = "<button type=\"button\" data-hide=\"alert\" class=\"close\">x</button>" +
  "<h4 class=\"alert-heading\">Error</h4>";
  element.className = "alert " + alertClass + " alert-dismissable";

  var ul = document.createElement("ul");
  ul.className = "list-unstyled";
  ul.innerHTML = "<li><span data-bind='text: message'></span></li>";
  element.appendChild(ul);

  ko.applyBindingsToNode(ul, { foreach: data });
  return { controlsDescendantBindings: true };
},

update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext)
{
  var value = ko.utils.unwrapObservable(valueAccessor());
  if(value.length>0)
  {
    $(element).slideDown();
  } else {
    $(element).fadeOut("fast");
  }
}
};
});

The init function does all of the initial construction. We take the basic div and add in the bootstrap classes we need. We also add a ul element which we use to create a list of errors from the message property of the array items. We also check the priority option to determine the class used to display the alert (e.g. error or warning etc).

The update function just adds in some jQuery animations to make the alert slideDown when you give it some elements and then fade out if you remove the elements.

I also added the following bit of jQuery to make the dismiss button work. The default behavior for a bootstrap dismissable alert is to remove the element from the page but we want to only hide it so we can later display again if we add more errors to the observable. We add a click event to any element with the data-hide attribute to fade out when clicked.

$(document).on("click", "[data-hide]", function()
{
	$(this).closest("." + $(this).attr("data-hide")).fadeOut("fast");
});

Alert Binding

Source is also available as a gist.

,

Leave a comment

Wild card tiles defs with spring MVC

A while ago I wrote about using Spring MVC to automatically scan for xml tiles definitions. This works beautifully but I later realised that you could go one better and do away with individual definitions in favour of wildcards. Essentially implementing your own convention over configuration.

Prerequisites
The spring setup is the same as in the previous article. You need to have:

  • A tiles view resolver
  • A spring bean of type TilesConfigurer with completeAutoload set to true
  • You need to include tiles 2.2 or greater and tiles-extras.jar

This is explained in greater detail in the previous post so here’s the link again if you need more detail.
Auto scanning tiles defs with spring MVC

Setting up wildcards definitions
First you need to decide on your folders structure. I’ve put everything under WEB-INF/jsp. Under this folder I have one folder called template which holds all the jsp fragments for headers and footers and the few xml tiles defs. The tiles definitions will still be automatically scanned, there will just be fewer of them. The second folder is called views which contains the actual pages with body content.

I’m using a base definition which I plan to override for different sections of the site. Each section can then have it’s own sidebar coming from a different jsp fragment. For example the admin section of the site will override the base definition with an admin specific sidebar. All admin related pages should use this admin definition.

Here’s the tiles definitions file with a simple base def and the overridden admin def.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>

    <definition name="base.definition" template="/WEB-INF/jsp/template/layout.jsp">
        <put-attribute name="title" value="" />
        <put-attribute name="header" value="/WEB-INF/jsp/template/header.jsp" />
        <put-attribute name="sidebar" value="/WEB-INF/jsp/template/sidebars/sidebar.jsp" />
        <put-attribute name="body" value="" />
        <put-attribute name="footer" value="/WEB-INF/jsp/template/footer.jsp" />
    </definition>
    
    <definition name="admin.definition" extends="base.definition">
        <put-attribute name="sidebar" value="/WEB-INF/jsp/template/sidebars/admin-sidebar.jsp" />
    </definition>
    
    <definition name="WILDCARD:admin/*" extends="admin.definition">
       <put-attribute name="title" value=" - {1}" />
       <put-attribute name="body" value="/WEB-INF/jsp/views/admin/{1}.jsp" />
    </definition>
    
</tiles-definitions>

We’re using the extends attribute to inherit as much as possible from the base definition. The admin base definition just overrides the sidebar location. We could if we wanted use this as a base for defining individual tiles views. Instead we have a definition with a name of “WILDCARD:admin/*”. This means any tiles view requested where the name starts admin/* will use this definition. The rest of the tile name is used to replace the {1} replacement variables.

So for example, if your controller returns a string of “admin/user” spring will look for a tile with this name. It should find the wildcard def and insert the title as “user” and the body jsp as /WEB-INF/jsp/views/admin/user.jsp.

There’s a bit more info in the tiles documentation.

, , ,

1 Comment

Auto scanning tiles defs with spring MVC

The merits of Tiles vs Sitemesh
If you’re using Spring MVC with JSP then the chances are you’re going to want some kind of templating framework to build the pages. I started using Apache Tiles first but became frustrated with the amount of XML config required. Each page to be rendered via tiles needs to be defined in an XML file, if you have a lot of views this file will quickly become unwieldy.

Looking for an alternative I came across a framework called sitemesh. This takes a different approach to tiles resulting in far less configuration. The main difference is that tiles is a composite view framework, whereas, sitemesh is a decorator. A tiles view is composed of many smaller components, these might be the header, sidebar and body content. Each component in the definition will be a JSP containing markup for just that part of the page. Sitemesh on the other hand can take an entire webpage and merge it with a decorator page to get the final result.

I tried Sitemesh because I was drawn to the minimal configuration but after a while I found I wanted some of the old Tiles functionality. Specifically I found I wanted to create different sidebar fragments for different groups of pages. You could do this using Sitemesh by creating different decorators based on url patterns but this would place restrictions on the urls. I decided to take another look at tiles and see if there was a more convenient way of organising the tiles defs.

Configuring tiles with Spring MVC
As it turns out Spring MVC provides a neat way of configuring tiles. First we need to setup a view resolver for tiles based views. You can configure as many view revolvers as you like with an order of priority so I have a JSP resolver that is used if a tiles definition cannot be found.

Here is a snippet from the context-servlet.xml.

  <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass">
      <value>org.springframework.web.servlet.view.tiles2.TilesView</value>
    </property>
    <property name="order" value="0" />
  </bean>

  <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="1" />
  </bean> 

Now when my Spring MVC controllers return a String (view name), first it will check for a tile definition with a matching name and if that fails it then looks for a jsp in /WEB-INF/jsp/***viewname***.jsp. This gives me the flexibility of being able to display plain old JSP’s if I want too. This is the typical tiles configuration that I had used previously.

The cool bit is the way we load the tiles definitions. As of Tiles 2.2 there is a new auto-loader which automatically configures Tiles and turns on all the new features. It’s kind of like Tiles’ answer to mvc:annotation-driven. This means we no longer have to manually enter locations for the tiles xml configurations. Instead they will be scanned automatically providing we use the correct naming convention. This allows us to separate the definitions into as many files as is convenient whilst not having to maintain a list of the xml files in the context-servlet.xml.

  <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
    <property name="completeAutoload" value="true" />
  </bean> 

See Spring doc

This tells spring to defer configuring tiles to the new auto-loader in Tiles 2.2. To use this you’ll need to make sure you have tiles 2.2 or greater and also tiles-extras.jar. This is the tiles part of my pom if you’re using Maven.

  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-servlet</artifactId>
    <version>2.2.2</version>
  </dependency>

  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-extras</artifactId>
    <version>2.2.2</version>
  </dependency>
		
  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-jsp</artifactId>
    <version>2.2.2</version>
  </dependency>

From the Tiles documentation here is a list of the features this will turn on.

  • Freemarker and Velocity support
  • using EL, OGNL and MVEL as evaluation languages
  • using Wildcards and Regular expression as pattern matching languages
  • loading Tiles 1.x definition files
  • loads all the files named “tiles*.xml” under /WEB-INF and under every META-INF in any part of the classpath

A hierarchy of tiles
So now I have a folder structure under WEB-INF which contains all of my tiles views. At the top level I have a basic template.

    <definition name="base.definition" template="/WEB-INF/jsp/template/layout.jsp">
        <put-attribute name="title" value="" />
        <put-attribute name="header" value="/WEB-INF/jsp/template/header.jsp" />
        <put-attribute name="sidebar" value="/WEB-INF/jsp/template/sidebars/sidebar.jsp" />
        <put-attribute name="body" value="" />
        <put-attribute name="footer" value="/WEB-INF/jsp/template/footer.jsp" />
    </definition>

I then override this basic template with child templates that contain the correct sidebar to suit the context. E.G. for the admin section:

    <definition name="admin.definition" extends="base.definition">
        <put-attribute name="sidebar" value="/WEB-INF/jsp/template/sidebars/admin.jsp" />
    </definition>

Finally I can create my admin views based on the admin template.

    <definition name="admin" extends="admin.definition">
        <put-attribute name="title" value=" - Admin" />
        <put-attribute name="body" value="/WEB-INF/jsp/views/admin/admin.jsp" />
    </definition>

I could have setup my tiles defs like this before without the auto-loader. The only difference now is it’s easier for me to split the defs up into different tiles.xml files. This allows you to put the tiles defs in the same folder as the related JSP’s and have the whole lot organised in a logical folder structure. It also means you’re less likely to have to maintain one monster of an xml file that contains all your definitions or have to keep dipping into the context.xml to keep adding a new tiles.xml location.

Note: in the next post you can combine this with wildcards to really minimize the xml configuration required.
Wild card tiles defs with spring MVC

, , , ,

2 Comments

Enum translations in Spring MVC

I recently came across this requirement but it wasn’t immediately obvious how to implement it. I have an enum in my application which defines the locales supported. For instance you might setup enum values of EN, FR and ES. (if English, French and Spanish are the languages you have translation properties files for) I then wanted to display a dropdown on the user screen with the values of this enum as available languages to select.

First stab
Here is the enum in question and my first go at displaying it.

/**
 * Languages supported with translations for the UI. A user can view the application in one 
 * of these languages.
 * 
 * @author Ben Thurley
 */
public enum SupportedLanguage 
{
  EN, FR, ES;
}

I got this piece of JSP from an answer on Stack Overflow

<form:select path="supportedLanguage">
   <form:options/>
</form:select>

This worked ok except the select dropdown just displayed EN, FR and ES. I needed a way of translating these codes into text for the users current selected language. I did see some solutions suggesting doing this in the controller. You could read all values and create a custom map of options with the right piece of translated text. I didn’t like the idea of this though as it was adding translation logic to the controller when for every other element it’s taken care of by Spring. There had to be another way and as it turned out, there was.

Spring custom formatter
Spring MVC allows us to write our own custom formatters. I just needed one that would take my enum code and format it to the translated string equivalent for the users locale.

This is what I ended up with:

public class SupportedLanguageFormatter implements Formatter<SupportedLanguage>
{

  @Resource
  private MessageSource messageSource;
	
  @Override
  public String print(SupportedLanguage object, Locale locale) 
  {
    // Lookup message translation, no args, default of English
    return messageSource.getMessage("supported.language." + object.name().toLowerCase(), null, "English", locale);
  }

  @Override
  public SupportedLanguage parse(String text, Locale locale) throws ParseException 
  {
    return SupportedLanguage.parse(text);
  }
}

This formatter does a two way translation. The print method takes a SupportedLanguage and looks up the relevant translated String. This is easily located using the injected MessageSource. For the reverse operation the parse method takes in a code from the UI (such as EN or FR) and returns an instance of the SupportedLanguage enum.

I tweaked the enum a bit so the parsing was encapsulated within the SupportedLanguage enum. Here’s the final version.

public enum SupportedLanguage 
{
  EN, FR, ES;

  public static List<SupportedLanguage> list() 
  {
    return Arrays.asList(values());
  }
	
  public static SupportedLanguage parse(String value)
  {
    SupportedLanguage lang = null;
    	
    for(SupportedLanguage test : list())
    {
      if(test.name().equalsIgnoreCase(value))
      {
        lang = test;
    	break;
      }
    }
    	
    return lang;
  }  
}

We then register the new formatter with spring.

  <mvc:annotation-driven conversion-service="conversionService">
  </mvc:annotation-driven>

  <!-- Custom formatters -->
  <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="formatters">
      <set>
        <bean class= "org.languagetool.web.formatter.SupportedLanguageFormatter" />
      </set>
    </property>
  </bean>

Now the SupportedLanguage enum is ready to be used. I did this by registering a ModelAttribute in the controller.

@Controller
@RequestMapping(value="admin/users")
@SessionAttributes({"userForm", "authoritiesList", "supportedLanguagesList"})
public class UserController
{
  ...
  @ModelAttribute("supportedLanguagesList")
  public List<SupportedLanguage> getAllSupportedLanguages() 
  {
    return SupportedLanguage.list();
  }  
  ...
}

This can now be used in the JSP as a set of options, I also added in an empty option if no language is selected on a new user form.

<form:select path="supportedLanguage">
  <spring:message code="option.select" var="selectOptionText" />
  <form:option value="" label="${selectOptionText}" />
  <form:options items="${supportedLanguagesList}" />
</form:select>

That’s almost it, now you just have to remember to add the translations to the relevant properties files.

# Languages
supported.language.en=English
supported.language.es=Spanish
supported.language.fr=French

, , , ,

5 Comments

Initialising DataTables with Twitter Bootstrap and Spring MVC Ajax

In the previous post I introduced handling Ajax requests from DataTables using Spring MVC.
Spring MVC with restful DataTables

This is only one side of the story though as I left out how I was doing the initialisation on the client side. I’m using DataTables with twitter bootstrap so my initialisation is doing two things, one setting up communication with the back end and two adding twitter bootstrap styling.

Continuing with the customer grid example this is my grid.

<table class="table table-striped table-bordered" id="customers">
  <thead>
    <tr> <th>ID</th> <th>Name</th> </tr>
  </thead>
  <tbody></tbody>
</table>
<script type="text/javascript">
	$(document).ready(function() {
	    $('#customers').dataTable( {
	    	"sAjaxSource": "/Root/customers/get",
	    	"bProcessing": true,
	    	"bServerSide": true,
	    	"sPaginationType": "bootstrap",
	    	"oLanguage": {"sLengthMenu": "_MENU_ records per page",
	    				  "sInfo": "Displaying _START_ to _END_ of _TOTAL_ records"},
	        "aoColumns":[
				{"mDataProp":"id"},
				{"mDataProp":"name"}
				]
	    } );
	} );	
</script>

The first three properties set up the Ajax processing, pagination type gives us bootstrap style paging buttons and oLanguage allows us to change the standard labels. When it came to mapping the columns I had to use the aoColumns property and setting the mDataProp value. In most of the examples online you’ll see a PHP script returning the JSON as an array but since we’re using Jackson we’re returning an object. The difference is this.

Array

{
  "aaData": [
    [
      "1",
      "Ben Thurley"
    ],
    [
      "2",
      "Another Person"
    ]
  ]
}

Object

{
  "aaData": [
    {
      "id" : "1",
      "name" : "Ben Thurley"
    },
    {
      "id" : "2",
      "name" : "Another Person"
    }
  ]
}

If you’re returning an array then you give DataTables the index of the property that matches the column, as we’re returning objects we have to give the name of the property that matches the column. We do this by setting the mDataProp property.

As an added bonus DataTables sends back these mDataProp values on the Ajax request which allows us to convert the sort column index into a meaningful column name.

The rest of the twitter bootstrap styling steps can be found on the DataTables site.
http://datatables.net/blog/Twitter_Bootstrap_2

It’s somewhat work in progress but I have also worked this into a JSP tag file so I don’t need to keep writing the same stuff in my JSP’s. It should in theory make it easy to change the tale plugin if required at a later date. I just added the following two tag files into WebRoot/WEB-INF/tags/table.

table.tag

<%@ tag language="java" %>
<%@ attribute name="id" required="true" %>
<%@ attribute name="datasource" required="true" rtexprvalue="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<c:set var="org_languagetool_tags_table_outputmode" value="TABLE" scope="request" />
	<table class="table table-striped table-bordered" id="${id}">
	  <thead>
	    <tr><jsp:doBody /></tr>
	  </thead>
	  <tbody></tbody>
	</table>
<c:set var="org_languagetool_tags_table_outputmode" value="SCRIPT" scope="request" />
<c:set var="org_languagetool_tags_table_firstcolumn" value="TRUE" scope="request" />
	<script type="text/javascript">
		$(document).ready(function() {
		    $('#${id}').dataTable( {
		    	"sAjaxSource": "<c:url value="${datasource}" />",
		    	"bProcessing": true,
		    	"bServerSide": true,
		    	"sPaginationType": "bootstrap",
		    	"oLanguage": {"sLengthMenu": "<spring:message code="table.records.count" />",
		    				  "sInfo": "<spring:message code="table.showing.records" />"},
		        "aoColumns":[
		                   	<jsp:doBody />
		                   	]
		    } );
		} );	
	</script>	

column.tag

<%@ tag language="java" %>
<%@ attribute name="field" required="true" %>
<%@ attribute name="label" required="true" rtexprvalue="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<c:choose>
  <c:when test="${org_languagetool_tags_table_outputmode == 'TABLE'}">
    <th><spring:message code="${label}" /></th>
  </c:when>
  <c:when test="${org_languagetool_tags_table_outputmode == 'SCRIPT'}">
    <c:choose>
      <c:when test="${org_languagetool_tags_table_firstcolumn == 'TRUE' }">
        <c:set var="org_languagetool_tags_table_firstcolumn" value="FALSE" scope="request" />
      </c:when>
      <c:otherwise>,</c:otherwise>
    </c:choose>
    {"mDataProp":"${field}"}
  </c:when>
</c:choose>

It’s not required unless you’re putting these in a jar but I also wrote out a tag library descriptor.

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" 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-jsptaglibrary_2_1.xsd">
  <tlib-version>1.0</tlib-version>
  <short-name>Table</short-name>
  <uri>http://bthurley.org/tags/table</uri>
  
  <tag-file>
    <name>table</name>
    <path>/WEB-INF/tags/table/table.tag</path>
  </tag-file>  
  
  <tag-file>
    <name>column</name>
    <path>/WEB-INF/tags/table/column.tag</path>
  </tag-file>
 
</taglib>

By using a tld I’ve been able to specify a uri for importing and using the tag. Otherwise you can give the path to import the tag.

<%@ taglib prefix="tab" uri="http://bthurley.org/tags/table" %>
<tab:table id="customers" datasource="/customers/get" >
  <tab:column field="id" label="customers.field.id" />
  <tab:column field="name" label="customers.field.name" />
</tab:table>

I guess I’ll be adding to these tags as time goes on and I think of new things.

, , , ,

12 Comments

Follow

Get every new post delivered to your Inbox.