Integrating Seam and GWT Integrating the JBoss Seam Framework with the GWT Toolkit : Use cases and patterns

Ferda Tartanoglu Neoxia 6563 2 Who we are

> Ferda TARTANOGLU, PhD – Consultant and Software Architect at Neoxia > 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 3 AGENDA

> Overview > Introducing Seam > Introducing GWT > Why Integrate? > Integration Patterns > Conclusion 4 Overview

> Web application for the company Intranet Seam

> Integrating Seam and GWT – Complementary technologies jBPM JSF Facelet EJB3

> It is also an integration of GWT with Seam’s underlying technologies – jBPM, JSF, Facelet, EJB3 ...

> Lessons learned – Architectural principles – Integration patterns 5 AGENDA

> Overview > Introducing Seam > Introducing GWT > Why Integrate? > Integration Patterns > Conclusion 6 Seam overview(1/ 2)

> A 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 7 Seam architecture (2/ 2)

JSF components – Facelets - Richfaces Presentation

JSF Request Controller

Seam components & contexts Context Management

EJB3 jBPM JPA Business Logic State Management 8 AGENDA

> Overview > Introducing Seam > Introducing GWT > Why Integrate? > Integration Patterns > Conclusion 9 GWT overview (1/ 2)

> 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 – No need to code in JavaScript – Remoting based on the Servlet standard  Server- side code written in Java as a Servlet 10 GWT model (2/ 2)

> 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 11 AGENDA

> Overview > Introducing Seam > Introducing GWT > Why Integrate? > Integration Patterns > Conclusion 12 A Case Study

> 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 13 Overlapping Features of Seam & GWT

> 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 14 Differences of Seam & GWT

> Seam lacks – Intuitive Ajax widgets – Lightweight and extensible UI component model – JavaScript library for client side components

> GWT does not provide – Support for stateful services – Extended persistence context – Global transactions – Bookmarkable pages – Support for security – Templates 15 Integration Issues

> 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 16 AGENDA

> Overview > Introducing Seam > Introducing GWT > Why Integrate? > Integration Patterns > Conclusion 17 Integration Patterns

> 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 18 Integration Patterns

> 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 19 Pattern 1 GWT widget in a JSF page (1/ 4) > Coexistance of GWT and JSF on the same page

> Using Seam for facelet layouts and themes

> GWT widgets for complex components and screens 20 Pattern 1 GWT widget in a JSF page (2/ 4) > JSF Page

21 Pattern 1 GWT widget in a JSF page (3/ 4) > JSF Page : content type

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"> (...) 22 Pattern 1 GWT widget in a JSF page (4/ 4) > GWT client- side : The widget public class AskQuestionWidget extends Composite { (...) }

> 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()); } } 23 Integration Patterns

> 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 24 Pattern 2 GWT as the presentation layer of Seam (1/ 6) > 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) 25 Pattern 2 GWT as the presentation layer of Seam (2/ 6) > 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); } 26 Pattern 2 GWT as the presentation layer of Seam (3/ 6) > 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; } 27 Pattern 2 GWT as the presentation layer of Seam (4/ 6) > GWT client- side: The widget code – The remote call getService().askIt(text, new AsyncCallback() { public void onFailure(Throwable t) { Window.alert(t.getMessage()); }

public void onSuccess(Object data) { Window.alert((String) data); } }); 28 Pattern 2 GWT as the presentation layer of Seam (5/ 6) > 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; } } 29 Pattern 2 GWT as the presentation layer of Seam (6/ 6)

GWT Presentation

Seam Remoting Request Controller

Seam components & contexts Context Management

EJB3 jBPM JPA Business Logic State Management 30 Pattern 1 & 2 GWT remoting + JSF

JSF components + GWT widgets Presentation

JSF Seam Remoting Request Controller

Seam components & contexts Context Management

EJB3 jBPM JPA Business Logic State Management 31 Integration Patterns

> 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 32 Pattern 3 GWT and Seam navigation rules (1/ 6) > We want to – Describe the navigation process using Seam’s pages.xml 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 33 Pattern 3 GWT and Seam navigation rules (2/ 6) > Actions have outcomes public String increment() { value++; return "success"; }

> Navigation rules

34 Pattern 3 GWT and Seam navigation rules (3/ 6)

> Seam navigation is based on JSF life cycle

> Seam remoting bypasses JSF servlet and accesses directly to the SeamResourceServlet – No FacesContext – No programmatic navigation API in Seam

> Methods called using Seam remoting return directly the output parameter, if any, to the caller 35 Pattern 3 GWT and Seam navigation rules (4/ 6) > 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 36 Pattern 3 GWT and Seam navigation rules (5/ 6) > The first method called through Seam Remoting public String increment() { value++; return "success"; }

> 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; } 37 Pattern 3 GWT and Seam navigation rules (6/ 6) > 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

38 Integration Patterns

> 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 39 Pattern 4 GWT in a Seam conversation (2/ 5) > 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 begin ask ask help ask help ask end public String begin() { (...) }

public String ask() { (...) }

public String help() { (...) }

@End public String end() { (...) }

@Destroy @Remove public void destroy() {} entityManager user } 40 Pattern 4 GWT in a Seam conversation (3/ 5) > 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

> EL expression #{conversation.id} is used to get the current conversation id 41 Pattern 4 GWT in a Seam conversation (4/ 5) > 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() {...}); 42 Pattern 4 GWT in a Seam conversation (5/ 5) > 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 context @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; } } 43 Integration Patterns

> 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 44 Pattern 5 GWT and Seam Business Processes (1/ 4) 45 Pattern 5 GWT and Seam Business Processes (2/ 4) > 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 46 Pattern 5 GWT and Seam Business Processes (3/ 4)

> 1st 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()); (…) 47 Pattern 5 GWT and Seam Business Processes (4/ 4)

> 2nd solution: use GWT’s RequestBuilder class to make direct HTTP calls – Get the taskId using Seam EL in the page – 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 } 48 Integration Patterns

> 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 49 Pattern 6 GWT and Seam Security (1/ 3)

> Hide a GWT widget based on Seam security rules

> Adapting remote service behaviour based on user permissions 50 Pattern 6 GWT and Seam Security (2/ 3) > Client- side, with JSF – Hide a GWT widget based on Seam security rules

51 Pattern 6 GWT and Seam Security (3/ 3) > 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; 52 AGENDA

> Overview > Introducing Seam > Introducing GWT > Why Integrate? > Integration Patterns > Conclusion 53 Conclusion

> 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 54 Questions Ferda TARTANOGLU http:/ / www.neoxia.com NEOXIA [email protected]