javax.persistence.TransactionRequiredException (using Arquillian)

I recently encountered javax.persistence.TransactionRequiredException when I am trying to perform some cleanup, on @After method in my unit test. I am currently playing with Arquillian (and it is such a great technology to complement Java EE).

The scenario is simple.

I have an Item entity, and I have ItemService. The service provides functionality to add an item and to retrieve it. That’s about it.

In unit test, for one reason or another, one might decide to clean up, or DELETE some item. However, in this case, I would very much like to keep my service layer clean, i.e. just because I happen to need a clean up on the test-side, I should not force my service to implement it. Perhaps another way to look at it is that this is my way to reduce coupling. The user of the service should knows about the service, and the service should not know about where it is being used. One direction, so to speak.

So, to start with, here’s the code:

ItemDistributionServiceTest

package com.dwuysan.service;

import com.dwuysan.entity.Item;
import com.dwuysan.util.EntityManagerProducer;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * @author denywuy
 */
@RunWith(Arquillian.class)
public class ItemDistributionServiceTest {

    private Item item;
    @Inject
    private ItemService itemService;
    @Inject
    private EntityManager em;

    @Deployment
    public static JavaArchive createTestArchive() {
        return ShrinkWrap.create(JavaArchive.class)
                .addClass(Item.class)
                .addClass(ItemService.class)
                .addClass(EntityManagerProducer.class)
                .addAsManifestResource("test-persistence.xml", ArchivePaths.create("persistence.xml"))
                .addAsManifestResource("META-INF/beans.xml", ArchivePaths.create("beans.xml"))
                .addAsResource("ValidationMessages.properties");
    }

    @Before
    public void setup() {
        this.item = new Item();
        item.setCode("item01");
        item.setName("item01");
        item.setUom("piece");

        this.item = this.itemService.getItem(this.itemService.createItem(item));
    }

    @After
    public void cleanUp() throws Exception {
        this.em.remove(em.merge(this.item));
    }

    @Test
    public void testDistribute() throws Exception {
        /*
         * Test omitted
         */
    }
}

So, to DELETE the item, I directly use EntityManager#remove(...). However, that results in the following error:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 11.847 sec <<< FAILURE!
testDistribute(com.dwuysan.service.ItemDistributionServiceTest)  Time elapsed: 0.625 sec  <<< ERROR!
javax.persistence.TransactionRequiredException
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145)
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.merge(EntityManagerWrapper.java:280)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

same as above

After further reading, I found that we need to explicitly initiates transaction. So, the code change slightly to:

ItemDistributionServiceTest

package com.dwuysan.service;

// the rest of the imports go here
import javax.annotation.Resource;
import javax.transaction.UserTransaction;

@RunWith(Arquillian.class)
public class ItemDistributionServiceTest {

    private Item item;

    // the rest of the injections go here
    @Resource
    private UserTransaction utx;

    @Deployment
    public static JavaArchive createTestArchive() {
        // same as above
    }

    @Before
    public void setup() {
        // same as above
    }

    @After
    public void cleanUp() throws Exception {
        utx.begin();
        this.em.remove(em.merge(this.item));
        utx.commit();
    }

    @Test
    public void testDistribute() throws Exception {
        /*
         * Test omitted
         */
    }
}

Reference:

Kosi2801, 2009, EntityManager throws TransactionRequiredException on merge() in JBoss JSF bean, accessed 29 March 2013.

JAAS-secured JAX-RS end point

With the advent of RESTFUL (JAX-RS) as the “preferred” way to create web service end points, for a long time I have always wondered how people implement security mechanism around it.

At the end of the day, I presume the underlying implementation of JAX-RS is servlet, and therefore its security might also be around what is already provided by the container, i.e. JAAS.

This post will cover my findings on how to step-by-step implement FORM-based security using JDBC realm, JAX-RS and how to test it using cURL, on Glassfish 3.

Setting up JDBC-realm

Firstly, since we are using JDBC-realm, let’s assume that we have created a JDBC connection to the underlying database under the JNDI jdbc/test.

The next step is to create a new realm. You can do this by going to server-config > Security > Realms and add a new realm. Select the realm type com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm, and then populate the mandatory fields.

  • Start by giving your new realm a name.
  • For JAAS Context, put jdbcRealm
  • Populate JNDI name, preferably starts with "jndi/"

