Convenient internationalization of JSP pages

2011-04-19

I’m going to explain an elegant way of doing i18n in JSP (JSPX) pages if you use Spring MVC. But first let’s recap the usual setup: you need to declare a “messageSource” bean of type MessageSource that reads localized messages from resource bundles:

<bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="fallbackToSystemLocale" value="false"/>
    <property name="cacheSeconds" value="2"/>
    <property name="defaultEncoding" value="UTF-8"/>
    <property name="basenames">
        <array>
            <value>WEB-INF/i18n/global_messages</value>
            <value>WEB-INF/i18n/spring_security_messages</value>
            <value>WEB-INF/i18n/validation_messages</value>
        </array>
    </property>
</bean>

Then, each time you need to localize something in your JSP, you use some tag library like this:

<spring:message code="button_text" var="buttonTextMessage" htmlEscape="true"/>
<input type="submit" value="${buttonTextMessage}"/>

Here we have a Spring tag that finds a message in a MessageSource by the given code, escapes it (in case it may contain markup characters like quotes, ampersands, etc.), assigns the result to a variable and prints that variable as the “value” attribute of HTML input element.

Now repeat this for every single piece of text that you want to internationalize, and your JSP pages will quickly become littered with i18n tags, making them barely readable. If you think that’s fine, well … good for you! But if you’re wondering why something as trivial as i18n should be so inconvenient, keep on reading.

What I’d like to do is replace previous code fragment with this:

<input type="submit" value="${msg.button_text}"/>

You should agree that it cannot get any simpler than that. And I cannot stress enough the relief I felt after discovering that internationalization can be as simple and pleasant as this. So let’s move on to implementation.

The key part of my solution is “msg” – an application scope attribute that implements java.util.Map interface and holds all MessageSource messages keyed by their code. To be more precise, it delegates to MessageSource for message lookup. Here’s the implementation:

public class MessageSourceMapAdapter implements Map<String, String> {

    private final MessageSource messageSource;

    public MessageSourceMapAdapter(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    public String get(Object key) {
        Locale locale = LocaleContextHolder.getLocale();
        String message = messageSource.getMessage(String.valueOf(key), null, locale);
        return StringEscapeUtils.escapeXml(message);
    }

    public boolean containsKey(Object key) {
        return true;
    }

    public boolean isEmpty() {
        return false;
    }

    public int size() {
        throw new UnsupportedOperationException();
    }

    public Set<String> keySet() {
        throw new UnsupportedOperationException();
    }

    public Collection<String> values() {
        throw new UnsupportedOperationException();
    }

    public Set<Entry<String, String>> entrySet() {
        throw new UnsupportedOperationException();
    }

    public boolean containsValue(Object value) {
        throw new UnsupportedOperationException();
    }

    public String put(String key, String value) {
        throw new UnsupportedOperationException();
    }

    public void putAll(Map<? extends String, ? extends String> m) {
        throw new UnsupportedOperationException();
    }

    public String remove(Object key) {
        throw new UnsupportedOperationException();
    }

    public void clear() {
        throw new UnsupportedOperationException();
    }
}

As you can see, it’s a simple adapter that exposes MessageSource through Map interface. Most of it is stub implementation of Map methods, except the get(key) method, which will be called by JSP Expression Language whenever we use . or [] operators on “msg” attribute. This method uses the Locale of current thread to lookup messages (LocaleContext is initialized by DispatcherServlet on each request). It also uses StringEscapeUtils of Apache Commons Lang to automatically escape markup characters in message text, if any.

The last step is to set up our MessageSourceMapAdapter as an application-scope attribute “msg”, so that it can be used in JSP pages. This can be done at application startup in a Spring application event handler:

public class ServletContextAttributeInitializer
    implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private ServletContext servletContext;
    @Autowired
    private MessageSource messageSource;

    public void onApplicationEvent(ContextRefreshedEvent event) {
        servletContext.setAttribute("msg", new MessageSourceMapAdapter(messageSource));
        servletContext.setAttribute("cp", servletContext.getContextPath());
    }
}

Spring will automatically inject ServletContext and MessageSource and call onApplicationEvent() method after application context is loaded. We only need to register our event handler as a bean:

<bean class="my.project.ServletContextAttributeInitializer"/>

You may have noticed that I also save servlet context path to “cp” attribute. That’s another convenience that allows me to use short notation of relative URL paths in JSP pages, e.g. <a href="${cp}/login"> instead of <a href="${pageContext.request.contextPath}/login">.

You can use this approach to set up arbitrary servlet context attributes and then access them directly in JSP.

Spring WS and JAXB without a Code Generator

2010-04-28

Note: although this post mostly talks about implementing web services, the manual object-XML mapping technique described here can also be applied to WS clients.

