Thursday 22 April 2010

Thread safety, Java Beans and Hibernate

I just read "Java Concurrency in Practice" by Brian Goetz et al and found it to be a fantastic educational experience. The main thing I learned is that I am a total novice when it comes to multi-threaded programming! My excuse is that I learned programming by building websites and applications, where it is popularly imagined that multi-threading is not really an issue. Also, I'm no computer scientist, just an ex-physicist who found out that pretending to know about the internet and programming pays better than doing a real job like physics. I digress.

I started to think about the standard patterns and practices used by web programmers when building web applications, especially using my favourite frameworks (Spring and Hibernate, of course) and wondered whether I should be more worried about threads than I usually am (i.e. not at all). After some serious head-scratching and blog-reading I have come to the following conclusions.

  1. There is evidence that Java Bean based frameworks could potentially be vulnerable to multi-threading issues due to the mutability of Java Beans
  2. I wouldn't worry about it too much (as long as they are thread-confined).

I better make it clear that I am not talking about the thread-safety of Hibernate or Spring themselves. By and large, as developers we accept these frameworks and given and while we should be aware of the thread-safety issues that they may have there is not much that we can do to change them in our applications. I'm talking about the standard components that we build on top of these frameworks. The thread-safety or otherwise of these frameworks is probably a worthy topic in itself, but it's not what I'm looking at here.

Let's start with Hibernate itself. Typically, persistent classes follow the Java Beans "pattern" of a no-args constructor with accessor and mutator objects for the private fields of the class (getters and setters). Java Beans are intrinsically "mutable" objects (they have mutators, after all!). Mutability on its own is not necessarily a thread-safety hazard, but the first recommendation for building thread-safe classes is to make them immutable - so Java Beans immediately seem to be a thread-safety hazard.

There are plenty of great resources explaining why mutable classes pose thread-safety hazard, including the "Java Concurrency In Practice" book, so I'll just summarise. The Java memory model makes no particular guarantees about the visibilty of changes in state between two threads, and in fact makes no guarantees about the order in which changes in state may seem to occur in two threads. This means that if thread 1 changes the state of a Java Bean field, thread 2 may not see this change immediately, or indeed at all. A further risk is that fields that are involved in invariants (i.e. are constrained by validation rules) could be modified so as to violate the invariants by different threads, even if the mutator methods contain logic to enforce the invariants.

So if Hibernate persistent classes are usually Java Beans, and Java Beans are mutable, and mutability is bad this surely seems to point to a potential thread-safety issue. So why am I sanguine about this risk?

The reason is that in general the risks posed by mutability are reduced when the objects in questions can be "thread-confined". In other words, they are only ever used by a single thread at a time. A mutable class will not pose thread-safety hazards if it is confined in this way. So, are Hibernate Java Beans thread-confined in a web application? The answer is potentially yes, depending on whether you store them somewhere that another thread can access them (like the HttpSession).

If your web application loads a Hibernate entity from a DAO or a service object that uses JPA (for instance) and then places this entity in a request for rendering in a view, it's pretty clear that this is thread-confined up to the point where the entity is placed in the request. Up to this point, it is only ever a local variable in a series of methods and is hence thread-confined (Actually, I don't know whether Hibernate is returning a unique instance for each call to Session.load() but I believe it does).

For example, here is a very brief illustration of retrieving a Hibernate entity for display on a page.

In the service object:
public Customer getCustomer(Integer customerId) {
return em.find(Customer.class, customerId);
}
in the controller:
@ModelAttribute("customer")
public Customer getCustomer() {
return customerService.getCustomer(customerId);
}

In the above example, the Customer entity instance is always thread confined. As a @ModelAttribute is stored in the HttpServletRequest it should be thread-confined as each request runs in its own thread which ends when the request is finished.

However, if the model is stored in the HttpSession, ServletContext or in a cache, then multiple threads might access the JavaBean. You are at the mercy of the thread safety of the HttpSession, ServletContext or cache provider.

