Integrating Seam and GWT

Arya MirInternet και Εφαρμογές Web

6 Νοε 2011 (πριν από 5 χρόνια και 10 μήνες)

1.352 εμφανίσεις

Introducing Seam Introducing GWT Why Integrate? Integration Patterns

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
>
Int roducing
Seam
>
Int roducing
GWT
>
Why Int egrat e?
>
Int egrat ion Pat t erns
>
Conclusion

4
Overview
>
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 ...
>
Lessons learned

Architectural principles

Integrat ion patterns
Seam
Google Web Toolkit
jBPM
JSF
Facelet
EJB3

5
AGENDA
>
Overview
>
Introducing
Seam
>
Int roducing
GWT
>
Why Int egrat e?
>
Int egrat ion Pat t erns
>
Conclusion

6
Seam
overview
(1/2)
>
A Java framework

For building stateful Web applications

With or without J
ava
EE
>
Glue
for integrating several technologies

Presentation layer with JSF,
Facelet s,
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
Seam components & contexts
jBPM
JPA
EJB3
Presentation
Request Controller
Context Management
Business Logic
State Management
JSF

8
AGENDA
>
Overview
>
Int roducing
Seam
>
Introducing
GWT
>
Why Int egrat e?
>
Int egrat ion Pat t erns
>
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 Ajax

No need to code in JavaScript

Remoting based on the Servlet standard

Server- side code writt en in Java as a Servlet

10
GWT model
(2/2)
>
Programming model

Java with some restrictions

Event- based cont roller
like

Swing

Asynchronous RPC for client- server communication

>
Deployment model

JavaScript for client- side computing

Host ed on any Web server

Execut ed on the user’s browser

Java Servlet for server- side computing

WAR packaging since v 1.6

11
AGENDA
>
Overview
>
Int roducing
Seam
>
Int roducing
GWT
>
Why Integrate?
>
Int egrat ion Pat t erns
>
Conclusion

12
A Case Study
>
An intranet business application with
specific

requirements

Interactive U
I

Aj ax !

Security

Aut hent ication

Secure communicat ion

Role- based aut horizat ions

Workflows

Long- running business processes wit h several participants

Messaging

Email

Persistence

St orage in MySQL dat abase

Transactions

ACID t ransact ions on DB resources

At omicit y and Isolat ion propert ies for mult i- page/act ion int eractive 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 comput ing

JavaScript remot ing with servlets for GWT

Servlets or EJB beans for Seam

14
Differences
of Seam & GWT
>
Seam lacks

Intuit ive 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

Bookmar
k
able pages

Support for s
ecurity

Templates

15
Integration
Issues
>
GWT

O
riented single page stateless applications

U
ses a subset of the JDK
>
Seam

O
riented 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
>
Int roducing
Seam
>
Int roducing
GWT
>
Why Int egrat e?
>
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

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

21
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"
>
<
f:view

contentType
=
"text/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"
>
<
html
>
(...)

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 wit h asynchronous requests by
JavaScript (Ajax)

25
Pattern
2
GWT as the presentation layer of Seam (2/6)
>
S
ervice 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 w
idget 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);

}
});


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
Seam Remoting
Seam components & contexts
jBPM
JPA
EJB3
Presentation
Request Controller
Context Management
Business Logic
State Management

30
Pattern

1 &
2
GWT remoting + JSF
JSF components + GWT widgets
Seam Remoting
Seam components & contexts
jBPM
JPA
EJB3
Presentation
Request Controller
Context Management
Business Logic
State Management
JSF

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 not ation

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
<
page

view-id
=

*
"
>

<
navigation
>

<
rule

if-outcome
=

success
"
>

<
redirect

view-id
=
"/home.xhtml"
/>

</
rule
>

</
navigation
>
</
page
>

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
request
s

First request using remoting API

Second request through JSF

36
Pattern
3
GWT and Seam navigation rules (5/6)
>
The first met hod 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)
>
G
enerate 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 n
avigation rules
<
page

view-id
=
"/redirectme"

action
=
"#{redirector.redirectme}"
>

<
param

name
=
"outcome"

value
=
"#{outcome}"
/>
</
page
>


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

public
String begin() { (...) }


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

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

@End

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


@Destroy

@Remove

public

void
destroy() {}
}
begin
end
ask
ask
ask
help
ask
help
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 c
lient - side
.xhtml
page
to get the conversat ion id
<
script

language
=
"javascript"
>

var
parameters = {

cid: '#{conversation.id}'

};
</
script
>
>
EL expression #{conversation.id} is used to get the current conversation id

41
Pattern
4
GWT in a Seam conversation

(4/5)
>
GWT c
lient- side : the remote service’s async interface
public

interface
GWTtoSeamAsync
extends
RemoteService {
public

void
askIt(
String cid
, String question, AsyncCallback
callback);
}
>
GWT c
lient- 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 s
erver- 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
)
>
1
st
solut ion: swit ch to direct j BPM 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
)
>
2
nd
solution: use GWT’s RequestBuilder class to make direct HTTP calls

Get t he t askId using Seam EL in t he page

<
script

language
=
"javascript"
>

var
parameters = { taskid: '#{task.id}‘ };

</
script
>

Send t he taskid as a met hod paramet er

Dictionary parameters
=
Dictionary.
getDictionary
(
"parameters"
);

String cid = parameters.get(

task
id"
);

Construct the HTTP GET request wit h t askid as a
ht t p request
paramet er

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

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
>
Int roducing
Seam
>
Int roducing
GWT
>
Why Int egrat e?
>
Int egrat ion Pat t erns
>
Conclusion

53
Conclusion
>
We can use both GWT and Seam in the same project

Some features int egrate 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 J
ava
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
ht tp://www.neoxia.com
NEOXIA
ferda.t art anoglu@neoxia.com