November 24, 2017

The Java EE 8 specification (JSR 366) Released 18 Sep, 2017.

The Java EE 8 specification (JSR 366) was released 18 Sep 2017.

https://jcp.org/en/jsr/detail?id=366

"What's New in Java EE 8

Java EE 8 continues to improve API and programming models needed for today's applications and adds features requested by our world-wide community. This release modernizes support for many industry standards and continues simplification of enterprise ready APIs. Enhancements include:
  • Java Servlet 4.0 API with HTTP/2 support
  • Enhanced JSON support including a new JSON binding API
  • A new REST Reactive Client API
  • Asynchronous CDI Events
  • A new portable Security API
  • Server-Sent Events support (Client & Server-side)
  • Support for Java SE 8 new capabilities (e.g. Date & Time API, Streams API, annotations enhancements)"
Java EE 8 builds on Java EE 7. The following JSRs are new or updated in Java EE 8:
  • JSR 366 – Java EE 8 Platform
  • JSR 365 – Contexts and Dependency Injection (CDI) 2.0
  • JSR 367 – The Java API for JSON Binding (JSON-B) 1.0
  • JSR 369 – Java Servlet 4.0
  • JSR 370 – Java API for RESTful Web Services (JAX-RS) 2.1
  • JSR 372 – JavaServer Faces (JSF) 2.3
  • JSR 374 – Java API for JSON Processing (JSON-P)1.1
  • JSR 375 – Java EE Security API 1.0
  • JSR 380 – Bean Validation 2.0
  • JSR 250 – Common Annotations 1.3
  • JSR 338 – Java Persistence 2.2
  • JSR 356 – Java API for WebSocket 1.1
  • JSR 919 – JavaMail 1.6"
http://www.oracle.com/technetwork/java/javaee/overview/index.html

The Java EE 8 Tutorial
https://javaee.github.io/tutorial/

And the source code is now published on github
https://github.com/javaee/tutorial-examples

GlassFish 5.0 was released 21 Oct 2017 and is the reference implementation for Java EE 8
https://en.wikipedia.org/wiki/GlassFish



November 19, 2017

HTTP Keep-Alive aka Persistant Connection with Apache httpd

HTTP Keep-Alive is also known as persistent connection. In the HTTP response you have

    Connection:Keep-Alive
    Keep-Alive:timeout=5, max=100

And to configure this in Apache httpd

    #
    # KeepAlive: Whether or not to allow persistent connections (more than
    # one request per connection). Set to "Off" to deactivate.
    #
    KeepAlive On

    #
    # MaxKeepAliveRequests: The maximum number of requests to allow
    # during a persistent connection. Set to 0 to allow an unlimited amount.
    # We recommend you leave this number high, for maximum performance.
    #
    MaxKeepAliveRequests 100

    #
    # KeepAliveTimeout: Number of seconds to wait for the next request from the
    # same client on the same connection.
    #
    KeepAliveTimeout 5

NOTE: MaxKeepAlive is a counter that counts down for each request and after that is a new HTTP session renegotiated, that can be costly if HTTPS is used, but is necessary to clean up lingering HTTP sessions.



Java EE 7 and What is New?

Overview Java EE 7

https://image.slidesharecdn.com/javaee7inaction-150506105621-conversion-gate02/95/java-ee7-in-action-10-638.jpg?cb=1430927843

Reference https://www.slideshare.net/ankarajug/java-ee7-in-action

JMS 2.0
  • Fluent APIs
  • Unchecked exceptions
  • MDB activation properties, JMS resource definition, default
    JMS resources
Java API for WebSocket NEW

Java API for JSON Processing NEW

Bean Validation 1.1
  • Method constraints @javax.validation.Valid
JAX-RS 2.0
  • Client API
JPA 2.1
  • Schema generation javax.persistence.schema-generation.database.action
JSF 2.2
  • File upload component h:inputFile
Batch Applications for the Java Platform NEW

Concurrency Utilities for Java EE NEW





Java EE 7 Simple WebSocket Example

One of the new technologies in Java EE 7 is WebSockets. A killer use case for web sockets is when a client need push notifications from the server. Previously such a client needed to constantly ask the server if there were any updates, which was ineffective and consumed a lot of server cpu. So lets implement a simple chat application that uses web sockets.

First the server. The whole layout or architecture behind web sockets reminds us very much as with jax-rs annotations. We start with a @ServerEndpoint class annotation, just like rest @Path.

Then you have only one mandatory method @OnMessage public void onMessage(String message, Session session). The method input parameters can be different, please read the javadoc.

Then you have 3 optional methods documented here. @OnOpen, @OnClose and @OnError

I will implement all 4 methods. I will also remember all sessions and will use CDI annotation @ApplicationScoped for that, but for it to work, we need to put the data in a separate POJO and annotate that also with @ApplicationScoped and let CDI handle the lifecycle via @Inject.

package se.magnuskkarlsson.example.javaee7.chat.boundary;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/chat")
@ApplicationScoped
public class ChatWebSocketServer {

