SlideShare une entreprise Scribd logo
1  sur  92
Télécharger pour lire hors ligne
The Magnificent Java EE 7	

in Wildfly-O-Rama
Antoine Sabot-Durand	

Java EE Expert	

Senior Software Developer @ Red Hat	

@antoine_sd
Antoine Sabot-Durand
Senior Software Developer at Red Hat	

Architect and Tech consultant	

16 years in IT	

Java & OSS :	

CDI co-spec lead	

CDI community development	

Agorava technical leader	


@antoine_sd
What’s in there ?
Short Java EE 7 Intro 	

Java EE History	

Java EE 7 main features	

Java EE 7 Content	

WildFly	

WildFly Roadmap	


Java EE 7 in action
Java EE Introduction
Java EE History

1998

1999

2000

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013
Java EE History

Java Professional
Edition	

Mai 1998

1998

1999

2000

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013
Java EE History

Java Professional
Edition	

Mai 1998

1998

1999

J2EE 1.2	

12/12/1999

2000

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013
Java EE History

Java Professional
Edition	

Mai 1998

1998

1999

J2EE 1.2	

12/12/1999

2000

J2EE 1.3	

09/24/2001

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013
Java EE History

Java Professional
Edition	

Mai 1998

1998

1999

J2EE 1.2	

12/12/1999

2000

J2EE 1.3	

09/24/2001

2001

2002

J2EE 1.4	

11/11/2003

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013
Java EE History

Java Professional
Edition	

Mai 1998

1998

1999

J2EE 1.2	

12/12/1999

2000

J2EE 1.3	

09/24/2001

2001

2002

J2EE 1.4	

11/11/2003

2003

Java EE 5	

05/11/2006

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013
Java EE History

Java Professional
Edition	

Mai 1998

1998

1999

J2EE 1.2	

12/12/1999

2000

J2EE 1.3	

09/24/2001

2001

2002

J2EE 1.4	

11/11/2003

2003

Java EE 5	

05/11/2006

2004

2005

2006

2007

Java EE 6	

12/10/2009

2008

2009

2010

2011

2012

2013
Java EE History

Java Professional
Edition	

Mai 1998

1998

1999

J2EE 1.2	

12/12/1999

2000

J2EE 1.3	

09/24/2001

2001

2002

J2EE 1.4	

11/11/2003

2003

Java EE 5	

05/11/2006

2004

2005

2006

2007

Java EE 6	

12/10/2009

2008

2009

Java EE 7	

06/22/2013

2010

2011

2012

2013
Java EE 7 Main Features
WebSocket client/server endpoints	

Batch Applications	

JSON Processing	

Concurrency Utilities	

Simplified JMS API	

@Transactional and @TransactionScoped	

JAX-RS Client API	

Pervasive CDI	

More annotated POJOs	

Faces Flow
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
Java EE 7 JSR
CDI
Extensions

JSF 2.2,

JSP 2.3,

EL 3.0

Web
Fragments

JAX-RS 2.0,
JAX-WS 2.2

JSON 1.0

WebSocket
1.0

CDI 1.1

Interceptors

1.2, JTA 1.2

Common
Annotations 1.1

EJB 3.2

Managed Beans 1.0

JPA 2.1

JMS 2.0

Concurrency 1.0

JCA 1.7

Batch 1.0

Bean
Validation
1.1

Servlet 3.1
JBoss WildFly
Previously named JBoss Application Server	

Named change to better differentiate Community from Supported
product	


Support Java EE 7	

Fast, Lightweight, Manageable	

Developer Friendly	

Open Source
WildFly Roadmap
Alpha 1 - May 2013	

Alpha 2 - June 2013 (Java EE 7 released on the 22)	

Alpha 3 - July 2013	

Alpha 4 - August 2013	

Beta 1 - October 2013	

CR1 - December 2013	

Final - Mar/Apr 2014 	

That’s 8/9 months after EE 7 release (better than 2 years for AS 7)
Download WildFly today

http://wildfly.org
Let’s get some action !
Welcome to Chat-e-Chat-o
Chat-e-Chat-o is a Startup which develop a SaaS chat service	

We raised fund from VC to create their first release	

CTO decided to use Java EE 7 to develop the service	

As the main developer, you have the task to implement all the
feature asked by marketing	

Events and name in this HOL are totally fictive	

Situation and use cases are simplified	

This is your story...
At the beginning
After reading some doc.You created the first chat demo	

It contains 4 files	

pom.xml : Maven configuration file 	

ChatEndPoint.java : A Java class corresponding to a websocket Endpoint	

index.html : Home Page of the Service	

websocket.js : a little JS lib to exchange with the server	


This 4 files are enough to start the application server with a (very)
basic chat service
Git Start
git clone git@github.com:antoinesd/magnificent-java-ee7.git!
!

git checkout beginning
pom.xml 1/2







<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>org.lab.javaee</groupId>

<artifactId>demo-chat</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>war</packaging>

<name>demo-chat</name>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>javax</groupId>

<artifactId>javaee-api</artifactId>

<version>7.0</version>

<scope>provided</scope>

</dependency>

</dependencies>

pom.xml 2/2
<build>

<finalName>${project.name}</finalName>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.0</version>

<configuration>

<source>1.7</source>

<target>1.7</target>

</configuration>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-war-plugin</artifactId>

<version>2.3</version>

<configuration>

<failOnMissingWebXml>false</failOnMissingWebXml>

</configuration>

</plugin>

<plugin>

<groupId>org.wildfly.plugins</groupId>

<artifactId>wildfly-maven-plugin</artifactId>

<version>1.0.0.Beta1</version>
<configuration>

<version>8.0.0.CR1</version>

</configuration>

</plugin>

</plugins>

</build>

</project>
index.html
<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>WebSocket Chat</title>

</head>

<body>

<h1>Chat!</h1>

<div style="text-align: center;">

<form action="">

<table>

<tr>

<td>

Users<br/>

<textarea readonly="true" rows="6" cols="20" id="userField"></textarea>

</td>

<td>

Chat Log<br/>

<textarea readonly="true" rows="6" cols="50" id="chatlogField"></textarea>

</td>

</tr>

<tr>

<td colspan="2">

<input id="textField" name="name" value="Duke" type="text"><br>

<input onclick="join();" value="Join" type="button">

<input onclick="send_message();" value="Chat" type="button">

</td>

</tr>

</table>

</form>

</div>

<div id="output"></div>

<script language="javascript" type="text/javascript" src="websocket.js"></script>

</body>

</html>
websocket.js
var
var
var
var



wsUri = "ws://" + document.location.host + "/demo-chat/websocket";

websocket = new WebSocket(wsUri);

username;

output = document.getElementById("output");


websocket.onopen = function (evt) {onOpen(evt)};

websocket.onmessage = function (evt) {onMessage(evt)};

websocket.onerror = function (evt) {onError(evt)};


!

function join() {

username = textField.value;

websocket.send(username + " joined");

}


!
function
!
function
!

send_message() {websocket.send(username + ": " + textField.value);}

onOpen() {writeToScreen("Connected to " + wsUri);}


function onMessage(evt) {

console.log("onMessage");

writeToScreen("RECEIVED: " + evt.data);

if (evt.data.indexOf("joined") != -1) {

userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "n";

} else {

chatlogField.innerHTML += evt.data + "n";

}

}


!
function
!

onError(evt) {writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);}


function writeToScreen(message) {output.innerHTML += message + "<br>";}
ChatEndPoint.java
import
import
import
import

!

javax.websocket.*;

javax.websocket.server.ServerEndpoint;

java.io.IOException;

java.util.*;


@ServerEndpoint("/websocket")

public class ChatEndpoint {

private static final Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());




@OnOpen

public void onOpen(Session peer) {

peers.add(peer);

}




