the magnificent java ee 7 in wildfly-o-rama

92
The Magnificent Java EE 7 in Wildfly-O-Rama Antoine Sabot-Durand Java EE Expert Senior Software Developer @ Red Hat @antoine_sd

Upload: antoine-sabot-durand

Post on 10-May-2015

2.024 views

Category:

Technology


0 download

DESCRIPTION

My Hands on for Java EE 7 You can grab the code on github : https://github.com/antoinesd/magnificent-java-ee7

TRANSCRIPT

Page 1: The Magnificent java EE 7 in Wildfly-O-Rama

The Magnificent Java EE 7 in Wildfly-O-Rama

Antoine Sabot-Durand Java EE Expert

Senior Software Developer @ Red Hat @antoine_sd

Page 2: The Magnificent java EE 7 in Wildfly-O-Rama

Antoine Sabot-DurandSenior 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

Page 3: The Magnificent java EE 7 in Wildfly-O-Rama

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

Page 4: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE Introduction

Page 5: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013

Page 6: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011

Java Professional Edition

Mai 1998

2012 2013

Page 7: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011

Java Professional Edition

Mai 1998

J2EE 1.2 12/12/1999

2012 2013

Page 8: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011

Java Professional Edition

Mai 1998

J2EE 1.2 12/12/1999

J2EE 1.3 09/24/2001

2012 2013

Page 9: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011

Java Professional Edition

Mai 1998

J2EE 1.2 12/12/1999

J2EE 1.3 09/24/2001

J2EE 1.4 11/11/2003

2012 2013

Page 10: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011

Java Professional Edition

Mai 1998

J2EE 1.2 12/12/1999

J2EE 1.3 09/24/2001

J2EE 1.4 11/11/2003

Java EE 5 05/11/2006

2012 2013

Page 11: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011

Java Professional Edition

Mai 1998

J2EE 1.2 12/12/1999

J2EE 1.3 09/24/2001

J2EE 1.4 11/11/2003

Java EE 5 05/11/2006

Java EE 6 12/10/2009

2012 2013

Page 12: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE History

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011

Java Professional Edition

Mai 1998

J2EE 1.2 12/12/1999

J2EE 1.3 09/24/2001

J2EE 1.4 11/11/2003

Java EE 5 05/11/2006

Java EE 6 12/10/2009

2012 2013

Java EE 7 06/22/2013

Page 13: The Magnificent java EE 7 in Wildfly-O-Rama

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

Page 14: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 15: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 16: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 17: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 18: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 19: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 20: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 21: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 22: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 23: The Magnificent java EE 7 in Wildfly-O-Rama

Java EE 7 JSR

EJB 3.2

Servlet 3.1

CDI Extensions

Bea

n Va

lidat

ion

1.1

Batch 1.0

Web Fragments

JCA 1.7JMS 2.0JPA 2.1

Managed Beans 1.0

Concurrency 1.0Common Annotations 1.1

Interceptors 1.2, JTA 1.2CDI 1.1

JSF 2.2,JSP 2.3,EL 3.0

JAX-RS 2.0, JAX-WS 2.2 JSON 1.0 WebSocket

1.0

Page 24: The Magnificent java EE 7 in Wildfly-O-Rama

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

JBoss WildFly

Page 25: The Magnificent java EE 7 in Wildfly-O-Rama

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)

WildFly Roadmap

Page 26: The Magnificent java EE 7 in Wildfly-O-Rama

Download WildFly today

http://wildfly.org

Page 27: The Magnificent java EE 7 in Wildfly-O-Rama

Let’s get some action !

Page 28: The Magnificent java EE 7 in Wildfly-O-Rama

Welcome to Chat-e-Chat-oChat-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...

Page 29: The Magnificent java EE 7 in Wildfly-O-Rama

At the beginningAfter 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

Page 30: The Magnificent java EE 7 in Wildfly-O-Rama

Git Start

git clone [email protected]:antoinesd/magnificent-java-ee7.git!

!

git checkout beginning

Page 31: The Magnificent java EE 7 in Wildfly-O-Rama

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>

Page 32: The Magnificent java EE 7 in Wildfly-O-Rama

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>

Page 33: The Magnificent java EE 7 in Wildfly-O-Rama

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>

Page 34: The Magnificent java EE 7 in Wildfly-O-Rama

websocket.jsvar wsUri = "ws://" + document.location.host + "/demo-chat/websocket"; var websocket = new WebSocket(wsUri); var username; var 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 send_message() {websocket.send(username + ": " + textField.value);} !function 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>";}

Page 35: The Magnificent java EE 7 in Wildfly-O-Rama

ChatEndPoint.javaimport javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import 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); } }}

Page 36: The Magnificent java EE 7 in Wildfly-O-Rama

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

Page 37: The Magnificent java EE 7 in Wildfly-O-Rama

Step 1 : Create a Chat ServiceAs 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

Page 38: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_1

Page 39: The Magnificent java EE 7 in Wildfly-O-Rama

beans.xml!

Activate CDI

To activate CDI you only have to create an empty file named beans.xml in folder src/main/webapp/WEB-INF

Page 40: The Magnificent java EE 7 in Wildfly-O-Rama

ChatService.java

@ApplicationScopedpublic 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); } }}

Page 41: The Magnificent java EE 7 in Wildfly-O-Rama

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); }}

Page 42: The Magnificent java EE 7 in Wildfly-O-Rama

Step 2 : Keyword detectionOur 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

Page 43: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_2

Page 44: The Magnificent java EE 7 in Wildfly-O-Rama