I’d like to start by confessing that I’m very picky about programming techniques that rely on source code generators. I’m also sceptical about other kinds of compile-time tools that generate artifacts like XML files. I had my share of bad experiences with these sorts of tools, not because they are buggy or badly designed, but simply because they are not perfect.

Well, nobody’s perfect, you say? True enough. IDE auto-formatters are not perfect either. The style of code that they produce often still requires manual formatting. But it’s not a bad thing, since as a programmer I always have the final word: if I don’t like the place where that curly brace was put, or the way that lengthy statement was wrapped, I go ahead and fix it manually.

Enter the Evil Code Generators

Now, what if I don’t like some artifact produced by a generator? It can be ugly, it can be slow, it can miss the point – oh, well, there’s nothing I can do about it, because all my efforts will be overwritten during the next generation. It may be suitable for 95% cases, but what about the remaining 5%? When these tools do the work for me, they do it their way, and they won’t let me have that small customization that I need. You see, that’s one problem with code generators. They assume too much.

In my book, generators are only suitable for one-shot spawning of artifacts, or for quickly creating some throw-away demos. In practice, however, these tools are often integrated into project build lifecycle, which is bad because:

  • Generated output cannot be manually edited,
  • Generated output cannot be version controlled (at least in a meaningful way),
  • You become dependent on the generator – without it, the source won’t even compile!
  • The thought that you are not in control of your code makes you feel dizzy.

When it comes to Web Services…

…developers choose to go either the “WSDL to Java” or “Java to WSDL” route. The “to” part is usually done with some sort of generator utility, which means losing control of either the WSDL contract or the Java code. What I’d like to show in this post is a simple setup of Spring Web Services and JAXB that does not involve compile-time generation of artifacts, so that when defining your service interface you can feel completely in charge of everything: the Java, the XML, and the binding between the two.

I chose Spring WS mostly because it promotes contract-first Web Services, and JAXB2 because it’s a popular (some would say “official”) XML data binding specification. I was tempted to skip the binding part entirely and just parse/build the darn XML messages with JDOM, but then I saw that it required too much effort, especially in prospect of growing the WS interfaces.

Although I do believe that JAXB was designed to be primarily used alongside code generators like wsimport (WSDL to Java), it also works without them. What we’re going to do is:

  1. Write XML Schema for our web service
  2. Write Java classes for XML binding, with JAXB annotations
  3. Implement the endpoint
  4. Assemble everything with Spring WS configuration

The XML Schema

Create a /WEB-INF/personService.xsd file where each request and response message is expressed by an <element> and each complex type (if we need deeper structures) is represented by a <complexType>. Let’s say that our service accepts some kind of person-ID and returns the person’s name and age, where name is a complex type that consists of firstName and lastName.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:foo="http://bar.foo"
    targetNamespace="http://bar.foo" elementFormDefault="qualified">

    <element name="GetPersonRequest">
        <complexType>
            <sequence>
                <element name="id" type="string"/>
            </sequence>
        </complexType>
    </element>

    <element name="GetPersonResponse">
        <complexType>
            <sequence>
                <element name="name" type="foo:FullName"/>
                <element name="age" type="int"/>
            </sequence>
        </complexType>
    </element>

    <complexType name="FullName">
        <sequence>
            <element name="firstName" type="string"/>
            <element name="lastName" type="string"/>
        </sequence>
    </complexType>

</schema>

The Java classes for XML binding

Now for each XML request, XML response and XML complex type we create a corresponding Java class and put JAXB annotations to bind it to XML. The Java classes that map to personService.xsd schema look like this:

@XmlRootElement(name="GetPersonRequest", namespace="http://bar.foo")
@XmlType(name="", propOrder={"id"})
@XmlAccessorType(XmlAccessType.FIELD)
public class GetPersonRequest {

    @XmlElement(name="id", namespace="http://bar.foo")
    private String id;

    /* normal getters and setters */
}

////////////////////////////////////////////////

@XmlRootElement(name="GetPersonResponse", namespace="http://bar.foo")
@XmlType(name="", propOrder={"name", "age"})
@XmlAccessorType(XmlAccessType.FIELD)
public class GetPersonResponse {

    @XmlElement(name="name", namespace="http://bar.foo")
    private FullName name;

    @XmlElement(name="age", namespace="http://bar.foo")
    private int age;

    /* normal getters and setters */
}

////////////////////////////////////////////////

@XmlType(name="FullName", namespace="http://bar.foo", propOrder={"firstName", "lastName"})
@XmlAccessorType(XmlAccessType.FIELD)
public class FullName {

    @XmlElement(name="firstName", namespace="http://bar.foo")
    private String firstName;

    @XmlElement(name="lastName", namespace="http://bar.foo")
    private String lastName;

    /* normal getters and setters */
}

