Tuesday, February 24, 2009

GWT Tips 2 - nocache.js getting cached in browser

I have recently discovered that, after version deployments, our GWT application does not work in some users' browsers unless they do a hard refresh on the browser.

A bit of investigation revealed that this is because their browsers are caching the all-important YOUR_MODULE_NAME.nocache.js file. This file is GWT's bootstrapping file and its content (not its name) is likely to change as you introduce changes and then gwt-compile your Java code. If a user has an older version of this js file cached in the browser, the application will not be able to properly communicate with your server code. One should make sure that this file does not get cached by the browser nor any proxy servers along the way.

You may wonder what is the significance the of the "nocache" bit in the name. What does it actually do? Well, it does not do anything! But having this identifiable string in the filename does allow you to configure your server to send HTTP header information to the client browser to stop it from caching the file.

If you are using Apache to serve your static files. You can simply edit your .htaccess file to send the correct HTTP header information to the client for this nocache.js file.

However, if you are using a Java application server such as Tomcat to server your static files, you have to create a servlet Filter to dispatch the necessary HTTP header information. Below is a filter I have written to do exactly this:



import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* {@link Filter} to add cache control headers for GWT generated files to ensure
* that the correct files get cached.
*
* @author See Wah Cheng
* @created 24 Feb 2009
*/
public class GWTCacheControlFilter implements Filter {

public void destroy() {
}

public void init(FilterConfig config) throws ServletException {
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
ServletException {

HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();

if (requestURI.contains(".nocache.")) {
Date now = new Date();
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setDateHeader("Date", now.getTime());
// one day old
httpResponse.setDateHeader("Expires", now.getTime() - 86400000L);
httpResponse.setHeader("Pragma", "no-cache");
httpResponse.setHeader("Cache-control", "no-cache, no-store, must-revalidate");
}

filterChain.doFilter(request, response);
}
}



Essentially, this filter checks whether the requested file name contains the string ".nocache.", and if it does, it sets the header to tell the browser and any proxy servers along the way to not cache the file. For an excellent explanation of the different header options, check out http://code.google.com/p/doctype/wiki/ArticleHttpCaching.

Of course, you would have to add this filter to your web.xml (host-mode as well as standalone mode):


<filter>
<filter-name>gwtCacheControlFilter</filter-name>
<filter-class>com.seewah.blog.GWTCacheControlFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>gwtCacheControlFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Monday, February 23, 2009

Spring Tips 1 - reading encrypted passwords in properties file

Have you ever wondered how you can use encrypted passwords in Java properties files that get loaded into your Spring ApplicationContext via a org.springframework.beans.factory.config.PropertyPlaceholderConfigurer?

Here is the answer - http://forum.springframework.org/showpost.php?s=6d689f6afe0143a9ab3a77bfbb8e017c&p=7965&postcount=6 (thanks to none other than Juergen Hoeller)

Pretty slick!

Friday, February 20, 2009

GWT Tips 1 - Chain of Responsibility

GWT application development (and AJAX programming in general) can sometimes prove problematic for web developers who has not yet adopted the mindset of asynchronous programming. In GWT, you make a RPC as follows:


foo.bar(param, new AsycnCallback<object>) {
public void onFailure(Throwable throwable) {
// handle exception
}
public void onSuccess(Object result) {
// successful execution of asynchronous RPC
}
}


What if you have to make a series of RPC calls such that an RPC call only gets invoked after the previous call has succeeded. Of course we can simply wrap this series of RPC calls inside one single RPC on the server side so that the client does not have to worry about synchronising the calls, but you maybe you want to update the user interface between calls, or you may want to execute some client-side logic before making the second call.

You may start off writing code like this:


foo.bar(param, new AsycnCallback<object>) {
public void onFailure(Throwable throwable) {
...
}
public void onSuccess(Object result) {
// some client-side logic before invoking the second RPC
foo2.bar2(param, new AsycnCallback<object>) {
public void onFailure(Throwable throwable) {
....
}
public void onSuccess(Object object) {
....
}
}
}
}


This is hard to follow and error-prone. A way to avoid nested RPC calls is to leverage the Chain of Responsibility design pattern. The main class in the design pattern is the AbstractHandler. The following is a basic implementation of this class:


/**
* An abstract handler in the Chain or Responsibility design pattern.
*
* @author See Wah Cheng
* @param <T>
* type of request object to handle
*/
public abstract class AbstractHandler<T> {

private Handler<T> successor;

public void setSuccessor(Handler<T> successor) {
this.successor = successor;
}

public Handler<T> getSuccessor() {
return successor;
}

public void handOverToSuccessor(T request) {
if (successor != null) {
successor.handleRequest(request);
}
}

public abstract void handleRequest(T request);
}


Given this class, to execute a series of RPC calls, one simply has to create a concrete implementation of this AbstractHandler for each RPC call and chain them together as follows: (where InvocationContext is some kind of class encapsulating the details needed for the various RPC invocation)


public class FooInvoker extends AbstractHandler<Invocationcontext> {
public void handleRequest(InvocationContext request) {
Object param = request.getFooParam();
foo.bar(param, new AsycnCallback<object>) {
public void onFailure(Throwable throwable) { // handle exception }
public void onSuccess(Object result) {
// some client-side logic before invoking the next RPC
// updating request object if necessary
handOverToSuccessor(request);
}
}
}
}

public class Foo2Invoker extends AbstractHandler<InvocationContext> {
public void handleRequest(InvocationContext request) {
Object param = request.getFoo2Param();
foo2.bar2(param, new AsycnCallback<object>) {
public void onFailure(Throwable throwable) { // handle exception }
public void onSuccess(Object result) {
// some client-side logic before invoking the next RPC
// updating request object if necessary
handOverToSuccessor(request);
}
}
}
}

InvocationContext request;
...
FooInvoker fooInvoker = new FooInvoker();
Foo2Invoker foo2Invoker = new Foo2Invoker();
fooInvoker.setSuccessor(foo2Invoker);
fooInvoker.handleRequest(request);


OK you may be shouting, "Isn't this a lot of code for something pretty simple? Er, agile? Hello?" Yes, it is more verbose, and whether this approach offers any benefit depends on the situation. If you are making three or more RPC calls in series, I definitely think this will lead to better quality code. If, inside each callback's onSuccess method, you are doing more than just invoking the next RPC, this will certainly lead to better code. If the individual stages are needed elsewhere, this again will lead to more reusable code.

Finally, an added benefit of this is that the order of execution can be altered quite easy just by shuffling the handler order in the chain (assuming that the order of execution does not matter!)

Wednesday, February 18, 2009

GWT and Spring Security

Update: I have put together a sample app to demonstrate the integration technique: http://seewah.blogspot.com/2009/06/gwt-and-spring-security-sample-demo.html

As promised, I am posting this article to share my experience with using Spring Security (formerly ACEGI) with GWT. Apologies for the delay. I guess I have just been busy + lazy!

First of all, for those of you who haven't, please read my previous blogs GWT Spring Integration and GWT Spring Integration - using ContextLoaderListener to see how to use Spring-managed service beans in GWT.

Again it is not my intention to provide a complete solution for GWT / Spring Security integration as there are so many ways of doing it, and which method to choose depend hugely on how you want to actually use Spring Security inside GWT. By sharing my limited experience here, I hope to give some ideas to those of you who are trying to come up with a solution that fits your needs.

So how do I want to use Spring Security in my GWT application?

I want to:

1) leverage Spring Security's SecurityContext mechanism to store authenticated token, which I can then access anywhere in my code
2) be able to annotate my service classes, so that Spring can apply method security using AOP to my service beans

I DO NOT want to:

1) let Spring Security automatically handle form authentication for me
2) rely on Spring Security to automatically redirect user to login page