@OnClose

public void onClose(Session peer) {

peers.remove(peer);

}




@OnMessage

public void message(String message, Session client) throws IOException, EncodeException {

for (Session peer : peers) {

peer.getAsyncRemote().sendText(message);

}

}

}

Files organization & launching
Files must be organized like this way	

To launch the app	

In your shell, go to the directory containing
the pom.xml file	

and type :	

mvn clean package wildfly:run!

To test the app browse to :	

http://localhost:8080/demo-chat
Step 1 : Create a Chat Service
As we will add functionalities to our application, we want to
separate future business logic from the Websocket endpoint	

That’s why we decide to create a ChatService classes to deal
with chat business logic	

To implement this you’ll have to :	

Activate CDI	

Create ChatService CDI Bean	

Remove all business logic from ChatEndpoint to put it in
ChatService
Git Shortcut

git checkout step_1
Activate CDI

To activate CDI you only have to
create an empty file named
beans.xml in folder

src/main/webapp/WEB-INF

beans.xml
!
ChatService.java
@ApplicationScoped

public class ChatService {




private final Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());




public boolean add(Session session) {

return peers.add(session);

}




public boolean remove(Object o) {

return peers.remove(o);

}






public void processMessage(String message) {

for (Session peer : peers) {

peer.getAsyncRemote().sendText(message);

}

}

}
ChatEndPoint.java
@ServerEndpoint("/websocket")

public class ChatEndpoint {




@Inject

private ChatService service;




@OnOpen

public void onOpen(Session peer) {

service.add(peer);

}




@OnClose

public void onClose(Session peer) {

service.remove(peer);

}




@OnMessage

public void message(String message, Session client) throws IOException, EncodeException {

service.processMessage(message);

}

}
Step 2 : Keyword detection
Our main partner is the Poodle website.They want to embed our
service but they need a solution to detect keywords in chat to
feed their advertising platform	

You decide to build a prototype of this feature with CDI built-in
observer pattern	

To implement this you’ll have to :	

Modify ChatService class by :	

Injecting an Event generator in the endpoint	

Modifying the message() method to fire the event	


Create an observer bean for the event
Git Shortcut

git checkout step_2
ChatService.java
import javax.enterprise.event.Event;

import javax.inject.Inject;
...


!

@ApplicationScoped

public class ChatService {



...
@Inject

private Event<String> events;
...


public void processMessage(String message) {

if (message.toLowerCase().indexOf("world") > -1)

events.fire(message);

for (Session peer : peers) {

peer.getAsyncRemote().sendText(message);

}

}
}

Bean with Observer

import javax.enterprise.event.Observes;




public class MessageObserver {




public void observesWorldMessages(@Observes String msg) {

System.out.println("Keyword was trapped : " + msg);

}

}
Keyword detection result
In your shell, go to the directory containing the pom.xml file	

and type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

When you type a message with «world» inside an event is
fired and an alert is written on the console
Step 3 : More decoupling with AOP
Ok, our system to detect certain keywords works nicely with some
kind of decoupling thanks to CDI events	

But the team is not happy to have this code directly into the service.
If other filtering needs occur, we’ll have a big if cascade in
processMessage() method	

So you decide to use AOP and interceptor to externalize event firing
from your main code :	

Extract interface from ChatService to allow use of Decorator	

Create a decorator to track Ad Word in the ChatService processMessage()
method	

Move the event generator to the Decorator
Git Shortcut

git checkout step_3
Extract Interface from ChatService
public interface ChatService {

boolean add(Session session);




boolean remove(Object o);



}

void processMessage(String message);


@ApplicationScoped

public class ChatServiceImpl implements ChatService {


!

…

!

}
Create the PoodleAdWord Decorator
@Decorator

@Priority(Interceptor.Priority.APPLICATION)

public abstract class PoddleAddWordDecorator implements ChatService {




@Inject

@Delegate

private ChatService delegateService;




private final List<String> adWords = new ArrayList<String>() {{

add("world");

add("duck");

add("cartman");

}};




@Inject

private Event<String> events; // This should be moved from ChatServiceImpl class




@Override

public void processMessage(String message) {

String lmessage = message.toLowerCase();

for (String s : adWords) {

if (lmessage.indexOf(s) > -1) {

events.fire(s);

}

}

delegateService.processMessage(message);

}

}
Final version of ChatServiceImpl
@ApplicationScoped

public class ChatServiceImpl implements ChatService {




private final Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());




@Override

public boolean add(Session session) {

return peers.add(session);

}




@Override

public boolean remove(Object o) {

return peers.remove(o);

}




@Override

public void processMessage(String message) {

for (Session peer : peers) {

peer.getAsyncRemote().sendText(message);

}

}

}
More decoupling result
Our business code doesn’t contain cross cuting concern
anymore	

We’re ready to add other filters with this pattern	

To test, type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

When you type a message containing an ad word (i.e. duck) an
event is fired and an alert is written on the console
Step 4 : Please be polite
The famous Mapple company is also very interested in our chat platform	

But they have a strict policy regarding bad words. So they need a solution
to catch bad words, get notification and replace them by good ones.	

As Poodle pay us more we want to give priority to their ad filter to be
sure that «bad» keywords are still trapped for them	

You know how to build this filter	

Create Qualifiers to differentiate Ad Word events from Bad Word events	

Build a new decorator to test messages content and correct impolite words	

Configure decorator priority to have the Poodle one in first	

Change existing event generator to add qualifiers top them
Git Shortcut

git checkout step_4
Create the AdWord qualifier
import javax.inject.Qualifier;

import java.lang.annotation.Documented;

import java.lang.annotation.Retention;




import static java.lang.annotation.RetentionPolicy.RUNTIME;


!

@Qualifier

@Documented

@Retention(RUNTIME)

public @interface AdWord {

}
Create the BadWord qualifier
import javax.inject.Qualifier;

import java.lang.annotation.Documented;

import java.lang.annotation.Retention;




import static java.lang.annotation.RetentionPolicy.RUNTIME;


!

@Qualifier

@Documented

@Retention(RUNTIME)

public @interface BadWord {

}
Create the Mapple Decorator
@Decorator

@Priority(Interceptor.Priority.APPLICATION + 10)

public abstract class MapplePoliteDecorator implements ChatService {




static final Map<String, String> DICTIONARY = new HashMap<String, String>() {{

put("fuck", "duck");

put("crap", "trap");

put("idiots", "world");

put("cartman", "Stan");

}};




@Inject

@Delegate

private ChatService delegateService;




@Inject

@BadWord

private Event<String> events;




@Override

public void processMessage(String message) {

String lmessage = message.toLowerCase();

String res = message;

for (String word : DICTIONARY.keySet())

if (lmessage.indexOf(word) > -1) {

res = res.replaceAll("(?i)" + word, DICTIONARY.get(word));

events.fire(word);

}

delegateService.processMessage(res);

}

}
Change existing code to introduce AdWord qualifier
@Decorator

@Priority(Interceptor.Priority.APPLICATION)

public abstract class PoddleAddWordDecorator implements ChatService {




…

@Inject

@AdWord

private Event<String> events;

…
}

public class MessageObserver {




public void observesAdWords(@Observes @AdWord String word) {

System.out.println("Ad word trapped : " + word);

}




public void observesbadWords(@Observes @BadWord String word) {

System.out.println("Bad word trapped : " + word);

}

}
Be polite result
We created a new Decorator that change message content after the 1st
decorator did its job.	

We’ll feed those dictionaries with a database later	

To test type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

When you type a message containing a bad word inside, message is
changed, an event is fired and an alert is written on the console. 	

If the bad word is also an ad word. The Addword is still track thanks to
priority
Step 5 : Intercept to log
Our code is nice with all this Decorators, but we’d like to
have an easy way to trace what code is called without
modifying it	