Some explanation:

  • each request and response element maps to @XmlRootElement class
  • each inner element maps to @XmlElement field
  • each complex type maps to @XmlType class, where propOrder sets the order of inner elements
  • since requests and responses are also anonymous complex types, they are annotated with a nameless @XmlType
  • @XmlAccessorType(XmlAccessType.FIELD) annotation tells JAXB to access field values directly

The endpoint implementation

It’s really up to you how you’re going to implement this part. Here’s just an example of using the @PayloadRoot annotation to map incoming XML request to a handler method:

@Endpoint
public class PersonEndpoint {

    @PayloadRoot(localPart = "GetPersonRequest", namespace = "http://bar.foo")
    public GetPersonResponse getPerson(GetPersonRequest request) {
        /* implementation code */
    }
}

The assembly

Define a Jaxb2Marshaller bean and set the classesToBeBound property to an array of all @XmlRootElement classes, so that they can be recognized by the marshaller.

DefaultWsdl11Definition can be used to publish WSDL definition based on personService.xsd, as long as we follow the convention of Request/Response suffixes in XML element names. And the rest are standard Spring WS affairs. A more or less complete setup may look like this:

<!-- the endpoint implementation -->
<bean class="foo.bar.PersonEndpoint"/>

<!-- publishes WSDL contract based on the given XML schema -->
<bean id="personService" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
    <property name="schema" ref="schema">
        <bean class="org.springframework.xml.xsd.SimpleXsdSchema">
            <property name="xsd" value="/WEB-INF/personService.xsd"/>
        </bean>
    </property>
    <property name="portTypeName" value="personInterface"/>
    <property name="locationUri" value="/ws/personService"/>
    <property name="targetNamespace" value="http://bar.foo"/>
</bean>

<!-- uses annotations to map XML requests to endpoint methods -->
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping"/>

<!-- passes endpoint method arguments and returned objects to JAXB marshaller -->
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
    <property name="marshaller" ref="jaxbMarshaller"/>
    <property name="unmarshaller" ref="jaxbMarshaller"/>
</bean>

<!-- uses JAXB annotations to marshall between XML messages and Java objects -->
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="classesToBeBound">
        <list>
            <value>foo.bar.GetPersonRequest</value>
            <value>foo.bar.GetPersonResponse</value>
        </list>
    </property>
</bean>

<!-- parses and builds SOAP messages -->
<bean class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory"/>

The dependencies

For the sake of completeness, here's a listing of relevant Maven dependencies that I used.

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core-tiger</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-xml</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-oxm-tiger</artifactId>
</dependency>

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
</dependency>
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
</dependency>
<dependency>
    <groupId>stax</groupId>
    <artifactId>stax-api</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.ws.commons.axiom</groupId>
    <artifactId>axiom-api</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.ws.commons.axiom</groupId>
    <artifactId>axiom-impl</artifactId>
</dependency>
<dependency>
    <groupId>xml-apis</groupId>
    <artifactId>xml-apis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.ws.commons.schema</groupId>
    <artifactId>XmlSchema</artifactId>
</dependency>

For a similar no-generated-code technique applied to JAX-WS services, check out this post.

Inherit Spring Security Context in Child Threads

2010-04-04

By default, Spring Security context is bound to ThreadLocal, which may catch you by surprise in some cases involving spawned threads.

So I setup my security infrastructure to authenticate users, populate their details from database, grant them authorities, I configure AccessDecisionManager and put @Secured annotations on my business methods to assert those authorities, etc. It all works well until my business code evolves to include asynchronous invocations. Then I find myself wondering: why am I getting AuthenticationCredentialsNotFoundException in places where the user is obviously authenticated?

Turns out that when a new thread is started it knows nothing about the security context of its parent thread. So if AccessDecisionManager gets called (e.g. if a @Secured method is invoked) from within the child thread, you get a security exception.

To work around that, you should change the SecurityContextHolder strategy to use InheritableThreadLocal for storing the security context. You can do that in code:

SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)

… or in XML configuration (which is better since you’ll only need to call the static method once during application startup):

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetClass"
        value="org.springframework.security.context.SecurityContextHolder"/>
    <property name="targetMethod" value="setStrategyName"/>
    <property name="arguments"><list><value>MODE_INHERITABLETHREADLOCAL</value></list></property>
</bean>

Note however, that you cannot share security context among sibling threads (e.g. in a thread pool). This method only works for child threads that are spawned by a thread that already contains a populated SecurityContext.

Diagram of Spring 3.0 module dependencies

2009-12-30

As Spring 3.0.0.RELEASE is finally out, I decided to draw a diagram that shows interdependency of modules comprising the latest Spring Framework. For the sake of simplicity, some direct dependencies have been omitted if they can be deduced transitively. Optional dependencies are not displayed.

Spring 3.0 modules