In other words, using Spring Security, I want to develop some form of RPC service which my GWT client can call to authenticate the username and password supplied by the user at the login screen. Once authentication has succeeded, a token which identifies the current user as being authenticated will be available to all subsequent RPC requests, so that I can either manually inspect the token inside the RPC request to enforce some form of authorization, or I can rely on Spring Security's off-the-shelf method security mechanism to allow or disallow user call certain methods in my Spring managed service beans.

I am going to break up the rest of the article into three different sections: An authentication service, HTTP Session Integration and Method Security

An Authentication service

The following is a simple implementation of such a service:


import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.context.SecurityContextImpl;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.userdetails.User;

public class AuthenticationServiceImpl implements AuthenticationService {

/**
* Authenticates against the supplied credentials,
* populating the Spring SecurityContext if
* credentials are OK.
*
* @param username
* @param password
* @return
* whether authentication is successful
*/
public boolean authenticate(String username, String password) {

// check credentials, e.g., by querying a database...
boolean authenticated = checkCredentials();

// look up authorities by, e.g., querying the database...
GrantedAuthority[] authorities = getGrantedAuthorities(username);

if (authenticated) {
User user = new User(username, password, true, true, true, true, authorities);
Authentication auth = new UsernamePasswordAuthenticationToken(user, password, authorities);
SecurityContext sc = new SecurityContextImpl();
sc.setAuthentication(auth);
SecurityContextHolder.setContext(sc);
}

return authenticated;
}

public void logout() {
SecurityContextHolder.clearContext();
}
}


This of course is a very simple implementation, but the point to note is within the authenticate method, an Spring Authentication object is created and inserted into the SecurityContext programmatically.