Next, do pay attention to the rest of the fields. It seems that Glassfish expects to see two tables. The first table is to contain a list of users, with usernames as their unique identifier. The second table is to list the groups that each user belongs to. Username is to be the foreign-key link between the two tables. (The next section should give you better idea on how the tables should look, they are after all very simple).

Once these tables are created, we can then populate the mandatory fields accordingly.

Populate database for testing purpose

The next step is to populate the table for testing purpose. Let’s just assume that we will be testing using username hpotter and password test. For the password however, note that Glassfish digest by default is SHA-256, as illustrated by the following screen shot.

sha-256

Hence, you need to encode the password test before insert. You can use encoder by technipixel, which will give you the String 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08.

The next step is to write some INSERT statements:

INSERT INTO person (id, password, username) VALUES (1, '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', 'hpotter');
COMMIT;
INSERT INTO person_role (username, user_group) VALUES ('hpotter', 'User');
INSERT INTO person_role (username, user_group) VALUES ('hpotter', 'Admin');
COMMIT;

Let’s move on to the next step.

Securing web application using JAAS

Quite a number of tutorials out there on JAAS with FORM authentication method. However, I thought I put it here again, with the hope that some might find it simpler.

web.xml

Make the following modification to your web.xml

    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file><!-- 1 -->
    </welcome-file-list>
    <security-constraint><!-- 2 -->
        <display-name>TestConstraint</display-name>
        <web-resource-collection>
            <web-resource-name>TestResource</web-resource-name>
            <description/>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>User</role-name>
            <role-name>Admin</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config><!-- 3 -->
        <auth-method>FORM</auth-method>
        <realm-name>testRealm</realm-name>
        <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/error.html</form-error-page>
        </form-login-config>
    </login-config>
    <security-role><!-- 4 -->
        <description/>
        <role-name>User</role-name>
    </security-role>
    <security-role><!-- 5 -->
        <description/>
        <role-name>Admin</role-name>
    </security-role>

Let’s go through them one-by-one.

  1. This is the file to be displayed on successful login. You can also use this file as redirection. For example, suppose you have a file called index.xhtml (a JSF page), you can use response.sendRedirect("index.jsf");
  2. This is the actual constraint, i.e. how you secure the application. This section is basically there to secure all access to the application, denoted by /* url pattern, and only allow access of user with the role of User and Admin.
  3. This part denotes that what we are using is FORM authentication method (which I’ll explain in more detail in the next section). Important part is to ensure the correct name of the security realm used, which in this case, testRealm, the same realm name we have given when setting it up via Glassfish admin page. The other part is to set the page containing j_security_check that the application will automatically redirect to in the event of request access has not been authenticated yet.
  4. The known role
  5. Same as previous section.

glassfish-web.xml

We also need to configure glassfish-web.xml so that the container knows about the mapping between groups from the database and the role recognised by the application.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
    <security-role-mapping>
        <role-name>Admin</role-name>
        <group-name>Admin</group-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>User</role-name>
        <group-name>User</group-name>
    </security-role-mapping>
    <class-loader delegate="true"/>
    <jsp-config>
        <property name="keepgenerated" value="true">
            <description>Keep a copy of the generated servlet class' java code.</description>
        </property>
    </jsp-config>
</glassfish-web-app>

N.B. If you use Netbeans, this file might be generated for you.

Login page: login.html

If we refer again to web.xml above, notice that the login page is pointing to login.html. For FORM authentication method, as per specification, we need to have a form with j_security_check, with j_username and j_password (Oracle 2013).

<!DOCTYPE html>
<html>
    <body>

        <form action="j_security_check" method="post">
            <p>
                <strong>Username</strong>
                <input type="text" name="j_username" size="25" />
            </p>
            <p>
                <strong>Password</strong>
                <input type="password" size="15" name="j_password" />
            </p>
            <p>
                <input type="submit" value="Submit" />
                <input type="reset" value="Reset" />
            </p>
        </form>
    </body>
</html>

With all of these completed, we can start up Glassfish, deploy our application and test it using any browser. Upon accessing the application, users should be directed to login.html to login. Remember to use hpotter as username and test as password. On successful login, the user should be redirected to index.jsp (which in turn redirects user to index.jsf, or anything the index.jsp is redirecting to, according to your requirement).

Create a RESTFUL end point

The next step of course is to create a RESTFUL end point, which is very simple. One of the posts I have written here might also be useful.

To start, assuming we have the following application path.

package com.dwuysan;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

/**
 * @author denywuy
 */
