Integrating Seam and GWT Integrating the JBoss Seam Framework with the GWT Toolkit : Use cases and patterns Ferda Tartanoglu Neox ia 6563
Who we are 2 > Ferda TARTANOGLU, PhD Consultant and Software Architect at Neox ia > Neoxia A consulting company specialized in information system governance and architecture Based in France (Paris) and Morocco (Casablanca) > The Seam/ GWT team Issam EL FATMI Nizar GARRACHE Mohamed Amine LIMEM Nicolas DASRIAUX
AGENDA 3 > Overview > Int roducing Seam > Int roducing GWT > Why Integrate? > Integration Patterns > Conclusion
Overview 4 > Web application for the company Intranet > Integrating Seam and GWT Complementary technologies > It is also an integration of GWT with Seam s underlying technologies jbpm, JSF, Facelet, EJB3... Seam jbpm JSF Facelet EJB3 Google Web Toolkit > Lessons learned Architectural principles Integration patterns
AGENDA 5 > Overview > Introducing Seam > Int roducing GWT > Why Integrate? > Integration Patterns > Conclusion
Seam overview(1/ 2) 6 > A Java framework For building stateful Web applications With or without Java EE > Glue for integrating several technologies Presentation layer with JSF, Facelets, Richfaces Business logic and persistence with EJB3 and JPA Business processes and workflows with jbpm Business rules with Drools Third party frameworks: Wicket, Spring, GWT > Provides advanced application security Authentication Identity management Authorization
Seam architecture (2/ 2) 7 JSF components Facelets - Richfaces Presentation JSF Request Controller Seam components & contexts Context Management EJB3 jbpm JPA Business Logic State Management
AGENDA 8 > Overview > Int roducing Seam > Introducing GWT > Why Integrate? > Integration Patterns > Conclusion
GWT overview (1/ 2) 9 > GWT provides mainly a Java- to- Javascript compiler Code is written in Java and is compiled to JavaScript Support for major browsers > Rich user interface library GWT widgets Third party widgets > Built- in Ajax No need to code in JavaScript Remoting based on the Servlet standard Server- side code written in Java as a Servlet
GWT model (2/ 2) 10 > Programming model Java with some restrictions Event- based controller like Swing Asynchronous RPC for client- server communication > Deployment model JavaScript for client- side computing Hosted on any Web server Executed on the user s browser Java Servlet for server- side computing WAR packaging since v 1.6
AGENDA 11 > Overview > Int roducing Seam > Int roducing GWT > Why Integrate? > Integration Patterns > Conclusion
A Case Study 12 > An intranet business application with specific requirements Interactive UI Ajax! Security Authentication Secure communication Role- based authorizations Workflows Long- running business processes with several participants Messaging Email Persistence Storage in MySQL database Transactions ACID transactions on DB resources Atomicity and Isolation properties for multi- page/ action interactive sessions
Overlapping Features of Seam & GWT 13 > Rich UI components JavaScript widgets supporting Ajax for GWT JSF components, Richfaces, JSF4Ajax for Seam > Support for server- side computing JavaScript remoting with servlets for GWT Servlets or EJB beans for Seam
Differences of Seam & GWT 14 > Seam lacks Intuitive Ajax widgets Lightweight and ex tensible UI component model JavaScript library for client side components > GWT does not provide Support for stateful services Ex tended persistence contex t Global transactions Bookmarkable pages Support for security Templates
Integration Issues 15 > GWT Oriented single page stateless applications Uses a subset of the JDK > Seam Oriented multi- page stateful applications Some features rely on JSF > We should try Using the benefits of each technologies Minimizing the integration effort
AGENDA 16 > Overview > Int roducing Seam > Int roducing GWT > Why Integrate? > Integration Patterns > Conclusion
Integration Patterns 17 > GWT client side widget in a JSF page > GWT as the presentation layer of Seam > GWT and Seam navigation rules > GWT in a Seam conversation > Taking part in a Seam business process > Seam Security and GWT
Integration Patterns 18 > GWT client side widget in a JSF page > GWT as the presentation layer of Seam > GWT and Seam navigation rules > GWT in a Seam conversation > Taking part in a Seam business process > Seam Security and GWT
Pattern 1 GWT widget in a JSF page (1/ 4) 19 > Coexistance of GWT and JSF on the same page > Using Seam for facelet layouts and themes > GWT widgets for complex components and screens
Pattern 1 GWT widget in a JSF page (2/ 4) 20 > JSF Page <ui:define name="body"> <script language="javascript" src= com.neoxia.gwtseam.gwt.myapplication.nocache.js"></script> <rich:panel > <h:panelgrid columns="2"> <s:div styleclass="info"> <table align="center"> <tr><td id="slot1"></td><td id="slot2"></td></tr> </table> </s:div> </h:panelgrid> </rich:panel> </ui:define>
Pattern 1 GWT widget in a JSF page (3/ 4) > JSF Page : content type <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/dtd/xhtml1- transitional.dtd"> 21 <f:view contenttype="text/html" <html> (...) xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a="http://richfaces.org/a4j" xmlns:s="http://jboss.com/products/seam/taglib">
Pattern 1 GWT widget in a JSF page (4/ 4) > GWT client- side : The widget public class AskQuestionWidget extends Composite { (...) } 22 > GWT client- side : The entry point Binding the widget to the placeholder in the JSF page public class MyApplication implements EntryPoint { public void onmoduleload() { RootPanel.get("slot1").add(new AskQuestionWidget()); } }
Integration Patterns 23 > GWT client side widget in a JSF page > GWT as the presentation layer of Seam > GWT and Seam navigation rules > GWT in a Seam conversation > Taking part in a Seam business process > Seam Security and GWT
Pattern 2 GWT as the presentation layer of Seam (1/ 6) 24 > GWT as the only presentation layer No JSF page No JSF life cycle > GWT widgets access to Seam components with asynchronous requests by JavaScript (Ajax)
Pattern 2 GWT as the presentation layer of Seam (2/ 6) 25 > Service interfaces The remote service interface public interface MyService { } public String askit(string question); GWT client- side asynchronous interface public interface MyServiceAsync extends RemoteService { } public void askit(string question, AsyncCallback callback);
Pattern 2 GWT as the presentation layer of Seam (3/ 6) 26 > GWT widget code The service stub to be used by the GWT client- side widget private MyServiceAsync getservice() { MyServiceAsync svc = (MyServiceAsync)GWT.create(MyService.class); String endpointurl = GWT.getModuleBaseURL() + "seam/resource/gwt"; } ((ServiceDefTarget)svc).setServiceEntryPoint(endpointURL); return svc;
Pattern 2 GWT as the presentation layer of Seam (4/ 6) 27 > GWT client- side: The widget code The remote call getservice().askit(text, new AsyncCallback<String>() { public void onfailure(throwable t) { Window.alert(t.getMessage()); } public void onsuccess(object data) { Window.alert((String) data); } });
Pattern 2 GWT as the presentation layer of Seam (5/ 6) 28 > Server- side Seam component @Name( com.neoxia.gwtseam.gwt.client.myservice") public class ServiceImpl implements MyService { @In Credentials credentials; } @WebRemote public String askit(string question) { String username = credentials.getusername(); return "Hello " + username; }
Pattern 2 GWT as the presentation layer of Seam (6/ 6) 29 GWT Presentation Seam Remoting Request Controller Seam components & contexts Context Management EJB3 jbpm JPA Business Logic State Management
Pattern 1 & 2 GWT remoting + JSF 30 JSF components + GWT widgets Presentation JSF Seam Remoting Request Controller Seam components & contexts Context Management EJB3 jbpm JPA Business Logic State Management
Integration Patterns 31 > GWT client side widget in a JSF page > GWT as the presentation layer of Seam > GWT and Seam navigation rules > GWT in a Seam conversation > Taking part in a Seam business process > Seam Security and GWT
Pattern 3 GWT and Seam navigation rules (1/ 6) 32 > We want to Describe the navigation process using Seam s pages.x ml or jpdl notation Make a remote call to a Seam component from GWT widget Get the URL or render page according to the outcome of the component method and the navigation process
Pattern 3 GWT and Seam navigation rules (2/ 6) > Actions have outcomes 33 public String increment() { value++; return "success"; } > Navigation rules <page view-id= *"> <navigation> <rule if-outcome= success"> <redirect view-id="/home.xhtml"/> </rule> </navigation> </page>
Pattern 3 GWT and Seam navigation rules (3/ 6) 34 > Seam navigation is based on JSF life cycle > Seam remoting bypasses JSF servlet and accesses directly to the SeamResourceServlet No FacesContex t No programmatic navigation API in Seam > Methods called using Seam remoting return directly the output parameter, if any, to the caller
Pattern 3 GWT and Seam navigation rules (4/ 6) 35 > Re- implement JSF navigation layers in the remote service Tight integration, JSF- dependent > Wait for Seam navigation to be promoted to the level of 1st class citizenship JSF- independent navigation API that can be used with any presentation framework > Workaround using 2 subsequent requests First request using remoting API Second request through JSF
Pattern 3 GWT and Seam navigation rules (5/ 6) > The first method called through Seam Remoting public String increment() { value++; return "success"; } 36 > The second method called through JSF The call is a standard JSF call, the method returns the same outcome and JSF render the page selected according to the navigation rules public String redirectme(string outcome) { return outcome; }
Pattern 3 GWT and Seam navigation rules (6/ 6) 37 > Generate a link or make a browser redirect to a specific URL > GWT client side code for the browser redirection public static native void redirect(string url)/*-{ $wnd.location = url; }-*/; > The call to the redirectme action with the outcome as a parameter redirect("http://www.neoxia.com/gwtseam/redirectme?outcome=" + outcome); > Additional navigation rules <page view-id="/redirectme" action="#{redirector.redirectme}"> <param name="outcome" value="#{outcome}"/> </page>
Integration Patterns 38 > GWT client side widget in a JSF page > GWT as the presentation layer of Seam > GWT and Seam navigation rules > GWT in a Seam conversation > Taking part in a Seam business process > Seam Security and GWT
Pattern 4 GWT in a Seam conversation (2/ 5) 39 > Conversational Seam component @Stateful @Name("askQuestion") @Scope(ScopeType.CONVERSATION) public class AskQuestionBean { @PersistenceContext(type=PersistenceContextType.EXTENDED) private EntityManager entitymanager; @In @Out private User user; @Begin public String begin() { (...) } begin ask ask help ask help ask end public String ask() { (...) } public String help() { (...) } @End public String end() { (...) } } @Destroy @Remove public void destroy() {} entitymanager user
Pattern 4 GWT in a Seam conversation (3/ 5) 40 > We need to get the conversation id and send it to the Seam component on the server- side > JavaScript on the client- side.xhtml page to get the conversation id <script language="javascript"> var parameters = { cid: '#{conversation.id}' }; </script> > EL expression #{conversation.id} is used to get the current conversation id
Pattern 4 GWT in a Seam conversation (4/ 5) 41 > GWT client- side : the remote service s async interface public interface GWTtoSeamAsync extends RemoteService { } public void askit(string cid, String question, AsyncCallback callback); > GWT client- side: the widget code The widget makes a remote call and sends the conversation id to the Seam remote service Dictionary parameters = Dictionary.getDictionary("parameters"); String cid = parameters.get("cid"); getservice().askit(cid, text, new AsyncCallback() {...});
Pattern 4 GWT in a Seam conversation (5/ 5) 42 > Seam server- side: the remote Seam component service Service façade: restore the context based on the conversation id and get the service instance in the contex t @Name( com.neoxia.gwtseam.gwt.client.gwttoseam") @Scope(ScopeType.EVENT) public class GWTtoSeamImpl implements GWTtoSeam { @In Manager manager; @WebRemote public String askit(string cid, String question) { // switch to the conversation manager.switchconversation(cid); // get the seam component in the conversation cid MyService myservice = (MyService) Component.getInstance( com.neoxia.gwtseam.gwt.client.myservice"); // call the action String answer = myservice.askit(question); return answer; } }
Integration Patterns 43 > GWT client side widget in a JSF page > GWT as the presentation layer of Seam > GWT and Seam navigation rules > GWT in a Seam conversation > Taking part in a Seam business process > Seam Security and GWT
Pattern 5 GWT and Seam Business Processes (1/ 4) 44
Pattern 5 GWT and Seam Business Processes (2/ 4) 45 > Seam JBPM annotations @CreateProcess @ResumeProcess @StartTask @BeginTask @EndTask @Transition > Implicit parameters : taskid and processid Value of the taskid and processid http request parameters > taskid and processid http request parameters not sent with GWT AJAX calls
Pattern 5 GWT and Seam Business Processes (3/ 4) 46 > 1 st solution: switch to direct jbpm API calls and programmatically get the ids @Stateful @Name("com.neoxia.intranet.demandeconge.client.DemandeCongeService") @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public class DemandeCongeServiceBean implements DemandeCongeService { @In private Actor actor; @CreateProcess(definition = "DemandeCongeProcess") public void createdemandecongeprocess(demandecongevo demandeconge) {( )} @TransactionAttribute(TransactionAttributeType.REQUIRED) public void updateetatdemandeconge(demandecongevo demandeconge) { JbpmConfiguration jbpmconfiguration = JbpmConfiguration.getInstance(); JbpmContext jbpmcontext = jbpmconfiguration.createjbpmcontext(); TaskMgmtSession taskmgmtsession = jbpmcontext.gettaskmgmtsession(); ProcessInstance processinstance = jbpmcontext.getprocessinstance(demandeconge.getid()); TaskInstance taskinstance = jbpmcontext.gettaskinstanceforupdate(processinstance.getid()); ( )
Pattern 5 GWT and Seam Business Processes (4/ 4) 47 > 2 nd solution: use GWT s RequestBuilder class to make direct HTTP calls Get the taskid using Seam EL in the page <script language="javascript"> var parameters = { taskid: '#{task.id} }; </script> Send the taskid as a method parameter Dictionary parameters = Dictionary.getDictionary("parameters"); String cid = parameters.get( taskid"); Construct the HTTP GET request with taskid as a http request parameter String url = "http://www.neoxia.com/gwt/step?taskid="+taskid; RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(url)); builder.setheader("content-type", "application/x-www-form-urlencoded"); try { builder.sendrequest(null, new RequestCallback() { /*(...)*/ }); } catch (RequestException e) { // Couldn't connect to server }
Integration Patterns 48 > GWT client side widget in a JSF page > GWT as the presentation layer of Seam > GWT and Seam navigation rules > GWT in a Seam conversation > Taking part in a Seam business process > Seam Security and GWT
Pattern 6 GWT and Seam Security (1/ 3) 49 > Hide a GWT widget based on Seam security rules > Adapting remote service behaviour based on user permissions
Pattern 6 GWT and Seam Security (2/ 3) 50 > Client- side, with JSF Hide a GWT widget based on Seam security rules <rich:panel > <h:panelgrid columns="2"> <s:div styleclass="info" rendered="#{identity.loggedin}"> <table align="center"> <tr><td id="slot1"></td><td id="slot2"></td></tr> </table> </s:div> </h:panelgrid> </rich:panel>
Pattern 6 GWT and Seam Security (3/ 3) 51 > Server- side: Accessing identity, credentials... Automatically injected by Seam! @Name( com.neoxia.gwtseam.gwt.client.myservice") public class ServiceImpl implements MyService { @In Identity identity; @In Credentials credentials;
AGENDA 52 > Overview > Int roducing Seam > Int roducing GWT > Why Integrate? > Integration Patterns > Conclusion
Conclusion 53 > We can use both GWT and Seam in the same project Some features integrate seamlessly Other features need more integration effort There are still few workarounds > GWT and Seam are both very active projects > GWT is now better integrated with Java EE standards JDK1.5 support since version 1.5 War packaging since version 1.6 > Seam is more and more decoupled from JSF and from JBoss AS Better GWT integration support since version 2.1.1
Questions 54
Ferda TARTANOGLU NEOXIA ferda.tart anoglu@neox ia.com http:/ / www.neoxia.com