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