@ApplicationPath(value = "resources")
public class ApplicationConfig extends Application {
}

Let us assume that we have the following simple RESTFUL service.

package com.dwuysan;

import com.dwuysan.entity.Outlet;
import com.dwuysan.service.OutletService;
import javax.annotation.ManagedBean;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path(value = "generic")
@RolesAllowed(value = "User")
@ManagedBean
public class GenericResource {

    @Inject
    private OutletService outletService;

    @GET
    @Path("{id}")
    public Outlet get(@PathParam(value = "id") final long id) {
        return this.outletService.getOutlet(id);
    }
}

Note that we have secured this service with javax.annotation.security.RolesAllowed annotation.

Testing secured RESTFUL service using curl

Given the RESTFUL service we created above, we should be able to test it using CURL with the following command:

curl -X GET -H "Accept:application/json" -H "Content-Type:application/json" http://localhost:8080/testApp/resources/generic/101

The above command translate to the following: hit the URL above using GET, with the headers Accept:application/json and Content-Type:application/json (cURL 2013)

Since we have secured our application, invocation as above will not work. The user will be redirected to login.html. Hence, our aim now is to first login. With cURL, we can submit parameters to login, i.e. username and password, and then obtain the cookie. To do that, we can use this command:

curl -b cookies.txt -c cookies.txt -d "j_username=hpotter&j_password=test" http://localhost:8080/testApp/j_security_check

This command is submitting username and password, to the j_security_check (remember our login.html that we have created previously), and storing the cookies obtain under the file cookies.txt.

If you open your cookies.txt, you may see the following:

# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_localhost     FALSE   /testApp     FALSE   0       JSESSIONID      245a317ab91fbb28244403346770

N.B. You might receive Document Moved response. This means login has been successful. Otherwise, you would get the raw html of the error.html again.

Once we have been authenticated successfully, we can use the cookies we have obtained from the login to invoke the RESTFUL service.

curl -X GET -H "Accept:application/json" -H "Content-Type:application/json" -b cookies.txt -c cookies.txt http://localhost:8080/testApp/resources/generic/101

References:

BalusC, 2012, ‘Does JSF support form based security’, accessed 12 February 2013.

Oracle, 2013, ‘Securing Web Application’, accessed 12 February 2013.

Wolff, N, 2005, ‘How do you handle authentication via cookie with CURL?’, accessed 12 February 2013.

Reduce eye strain with Netbeans Dark Nimbus Theme

If you do feel that your IDE is WAYYYY TOO BRIGHT, well, Netbeans 7.3 RC1 Dark Nimbus Theme probably can help.

What you need to do:

  • Go to Plugins, and download the Netbeans Dark Nimbus Theme
  • Go to <Netbeans home directory>/etc/netbeans.conf
  • Append --laf Nimbus on the option netbeans_default_options
  • Restart IDE
  • Go to Options > Fonts & Colors, then select Norway Today

Injecting EJB into a JAX-RS

Following my previous post here, I tried to inject an EJB 3.1 stateless session bean into this resource, only to find the infamous java.lang.NullPointerException.

Supposed you have an EJB as follows:

MainService

package com.wordpress.dwuysan.service;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;

@Stateless
@LocalBean
public class MainService {

    public String sayHello(final String name) {
        return "Hello" + name;
    }
}

And injecting it in a JAX-RS bean:

GenericResource

package com.wordpress.dwuysan;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path(value = "generic")
public class GenericResource {

    @Inject
    private com.wordpress.dwuysan.service.MainService mainService;

    @GET
    public String get() {
        return this.mainService.sayHello("test");
    }
}

This will result in java.lang.NullPointerException.

To fix this, the JAX-RS bean must also be “managed”, so simply add the annotation javax.annotation.ManagedBean to your JAX-RS bean (Nelson 2011)

References:

Nelson, L, 2011, ‘How do I inject a local stateless session bean into a JAX-RS resource using CDI?’, accessed 06 December 2012.

Starting with JAX-RS: Configuring javax.ws.rs.ApplicationPath

I recently started with a very simple Hello-World-like JAX-RS. So, to start with, I created a class like this:

GenericResource

