SlideShare una empresa de Scribd logo
1 de 92
Descargar para leer sin conexión
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

Más contenido relacionado

Destacado

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
 

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

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

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

Último

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
"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
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
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
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
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
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
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
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 

Último (20)

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
"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
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
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
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
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
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
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.
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 

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