    private final Logger log = Logger.getLogger(ChatWebSocketServer.class.getName());
    @Inject ChatSessions sessions;

    @OnOpen
    public void open(Session session) {
        sessions.getSessions().put(session.getId(), session);
        log.info("OPEN session " + session.getId());
        log.info("size " + sessions.getSessions().size());
    }

    @OnClose
    public void close(Session session) {
        sessions.getSessions().remove(session.getId());
        log.info("CLOSE session " + session.getId());
        log.info("size " + sessions.getSessions().size());
    }

    @OnError
    public void onError(Throwable error) {
        log.log(Level.SEVERE, "onError", error);
    }

    @OnMessage
    public void handleMessage(final String message, Session session) {
        log.info("size " + sessions.getSessions().size());
        sessions.getSessions().forEach((key, value) -> {
            try {
                value.getBasicRemote().sendText(message);
                log.info("SEND session " + value.getId() + ", message " + message);
            } catch (Exception e) {
                log.log(Level.SEVERE, "Failed to send text", e);
            }
        });
    }

}
package se.magnuskkarlsson.example.javaee7.chat.boundary;

import java.util.HashMap;
import java.util.Map;
import javax.enterprise.context.ApplicationScoped;
import javax.websocket.Session;

@ApplicationScoped
public class ChatSessions {
    
    private final Map<String, Session> sessions = new HashMap<>();

    public Map<String, Session> getSessions() {
        return sessions;
    }    
    
}

Now to the client. It is made up of a web page and javascript.

<!DOCTYPE html>
<html>
    <head>
        <title>Web Socket Demo</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="websocket.js"></script>
    </head>
    <body>
        <div>
            <form id="chatForm">
                Message: <input type="text" id="message" />
                <input type="button" value="Send" onclick="formSubmit()" />
            </form>
        </div>
        <div id="messages">
        </div>
    </body>
</html>

var socket = new WebSocket("ws://localhost:8080/example-javaee7/chat");
socket.onmessage = onMessage;

function onMessage(event) {
    var message = event.data;
    appendHtml("<--- Server : " + message);
}

function formSubmit() {
    var form = document.getElementById("chatForm");
    var message = form.elements["message"].value;
    socket.send(message);
    appendHtml("---> You : " + message);
}