For that we’ll need another kind of AOP : an interceptor to log
information	

Create an interceptor binding	

Create the Log interceptor 	

Use it in our code
Git Shortcut

git checkout step_5
Create the Interceptor Binding




import
import
import
import
import

javax.interceptor.InterceptorBinding;

java.lang.annotation.ElementType;

java.lang.annotation.Retention;

java.lang.annotation.RetentionPolicy;

java.lang.annotation.Target;


@InterceptorBinding

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

public @interface Log {

}
Create the interceptor
@Interceptor

@Log

@Priority(Interceptor.Priority.APPLICATION)

public class LoggerInterceptor {




@AroundInvoke

public Object manageTransaction(InvocationContext ctx) throws Exception {

System.out.println("*** Before " + ctx.getMethod().toString());

Object res = ctx.proceed();

System.out.println("*** After " + ctx.getMethod().toString());

return res;




}

}
Using the Interceptor

@ApplicationScoped

@Log

public class ChatServiceImpl implements ChatService {

…
}
Log Interceptor result
We created an interceptor and its binding to activate logging
by annotation	

To test type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

All calls on ChatServiceImpl will be logged to the console
Step 6 : Plastic surgery
Let’s face the cruel truth our UI is totally ugly!	

As we decided to use Java EE stack, we give a try to JSF for
our front	

Out of the box JSF doesn’t provide rich component, we’re
going to use Primefaces to produce a nice UI proposal	

So, in this step, we’ll develop a JSF chat page to enhance the
user experience
Git Shortcut

git checkout step_6
Adding PrimeFaces to the POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
…

<dependencies>

…

<dependency>

<groupId>org.primefaces</groupId>

<artifactId>primefaces</artifactId>

<version>4.0</version>

<scope>runtime</scope>

</dependency>

</dependencies>

…

</project>
The JSF Page
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html
xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

<title>WebSocket Chat</title>

</h:head>

<h:body>

<p:layout style="width:1024px;height:600px;margin-left: auto;margin-right: auto;">

<p:layoutUnit position="center" header="Chat-e-Chat-o">

<div style="text-align: center;">

<h:form id="chat">

<table>

<tr>

<td>

Users<br/>

<p:inputTextarea readonly="true" rows="6" cols="20" id="userField"/>

</td>

<td>

Chat Log<br/>

<p:inputTextarea readonly="true" rows="6" cols="50" id="chatlogField"/>

</td>

</tr>

<tr>

<td colspan="2">

<p:inputText id="textField" name="name" value="Duke"/><br/>

<p:commandButton onclick="join();" value="Join" id="join"/>

<p:commandButton onclick="send_message();" value="Chat" id="chat"/>

</td>

</tr>

</table>

</h:form>

</div>

<div id="output"></div>

<script language="javascript" type="text/javascript" src="websocket.js"></script>

</p:layoutUnit>

</p:layout>

</h:body>

</html>
Modification of websocket.js
var wsUri = "ws://" + document.location.host + "/
demo-chat/websocket";


!

...

!

var userField =
document.getElementById("chat:userField");

var chatlogField =
document.getElementById("chat:chatlogField");

var textField =
document.getElementById("chat:textField");


!



...
function join() {

username = textField.value;

websocket.send(username + " joined");

document.getElementById("chat:join").disabled =
true;

}

JSF generates different component
id so we have to adapt the code	

We also choose to disable the
«join» button after usage to give
focus to chat button
New content for index.html

<html>

<head>

<meta http-equiv="Refresh" content="0; URL=index.jsf">

</head>

</html>
Plastic surgery result
We got a better UI and user experience. Ok there’s still work
to do, but we have the POC here ;)	

To test type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

Beautiful isn’t it ?
Step 7 : A bit of structure
So we get message and dispatch them to all people, but we don’t
do anything of them	

It could be nice to receive structured message in JSON format and
create our own object from it	

In this step we’re gone :	

Change client side js to generate JSON structure with username and
message	

Create a Message class to contain the java version of this JSON structure	

Change the ChatService bean to deserialize JSON message with the new
JSONP specification
Git Shortcut

git checkout step_7
Websocket.js modification
function send_message() {

var msg = new Object();

msg.user = username;

msg.content = textField.value;

websocket.send(JSON.stringify(msg));

}






...