The idea of this diagram is to get a bird’s-eye view of Spring Framework architecture. Also,  if you use Maven’s central repository and include, e.g. spring-tx in your project, you should understand that you’re also including spring-context, spring-aop, spring-expression, spring-beans and spring-core.

For a quick explanation of what’s inside each of the modules and which ones you should use, see this excelent post by Keith Donald.

Access Spring WS MessageContext from anywhere

2009-11-07

UPDATE (2011-03-27): This article is relevant to those using the 1.5 version of Spring WS. Since version 2.0 it is trivial to access MessageContext by simply declaring it as one of the arguments in the handling method.

Spring Web Services framework has a special MessageContext class for holding request and response messages as well as arbitrary properties during the processing of a WS request. This class is especially useful if you are writing your own endpoint interceptors, because it allows you to do whatever you want with all incoming or outgoing web service messages, regardless of the endpoint in which they are processed.

There is certainly no problem getting to MessageContext in an EndpointInterceptor (all interface methods contain a MessageContext parameter), but what if you need to access it in your endpoint handler? For example, if you had to know the content type of all SOAP attachments that came in request, you would do it like this:

SoapMessage request = (SoapMessage) messageContext.getRequest();
for (Iterator it = request.getAttachments(); it.hasNext();) {
    Attachment attachment = (Attachment) it.next();
    System.out.println(attachment.getContentType());
}

You could do that in a MessageEndpoint, but not in a PayloadEndpoint where you have no access to MessageContext since it is not passed as parameter to your endpoint method.

Curiously, TransportContext does not have this limitation, as it is bound to current thread and accessible via TransportContextHolder.getTransportContext(). Users of Spring Security will remember that SecurityContext can be accessed in the same manner via SecurityContextHolder.getContext(). Notice a recurring theme here? What we lack in Spring WS is a “MessageContextHolder” class that would allow us to access MessageContext from anywhere in our code. Let’s go ahead and implement this missing utility.

MessageContextHolder is going to be a really simple utility class that can store and retrieve a reference to MessageContext in local thread.

public final class MessageContextHolder {

    private static ThreadLocal<MessageContext> threadLocal =
        new ThreadLocal<MessageContext>() {
            @Override
            protected MessageContext initialValue() {
                return null;
            }
        };

    private MessageContextHolder() {
    }

    public static MessageContext getMessageContext() {
        return threadLocal.get();
    }

    public static void setMessageContext(MessageContext context) {
        threadLocal.set(context);
    }

    public static void removeMessageContext() {
        threadLocal.remove();
    }
}

Next we need an endpoint interceptor that puts MessageContext to “Holder” before WS request is processed, and removes it when WS response (or fault) is about to be sent.

public class MessageContextHolderInterceptor implements EndpointInterceptor {

    public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
        MessageContextHolder.setMessageContext(messageContext);
        return true;
    }

    public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
        MessageContextHolder.removeMessageContext();
        return true;
    }

    public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
        MessageContextHolder.removeMessageContext();
        return true;
    }
}

Finally, we configure whatever EndpointMapping beans we use to include our interceptor:

<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
    <property name="interceptors">
        <list>
            <bean class="my.project.MessageContextHolderInterceptor"/>
        </list>
    </property>
</bean>

Now once this interceptor does its job upon each request, you can say MessageContextHolder.getMessageContext() and you’ll get current MessageContext whenever you need it.

Are you a Spring developer?

2009-09-08

I hate it when I see job titles that include the name of a software framework in it, like “ASP.NET developer”, “SharePoint developer”, “Struts developer”, etc. They make it sound as if knowing how to use the framework in question is the only competence the candidate is supposed to have. In reality, since any framework is just a leaky abstraction of the underlying platform services, knowing the dirty details of what’s abstracted away is an absolute must.

Now, assuming you are a Java developer and have used Spring before, what would you say if someone would ask you: Are you a Spring developer? A normal response ought to be No, I don’t develop the framework, though I’ve used Spring in some projects, but you already know that’s not what was meant by the question. How come the concept of Spring developer does not cause confusion or ambiguity? Because it highlights Spring Framework’s de facto status as a sort of “programming model” and a core competence.

But let’s make this clear shall we. For what it’s worth, Spring is not a programming model. AOP is a programming model. Inversion of control is a programming principle. Dependency injection is a programming technique. Enterprise service abstraction is a complex application of OOP patterns to isolate business code from infrastructural changes. Spring is an application framework that successfully applies all of the above and wraps it in a box with a catchy label. If you add other Spring portfolio projects, tools and community contributions, you may also argue that Spring starts to look like a more or less coherent development environment.

Java landscape is huge, but Spring has become so versatile that it has given a new perspective to it and keeps reshaping this landscape into something … not even sure how I should call it. Would “leaner” be the right adjective? Personally I’m very enthusiastic about what SpringSource and the community around it are doing. Perhaps that is why I’m starting a blog dedicated to Spring Framework.