function appendHtml(message) {
    var div = document.getElementById("messages")
    div.innerHTML += "

" + message + "

"; }

November 18, 2017

Java 8 Nashorn Using JavaScript on the JVM

Nashorn is the official JavaScript Engine in the Java Virtual Machine since Version 8. It supports and implements the ECMAScript 5.1 specification and competes among others directly with Google V8 (the script engine behind Node.js). Nashorn compiles JavaScript to Java Bytecode during runtime and thus provides high interoperability of Java and JavaScript.

Lets give it a try with our previous example in Java EE 7 Implementing Statistics with Interceptor, CDI Observes and LongSummaryStatistics

#!/usr/bin/jjs -fv

var uri = "http://localhost:8080/example-javaee7/rest/statistics"
var command = "curl ${uri}"
$EXEC(command)
var result = $OUT
print(result)
var resultAsArray = JSON.parse(result)
print(resultAsArray)

Now call it

$ chmod +x nashorn-demo.js
$ ./nashorn-demo.js 
nashorn full version 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12
{"statistics":"LongSummaryStatistics{count=18, sum=111, min=0, average=6.166667, max=75}"}
[object Object]

Java EE 7 Implementing Statistics with Interceptor, CDI Observes and LongSummaryStatistics

Java EE 7 comes with many built in techniques. Lets add statistics to our application.

First we use the Interceptor to interceptor our method that we want to get performance statistics from.

package se.magnuskkarlsson.example.javaee7.monitoring.control;

import se.magnuskkarlsson.example.javaee7.monitoring.entity.PerformanceEvent;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class PerformanceInterceptor {

    @Inject
    Event events;
    
    @AroundInvoke
    public Object intercept(InvocationContext ctx) throws Exception {
        String className = ctx.getTarget().getClass().getName();
        String methodName = ctx.getMethod().getName();
        long start = System.currentTimeMillis();
        Object object = null;
        try {
            object = ctx.proceed();
        } finally {
            long duration = System.currentTimeMillis() - start;
            events.fire(new PerformanceEvent(className, methodName, duration));
        }
        return object;
    }

}

Above we only collect information and then use EE Event to fire it to a Observes. The data Object is a POJO.

package se.magnuskkarlsson.example.javaee7.monitoring.entity;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class PerformanceEvent {
   
    private final String clazz;
    private final String method;
    private final long duration;

    public PerformanceEvent(String clazz, String method, long duration) {
        this.clazz = clazz;
        this.method = method;
        this.duration = duration;
    }

    public String getClazz() {
        return clazz;
    }

    public String getMethod() {
        return method;
    }

    public long getDuration() {
        return duration;
    }

    @Override
    public String toString() {
        return "PerformanceEvent{" + "clazz=" + clazz + ", method=" + method + ", duration=" + duration + '}';
    }
    
}

And the Observes that recieves the Event.

package se.magnuskkarlsson.example.javaee7.monitoring.control;

import java.util.LongSummaryStatistics;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.enterprise.event.Observes;
import javax.inject.Singleton;
import se.magnuskkarlsson.example.javaee7.monitoring.entity.PerformanceEvent;
import java.util.stream.Collectors;

@Singleton
// ConcurrencyManagement.Bean will make singleton bean open for concurrent calls
// see https://docs.oracle.com/javaee/7/tutorial/ejb-basicexamples002.htm
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class StatisticsObserver {

    CopyOnWriteArraySet events = new CopyOnWriteArraySet<>();
    
    public void log(@Observes PerformanceEvent event) {
        events.add(event);
    }

    public LongSummaryStatistics getStatistics() {
        return events.stream().collect(Collectors.summarizingLong(PerformanceEvent::getDuration));
    }
    
}

To be able to collect statistics from many concurrent methods, we first make the class a Singleton and then make it concurrent by using ConcurrencyManagement.Bean. Now we will receive concurrent incoming calls, so to make it thread safe we use CopyOnWriteArraySet.

So the now the collection is done with Interceptor and the calculation is done with LongSummaryStatistics. Now expose it via REST.

package se.magnuskkarlsson.example.javaee7.monitoring.boundary;

import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonObject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import se.magnuskkarlsson.example.javaee7.monitoring.control.StatisticsObserver;

@Path("/statistics")
@Produces({MediaType.APPLICATION_JSON})
public class StatisticsRest {
    
    @Inject
    StatisticsObserver bean;
    
    @GET
    public JsonObject getStatistics() {
        return Json.createObjectBuilder().add("statistics", bean.getStatistics().toString()).build();
    }
    
}

Then call the application a couple of times, then test the statistics via, e.g. a curl command.

$ curl -i -H"Accept: application/json" http://localhost:8080/example-javaee7/rest/statistics
HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: JBoss-EAP/7
Content-Type: application/json
Content-Length: 90
Date: Sat, 18 Nov 2017 03:32:41 GMT

{"statistics":"LongSummaryStatistics{count=18, sum=111, min=0, average=6.166667, max=75}"}

To see more for Interceptor, please see my previous blog Java EE 7 Performance Monitor with Interceptors, Event and Observes .

November 17, 2017

Java EE 7 Performance Monitor with Interceptors, Event and Observes

Lets say you want to performance monitor your business class, that can be achieved with Java EE 7 Interceptors and @Observes. Lets start with the interceptor. Here will only want to encapsulate the actual aggregation and after collecting we use the Java EE 7 Event to send it to the @Observes. A clean separation of concerns.

package se.magnuskkarlsson.example.javaee7;

import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class PerformanceInterceptor {

    @Inject
    Event<PerformanceEvent> events;
    
    @AroundInvoke
    public Object intercept(InvocationContext ctx) throws Exception {
        String className = ctx.getTarget().getClass().getName();
        String methodName = ctx.getMethod().getName();
        long start = System.currentTimeMillis();
        Object object = null;
        try {
            object = ctx.proceed();
        } finally {
            long duration = System.currentTimeMillis() - start;
            events.fire(new PerformanceEvent(className, methodName, duration));
        }
        return object;
    }
}

And the class that holds the data is a POJO.

package se.magnuskkarlsson.example.javaee7;

public class PerformanceEvent {
   
    private final String clazz;
    private final String method;
    private final long duration;

    public PerformanceEvent(String clazz, String method, long duration) {
        this.clazz = clazz;
        this.method = method;
        this.duration = duration;
    }

    public String getClazz() {
        return clazz;
    }

    public String getMethod() {
        return method;
    }

    public long getDuration() {
        return duration;
    }

    @Override
    public String toString() {
        return "PerformanceEvent{" + "clazz=" + clazz + ", method=" + method + ", duration=" + duration + '}';
    }
    
}

And the @Observes.

package se.magnuskkarlsson.example.javaee7;

import java.util.logging.Logger;
import javax.enterprise.event.Observes;

public class PerformanceObserver {

    private final Logger log = Logger.getLogger(PerformanceObserver.class.getName());
    
    public void log(@Observes PerformanceEvent event) {
        log.info(event.toString());
    }

}

And to use in your class that we want to performance measure.

package se.magnuskkarlsson.example.javaee7.control;

import se.magnuskkarlsson.example.javaee7.PerformanceInterceptor;

@Stateless
@Interceptors(PerformanceInterceptor.class)
public class EmployeeBean {

// the public methods we want to measure goes here ...
}

And when we run it

00:37:38,008 INFO  [se.magnuskkarlsson.example.javaee7.PerformanceObserver] (default task-9) PerformanceEvent{clazz=se.magnuskkarlsson.example.javaee7.control.EmployeeBean, method=delete, duration=2}