Seam 2.2.0 + GWT 2.0.3 + Gilead 1.3.1
sunfire Apr 16, 2010 8:45 PMWell, I just managed to get a very basic integration of Seam, GWT and Gilead going and since it took me a few hours I thought I post the result here so maybe to save somebody else some of the headaches I had.
First thing to to is get GWT 2.0.3 and Seam 2.2.0 working together. You can find a guide and the required classes here. It is quite nice and it worked for me within minutes.
Next thing to get the Gilead integration is to put these classes into your application:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface GileadEnabled { }
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.jboss.seam.annotations.intercept.Interceptors; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Interceptors(GileadEnabledInterceptor.class) public @interface GileadEnabledClass { }
import java.lang.reflect.Method; import net.sf.gilead.gwt.GileadRPCHelper; import org.jboss.seam.Component; import org.jboss.seam.annotations.intercept.AroundInvoke; import org.jboss.seam.annotations.intercept.Interceptor; import org.jboss.seam.intercept.AbstractInterceptor; import org.jboss.seam.intercept.InvocationContext; import org.jboss.seam.transaction.TransactionInterceptor; import org.jboss.seam.web.ServletContexts; @SuppressWarnings("serial") @Interceptor(stateless = true,around={TransactionInterceptor.class}) public class GileadEnabledInterceptor extends AbstractInterceptor { @AroundInvoke public Object aroundInvoke(InvocationContext ic) throws Exception { Method m = ic.getMethod(); GileadEnabled ge = m.getAnnotation(GileadEnabled.class); if (ge != null) { GileadSetup gileadSetup = (GileadSetup) Component.getInstance("gileadSetup"); Object[] parameters = ic.getParameters(); GileadRPCHelper.parseInputParameters(parameters, gileadSetup.getBeanManager(), ServletContexts.getInstance().getRequest().getSession()); Object result = ic.proceed(); result = GileadRPCHelper.parseReturnValue(result, gileadSetup.getBeanManager()); return result; } else { return ic.proceed(); } } public boolean isInterceptorEnabled() { return true; } }
The last part you need is a class that will setup some Gilead stuff
@SuppressWarnings("serial") @Name("gileadSetup") @Scope(ScopeType.SESSION) @AutoCreate public class GileadSetup extends PersistentRemoteService { public GileadSetup() { //here you need to setup Gilead as you would usually do if you use Gilead as a servlet. //note that the EntityManagerFactory you use initialize Gilead should be the same as the one used //to setup your seam EntityManager's if you want to use Seam managed persistence contexts for Gilead entities } }
That should be it. You now have two new annotations to make sure Gilead is modifying the entities transfered between GWT and your Seam component.
Here a little example to see how it can be used:
import javax.persistence.EntityManager; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.remoting.WebRemote; @Name("your.gwt.gilead.example.SimpleGwtRPCDSService") @Scope(ScopeType.SESSION) @GileadEnabledClass public class SimpleGwtRPCDSServiceImpl implements SimpleGwtRPCDSService { @In(create = true) private EntityManager entityManager; @WebRemote @GileadEnabled @Transactional public User add(User record) { entityManager.persist(record); return record; } @SuppressWarnings("unchecked") @WebRemote @GileadEnabled public List<User> fetch() { List<User> userList = entityManager.createQuery("SELECT u FROM User u").getResultList(); return userList; } @WebRemote @GileadEnabled @Transactional public void remove(User record) { entityManager.remove(record); } @WebRemote @GileadEnabled @Transactional public User update(User record) { return entityManager.merge(record); } }
This is kind of a stupid example but you see that you will have to annotate your component class with @GileadEnabledClass and every method with entities as parameters or as a result need to be annotated with @GileadEnabled.
You can now get a reference to the component from your GWT client as it is described in the regular Seam docs. Note that you will need to setup the Gilead as usual and all its restrictions apply. This is really just so that you can use Seam components in all their glory as your GWT/Gilead service endpoints instead of regular servlets that extend from PersistentRemoteService.
Please also note that this is the first time that I played around with GWT and also Gilead so I have no idea if it will work for more complex scenarios or if it will just be a total fail... maybe some GWT/Gilead guru has some nice improvement ideas? :)
Suggestions are always welcome.
Cheers, Thorsten