ChatService.javaimport javax.enterprise.event.Event; import javax.inject.Inject; ...!@ApplicationScopedpublic 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); } } }

Page 45: The Magnificent java EE 7 in Wildfly-O-Rama

Bean with Observer

import javax.enterprise.event.Observes; public class MessageObserver { public void observesWorldMessages(@Observes String msg) { System.out.println("Keyword was trapped : " + msg); } }

Page 46: The Magnificent java EE 7 in Wildfly-O-Rama

Keyword detection resultIn 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

Page 47: The Magnificent java EE 7 in Wildfly-O-Rama

Step 3 : More decoupling with AOPOk, 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

Page 48: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_3

Page 49: The Magnificent java EE 7 in Wildfly-O-Rama

Extract Interface from ChatService

public interface ChatService { boolean add(Session session); boolean remove(Object o); void processMessage(String message);}

@ApplicationScopedpublic class ChatServiceImpl implements ChatService {!… !}

Page 50: The Magnificent java EE 7 in Wildfly-O-Rama

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); }}

Page 51: The Magnificent java EE 7 in Wildfly-O-Rama

Final version of ChatServiceImpl

@ApplicationScopedpublic 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); } }}

Page 52: The Magnificent java EE 7 in Wildfly-O-Rama

More decoupling resultOur 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

Page 53: The Magnificent java EE 7 in Wildfly-O-Rama

Step 4 : Please be politeThe 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

Page 54: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_4

Page 55: The Magnificent java EE 7 in Wildfly-O-Rama

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

Page 56: The Magnificent java EE 7 in Wildfly-O-Rama

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

Page 57: The Magnificent java EE 7 in Wildfly-O-Rama

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); }}

Page 58: The Magnificent java EE 7 in Wildfly-O-Rama

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); }}

Page 59: The Magnificent java EE 7 in Wildfly-O-Rama

Be polite resultWe 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

Page 60: The Magnificent java EE 7 in Wildfly-O-Rama

Step 5 : Intercept to logOur 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

Page 61: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_5

Page 62: The Magnificent java EE 7 in Wildfly-O-Rama

Create the Interceptor Binding

import javax.interceptor.InterceptorBinding; import java.lang.annotation.ElementType;import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @InterceptorBinding@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME) public @interface Log { }

Page 63: The Magnificent java EE 7 in Wildfly-O-Rama

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

Page 64: The Magnificent java EE 7 in Wildfly-O-Rama

Using the Interceptor

@ApplicationScoped@Logpublic class ChatServiceImpl implements ChatService {… }

Page 65: The Magnificent java EE 7 in Wildfly-O-Rama

Log Interceptor resultWe 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

Page 66: The Magnificent java EE 7 in Wildfly-O-Rama

Step 6 : Plastic surgeryLet’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

Page 67: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_6

Page 68: The Magnificent java EE 7 in Wildfly-O-Rama

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>

Page 69: The Magnificent java EE 7 in Wildfly-O-Rama

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>

Page 70: The Magnificent java EE 7 in Wildfly-O-Rama

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

Modification of websocket.js

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

Page 71: The Magnificent java EE 7 in Wildfly-O-Rama

New content for index.html

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

Page 72: The Magnificent java EE 7 in Wildfly-O-Rama

Plastic surgery resultWe 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 ?

Page 73: The Magnificent java EE 7 in Wildfly-O-Rama

Step 7 : A bit of structureSo 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

Page 74: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_7

Page 75: The Magnificent java EE 7 in Wildfly-O-Rama

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"; }

Page 76: The Magnificent java EE 7 in Wildfly-O-Rama

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

Page 77: The Magnificent java EE 7 in Wildfly-O-Rama

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); }}

Page 78: The Magnificent java EE 7 in Wildfly-O-Rama

Structure resultWe 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...

Page 79: The Magnificent java EE 7 in Wildfly-O-Rama

Step 8 : Save our messagesNow 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

Page 80: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_8

Page 81: The Magnificent java EE 7 in Wildfly-O-Rama

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>

Page 82: The Magnificent java EE 7 in Wildfly-O-Rama

public class ConfigPersistence { @PersistenceContext @Produces private EntityManager em; }

ConfigPersistence.java

Page 83: The Magnificent java EE 7 in Wildfly-O-Rama

@Entity@Vetoedpublic 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; } }

Message.java modification

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

Page 84: The Magnificent java EE 7 in Wildfly-O-Rama

ChatService modificationpublic 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); } }}

Page 85: The Magnificent java EE 7 in Wildfly-O-Rama

Save our messages resultWe 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...

Page 86: The Magnificent java EE 7 in Wildfly-O-Rama

Step 9 : Message in a bottlePoodle 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

Page 87: The Magnificent java EE 7 in Wildfly-O-Rama

Git Shortcut

git checkout step_9

Page 88: The Magnificent java EE 7 in Wildfly-O-Rama

Message queue and SenderServiceimport javax.annotation.Resource; import javax.inject.Inject; import javax.jms.JMSContext;import javax.jms.JMSDestinationDefinition; import 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); }}

Page 89: The Magnificent java EE 7 in Wildfly-O-Rama

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); }}

Page 90: The Magnificent java EE 7 in Wildfly-O-Rama

The Message Driven Beanimport org.lab.javaee.chat.AdWord; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.enterprise.event.Event;import javax.inject.Inject; import javax.jms.JMSException;import javax.jms.Message;import 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); } }}

Page 91: The Magnificent java EE 7 in Wildfly-O-Rama

Message in a bottle resultWe 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

Page 92: The Magnificent java EE 7 in Wildfly-O-Rama

Questions