In fact, it is recommended to synchronize access to attributes stored in the HttpSession unless contained in an immutable object, because multiple threads may access it simultaneously. The same is true of the SerlvetContext. A well-designed cache should be designed with concurrency in mind and have appropriate synchronization - but you should make sure of this.

So in conclusion, if you want to avoid thread-safety problems with Java Beans, confine them to a single thread and avoid storing them in places where multiple threads could access them such as the HttpSession, ServletContext or a cache (unless you are sure that the cache is thread-safe).

Wednesday 21 April 2010

Using JSR 303 with "classic" Spring Validators (enter the SpringValidatorAdapter)

Spring 3.0 has a number of new features, one of which is support for JSR303. JSR303 adds annotation-driven validation for Java Beans which is intended to replace hand-coded validation code. This has obvious ramifications for Spring MVC as a key part of this framework includes support for validation of web forms using hand-coded Validator implementations. I'm gradually upgrading a Spring 2.x MVC application to Spring 3.0 at the moment, with the emphasis on gradual. So while I'd like to use JSR 303, I'm not ready yet to re-code the 50 odd Controller implementations to use the new annotation-driven style (even though I hate seeing warnings in Eclipse). Luckily, Spring makes it really easy to have the best of both worlds using the SpringValidatorAdapter. Put simply, this class wraps the JSR303 adapter and provides convenience methods to enable you to easily support the old style Validator interface methods. You can then use the annotations in your command/form objects and the old-school Validators in your Controller classes. Here is a simple example command object using the JSR 303 annotations. They are pretty self-evident and there are loads of blogs that explain what they do.
public class MyCommand implements Serializable {

private static final long serialVersionUID = 42L;

@NotNull
@Min(value=1L)
private Integer projectId;

@NotNull
@Min(value=1L)
private Integer employeeId;

@NotNull
@Min(value=1L)
@Max(value=999L)
private BigDecimal hoursToComplete;

     // Constructors, accessors, mutators, equals, hashcode omitted :-)
}
The Validator for this class is then very simple. Create a Validator implementation as per usual, and then inject the SpringValidatorAdapter class into it. I've done this through the constructor, as I am trying to appear clever and multi-threaded by marking the SpringValidatorAdapter instance as final. Oh yeah, feel my muscles.
public class MyCommandCommandValidator implements Validator {

private final SpringValidatorAdapter validator;

public MyCommandCommandValidator(SpringValidatorAdapter validator) {
 super();
 this.validator = validator;
}

@SuppressWarnings("unchecked")
@Override
public boolean supports(Class givenClass) {
 return validator.supports(givenClass);
}

@Override
public void validate(Object target, Errors errors) {
 validator.validate(target, errors);
 
 // More custom validation here

}
}
Note that you could just use the SpringValidationAdapter directly (without wrapping it in your own Validator implementation) if you are only doing JSR303 validation. It's also possible to write your own JSR303 custom validation routines, which might be a better long term architecture than the mixed approach above. The Spring LocalValidatorFactoryBean implements the main JSR303 Validator interface as well as SpringValidatorAdapter. So the Spring configuration is simple. You do need to have the Hibernate Validator reference implementation available on the classpath or an alternative.



   

Job done! The only other thing to note is that the message codes are set by the JSR303 Validator, so you may have less control over them. For example:

public void testValidateNotNullFields() throws Exception {

 // Perform validation
 validator.validate(command, errors);

 // Check error count
 assertEquals(Integer.valueOf(3), Integer.valueOf(errors.getErrorCount()));
 
 // Test employeeId field
 FieldError employeeIdError = errors.getFieldError("employeeId");
 assertNotNull(employeeIdError);
 assertEquals("NotNull", employeeIdError.getCode());

}

In this test, the employeeId field was not set in the command. The Validator created a field error under key "employeeId" with the error code "NotNull" as it was the @NotNull constraint that was violated (and not in a good way). In summary - using JSR303 with "classic" validators is really easy thanks to the SpringValidatorAdapter class. Woot.

Tuesday 20 April 2010

Spring Security 3.0 and Spring EL

