GWT, jpa, spring, spring security & GAE all together

Very hard to find a single article covering all the topics together. I was able to complete this setup after struggling around a week. Here below are the steps on how to configure gwt application under the spring framework along with spring security. It also works on a GAE (google app engine) server. Every get service should extend from the class GWTSpringController. This makes get service runs on the spring context on the server side.

So lets first create GWTSpringController class. 

GWT Spring Controller

		
package com.beda.pushurl.server;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public abstract class GWTSpringController extends RemoteServiceServlet implements Controller, ServletContextAware {
private ServletContext servletContext;
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Override
public ServletContext getServletContext() {
return servletContext;
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
super.doPost(request, response);
return null;
}
}
 

EMF.java (Entity manager factory class)

		
package com.beda.pushurl.server;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public final class EMF {
private static final EntityManagerFactory emfInstance =
Persistence.createEntityManagerFactory("transactions-optional");
private EMF() {}
public static EntityManagerFactory get() {
return emfInstance;
}
}
 

Create domain classes and Dao classes User.java (domain object ) keep in mind that we are using jpa to database operations along with spring. This class inherits from the UserDetails class.

		
package com.beda.pushurl.server.domain;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.beda.pushurl.server.domain.Authority;
import com.google.appengine.api.datastore.Key;

@Entity
public class User  implements UserDetails {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Key key;
	public Key getKey()
	{
		return key;
	}
	public void setKey(Key key)
	{
		this.key=key;
	}
	private String userName;

	private String password;

	private String displayName;

	private  ArrayList authorities;

	public User() {
		authorities=new ArrayList();
	}

	public void setUsername(String name) {
		this.userName = name;
	}

	public void setDisplayName(String displayName) {
		this.displayName = displayName;
	}

	public String getDisplayName() {
		return displayName;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPassword() {
		return password;
	}

	public Collection getAuthorities() {
		Collection test= new ArrayList();
		for(int i=0;i

    	
    
    

Authority.java

		
package com.beda.pushurl.server.domain;

import org.springframework.security.core.GrantedAuthority;

public class Authority implements GrantedAuthority {

	private String authority;
	public void setAuthority(String authority)
	{
		this.authority=authority;
	}
	public String getAuthority() {
		// TODO Auto-generated method stub
		return authority;
	}

}
 

Create genertic dao interface. (it serves basic crud operation, getall, getbyid,add,update,delete)

		
package com.beda.pushurl.server.dao;

import java.io.Serializable;
import java.util.List;

public interface Dao {
	public void Save(T object);

	public void Delete(T object);

	public List GetAll();

	public T Get(ID id);

	public List GetByQueryString(String queryString);
}
 

Implement the generic dao

		
package com.beda.pushurl.server.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.jdo.annotations.Transactional;
import javax.persistence.EntityManager;

import org.springframework.orm.jpa.JpaTemplate;

import com.beda.pushurl.server.EMF;

public abstract class DaoImpl implements Dao {
	protected EntityManager entityManager;

	JpaTemplate jpaTemplate;

	DaoImpl()
	{
		this.entityManager= EMF.get().createEntityManager();
		jpaTemplate= new JpaTemplate(entityManager);
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
		jpaTemplate= new JpaTemplate( entityManager);
	}

	Class persistanceClass;

	public void Delete(T object) {
		jpaTemplate.remove(object);
	}

	public List GetAll() {

		return entityManager.createQuery("SELECT  FROM " + getPersistanceClass().getName()).getResultList();

	}

	@Transactional
	public void Save(T object) {

		object=entityManager.merge(object);
		entityManager.persist(object);

	}

	public List GetByQueryString(String queryString) {

		return entityManager.createQuery(queryString).getResultList();
	}

	public T Get(ID id) {

		return jpaTemplate.find(getPersistanceClass(), id);
	}
	private Class getPersistanceClass()
	{
		if (persistanceClass == null)
			persistanceClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

		return persistanceClass;
	}

}
 

Create userdao interface extenuating the generic dao.

		
package com.beda.pushurl.server.dao;

import com.beda.pushurl.server.domain.User;

public interface UserDAO extends Dao {

	public User getByUsername(String userName);
}
 

Implement userdao.

		
package com.beda.pushurl.server.dao;

import java.util.List;

import com.beda.pushurl.server.domain.User;

public class UserDAOImpl extends DaoImpl implements UserDAO {

	public User getByUsername(String userName) {
		// TODO Auto-generated method stub
		List users= this.GetByQueryString("select u FROM User u where u.userName='" + userName +"'" );
		if(users.size()>0)return users.get(0);
		return null;
	}

} 

Create GWT services. Gwt service extends RemoteServiceServlet class. But here we are using GWT along with Spring framework, so we have created a class (named GWTSpringController) extending RemoteServiceServlet and implementing required spring interfaces. Now every GWT services will extend from the GWTSpringController(Remember this class is created at the top of this article) GWT client side 

AuthenticationService.java

		
package com.beda.pushurl.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("auth.rpc")
public interface AuthenticationService extends RemoteService {

	String getCurrentUser();
	boolean checkAuthentication();
} 

AuthenticationServiceAsync

		
package com.beda.pushurl.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface AuthenticationServiceAsync {

	void getCurrentUser(AsyncCallback callback);

	void checkAuthentication(AsyncCallback callback);

} 

AuthenticationServiceImpl.java(Implementation of AutheticationService on service side)

		
package com.beda.pushurl.server;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import com.beda.pushurl.client.AuthenticationService;

public class AuthenticationServiceImpl extends GWTSpringController implements
		AuthenticationService {

	public String getCurrentUser() {
		// TODO Auto-generated method stub
		final Object[] currentUser = SecurityContextHolder.getContext().getAuthentication().getAuthorities().toArray();
		String data="";
		for(int i=0;i

    	
    
    

See below how i have use autheticationService to redirect to the login page (if user is not logged in) on gwt modules.

		public class PushUrl implements EntryPoint {

	public void onModuleLoad() {

		setUserInfo();

	}
}
private void setUserInfo()
	{
		AsyncCallback callback = new AsyncCallback() {

			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
				//display error message
			}

			public void onSuccess(String result) {
				// TODO Auto-generated method stub
				if(result.contains("ROLE_ANONYMOUS"))
				{
					 String url="/login.jsp";
					 Window.open(url, "_self", "");
				}
				}

		};
		authService.getCurrentUser(callback);
	} 

Configuration side (web.xml)

		





  
        dispatcher
        org.springframework.web.servlet.DispatcherServlet
        1
  
  
  dispatcher
  *.rpc
  

  
    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy
	
	
    springSecurityFilterChain
    /*
	

 
    org.springframework.web.context.ContextLoaderListener
  

  
  
    PushUrl.html
  


 

dispatcher-servlet.xml

		



	
		
			
			/**/users.rpc=userService
			/**/categories.rpc=categoryService
			/**/auth.rpc=authService
			
		
	
 

appengine-web.xml

		


	pushurl
	1

	
	
		
	
	true
 

applicationContext.xml

		


	
		

		
	
	
				
				
	
	
				
	
	
		
	
	

	

	

	
	
	
	
		
		
		
		
    	
    	
    	
    

	
  

   
  


 
blog comments powered by Disqus