function onMessage(evt) {

console.log("onMessage : " + evt.data);

writeToScreen("RECEIVED: " + evt.data);

if (evt.data.indexOf("joined") != -1) {

userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "n";

} else {

var msg = JSON.parse(evt.data)

chatlogField.innerHTML += msg.content + " said " + msg.user + "n";

}
New Message Class
public class Message {




private String user;

private String content;




public String getUser() {

return user;

}




public void setUser(String user) {

this.user = user;

}




public String getContent() {

return content;

}




public void setContent(String content) {

this.content = content;

}

}
ChatService processMessage modification
public void processMessage(String message) {

System.out.println(message);

JsonReader reader = Json.createReader(new StringReader(message));

try {

JsonObject msgObj = reader.readObject();

Message msg = new Message();

msg.setUser(msgObj.getString("user"));

msg.setContent(msgObj.getString("content"));

System.out.println("Message from " + msg.getUser() + " : " + msg.getContent());

} catch (JsonParsingException e) {

System.out.println("Message is not in JSON format");

} finally {

reader.close();

}

for (Session peer : peers) {

peer.getAsyncRemote().sendText(message);

}

}
Structure result
We got now a data structure for all the messages. We can use
it to provide other service (history, search, etc...)	

To test type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

Nothing changed... But look at the console...
Step 8 : Save our messages
Now we have messages in a nice Pojo. What about persist
them to provide new services	

In this step we’re gone :	

Add a JPA configuration	

Turn our Pojo into a JPA entity	

Create a service to handle message
Git Shortcut

git checkout step_8
Persistence.xml in META-INF




<?xml version="1.0" encoding="UTF-8"?>

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd"

version="2.1">





<persistence-unit name="chatPU" transaction-type="JTA">

<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>

<properties>





<!-- Properties for Hibernate -->

<property name="hibernate.hbm2ddl.auto" value="create-drop"/>

<property name="hibernate.show_sql" value="true"/>

<property name="hibernate.format_sql" value="true"/>

<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

</properties>

</persistence-unit>

</persistence>
ConfigPersistence.java





public class ConfigPersistence {




}

@PersistenceContext

@Produces

private EntityManager em;

Message.java modification
@Entity

@Vetoed

public class Message {






@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private Long id;




@Column(name = "USERNAME")

private String user;

private String content;




!



...
public Long getId() {

return id;

}





public void setId(Long id) {

this.id = id;

}

}

We transform the class in an
entity.	

Note the @Vetoed CDI
annotation that exclude the class
from being a bean 	

We should also change the
column name of user. Because
user is a reserved name in SQL
ChatService modification
public class ChatServiceImpl implements ChatService {




…
@Inject

EntityManager em;




…

@Override

public void persistMessage(Message msg) {

em.persist(msg);

}




…

@Override

@Transactional

public void processMessage(String message) {

System.out.println(message);

JsonReader reader = Json.createReader(new StringReader(message));

try {

JsonObject msgObj = reader.readObject();

Message msg = new Message();

msg.setUser(msgObj.getString("user"));

msg.setContent(msgObj.getString("content"));

System.out.println("Message from " + msg.getUser() + " : " + msg.getContent());

persistMessage(msg);

} catch (JsonParsingException e) {

System.out.println("Message is not in JSON format");

} finally {

reader.close();

}

for (Session peer : peers) {

peer.getAsyncRemote().sendText(message);

}

}

}
Save our messages result
We saved our messages to provide future services (history,
search, etc...)	

To test type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

Nothing changed... But look at the console...
Step 9 : Message in a bottle
Poodle plan to provide an appliance to send ad to our
application	

This appliance uses JMS to receive information asynchronously	

So we decide to build a POC to test Messaging feature in Java
EE 7	

Create a message queue and a Sender Service	

Modify PoodleAdWord Decorator to use the sender Bean	

Create a MDB to mock appliance side and listen to our messages
Git Shortcut

git checkout step_9
Message queue and SenderService
import
import
import
import
import



javax.annotation.Resource;

javax.inject.Inject;

javax.jms.JMSContext;

javax.jms.JMSDestinationDefinition;

javax.jms.Queue;




@JMSDestinationDefinition(name = "java:global/jms/myQueue",

resourceAdapter = "jmsra",

interfaceName = "javax.jms.Queue",

destinationName = "classicQueue",

description = "My Sync Queue")





public class JmsSenderService {




@Resource(mappedName = "java:global/jms/myQueue")

private Queue myQueue;




@Inject

private JMSContext jmsContext;




public void sendMessage(String message) {

jmsContext.createProducer().send(myQueue, message);

}

}
PoodleAdWord decorator modification
public abstract class PoddleAddWordDecorator implements ChatService {




…

@Inject

JmsSenderService jms;




…




@Override

public void processMessage(String message) {

String lmessage = message.toLowerCase();

for (String s : adWords) {

if (lmessage.indexOf(s) > -1) {

jms.sendMessage(s);

}

}

delegateService.processMessage(message);

}

}
The Message Driven Bean
import org.lab.javaee.chat.AdWord;




import
import
import
import
import
import
import



javax.ejb.ActivationConfigProperty;

javax.ejb.MessageDriven;

javax.enterprise.event.Event;

javax.inject.Inject;

javax.jms.JMSException;

javax.jms.Message;

javax.jms.MessageListener;


@MessageDriven(activationConfig = {

@ActivationConfigProperty(propertyName = "destinationLookup",

propertyValue = "java:global/jms/myQueue"),

@ActivationConfigProperty(propertyName = "destinationType",

propertyValue = "javax.jms.Queue"),

})

public class PoodleAdListener implements MessageListener {




@Inject

@AdWord

private Event<String> adWordEvents;




}

@Override

public void onMessage(Message msg) {

try {

System.out.println("**** Poodle MDB receiving Ad Word thru jms : " + msg.getJMSMessageID());

adWordEvents.fire(msg.getBody(String.class));

} catch (JMSException e) {

throw new RuntimeException("Something nasty happened", e);

}

}

Message in a bottle result
We put a messaging system in place with two classes and two
annotations	

To test type :

mvn clean package wildfly:run!
To test the app browse to :

http://localhost:8080/demo-chat	

Enter an ad word and check the console
Questions

Contenu connexe

En vedette

Apache Deltaspike the CDI Toolbox (Java One 2015)
Apache Deltaspike the CDI Toolbox (Java One 2015)Apache Deltaspike the CDI Toolbox (Java One 2015)
Apache Deltaspike the CDI Toolbox (Java One 2015)Antoine Sabot-Durand
 
Invoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamicInvoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamicAntoine Sabot-Durand
 
Introduction to cdi given at java one 2014
Introduction to cdi given at java one 2014Introduction to cdi given at java one 2014
Introduction to cdi given at java one 2014Antoine Sabot-Durand
 
Extending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeExtending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeAntoine Sabot-Durand
 
Writing Java EE microservices using WildFly Swarm
Writing Java EE microservices using WildFly SwarmWriting Java EE microservices using WildFly Swarm
Writing Java EE microservices using WildFly SwarmComsysto Reply GmbH
 
CDI mis en pratique avec Seam Social et Weld OSGI
CDI mis en pratique avec Seam Social et Weld OSGICDI mis en pratique avec Seam Social et Weld OSGI
CDI mis en pratique avec Seam Social et Weld OSGIAntoine Sabot-Durand
 
Java EE, un ami qui vous veut du bien
Java EE, un ami qui vous veut du bienJava EE, un ami qui vous veut du bien
Java EE, un ami qui vous veut du bienAntoine Sabot-Durand
 

En vedette (19)

CDI In Real Life
CDI In Real LifeCDI In Real Life
CDI In Real Life
 
Devoxx Java Social and Agorava
Devoxx Java Social and AgoravaDevoxx Java Social and Agorava
Devoxx Java Social and Agorava
 
CDI 2.0 is coming
CDI 2.0 is comingCDI 2.0 is coming
CDI 2.0 is coming
 
Apache Deltaspike the CDI Toolbox (Java One 2015)
Apache Deltaspike the CDI Toolbox (Java One 2015)Apache Deltaspike the CDI Toolbox (Java One 2015)
Apache Deltaspike the CDI Toolbox (Java One 2015)
 
Invoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamicInvoke dynamite in Java EE with invoke dynamic
Invoke dynamite in Java EE with invoke dynamic
 
The path to cdi 2.0
The path to cdi 2.0The path to cdi 2.0
The path to cdi 2.0
 
Advanced CDI in live coding
Advanced CDI in live codingAdvanced CDI in live coding
Advanced CDI in live coding
 
CDI 2.0 is coming
CDI 2.0 is comingCDI 2.0 is coming
CDI 2.0 is coming
 
Going further with CDI 1.2
Going further with CDI 1.2Going further with CDI 1.2
Going further with CDI 1.2
 
Apache DeltaSpike the CDI toolbox
Apache DeltaSpike the CDI toolboxApache DeltaSpike the CDI toolbox
Apache DeltaSpike the CDI toolbox
 
Mute Java EE DNA with CDI
Mute Java EE DNA with CDI Mute Java EE DNA with CDI
Mute Java EE DNA with CDI
 
Introduction to cdi given at java one 2014
Introduction to cdi given at java one 2014Introduction to cdi given at java one 2014
Introduction to cdi given at java one 2014
 
Extending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeExtending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss Forge
 
CDI 1.1 university
CDI 1.1 universityCDI 1.1 university
CDI 1.1 university
 
Adopt a JSR: CDI 2.0 at Devoxx UK
Adopt a JSR: CDI 2.0 at Devoxx UKAdopt a JSR: CDI 2.0 at Devoxx UK
Adopt a JSR: CDI 2.0 at Devoxx UK
 
CDI 2.0 is upon us Devoxx
CDI 2.0 is upon us DevoxxCDI 2.0 is upon us Devoxx
CDI 2.0 is upon us Devoxx
 
Writing Java EE microservices using WildFly Swarm
Writing Java EE microservices using WildFly SwarmWriting Java EE microservices using WildFly Swarm
Writing Java EE microservices using WildFly Swarm
 
CDI mis en pratique avec Seam Social et Weld OSGI
CDI mis en pratique avec Seam Social et Weld OSGICDI mis en pratique avec Seam Social et Weld OSGI
CDI mis en pratique avec Seam Social et Weld OSGI
 
Java EE, un ami qui vous veut du bien
Java EE, un ami qui vous veut du bienJava EE, un ami qui vous veut du bien
Java EE, un ami qui vous veut du bien
 

Similaire à The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 6 : Paving The Path For The Future
Java EE 6 : Paving The Path For The FutureJava EE 6 : Paving The Path For The Future
Java EE 6 : Paving The Path For The FutureIndicThreads
 
Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010
Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010
Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010Arun Gupta
 
Java EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 India
Java EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 IndiaJava EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 India
Java EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 IndiaArun Gupta
 
Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010
Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010
Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010Arun Gupta
 
best java training center in chennai
best java training center in chennaibest java training center in chennai
best java training center in chennaisathis est
 
Spark IT 2011 - Java EE 6 Workshop
Spark IT 2011 - Java EE 6 WorkshopSpark IT 2011 - Java EE 6 Workshop
Spark IT 2011 - Java EE 6 WorkshopArun Gupta
 
Future of Java EE with Java SE 8
Future of Java EE with Java SE 8Future of Java EE with Java SE 8
Future of Java EE with Java SE 8Hirofumi Iwasaki
 
Java EE 6 & GlassFish v3 @ DevNexus
Java EE 6 & GlassFish v3 @ DevNexusJava EE 6 & GlassFish v3 @ DevNexus
Java EE 6 & GlassFish v3 @ DevNexusArun Gupta
 
Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010
Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010
Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010Arun Gupta
 
Java EE7 Demystified
Java EE7 DemystifiedJava EE7 Demystified
Java EE7 DemystifiedAnkara JUG
 
Future of Java EE with SE 8 (revised)
Future of Java EE with SE 8 (revised)Future of Java EE with SE 8 (revised)
Future of Java EE with SE 8 (revised)Hirofumi Iwasaki
 
JavaEE 6 and GlassFish v3 at SFJUG
JavaEE 6 and GlassFish v3 at SFJUGJavaEE 6 and GlassFish v3 at SFJUG
JavaEE 6 and GlassFish v3 at SFJUGMarakana Inc.
 
Java and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystemJava and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystemRafael Winterhalter
 

Similaire à The Magnificent java EE 7 in Wildfly-O-Rama (20)

Java EE 6 : Paving The Path For The Future
Java EE 6 : Paving The Path For The FutureJava EE 6 : Paving The Path For The Future
Java EE 6 : Paving The Path For The Future
 
Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010
Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010
Java EE 6 & GlassFish v3: Paving the path for the future - Spark IT 2010
 
Java EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 India
Java EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 IndiaJava EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 India
Java EE 6 & GlassFish v3: Paving the path for the future - Tech Days 2010 India
 
Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010
Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010
Java EE 6 & GlassFish v3 at Vancouver JUG, Jan 26, 2010
 
NLOUG 2018 - Future of JSF and ADF
NLOUG 2018 - Future of JSF and ADFNLOUG 2018 - Future of JSF and ADF
NLOUG 2018 - Future of JSF and ADF
 
best java training center in chennai
best java training center in chennaibest java training center in chennai
best java training center in chennai
 
Java EE 6 & Spring: A Lover's Quarrel
Java EE 6 & Spring: A Lover's QuarrelJava EE 6 & Spring: A Lover's Quarrel
Java EE 6 & Spring: A Lover's Quarrel
 
Java EE 6 and GlassFish portfolio
Java EE 6 and GlassFish portfolioJava EE 6 and GlassFish portfolio
Java EE 6 and GlassFish portfolio
 
Spark IT 2011 - Java EE 6 Workshop
Spark IT 2011 - Java EE 6 WorkshopSpark IT 2011 - Java EE 6 Workshop
Spark IT 2011 - Java EE 6 Workshop
 
Future of Java EE with Java SE 8
Future of Java EE with Java SE 8Future of Java EE with Java SE 8
Future of Java EE with Java SE 8
 
Java EE 6 & GlassFish v3 @ DevNexus
Java EE 6 & GlassFish v3 @ DevNexusJava EE 6 & GlassFish v3 @ DevNexus
Java EE 6 & GlassFish v3 @ DevNexus
 
Java E
Java EJava E
Java E
 
Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010
Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010
Java EE 6 Hands-on Workshop at Dallas Tech Fest 2010
 
Java EE7 Demystified
Java EE7 DemystifiedJava EE7 Demystified
Java EE7 Demystified
 
Future of Java EE with SE 8 (revised)
Future of Java EE with SE 8 (revised)Future of Java EE with SE 8 (revised)
Future of Java EE with SE 8 (revised)
 
JavaEE 6 and GlassFish v3 at SFJUG
JavaEE 6 and GlassFish v3 at SFJUGJavaEE 6 and GlassFish v3 at SFJUG
JavaEE 6 and GlassFish v3 at SFJUG
 
Java EE 6 Aquarium Paris
Java EE 6 Aquarium ParisJava EE 6 Aquarium Paris
Java EE 6 Aquarium Paris
 
Java EE6 Overview
Java EE6 OverviewJava EE6 Overview
Java EE6 Overview
 
Java and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystemJava and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystem
 
J2 Ee Overview
J2 Ee OverviewJ2 Ee Overview
J2 Ee Overview
 

Dernier

CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 

Dernier (20)

CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 

The Magnificent java EE 7 in Wildfly-O-Rama

  • 1. The Magnificent Java EE 7 in Wildfly-O-Rama Antoine Sabot-Durand Java EE Expert Senior Software Developer @ Red Hat @antoine_sd
  • 2. Antoine Sabot-Durand Senior Software Developer at Red Hat Architect and Tech consultant 16 years in IT Java & OSS : CDI co-spec lead CDI community development Agorava technical leader @antoine_sd
  • 3. What’s in there ? Short Java EE 7 Intro Java EE History Java EE 7 main features Java EE 7 Content WildFly WildFly Roadmap Java EE 7 in action
  • 6. Java EE History Java Professional Edition Mai 1998 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
  • 7. Java EE History Java Professional Edition Mai 1998 1998 1999 J2EE 1.2 12/12/1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
  • 8. Java EE History Java Professional Edition Mai 1998 1998 1999 J2EE 1.2 12/12/1999 2000 J2EE 1.3 09/24/2001 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
  • 9. Java EE History Java Professional Edition Mai 1998 1998 1999 J2EE 1.2 12/12/1999 2000 J2EE 1.3 09/24/2001 2001 2002 J2EE 1.4 11/11/2003 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
  • 10. Java EE History Java Professional Edition Mai 1998 1998 1999 J2EE 1.2 12/12/1999 2000 J2EE 1.3 09/24/2001 2001 2002 J2EE 1.4 11/11/2003 2003 Java EE 5 05/11/2006 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
  • 11. Java EE History Java Professional Edition Mai 1998 1998 1999 J2EE 1.2 12/12/1999 2000 J2EE 1.3 09/24/2001 2001 2002 J2EE 1.4 11/11/2003 2003 Java EE 5 05/11/2006 2004 2005 2006 2007 Java EE 6 12/10/2009 2008 2009 2010 2011 2012 2013
  • 12. Java EE History Java Professional Edition Mai 1998 1998 1999 J2EE 1.2 12/12/1999 2000 J2EE 1.3 09/24/2001 2001 2002 J2EE 1.4 11/11/2003 2003 Java EE 5 05/11/2006 2004 2005 2006 2007 Java EE 6 12/10/2009 2008 2009 Java EE 7 06/22/2013 2010 2011 2012 2013
  • 13. Java EE 7 Main Features WebSocket client/server endpoints Batch Applications JSON Processing Concurrency Utilities Simplified JMS API @Transactional and @TransactionScoped JAX-RS Client API Pervasive CDI More annotated POJOs Faces Flow
  • 14. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 15. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 16. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 17. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 18. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 19. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 20. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 21. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 22. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 23. Java EE 7 JSR CDI Extensions JSF 2.2,
 JSP 2.3,
 EL 3.0 Web Fragments JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket 1.0 CDI 1.1 Interceptors
 1.2, JTA 1.2 Common Annotations 1.1 EJB 3.2 Managed Beans 1.0 JPA 2.1 JMS 2.0 Concurrency 1.0 JCA 1.7 Batch 1.0 Bean Validation 1.1 Servlet 3.1
  • 24. JBoss WildFly Previously named JBoss Application Server Named change to better differentiate Community from Supported product Support Java EE 7 Fast, Lightweight, Manageable Developer Friendly Open Source
  • 25. WildFly Roadmap Alpha 1 - May 2013 Alpha 2 - June 2013 (Java EE 7 released on the 22) Alpha 3 - July 2013 Alpha 4 - August 2013 Beta 1 - October 2013 CR1 - December 2013 Final - Mar/Apr 2014 That’s 8/9 months after EE 7 release (better than 2 years for AS 7)
  • 27. Let’s get some action !
  • 28. Welcome to Chat-e-Chat-o Chat-e-Chat-o is a Startup which develop a SaaS chat service We raised fund from VC to create their first release CTO decided to use Java EE 7 to develop the service As the main developer, you have the task to implement all the feature asked by marketing Events and name in this HOL are totally fictive Situation and use cases are simplified This is your story...
  • 29. At the beginning After reading some doc.You created the first chat demo It contains 4 files pom.xml : Maven configuration file ChatEndPoint.java : A Java class corresponding to a websocket Endpoint index.html : Home Page of the Service websocket.js : a little JS lib to exchange with the server This 4 files are enough to start the application server with a (very) basic chat service
  • 30. Git Start git clone git@github.com:antoinesd/magnificent-java-ee7.git! ! git checkout beginning
  • 31. pom.xml 1/2 
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>org.lab.javaee</groupId>
 <artifactId>demo-chat</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>war</packaging>
 <name>demo-chat</name>
 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>
 <dependencies>
 <dependency>
 <groupId>javax</groupId>
 <artifactId>javaee-api</artifactId>
 <version>7.0</version>
 <scope>provided</scope>
 </dependency>
 </dependencies>

  • 32. pom.xml 2/2 <build>
 <finalName>${project.name}</finalName>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-compiler-plugin</artifactId>
 <version>3.0</version>
 <configuration>
 <source>1.7</source>
 <target>1.7</target>
 </configuration>
 </plugin>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-war-plugin</artifactId>
 <version>2.3</version>
 <configuration>
 <failOnMissingWebXml>false</failOnMissingWebXml>
 </configuration>
 </plugin>
 <plugin>
 <groupId>org.wildfly.plugins</groupId>
 <artifactId>wildfly-maven-plugin</artifactId>
 <version>1.0.0.Beta1</version> <configuration>
 <version>8.0.0.CR1</version>
 </configuration>
 </plugin>
 </plugins>
 </build>
 </project>
  • 33. index.html <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>WebSocket Chat</title>
 </head>
 <body>
 <h1>Chat!</h1>
 <div style="text-align: center;">
 <form action="">
 <table>
 <tr>
 <td>
 Users<br/>
 <textarea readonly="true" rows="6" cols="20" id="userField"></textarea>
 </td>
 <td>
 Chat Log<br/>
 <textarea readonly="true" rows="6" cols="50" id="chatlogField"></textarea>
 </td>
 </tr>
 <tr>
 <td colspan="2">
 <input id="textField" name="name" value="Duke" type="text"><br>
 <input onclick="join();" value="Join" type="button">
 <input onclick="send_message();" value="Chat" type="button">
 </td>
 </tr>
 </table>
 </form>
 </div>
 <div id="output"></div>
 <script language="javascript" type="text/javascript" src="websocket.js"></script>
 </body>
 </html>
  • 34. websocket.js var var var var 
 wsUri = "ws://" + document.location.host + "/demo-chat/websocket";
 websocket = new WebSocket(wsUri);
 username;
 output = document.getElementById("output");
 websocket.onopen = function (evt) {onOpen(evt)};
 websocket.onmessage = function (evt) {onMessage(evt)};
 websocket.onerror = function (evt) {onError(evt)};
 ! function join() {
 username = textField.value;
 websocket.send(username + " joined");
 }
 ! function ! function ! send_message() {websocket.send(username + ": " + textField.value);}
 onOpen() {writeToScreen("Connected to " + wsUri);}
 function onMessage(evt) {
 console.log("onMessage");
 writeToScreen("RECEIVED: " + evt.data);
 if (evt.data.indexOf("joined") != -1) {
 userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "n";
 } else {
 chatlogField.innerHTML += evt.data + "n";
 }
 }
 ! function ! onError(evt) {writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);}
 function writeToScreen(message) {output.innerHTML += message + "<br>";}
  • 35. ChatEndPoint.java import import import import ! javax.websocket.*;
 javax.websocket.server.ServerEndpoint;
 java.io.IOException;
 java.util.*;
 @ServerEndpoint("/websocket")
 public class ChatEndpoint {
 private static final Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
 
 @OnOpen
 public void onOpen(Session peer) {
 peers.add(peer);
 }
 
 @OnClose
 public void onClose(Session peer) {
 peers.remove(peer);
 }
 
 @OnMessage
 public void message(String message, Session client) throws IOException, EncodeException {
 for (Session peer : peers) {
 peer.getAsyncRemote().sendText(message);
 }
 }
 }

  • 36. Files organization & launching Files must be organized like this way To launch the app In your shell, go to the directory containing the pom.xml file and type : mvn clean package wildfly:run! To test the app browse to : http://localhost:8080/demo-chat
  • 37. Step 1 : Create a Chat Service As we will add functionalities to our application, we want to separate future business logic from the Websocket endpoint That’s why we decide to create a ChatService classes to deal with chat business logic To implement this you’ll have to : Activate CDI Create ChatService CDI Bean Remove all business logic from ChatEndpoint to put it in ChatService
  • 39. Activate CDI To activate CDI you only have to create an empty file named beans.xml in folder
 src/main/webapp/WEB-INF beans.xml !
  • 40. ChatService.java @ApplicationScoped
 public class ChatService {
 
 private final Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
 
 public boolean add(Session session) {
 return peers.add(session);
 }
 
 public boolean remove(Object o) {
 return peers.remove(o);
 }
 
 
 public void processMessage(String message) {
 for (Session peer : peers) {
 peer.getAsyncRemote().sendText(message);
 }
 }
 }
  • 41. ChatEndPoint.java @ServerEndpoint("/websocket")
 public class ChatEndpoint {
 
 @Inject
 private ChatService service;
 
 @OnOpen
 public void onOpen(Session peer) {
 service.add(peer);
 }
 
 @OnClose
 public void onClose(Session peer) {
 service.remove(peer);
 }
 
 @OnMessage
 public void message(String message, Session client) throws IOException, EncodeException {
 service.processMessage(message);
 }
 }
  • 42. Step 2 : Keyword detection Our main partner is the Poodle website.They want to embed our service but they need a solution to detect keywords in chat to feed their advertising platform You decide to build a prototype of this feature with CDI built-in observer pattern To implement this you’ll have to : Modify ChatService class by : Injecting an Event generator in the endpoint Modifying the message() method to fire the event Create an observer bean for the event
  • 44. ChatService.java import javax.enterprise.event.Event;
 import javax.inject.Inject; ...
 ! @ApplicationScoped
 public class ChatService { 
 ... @Inject
 private Event<String> events; ... 
 public void processMessage(String message) {
 if (message.toLowerCase().indexOf("world") > -1)
 events.fire(message);
 for (Session peer : peers) {
 peer.getAsyncRemote().sendText(message);
 }
 } }

  • 45. Bean with Observer import javax.enterprise.event.Observes;
 
 public class MessageObserver {
 
 public void observesWorldMessages(@Observes String msg) {
 System.out.println("Keyword was trapped : " + msg);
 }
 }
  • 46. Keyword detection result In your shell, go to the directory containing the pom.xml file and type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat When you type a message with «world» inside an event is fired and an alert is written on the console
  • 47. Step 3 : More decoupling with AOP Ok, our system to detect certain keywords works nicely with some kind of decoupling thanks to CDI events But the team is not happy to have this code directly into the service. If other filtering needs occur, we’ll have a big if cascade in processMessage() method So you decide to use AOP and interceptor to externalize event firing from your main code : Extract interface from ChatService to allow use of Decorator Create a decorator to track Ad Word in the ChatService processMessage() method Move the event generator to the Decorator
  • 49. Extract Interface from ChatService public interface ChatService {
 boolean add(Session session);
 
 boolean remove(Object o);
 
 } void processMessage(String message);
 @ApplicationScoped
 public class ChatServiceImpl implements ChatService {
 ! … ! }
  • 50. Create the PoodleAdWord Decorator @Decorator
 @Priority(Interceptor.Priority.APPLICATION)
 public abstract class PoddleAddWordDecorator implements ChatService {
 
 @Inject
 @Delegate
 private ChatService delegateService;
 
 private final List<String> adWords = new ArrayList<String>() {{
 add("world");
 add("duck");
 add("cartman");
 }};
 
 @Inject
 private Event<String> events; // This should be moved from ChatServiceImpl class
 
 @Override
 public void processMessage(String message) {
 String lmessage = message.toLowerCase();
 for (String s : adWords) {
 if (lmessage.indexOf(s) > -1) {
 events.fire(s);
 }
 }
 delegateService.processMessage(message);
 }
 }
  • 51. Final version of ChatServiceImpl @ApplicationScoped
 public class ChatServiceImpl implements ChatService {
 
 private final Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
 
 @Override
 public boolean add(Session session) {
 return peers.add(session);
 }
 
 @Override
 public boolean remove(Object o) {
 return peers.remove(o);
 }
 
 @Override
 public void processMessage(String message) {
 for (Session peer : peers) {
 peer.getAsyncRemote().sendText(message);
 }
 }
 }
  • 52. More decoupling result Our business code doesn’t contain cross cuting concern anymore We’re ready to add other filters with this pattern To test, type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat When you type a message containing an ad word (i.e. duck) an event is fired and an alert is written on the console
  • 53. Step 4 : Please be polite The famous Mapple company is also very interested in our chat platform But they have a strict policy regarding bad words. So they need a solution to catch bad words, get notification and replace them by good ones. As Poodle pay us more we want to give priority to their ad filter to be sure that «bad» keywords are still trapped for them You know how to build this filter Create Qualifiers to differentiate Ad Word events from Bad Word events Build a new decorator to test messages content and correct impolite words Configure decorator priority to have the Poodle one in first Change existing event generator to add qualifiers top them
  • 55. Create the AdWord qualifier import javax.inject.Qualifier;
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 ! @Qualifier
 @Documented
 @Retention(RUNTIME)
 public @interface AdWord {
 }
  • 56. Create the BadWord qualifier import javax.inject.Qualifier;
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 ! @Qualifier
 @Documented
 @Retention(RUNTIME)
 public @interface BadWord {
 }
  • 57. Create the Mapple Decorator @Decorator
 @Priority(Interceptor.Priority.APPLICATION + 10)
 public abstract class MapplePoliteDecorator implements ChatService {
 
 static final Map<String, String> DICTIONARY = new HashMap<String, String>() {{
 put("fuck", "duck");
 put("crap", "trap");
 put("idiots", "world");
 put("cartman", "Stan");
 }};
 
 @Inject
 @Delegate
 private ChatService delegateService;
 
 @Inject
 @BadWord
 private Event<String> events;
 
 @Override
 public void processMessage(String message) {
 String lmessage = message.toLowerCase();
 String res = message;
 for (String word : DICTIONARY.keySet())
 if (lmessage.indexOf(word) > -1) {
 res = res.replaceAll("(?i)" + word, DICTIONARY.get(word));
 events.fire(word);
 }
 delegateService.processMessage(res);
 }
 }
  • 58. Change existing code to introduce AdWord qualifier @Decorator
 @Priority(Interceptor.Priority.APPLICATION)
 public abstract class PoddleAddWordDecorator implements ChatService {
 
 …
 @Inject
 @AdWord
 private Event<String> events;
 … } public class MessageObserver {
 
 public void observesAdWords(@Observes @AdWord String word) {
 System.out.println("Ad word trapped : " + word);
 }
 
 public void observesbadWords(@Observes @BadWord String word) {
 System.out.println("Bad word trapped : " + word);
 }
 }
  • 59. Be polite result We created a new Decorator that change message content after the 1st decorator did its job. We’ll feed those dictionaries with a database later To test type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat When you type a message containing a bad word inside, message is changed, an event is fired and an alert is written on the console. If the bad word is also an ad word. The Addword is still track thanks to priority
  • 60. Step 5 : Intercept to log Our code is nice with all this Decorators, but we’d like to have an easy way to trace what code is called without modifying it For that we’ll need another kind of AOP : an interceptor to log information Create an interceptor binding Create the Log interceptor Use it in our code
  • 62. Create the Interceptor Binding 
 import import import import import javax.interceptor.InterceptorBinding;
 java.lang.annotation.ElementType;
 java.lang.annotation.Retention;
 java.lang.annotation.RetentionPolicy;
 java.lang.annotation.Target;
 @InterceptorBinding
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Log {
 }
  • 63. Create the interceptor @Interceptor
 @Log
 @Priority(Interceptor.Priority.APPLICATION)
 public class LoggerInterceptor {
 
 @AroundInvoke
 public Object manageTransaction(InvocationContext ctx) throws Exception {
 System.out.println("*** Before " + ctx.getMethod().toString());
 Object res = ctx.proceed();
 System.out.println("*** After " + ctx.getMethod().toString());
 return res;
 
 }
 }
  • 64. Using the Interceptor @ApplicationScoped
 @Log
 public class ChatServiceImpl implements ChatService {
 … }
  • 65. Log Interceptor result We created an interceptor and its binding to activate logging by annotation To test type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat All calls on ChatServiceImpl will be logged to the console
  • 66. Step 6 : Plastic surgery Let’s face the cruel truth our UI is totally ugly! As we decided to use Java EE stack, we give a try to JSF for our front Out of the box JSF doesn’t provide rich component, we’re going to use Primefaces to produce a nice UI proposal So, in this step, we’ll develop a JSF chat page to enhance the user experience
  • 68. Adding PrimeFaces to the POM <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion> …
 <dependencies>
 …
 <dependency>
 <groupId>org.primefaces</groupId>
 <artifactId>primefaces</artifactId>
 <version>4.0</version>
 <scope>runtime</scope>
 </dependency>
 </dependencies>
 …
 </project>
  • 69. The JSF Page <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:ui="http://java.sun.com/jsf/facelets">
 <h:head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 <title>WebSocket Chat</title>
 </h:head>
 <h:body>
 <p:layout style="width:1024px;height:600px;margin-left: auto;margin-right: auto;">
 <p:layoutUnit position="center" header="Chat-e-Chat-o">
 <div style="text-align: center;">
 <h:form id="chat">
 <table>
 <tr>
 <td>
 Users<br/>
 <p:inputTextarea readonly="true" rows="6" cols="20" id="userField"/>
 </td>
 <td>
 Chat Log<br/>
 <p:inputTextarea readonly="true" rows="6" cols="50" id="chatlogField"/>
 </td>
 </tr>
 <tr>
 <td colspan="2">
 <p:inputText id="textField" name="name" value="Duke"/><br/>
 <p:commandButton onclick="join();" value="Join" id="join"/>
 <p:commandButton onclick="send_message();" value="Chat" id="chat"/>
 </td>
 </tr>
 </table>
 </h:form>
 </div>
 <div id="output"></div>
 <script language="javascript" type="text/javascript" src="websocket.js"></script>
 </p:layoutUnit>
 </p:layout>
 </h:body>
 </html>
  • 70. Modification of websocket.js var wsUri = "ws://" + document.location.host + "/ demo-chat/websocket";
 ! ... ! var userField = document.getElementById("chat:userField");
 var chatlogField = document.getElementById("chat:chatlogField");
 var textField = document.getElementById("chat:textField");
 ! 
 ... function join() {
 username = textField.value;
 websocket.send(username + " joined");
 document.getElementById("chat:join").disabled = true;
 } JSF generates different component id so we have to adapt the code We also choose to disable the «join» button after usage to give focus to chat button
  • 71. New content for index.html <html>
 <head>
 <meta http-equiv="Refresh" content="0; URL=index.jsf">
 </head>
 </html>
  • 72. Plastic surgery result We got a better UI and user experience. Ok there’s still work to do, but we have the POC here ;) To test type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat Beautiful isn’t it ?
  • 73. Step 7 : A bit of structure So we get message and dispatch them to all people, but we don’t do anything of them It could be nice to receive structured message in JSON format and create our own object from it In this step we’re gone : Change client side js to generate JSON structure with username and message Create a Message class to contain the java version of this JSON structure Change the ChatService bean to deserialize JSON message with the new JSONP specification
  • 75. Websocket.js modification function send_message() {
 var msg = new Object();
 msg.user = username;
 msg.content = textField.value;
 websocket.send(JSON.stringify(msg));
 }
 
 
 ...
 function onMessage(evt) {
 console.log("onMessage : " + evt.data);
 writeToScreen("RECEIVED: " + evt.data);
 if (evt.data.indexOf("joined") != -1) {
 userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "n";
 } else {
 var msg = JSON.parse(evt.data)
 chatlogField.innerHTML += msg.content + " said " + msg.user + "n";
 }
  • 76. New Message Class public class Message {
 
 private String user;
 private String content;
 
 public String getUser() {
 return user;
 }
 
 public void setUser(String user) {
 this.user = user;
 }
 
 public String getContent() {
 return content;
 }
 
 public void setContent(String content) {
 this.content = content;
 }
 }
  • 77. ChatService processMessage modification public void processMessage(String message) {
 System.out.println(message);
 JsonReader reader = Json.createReader(new StringReader(message));
 try {
 JsonObject msgObj = reader.readObject();
 Message msg = new Message();
 msg.setUser(msgObj.getString("user"));
 msg.setContent(msgObj.getString("content"));
 System.out.println("Message from " + msg.getUser() + " : " + msg.getContent());
 } catch (JsonParsingException e) {
 System.out.println("Message is not in JSON format");
 } finally {
 reader.close();
 }
 for (Session peer : peers) {
 peer.getAsyncRemote().sendText(message);
 }
 }
  • 78. Structure result We got now a data structure for all the messages. We can use it to provide other service (history, search, etc...) To test type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat Nothing changed... But look at the console...
  • 79. Step 8 : Save our messages Now we have messages in a nice Pojo. What about persist them to provide new services In this step we’re gone : Add a JPA configuration Turn our Pojo into a JPA entity Create a service to handle message
  • 81. Persistence.xml in META-INF 
 <?xml version="1.0" encoding="UTF-8"?>
 <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd"
 version="2.1">
 
 <persistence-unit name="chatPU" transaction-type="JTA">
 <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
 <properties>
 
 <!-- Properties for Hibernate -->
 <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
 <property name="hibernate.show_sql" value="true"/>
 <property name="hibernate.format_sql" value="true"/>
 <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
 </properties>
 </persistence-unit>
 </persistence>
  • 82. ConfigPersistence.java 
 
 public class ConfigPersistence {
 
 } @PersistenceContext
 @Produces
 private EntityManager em;

  • 83. Message.java modification @Entity
 @Vetoed
 public class Message {
 
 
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 
 @Column(name = "USERNAME")
 private String user;
 private String content;
 
 ! 
 ... public Long getId() {
 return id;
 }
 
 public void setId(Long id) {
 this.id = id;
 }
 } We transform the class in an entity. Note the @Vetoed CDI annotation that exclude the class from being a bean We should also change the column name of user. Because user is a reserved name in SQL
  • 84. ChatService modification public class ChatServiceImpl implements ChatService {
 
 … @Inject
 EntityManager em;
 
 …
 @Override
 public void persistMessage(Message msg) {
 em.persist(msg);
 }
 
 …
 @Override
 @Transactional
 public void processMessage(String message) {
 System.out.println(message);
 JsonReader reader = Json.createReader(new StringReader(message));
 try {
 JsonObject msgObj = reader.readObject();
 Message msg = new Message();
 msg.setUser(msgObj.getString("user"));
 msg.setContent(msgObj.getString("content"));
 System.out.println("Message from " + msg.getUser() + " : " + msg.getContent());
 persistMessage(msg);
 } catch (JsonParsingException e) {
 System.out.println("Message is not in JSON format");
 } finally {
 reader.close();
 }
 for (Session peer : peers) {
 peer.getAsyncRemote().sendText(message);
 }
 }
 }
  • 85. Save our messages result We saved our messages to provide future services (history, search, etc...) To test type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat Nothing changed... But look at the console...
  • 86. Step 9 : Message in a bottle Poodle plan to provide an appliance to send ad to our application This appliance uses JMS to receive information asynchronously So we decide to build a POC to test Messaging feature in Java EE 7 Create a message queue and a Sender Service Modify PoodleAdWord Decorator to use the sender Bean Create a MDB to mock appliance side and listen to our messages
  • 88. Message queue and SenderService import import import import import 
 javax.annotation.Resource;
 javax.inject.Inject;
 javax.jms.JMSContext;
 javax.jms.JMSDestinationDefinition;
 javax.jms.Queue;
 
 @JMSDestinationDefinition(name = "java:global/jms/myQueue",
 resourceAdapter = "jmsra",
 interfaceName = "javax.jms.Queue",
 destinationName = "classicQueue",
 description = "My Sync Queue")
 
 
 public class JmsSenderService {
 
 @Resource(mappedName = "java:global/jms/myQueue")
 private Queue myQueue;
 
 @Inject
 private JMSContext jmsContext;
 
 public void sendMessage(String message) {
 jmsContext.createProducer().send(myQueue, message);
 }
 }
  • 89. PoodleAdWord decorator modification public abstract class PoddleAddWordDecorator implements ChatService {
 
 …
 @Inject
 JmsSenderService jms;
 
 …
 
 @Override
 public void processMessage(String message) {
 String lmessage = message.toLowerCase();
 for (String s : adWords) {
 if (lmessage.indexOf(s) > -1) {
 jms.sendMessage(s);
 }
 }
 delegateService.processMessage(message);
 }
 }
  • 90. The Message Driven Bean import org.lab.javaee.chat.AdWord;
 
 import import import import import import import 
 javax.ejb.ActivationConfigProperty;
 javax.ejb.MessageDriven;
 javax.enterprise.event.Event;
 javax.inject.Inject;
 javax.jms.JMSException;
 javax.jms.Message;
 javax.jms.MessageListener;
 @MessageDriven(activationConfig = {
 @ActivationConfigProperty(propertyName = "destinationLookup",
 propertyValue = "java:global/jms/myQueue"),
 @ActivationConfigProperty(propertyName = "destinationType",
 propertyValue = "javax.jms.Queue"),
 })
 public class PoodleAdListener implements MessageListener {
 
 @Inject
 @AdWord
 private Event<String> adWordEvents;
 
 } @Override
 public void onMessage(Message msg) {
 try {
 System.out.println("**** Poodle MDB receiving Ad Word thru jms : " + msg.getJMSMessageID());
 adWordEvents.fire(msg.getBody(String.class));
 } catch (JMSException e) {
 throw new RuntimeException("Something nasty happened", e);
 }
 }

  • 91. Message in a bottle result We put a messaging system in place with two classes and two annotations To test type :
 mvn clean package wildfly:run! To test the app browse to :
 http://localhost:8080/demo-chat Enter an ad word and check the console