Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Java EE Introduction

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Java EE History 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 Java Professional Edition Mai 1998 2012 2013

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 15

Slide 15 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 16

Slide 16 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 17

Slide 17 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 18

Slide 18 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 19

Slide 19 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 20

Slide 20 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 21

Slide 21 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 22

Slide 22 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 23

Slide 23 text

Java EE 7 JSR EJB 3.2 Servlet 3.1 CDI Extensions Bean Validation 1.1 Batch 1.0 Web Fragments JCA 1.7 JMS 2.0 JPA 2.1 Managed Beans 1.0 Concurrency 1.0 Common Annotations 1.1 Interceptors
 1.2, JTA 1.2 CDI 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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Download WildFly today http://wildfly.org

Slide 27

Slide 27 text

Let’s get some action !

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

Git Start git clone git@github.com:antoinesd/magnificent-java-ee7.git! ! git checkout beginning

Slide 31

Slide 31 text

pom.xml 1/2 
 4.0.0
 org.lab.javaee
 demo-chat
 1.0-SNAPSHOT
 war
 demo-chat
 
 
 UTF-8
 
 
 
 
 javax
 javaee-api
 7.0
 provided
 
 


Slide 32

Slide 32 text

pom.xml 2/2 
 ${project.name}
 
 
 org.apache.maven.plugins
 maven-compiler-plugin
 3.0
 
 1.7
 1.7
 
 
 
 org.apache.maven.plugins
 maven-war-plugin
 2.3
 
 false
 
 
 
 org.wildfly.plugins
 wildfly-maven-plugin
 1.0.0.Beta1 
 8.0.0.CR1
 
 
 
 


Slide 33

Slide 33 text

index.html 
 
 
 WebSocket Chat
 
 


Chat!


 
 
 
 
 Users

 
 
 
 Chat Log

 
 
 
 
 


 
 
 
 
 
 


 
 


Slide 34

Slide 34 text

websocket.js var 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('ERROR: ' + evt.data);}
 ! function writeToScreen(message) {output.innerHTML += message + "
";}

Slide 35

Slide 35 text

ChatEndPoint.java import javax.websocket.*;
 import javax.websocket.server.ServerEndpoint;
 import java.io.IOException;
 import java.util.*;
 ! @ServerEndpoint("/websocket")
 public class ChatEndpoint {
 private static final Set peers = Collections.synchronizedSet(new HashSet());
 
 @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);
 }
 }
 }


Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

Git Shortcut git checkout step_1

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

ChatService.java @ApplicationScoped
 public class ChatService {
 
 private final Set peers = Collections.synchronizedSet(new HashSet());
 
 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);
 }
 }
 }

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

Git Shortcut git checkout step_2

Slide 44

Slide 44 text

ChatService.java import javax.enterprise.event.Event;
 import javax.inject.Inject; ...
 ! @ApplicationScoped
 public class ChatService { 
 ... @Inject
 private Event events; ... 
 public void processMessage(String message) {
 if (message.toLowerCase().indexOf("world") > -1)
 events.fire(message);
 for (Session peer : peers) {
 peer.getAsyncRemote().sendText(message);
 }
 } }


Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Git Shortcut git checkout step_3

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

Create the PoodleAdWord Decorator @Decorator
 @Priority(Interceptor.Priority.APPLICATION)
 public abstract class PoddleAddWordDecorator implements ChatService {
 
 @Inject
 @Delegate
 private ChatService delegateService;
 
 private final List adWords = new ArrayList() {{
 add("world");
 add("duck");
 add("cartman");
 }};
 
 @Inject
 private Event 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);
 }
 }

Slide 51

Slide 51 text

Final version of ChatServiceImpl @ApplicationScoped
 public class ChatServiceImpl implements ChatService {
 
 private final Set peers = Collections.synchronizedSet(new HashSet());
 
 @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);
 }
 }
 }

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

Git Shortcut git checkout step_4

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

Create the Mapple Decorator @Decorator
 @Priority(Interceptor.Priority.APPLICATION + 10)
 public abstract class MapplePoliteDecorator implements ChatService {
 
 static final Map DICTIONARY = new HashMap() {{
 put("fuck", "duck");
 put("crap", "trap");
 put("idiots", "world");
 put("cartman", "Stan");
 }};
 
 @Inject
 @Delegate
 private ChatService delegateService;
 
 @Inject
 @BadWord
 private Event 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);
 }
 }

Slide 58

Slide 58 text

Change existing code to introduce AdWord qualifier @Decorator
 @Priority(Interceptor.Priority.APPLICATION)
 public abstract class PoddleAddWordDecorator implements ChatService {
 
 …
 @Inject
 @AdWord
 private Event 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);
 }
 }

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

Git Shortcut git checkout step_5

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

Using the Interceptor @ApplicationScoped
 @Log
 public class ChatServiceImpl implements ChatService {
 … }

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

Git Shortcut git checkout step_6

Slide 68

Slide 68 text

Adding PrimeFaces to the POM 
 4.0.0 …
 
 …
 
 org.primefaces
 primefaces
 4.0
 runtime
 
 
 …


Slide 69

Slide 69 text

The JSF Page 
 
 
 
 
 WebSocket Chat
 
 
 
 


 
 
 
 
 Users

 
 
 
 Chat Log

 
 
 
 
 


 
 
 
 
 
 


 
 
 
 


Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

New content for index.html 
 
 
 


Slide 72

Slide 72 text

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 ?

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

Git Shortcut git checkout step_7

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

Git Shortcut git checkout step_8

Slide 81

Slide 81 text

Persistence.xml in META-INF 
 
 
 
 java:jboss/datasources/ExampleDS
 
 
 
 
 
 
 
 
 
 


Slide 82

Slide 82 text


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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

Git Shortcut git checkout step_9

Slide 88

Slide 88 text

Message queue and SenderService import 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);
 }
 }

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

The Message Driven Bean import 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 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);
 }
 }
 }

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

Questions