package com.wordpress.dwuysan;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path(value = "generic")
public class GenericResource {

    @GET
    public String get() {
        return "Hello World";
    }
}

Once the application server is running, when I run curl http://<web application address>/generic, it failed.

After a little bit of Google-ing around, I found that you need to set up the resource path, either by installing a correct servlet on web.xml, or if you are fortunate enough and are using Java EE 6, you can use @javax.ws.rs.ApplicationPath and extends javax.ws.rs.core.Application (Kuchtiak 2009).

So, once I add this class:

ApplicationConfig

package com.wordpress.dwuysan;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath(value = "resources")
public class ApplicationConfig extends Application {
}

I can now invoke curl http://<web application address>/resources/generic, I got correct response.

References:

Kuchtiak, M, 2009, 'How to Combine REST Services with EJB 3.1', accessed 06 December 2012.

Netbeans 7.3 connecting to local mysql

I thought I’ll write this one up since I just spent 30 minutes trying to connect to local mysql.

I just downloaded the new Netbeans 7.3 Beta 2, and am now trying to play around with MySql. So, firstly, I simply use the Synaptic Package Manager and install mysql. Once that’s done, it’s time to connect.

I have used Oracle in the past and have managed to connect to it via Netbeans Services > Database (and downloading the ojdbc drivers, connecting, etc etc, they all goes without saying). With MySql however, I notice, there is a dedicated menu Register MySql Server.

Ooooooooooooooohhhhhhhhhhh…… fantastic!!!

Okay …

Then comes the page this this MySQL Server Properties. Hmmm, what values should I put in? …

Well, I spent some time looking up google and also trying various entries. I thought I’ll just share the screenshot here:

mysqlConfig

Basic Authentication with SOAP Web Service

Nothing new this time around, but I thought I’ll post an entry anyway, more as a reminder for myself in case I need it again.

Every now and then, you would need to invoke a web service end point using basic authentication. I am sure modern frameworks, such as JAX-WS (MKyong 2010), can do this easily.

However, in the unfortunate case you ever find that you would need to manually do this, the formula is to add a header entry as follows (Wikipedia 2012).

Header Value
Authorization Basic (followed by username + ‘:’ + password, encoded in base64)

Assuming that the end point service you would like to invoke has the credentials of username being adumbledore and password being Sherbet Lemon (if you don’t understand, suggest read Harry Potter), then first thing you would want to do is to structure it like this:

adumbledore:Sherbet Lemon

Then, use base64 encoder to encode it. For example, google would suggest this.

Then all you need to do is to add the Authorization header. See the image below.

References:

MKyong, 2010, Application Authentication with JAX-WS, accessed 14 May 2012.

Opinionatedgeek.com, 2012, Base 64 encoder, accessed 14 May 2012.

Wikipedia, 2012, Basic access authentication, accessed 14 May 2012.

JAX-WS, wsimport, and the error “MustUnderstand headers … not understood”

Following the previous adventure surrounding collision in the object factory class, this time around we take it a step further. Instead of simply using xjc command from JAXB and marshall/unmarshall elements into the SOAP envelope, we thought lets use wsimport against the WSDL instead. Again, wsimport is part of standard JDK.

The tool wsimport also makes use of xjc and therefore the collision issue also occurred. Thankfully, we can specify the binding (-b) argument with wsimport as well. Even better, use the following maven plugin:

<plugin>
    <groupId>org.jvnet.jax-ws-commons</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>2.1</version>
    <executions>
        <execution>
            <goals>
                <goal>wsimport</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <target>2.1</target>
        <extension>true</extension>
        <bindingDirectory>src/main/resources</bindingDirectory>
        <bindingFiles>
            <bindingFile>bindings.xjb</bindingFile>
        </bindingFiles>
        <wsdlDirectory>src/main/resources</wsdlDirectory>
        <wsdlFiles>
            <wsdlFile>schemas.ppsr.gov.au.2011.04.services.wsdl</wsdlFile>
        </wsdlFiles>
    </configuration>
</plugin>

All is well and good now.

When we actually hit the end point, the following error is thrown:

27/03/2012 6:40:20 PM com.sun.xml.internal.ws.protocol.soap.MUTube getMisUnderstoodHeaders
INFO: Element not understood={http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security
Exception: MustUnderstand headers:[{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood

The interesting thing is that invoking using soapUI, all worked okay, and the following response returned:


<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Header>
        <wsse:Security
            xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
            S:mustUnderstand="1">
            <wsse:UsernameToken 
                xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                wsu:Id="UsernameToken-1">
                <wsse:Username><!-- omitted --></wsse:Username>
                <wsse:Password 
                    Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
                    <!-- omitted -->
                </wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
                    <!-- omitted -->
                </wsse:Nonce>
                <wsu:Created>2012-03-27T07:40:19.628Z</wsu:Created>
            </wsse:UsernameToken>
        </wsse:Security>
    </S:Header>
    <S:Body>
        <ns2:PingRequestMessage
            xmlns="http://schemas.ppsr.gov.au/2011/04/data"
            xmlns:ns2="http://schemas.ppsr.gov.au/2011/04/services"
            xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
            xmlns:ns4="http://schemas.ppsr.gov.au/faults" />
    </S:Body>
</S:Envelope>

After further reading, we discover it’s mostly related to the mustUnderstand and the way we use javax.xml.ws.handler.soap.SOAPHandler (White 2010). Reading javadoc itself is not enough, since the getHeaders() method simply says “Gets the header blocks that can be processed by this Handler instance” (Oracle 2011).

Therefore, to resolve this issue, our handler must understand the response, and that’s done by “handling” the response as follows:

PPSRSOAPMessageHandler

package com.wordpress.dwuysan;

import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class PPSRSOApMessageHandler implements SOAPHandler<SOAPMessageContext> {
    // ... the rest of the code omitted

    @Override
    public Set<QName> getHeaders() {
        final QName securityHeader = new QName(
            "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
            "Security",
            "wsse");

        // ... "understand" the response, very complex logic goes here
        // ... "understand" the response, very complex logic goes here
        // ... "understand" the response, very complex logic goes here

        final HashSet headers = new HashSet();
        headers.add(securityHeader);

        // notify the runtime that this is handled
        return headers;
    }

    // ... the rest of the code omitted
}

References:
Oracle, 2011, SOAPHandler (Java EE 6), accessed 02 April 2012.

White, J, 2010, Working with Headers in JAX-WS SOAPHandlers, accessed 02 April 2012.

Hollywood Principle – translated

For as long as dependency injection gained its popularity (starting with Spring, then followed by Java EE, etc), people have always associated DI with Hollywood Principle – Don’t call us, we’ll call you.

Yet, perhaps it’s just my own ignorance, I have never found any direct translation as to why dependency injection is “Don’t call us, we’ll call you”. Even during some interviews, I have heard quite a number of people being asked, What do you know about Hollywood Principle?. The answer generally follows the line of:

  • “It’s dependency injection, period”, or
  • “It’s like Spring where by your objects are instantiated with its dependencies, period”.

I have never really found a satisfactory explanation, until today.

Therefore, perhaps more for my own reference, with the hope that those who are as confused as I was previously would find this post beneficial, the best explanation I found is from one of the post by Andrew Binstock (2008). Following is one of the paragraphs I found from the author’s post that I paraphrased.

“Dependency Injection was originally called Inversion of Control (IoC) because as opposed to the normal control sequence where an object finds the objects it depends on by itself, and then calls them, in IoC it is reversed. The dependencies are handed to the object when it’s created. This also illustrates the Hollywood Principle at work: Don’t call around for your dependencies, we (in this case the IoC container/runtime) will give them to you when we need you(Binstock 2008).

Reference:

Binstock, A, 2008, Binstock on Software: Excellent Explanation of Dependency Injection (Inversion of Control), accessed 22 March 2012.

Cross-field validation using Bean Validation (JSR 303)

I recently introduced the use of Bean Validation in one of the project I was working on. At the very start, it was just a complete experiment with a very “defensive” implementation, with the mindset that if the use of this API proved to be problematic, it would be thrown away.

Turned out to be a very good set of API, and it is very enjoyable to use.

It is true that there are things to read, learn and experiment (here, unit testing helps A LOT) and the site from JBoss helped a lot.

Amongst the many things I learnt, one of the immediate requirement I encountered was the ability to implement a cross-field validation. I suppose it is understandable as to why the cross-field validation is not part of the standard API. Why how would one standardise such case with so many variations/approaches, etc. I am sure though that the JSR team will eventually address it.

That being said, Bean Validation allows flexibility via the use of Custom Validator and with that, cross-field validation can be implemented. The example that I used in this entry today is based on the post in stackoverflow.com by user Nicko (Nicko 2010).

Supposed there is an entity called Purchase. A Purchase must be allocated to correct authorisation department, and also payment department. For a Purchase to be considered valid, it must also be authorised by a person from that authorisation department, and paid by someone from the payment department. (This might be a silly example, but you’ll get the intention)..

Using the example from stackoverflow.com, the classes are:

EnrolmentValid

package com.wordpress.dwuysan;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

/**
 * @author dwuysan
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnrolmentValidator.class)
public @interface EnrolmentValid {

    String message() default "{com.wordpress.dwuysan.EnrolmentValid.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String personNoFieldName();

    String departmentNoFieldName();

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        EnrolmentValid[] value();
    }
}

EnrolmentValidator

package com.wordpress.dwuysan;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.apache.commons.beanutils.BeanUtils;

/**
 * @author dwuysan
 */
public class EnrolmentValidator 
        implements ConstraintValidator<EnrolmentValid, Object> {

    private String personNoFieldName;
    private String departmentNoFieldName;

    @Override
    public void initialize(final EnrolmentValid a) {
        this.personNoFieldName = a.personNoFieldName();
        this.departmentNoFieldName = a.departmentNoFieldName();
    }

    @Override
    public boolean isValid(
                final Object t, final ConstraintValidatorContext cvc) {
        final Object personNo;
        final Object departmentNo;
        try {
            personNo = BeanUtils.getProperty(t, 
                this.personNoFieldName);
            departmentNo = BeanUtils.getProperty(t,
                this.departmentNoFieldName);
            /* Validation logic goes here */
        } catch (final Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }

        if (personNo == null || departmentNo == null) { return true; }

        // return false, just to make it always fail
        return false;
    }
}

Purchase

package com.wordpress.dwuysan;

import javax.validation.constraints.NotNull;

/**
 * @author dwuysan
 */
@EnrolmentValid.List(value = {
    @EnrolmentValid(
        personNoFieldName = "authorisePersonNo", 
        departmentNoFieldName = "authorisationDepartmentNo", 
        message="Authoriser does not belong to the auth department"),
    @EnrolmentValid(
        personNoFieldName = "payerPersonNo", 
        departmentNoFieldName = "paymentDepartmentNo", 
        message="Payer does not belong to the payment department")
})
public class Purchase {

    private Integer authorisePersonNo;
    private Integer payerPersonNo;

    @NotNull
    private Integer authorisationDepartmentNo;
    
    @NotNull
    private Integer paymentDepartmentNo;
    
    /* accessor/mutator methods not shown */
}

Have tried this approach and it worked perfectly. However, if then we were to refactor the fields, say in this case the names of the properties are too long and it should be changed to authPersNo and , then this example would fail (again, of course JUnit will pick this up).

ALTERNATIVE APPROACH

The other option is to actually remove the use of “reflection”, and instead, use an additional class just exposing those fields to be validated.

EnrolmentValidation

package com.wordpress.dwuysan;

/**
 * @author dwuysan
 */
public final class EnrolmentValidation {
    private final Integer personNo;
    private final Integer departmentNo;

    public EnrolmentValidation(
            final Integer personNo, 
            final Integer departmentNo) {
        this.personNo = personNo;
        this.departmentNo = departmentNo;
    }

    public Integer getDepartmentNo() {
        return departmentNo;
    }

    public Integer getPersonNo() {
        return personNo;
    }
}

Then change the Validator to directly access the fields (instead of using reflection).

EnrolmentValidator

package com.wordpress.dwuysan;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * @author dwuysan
 */
public class EnrolmentValidator 
        implements ConstraintValidator<EnrolmentValid, EnrolmentValidation> {

    @Override
    public void initialize(final EnrolmentValid a) {}
    
    @Override
    public boolean isValid(
                final EnrolmentValidation t, 
                final ConstraintValidatorContext cvc) {
        if (t.getPersonNo() == null || t.getDepartmentNo() == null) {
            return true;
        }
        /* Validation logic goes here */

        // return false, just to make it always fail
        return false;
    }
}

Also, change the annotation by removing the field names.

EnrolmentValid

package com.wordpress.dwuysan;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

/**
 * @author dwuysan
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnrolmentValidator.class)
public @interface EnrolmentValid {

    String message() default "{com.wordpress.dwuysan.EnrolmentValid.message}";

    Class[] groups() default {};

    Class[] payload() default {};

    // String personNoFieldName();

    // String departmentNoFieldName();

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        EnrolmentValid[] value();
    }
}

THEN, the problematic one is the Purchase class itself. For a start, we could simply add methods returning EnrolmentValidation object, with the method annotated with @EnrolmentValid

Purchase

package com.wordpress.dwuysan;

import javax.validation.constraints.NotNull;

/**
 * @author dwuysan
 */
public class Purchase {

    private Integer authorisePersonNo;
    private Integer payerPersonNo;

    @NotNull
    private Integer authorisationDepartmentNo;
    
    @NotNull
    private Integer paymentDepartmentNo;

    @EnrolmentValid
    public EnrolmentValidation getAuthPersonDepartmentEnrolmentValidation() {
        return new EnrolmentValidation(
            this.authorisePersonNo, 
            this.authorisationDepartmentNo);
    }

    @EnrolmentValid
    public EnrolmentValidation getPayerDepartmentEnrolmentValidation() {
        return new EnrolmentValidation(
            this.payerPersonNo,
            this.paymentDepartmentNo);
    }

    /* accessor/mutator methods not shown */
}

That works as expected. However, it may not be the most ideal scenario since the class Purchase is now “polluted” with validation specific methods. Also, some prefer clear separation between the domain model and its validation. One way to achieve this is to use interface (and an Adapter class).

Please refer to the following interface.

PurchaseValidation

package com.wordpress.dwuysan;

import javax.validation.constraints.NotNull;

/**
 * @author dwuysan
 */
public interface PurchaseValidation {

    @NotNull
    Integer getPayerPersonNo();

    @NotNull
    Integer getPaymentDepartmentNo();

    @NotNull
    Integer getAuthorisePersonNo();

    @NotNull
    Integer getAuthorisationDepartmentNo();

    @EnrolmentValid
    EnrolmentValidation getAuthPersonDepartmentEnrolmentValidation();

    @EnrolmentValid
    EnrolmentValidation getPayerDepartmentEnrolmentValidation();
}

I supposed the way to look at it is to say, “Here is the list of validations relating to Purchase“. And so that the class Purchase is not tainted with validation logic, create a simple Adapter class as follows.

PurchaseValidationAdapter

package com.wordpress.dwuysan;

/**
 * @author dwuysan
 */
public class PurchaseValidationAdapter implements PurchaseValidation {
    private final Purchase purchase;

    public PurchaseValidationAdapter(Purchase purchase) {
        this.purchase = purchase;
    }

    @Override
    public Integer getPayerPersonNo() {
        return this.purchase.getPayerPersonNo();
    }

    @Override
    public Integer getPaymentDepartmentNo() {
        return this.purchase.getPaymentDepartmentNo();
    }

    @Override
    public Integer getAuthorisePersonNo() {
        return this.purchase.getAuthorisePersonNo();
    }

    @Override
    public Integer getAuthorisationDepartmentNo() {
        return this.purchase.getAuthorisationDepartmentNo();
    }

    @Override
    public EnrolmentValidation getAuthPersonDepartmentEnrolmentValidation() {
        return new EnrolmentValidation(
                this.purchase.getAuthorisePersonNo(),
                this.purchase.getAuthorisationDepartmentNo());
    }

    @Override
    public EnrolmentValidation getPayerDepartmentEnrolmentValidation() {
        return new EnrolmentValidation(
                this.purchase.getPayerPersonNo(),
                this.purchase.getPaymentDepartmentNo());
    }
}

CONSIDERATIONS

I suppose the alternative approach presented here removes the use of “reflection”, and at the same time introduces the separation between the validation layer and the actual business domain model. Using Adapter, we can also adapt other models into a single validation layer. For example, when dealing with a legacy code, an application may have multiple class representing the very same business object. In this case, perhaps consider a class like PurchaseSummary, PurchaseLite, etc. This alternative approach, however, does introduce more code.

I am sure that people who have used JSR-303 have also encountered the need of cross-field validation. I am interested to know their thoughts and any comment to this post is very welcomed.

References:
Nicko, 2010, Cross field validation with Hibernate Validator (JSR 303), accessed 20 March 2012.