We can simply turn this into a RPC service by creating a com.google.gwt.user.server.rpc.RemoteServiceServlet implementation in which we either access AuthenticationServiceImpl directly or via a Spring ApplicationContext as described in my previous blogs GWT Spring Integration and GWT Spring Integration - using ContextLoaderListener.

Now we have a service that effectively let us "log into" the system. However, this on its own is rather useless, as the token is not available to subsequent request threads. If we have a RPC service for retrieving documents, and we would like to protect the documents, we really would want to be able to, inside the service, inspect the SecurityContext to see whether an authenticated token exists. We want be able to do the following, which we cannot do... yet:


if (SecurityContextHolder.getContext() == null
SecurityContextHolder.getContext().getAuthentication() == null
!SecurityContextHolder.getContext().getAuthentication().isAuthenticated) {

// no authenticated token found, stop user from retrieving documents
}


HTTP Session Integration

Luckily, Spring Security provides a filter, org.springframework.security.context.HttpSessionContextIntegrationFilter, which automatically synchronises the current SecurityContext with a http session object, thus, making the token available to all subsequent request threads.

We can enable this filter in a number of ways. We can create the filter directly in web.xml (host-mode or standalone mode). Or we can create a org.springframework.security.util.FilterToBeanProxy in web.xml and define a FilterChainProxy in the Spring ApplicationContext. Or we can, as most people do nowadays, create a org.springframework.web.filter.DelegatingFilterProxy called springSecurityFilterChain (note: the naming is crucial) in web.xml and use Spring Security Namespace Configuration in the ApplicationContext to create the necessary beans. We will have a look at this last approach.

In web.xml


<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
<listener>

<listener>
<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>


In Application Context:


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"....>

<security:http entry-point-ref="dummyEntryPoint" create-session="always" />

<bean id="dummyEntryPoint" class="com.seewah.blog.DummyEntryPoint" />
...
<beans>


This is pretty neat, except for the fact that we have to create a "dummy" org.springframework.security.ui.AuthenticationEntryPoint, even though we are not replying on Spring Security to redirect user to login page. Unfortunately, by design, the security:http tag requires an AuthenticationEntryPoint, so I created this class:


public class DummyEntryPoint implements AuthenticationEntryPoint {

public void commence(ServletRequest request, ServletResponse response, AuthenticationException e) throws IOException, ServletException {

throw new IllegalStateException("This implementation is a dummy class, created purely so that spring security namespace tags can be used in application context, and this method should never be called");
}
}


OK, so now we have a way to "log into" the system, and we can inspect the SecurityContext in subsequent RPC requests to grant or deny users access to certain services. However, we would like to go one step further. We would like to leverage the excellent method security feature provided by Spring Security because we like our security layer to be non-invasive, and we like AOP.

Method Security

We configure method security as follows:

In Application Context:



<security:global-method-security secured-annotations="enabled" jsr250-annotations="disabled" />

<bean id="dummyAuthenticationProvider" class="com.seewah.blog.DummyAuthenticationProvider">
<security:custom-authentication-provider />
</bean>


Unfortunately, again, because of the way Spring Security Namespace Configuration works, we have to introduce another dummy class, even though it will never be used. Remember our AuthenticationServiceImpl creates authenticated token programmatically and method security will simply grant / deny access based on the presence of this token. Hence the authencationProvider here becomes redundant. We implement the dummy class as follows:


public class DummyAuthenticationProvider implements AuthenticationProvider {

public Authentication authenticate(Authentication authentication) throws AuthenticationException {

throw new IllegalStateException("This implementation is a dummy class, created purely so that spring security namespace tags can be used in application context, and this method should never be called");
}

@SuppressWarnings("unchecked")
public boolean supports(Class clazz) {

throw new IllegalStateException("This implementation is a dummy class, created purely so that spring security namespace tags can be used in application context, and this method should never be called");
}
}


Of course, as method security is implemented using AOP in Spring, only Spring-managed beans are protected, which means in order to use this mechanism to protect our service layer, we MUST access these services via the Spring ApplicationContext (GWT Spring Integration and GWT Spring Integration - using ContextLoaderListener) and NOT directly.

When a protected method is accessed without an authenticated token being present in the SecurityContext, Spring throws a SpringSecurityException. If we let this exception propagate all the way to the GWT client code, we are most certainly going to be greeted with the dreaded SerializableException error. Instead we should catch this exception and rethrow an exception that GWT can safely serialize and pass to the client side. We define such an exception, ServiceSecurityException, in our GWT client package, and now we have a mechanism that translates a Spring Security method security exception into a GWT client exception:

On the server


public class DocumentServiceImpl implements DocumentService {

@org.springframework.security.annotation.Secured("ROLE_ADMIN")
public void delete(Long id) {
...
}
}