Among the many improvements in Spring Security 3.0 is the ability to use the Spring Expression Language (SPEL) to secure methods and URLs. This immediately opens up the possibility of more sophisticated "domain object security" on service methods and URLs. To secure service methods, a number of additional attributes have been added that support the SPEL. The most immediately useful is the @PreAuthorize attribute which is similar to the old @Secured attribute in intent but with a bit of SPEL processing thrown in as well. The documentation gives the following example:
@PreAuthorize("#contact.name == principal.name)")
public void doSomething(Contact contact);
The #contact refers to the contact parameter in the method. The tag causes all of the method parameters to be injected as variables into the expression language evaluation context. Variables are referenced using the # prefix. This script basically checks that the #contact variable has a name field that matches the name field in the current principal object (principal is an implicit object that is the current Spring Security Principal implementation). There are3 other attributes that have been added for filtering and post-authorisation. You can also use SPEL to restrict access to URLs.
<http expressions="true>
<intercept-url pattern="/admin*" access="hasRole('admin') and hasIpAddress('192.168.1.0/24')">
...
</intercept-url>
</http>
A great feature of this is that the EL has access to the HttpServletRequest in the EvaluationContext for the web request, meaning that you can peek at request parameters in the EL to grant access based on their values. Another useful feature is being able to check access to a specific URL in the Spring Security taglibs before rendering content.
<sec:authorize url="/admin">

This content will only be visible to users who are authorized to send requests to the "/admin" URL.

</sec:authorize>
These are all very useful features. However, there are a number of problems with the support offered for EL base access control that I have discovered. My immediate instinct was to define EL based access control inside the security context with the <intercept-url /> and then use <sec:authorize url="/xxx" /> in JSPs to render links only when a user has access to them. This works well up to a point. Problems start to occur when you need to evaluate objects in the request in the expression and try to authorize those URLs using the tag. For example, take the following EL definition which checks that the employee id supplied in the request matches the employee id of the logged in principal.
<intercept-url pattern="/timesheetview.htm"
access="principal.employeeId ==
T(java.lang.Integer).valueOf(request.getParameter('employeeId'))" />
This on its own works well enough. If you request the URL in a browser, requests are correctly authorised (or not). However, if you then try to use the <sec:authorize url="/xxx" /> tag in a JSP to check access to this URL, things no longer work. For example, the script below seems like it should work.
<c:url value="/timesheetview.htm" var="url">
<c:param name="employeeId" value="${employeeId}>
<c:url>
<sec:authorize url="${url}">
<a href="${url}">View timesheet<a>
</sec:authorize>
The problem is that the authorize tag does not allow scripting variables in the url attribute. However, there is a further problem which means that even if it did you still can't dynamically check access based on a request parameter. My first attempt at a workaround was this:
<sec:authorize url="/timesheetview.htm?employeeId=123">
<a href="/timesheetview.htm?employeeId=123">View timesheet<a>
</sec:authorize>
This gets around the scripting issue, but fails for a more fundamental reason (above the fact that employee id must be hard-coded). The reason this doesn't work is that Spring Security issues a "dummy" request to the URL to see whether access is denied or granted. The dummy request is made using an instance of org.springframework.security.web.access.DummyRequest which is a partial implementation of HttpServletRequest. Specifically, most operations cause an OperationNotSupportedException - including HttpServletRequest.getParameter(String name). That means that when the EL expression executes, it tries to call request.getParameter() which in turns causes the OperationNotSupportedException. It is in fact impossible in Spring Security 3.0 to use an EL expression in the <intercept-url /> in combination with the <sec:authorize url="xxx"> tag in a situation where the url in question is secured with an expression that accesses the HttpServletRequest - regardless of whether the parameter is supplied in the request or not. These problems mean that this exciting feature falls quite short of expectations when used in what seems to be a fairly obvious scenario. I'd like to see the DummyRequest be able to support request parameters in a future version that are evaluated based on the contents of the url attribute. This attribute should support scripting variables to enable parameters to be passed in using <c:url> Don't get me wrong - it's still awesome. Spring Security 3.0 is a worthwhile upgrade but there is always room for improvement.