(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
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...
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
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
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
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
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
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
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); } }
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
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
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
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
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
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
... ! 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
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 ?
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
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...
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
= 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
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...
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
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