public class DocumentServiceServlet extends DependencyInjectionRemoteServiceServlet implements ... {

@Autowired
private DocumentService documentService;

public void delete(Long id) throws ServiceSecurityException {
try {
documentService.delete(id);
} catch (SpringSecurityException e) {
throw new ServiceSecurityException(e.getMessage());
}
}
....
}



Inside the client


documentServiceAsync.delete(id, new AsyncCallback<Object>() {
public void onFailure(Throwable throwable) {
if (throwable instanceof ServiceSecurityException) {
// client side logic to redirect user to login page, for example
} else {
...
}
}
...
});


Of course, seeing that we need client-side exception handling whenever we invoke an "secured" RPC call, we may as well create an AutoErrorHandlingAsyncCallback and invoke all our RPC calls passing through an instance of this callback instead of the normal AsyncCallback object:


public abstract class AutoErrorHandlingAsyncCallback<T> implements AsyncCallback<T> {

final public void onFailure(Throwable throwable) {
if (throwable instanceof ServiceSecurityException) {
// client side logic to redirect user to login page, for example
} else {
...
}
}
}


OK this way of using Spring Security method security is not as non-invasive as we have perhaps hoped, but IMHO this is far better than writing code to check for authenticated token in SecurityContext in the services themselves.

GWT Spring Integration - using ContextLoaderListener

Update: I have put together a sample app to demonstrate the integration technique: http://seewah.blogspot.com/2009/06/gwt-and-spring-security-sample-demo.html Just take out applicationContext-security.xml if you are not interested in the Spring Security aspect!

Just a quick followup post to my last post http://seewah.blogspot.com/2008/07/gwt-and-spring.html.

In the last post I demostrated how to use the SpringApplicationContextLoader to manually load an application context from an xml file and subsequently to access Spring-managed beans via this class inside DependencyInjectionRemoteServiceServlet.

For one reason or another, I have moved away from this approach and gone back to the traditional means of using the org.springframework.web.context.ContextLoaderListener in web.xml to load application contexts. So this is what to do if you prefer this approach.

First of all, create the listener as you would with a normal Spring web application


<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


in web.xml. If you are running in host mode, this is found under the tomcat/webapps/ROOT/WEB-INF folder inside your project. Otherwise, just edit the usual web.xml inside your webapps folder in your tomcat installation.

Now, inside DependencyInjectionRemoteServiceServlet, simply use the static org.springframework.web.context.support.WebApplicationContextUtils.getWebApplicationContext(ServletContext sc) method to access the loaded application context. This following is the revised class:


import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* {@link RemoteServiceServlet} that automatically injects IoC dependency.
* "org.springframework.beans.factory.annotation.Autowired" annotation is used
* for marking which fields to inject into. Uses
* {@link SpringApplicationContextLoader} to retrieve beans by name.
* <p>
* Note that the current implementation will only inject "declared" fields, and
* not inherited fields. Fields can be private, protected, package or public.
*
* @author See Wah Cheng
* @created 27 Jun 2008
*/
@SuppressWarnings("serial")
public class DependencyInjectionRemoteServiceServlet extends RemoteServiceServlet {

protected static Logger logger = Logger.getLogger(DependencyInjectionRemoteServiceServlet.class);

@Override
public void init() throws ServletException {
super.init();
doDependencyInjection();
}

/**
* Carries out dependency injection. This implementation uses Spring IoC
* container.
*
* @exception NoSuchBeanDefinitionException
* if a suitable bean cannot be found in the Spring application
* context. The current implementation looks up beans by name
*/
protected void doDependencyInjection() {

for (Field field : getFieldsToDependencyInject()) {
try {
boolean isFieldAccessible = field.isAccessible();
if (!isFieldAccessible) {
field.setAccessible(true);
}
field.set(this, WebApplicationContextUtils.getWebApplicationContext(getServletContext()).getBean(field.getName()));
if (!isFieldAccessible) {
field.setAccessible(false);
}
logger.debug("Dependency injection successful: " + this.getClass().getName() + "." + field.getName());
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

/**
* Find annotated fields to inject.
*
* @return a list of all the annotated fields
*/
private Set<Field> getFieldsToDependencyInject() {
Set<Field> fieldsToInject = new HashSet<Field>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.getAnnotation(Autowired.class) != null) {
fieldsToInject.add(field);
}
}
return fieldsToInject;
}
}


Note that there are two changes to this class. First of all, doDependencyInjection() now accesses the application context using the org.springframework.web.context.support.WebApplicationContextUtils class as described above. Secondly, doDependencyInjection() is now invoked from inside the servlet's init() method and not its constructor. This is because, when org.springframework.web.context.support.WebApplicationContextUtils.getWebApplicationContext(ServletContext sc) is invoked inside doDependencyInjection(), a reference to the servlet's ServletContext must be obtained, and this is only available after the servlet object has been constructed.