Thursday Nov 29, 2012

Collaborative Whiteboard using WebSocket in GlassFish 4 - Text/JSON and Binary/ArrayBuffer Data Transfer (TOTD #189)


This blog has published a few blogs on using JSR 356 Reference Implementation (Tyrus) as its integrated in GlassFish 4 promoted builds.
  • TOTD #183: Getting Started with WebSocket in GlassFish
  • TOTD #184: Logging WebSocket Frames using Chrome Developer Tools, Net-internals and Wireshark
  • TOTD #185: Processing Text and Binary (Blob, ArrayBuffer, ArrayBufferView) Payload in WebSocket
  • TOTD #186: Custom Text and Binary Payloads using WebSocket
One of the typical usecase for WebSocket is online collaborative games. This Tip Of The Day (TOTD) explains a sample that can be used to build such games easily.

The application is a collaborative whiteboard where different shapes can be drawn in multiple colors. The shapes drawn on one browser are automatically drawn on all other peer browsers that are connected to the same endpoint. The shape, color, and coordinates of the image are transfered using a JSON structure. A browser may opt-out of sharing the figures. Alternatively any browser can send a snapshot of their existing whiteboard to all other browsers. Take a look at this video to understand how the application work and the underlying code.



The Java API for WebSocket has evolved since this sample was first created. Here is the source code corresponding to different builds of GlassFish:
GlassFish4 4 Build Source Code
66 here
74 here
76 here
78 here
84 here
The code in the application is explained below.

The web page (index.jsp) has a HTML5 Canvas as shown:
<canvas id="myCanvas" width="150" height="150" style="border:1px solid #000000;"></canvas>
And some radio buttons to choose the color and shape. By default, the shape, color, and coordinates of any figure drawn on the canvas are put in a JSON structure and sent as a message to the WebSocket endpoint. The JSON structure looks like:
{
"shape": "square",
"color": "#FF0000",
"coords": {
"x": 31.59999942779541,
"y": 49.91999053955078
}
}
The endpoint definition looks like:
@WebSocketEndpoint(value = "websocket",
encoders = {FigureDecoderEncoder.class},
decoders = {FigureDecoderEncoder.class})
public class Whiteboard {

As you can see, the endpoint has decoder and encoder registered that decodes JSON to a Figure (a POJO class) and vice versa respectively. The decode method looks like:
public Figure decode(String string) throws DecodeException {
try {
JSONObject jsonObject = new JSONObject(string);
return new Figure(jsonObject);
} catch (JSONException ex) {
throw new DecodeException("Error parsing JSON", ex.getMessage(), ex.fillInStackTrace());
}
}
And the encode method looks like:
public String encode(Figure figure) throws EncodeException {
return figure.getJson().toString();
}
FigureDecoderEncoder implements both decoder and encoder functionality but thats purely for convenience. But the recommended design pattern is to keep them in separate classes. In certain cases, you may even need only one of them.

On the client-side, the Canvas is initialized as:
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
canvas.addEventListener("click", defineImage, false);

The defineImage method constructs the JSON structure as shown above and sends it to the endpoint using websocket.send().

An instant snapshot of the canvas is sent using binary transfer with WebSocket. The WebSocket is initialized as:
var wsUri = "ws://localhost:8080/whiteboard/websocket";
var websocket = new WebSocket(wsUri);
websocket.binaryType = "arraybuffer";

The important part is to set the binaryType property of WebSocket to arraybuffer. This ensures that any binary transfers using WebSocket are done using ArrayBuffer as the default type seem to be blob. The actual binary data transfer is done using the following:

var image = context.getImageData(0, 0, canvas.width, canvas.height);
var buffer = new ArrayBuffer(image.data.length);
var bytes = new Uint8Array(buffer);
for (var i=0; i<bytes.length; i++) {
bytes[i] = image.data[i];
}
websocket.send(bytes);

This comprehensive sample shows the following features of JSR 356 API:
  • Annotation-driven endpoints
  • Send/receive text and binary payload in WebSocket
  • Encoders/decoders for custom text payload

In addition, it also shows how images can be captured and drawn using HTML5 Canvas in a JSP.

How could this be turned in to an online game ? Imagine drawing a Tic-tac-toe board on the canvas with two players playing and others watching. Then you can build access rights and controls within the application itself. Instead of sending a snapshot of the canvas on demand, a new peer joining the game could be automatically transferred the current state as well. Do you want to build this game ?

I built a similar game a few years ago. Do somebody want to rewrite the game using WebSocket APIs ? :-)

Many thanks to Jitu and Akshay for helping through the WebSocket internals!

Here are some references for you:
Subsequent blogs will discuss the following topics (not necessary in that order) ...
  • Error handling
  • Interface-driven WebSocket endpoint
  • Java client API
  • Client and Server configuration
  • Security
  • Subprotocols
  • Extensions
  • Other topics from the API

Tuesday Nov 27, 2012

Non-blocking I/O using Servlet 3.1: Scalable applications using Java EE 7 (TOTD #188)


Servlet 3.0 allowed asynchronous request processing but only traditional I/O was permitted. This can restrict scalability of your applications. In a typical application, ServletInputStream is read in a while loop.
public class TestServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
         throws IOException, ServletException {    
ServletInputStream input = request.getInputStream();
       byte[] b = new byte[1024];
       int len = -1;
       while ((len = input.read(b)) != -1) {
          . . .
       }
   }
}
If the incoming data is blocking or streamed slower than the server can read then the server thread is waiting for that data. The same can happen if the data is written to ServletOutputStream.

This is resolved in Servet 3.1 (JSR 340, to be released as part Java EE 7) by adding event listeners - ReadListener and WriteListener interfaces. These are then registered using ServletInputStream.setReadListener and ServletOutputStream.setWriteListener. The listeners have callback methods that are invoked when the content is available to be read or can be written without blocking.

The updated doGet in our case will look like:

AsyncContext context = request.startAsync();
ServletInputStream input = request.getInputStream();
input.setReadListener(new MyReadListener(input, context));

Invoking setXXXListener methods indicate that non-blocking I/O is used instead of the traditional I/O. At most one ReadListener can be registered on ServletIntputStream and similarly at most one WriteListener can be registered on ServletOutputStream. ServletInputStream.isReady and ServletInputStream.isFinished are new methods to check the status of non-blocking I/O read. ServletOutputStream.canWrite is a new method to check if data can be written without blocking.

 MyReadListener implementation looks like:

@Override
public void onDataAvailable() {
try {
StringBuilder sb = new StringBuilder();
int len = -1;
byte b[] = new byte[1024];
while (input.isReady()
&& (len = input.read(b)) != -1) {
String data = new String(b, 0, len);
System.out.println("--> " + data);
}
} catch (IOException ex) {
Logger.getLogger(MyReadListener.class.getName()).log(Level.SEVERE, null, ex);
}
}

@Override
public void onAllDataRead() {
System.out.println("onAllDataRead");
context.complete();
}

@Override
public void onError(Throwable t) {
t.printStackTrace();
context.complete();
}

This implementation has three callbacks:
  • onDataAvailable callback method is called whenever data can be read without blocking
  • onAllDataRead callback method is invoked data for the current request is completely read.
  • onError callback is invoked if there is an error processing the request.
Notice, context.complete() is called in onAllDataRead and onError to signal the completion of data read.

For now, the first chunk of available data need to be read in the doGet or service method of the Servlet. Rest of the data can be read in a non-blocking way using ReadListener after that. This is going to get cleaned up where all data read can happen in ReadListener only.

The sample explained above can be downloaded from here and works with GlassFish 4.0 build 64 and onwards.

The slides and a complete re-run of What's new in Servlet 3.1: An Overview session at JavaOne is available here.

Here are some more references for you:

Monday Nov 26, 2012

What's new in EJB 3.2 ? - Java EE 7 chugging along!


EJB 3.1 added a whole ton of features for simplicity and ease-of-use such as @Singleton, @Asynchronous, @Schedule, Portable JNDI name, EJBContainer.createEJBContainer, EJB 3.1 Lite, and many others. As part of Java EE 7, EJB 3.2 (JSR 345) is making progress and this blog will provide highlights from the work done so far. This release has been particularly kept small but include several minor improvements and tweaks for usability.

  • More features in EJB.Lite
    • Asynchronous session bean
    • Non-persistent EJB Timer service

      This also means these features can be used in embeddable EJB container and there by improving testability of your application.
  • Pruning - The following features were made Proposed Optional in Java EE 6 and are now made optional.
    • EJB 2.1 and earlier Entity Bean Component Contract for CMP and BMP
    • Client View of an EJB 2.1 and earlier Entity Bean
    • EJB QL: Query Language for CMP Query Methods
    • JAX-RPC-based Web Service Endpoints and Client View

      The optional features are moved to a separate document and as a result EJB specification is now split into Core and Optional documents. This allows the specification to be more readable and better organized.
  • Updates and Improvements
    • Transactional lifecycle callbacks in Stateful Session Beans, only for CMT. In EJB 3.1, the transaction context for lifecyle callback methods (@PostConstruct, @PreDestroy, @PostActivate, @PrePassivate) are defined as shown.


@PostConstruct @PreDestroy
@PrePassivate
@PostActivate
Stateless
Unspecified
Unspecified N/A
N/A
Stateful
Unspecified Unspecified Unspecified Unspecified
Singleton
Bean's transaction
management type
Bean's transaction
management type
N/A
N/A

In EJB 3.2, stateful session bean lifecycle callback methods can opt-in to be transactional. These methods are then executed in a transaction context as shown.


@PostConstruct @PreDestroy
@PrePassivate
@PostActivate
Stateless
Unspecified
Unspecified N/A
N/A
Stateful
Bean's transaction
management type
Bean's transaction
management type
Bean's transaction
management type
Bean's transaction
management type
Singleton
Bean's transaction
management type
Bean's transaction
management type
N/A
N/A

For example, the following stateful session bean require a new transaction to be started for @PostConstruct and @PreDestroy lifecycle callback methods.

@Stateful
public class HelloBean {
   @PersistenceContext(type=PersistenceContextType.EXTENDED)
   private EntityManager em;
   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
   @PostConstruct
   public void init() {
        myEntity = em.find(...);
   }

   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)    @PostConstruct    public void destroy() {        em.flush();    }
}

Notice, by default the lifecycle callback methods are not transactional for backwards compatibility. They need to be explicitly opt-in to be made transactional.
  • Opt-out of passivation for stateful session bean - If your stateful session bean needs to stick around or it has non-serializable field then the bean can be opt-out of passivation as shown.

    @Stateful(passivationCapable=false)
    public class HelloBean {
        private NonSerializableType ref = ...

    . . .

    }
  • Simplified the rules to define all local/remote views of the bean. For example, if the bean is defined as:
    @Stateless
    public class Bean implements Foo, Bar {
        . . .
    }
    where Foo and Bar have no annotations of their own, then Foo and Bar are exposed as local views of the bean. The bean may be explicitly marked @Local as
    @Local
    @Stateless
    public class Bean implements Foo, Bar {
        . . .
    }

    then this is the same behavior as explained above, i.e. Foo and Bar are local views.

    If the bean is marked @Remote as:
    @Remote
    @Stateless
    public class Bean implements Foo, Bar {
        . . .
    }
    then Foo and Bar are remote views. If an interface is marked @Local or @Remote then each interface need to be explicitly marked explicitly to be exposed as a view. For example:

    @Remote
    public interface Foo { . . . }

    @Stateless
    public class Bean implements Foo, Bar {
        . . .
    }
    only exposes one remote interface Foo.

    Section 4.9.7 from the specification provide more details about this feature.
  • TimerService.getAllTimers is a newly added convenience API that returns all timers in the same bean. This is only for displaying the list of timers as the timer can only be canceled by its owner.
  • Removed restriction to obtain the current class loader, and allow to use java.io package. This is handy if you want to do file access within your beans.
  • JMS 2.0 alignment - A standard list of activation-config properties is now defined
    • destinationLookup
    • connectionFactoryLookup
    • clientId
    • subscriptionName
    • shareSubscriptions
  • Tons of other clarifications through out the spec. Appendix A provide a comprehensive list of changes since EJB 3.1.
  • ThreadContext in Singleton is guaranteed to be thread-safe.
  • Embeddable container implement Autocloseable.

A complete replay of Enterprise JavaBeans Today and Tomorrow from JavaOne 2012 can be seen here (click on CON4654_mp4_4654_001 in Media).

The specification is still evolving so the actual property or method names or their actual behavior may be different from the currently proposed ones.

Are there any improvements that you'd like to see in EJB 3.2 ? The EJB 3.2 Expert Group would love to hear your feedback. An Early Draft of the specification is available. The latest version of the specification can always be downloaded from here.

These features will start showing up in GlassFish 4 Promoted Builds soon.

Wednesday Nov 21, 2012

JPA 2.1 Schema Generation (TOTD #187)

UPDATED: May 24, 2012

JPA 2.1 specification is now final and can be download from here. The Reference Implementation is integrated in GlassFish 4 Promoted Builds (soon to be final). The Schema Generation property names have changed since the blog was originally published and is now updated in the table below.

Blog from Nov 11, 2012

This blog explained some of the key features of JPA 2.1 earlier. Since then Schema Generation has been added to JPA 2.1. This Tip Of The Day (TOTD) will provide more details about this new feature in JPA 2.1.

Schema Generation refers to generation of database artifacts like tables, indexes, and constraints in a database schema. It may or may not involve generation of a proper database schema depending upon the credentials and authorization of the user. This helps in prototyping of your application where the required artifacts are generated either prior to application deployment or as part of EntityManagerFactory creation. This is also useful in environments that require provisioning database on demand, e.g. in a cloud.

This feature will allow your JPA domain object model to be directly generated in a database. The generated schema may need to be tuned for actual production environment. This usecase is supported by allowing the schema generation to occur into DDL scripts which can then be further tuned by a DBA.

The following set of properties in persistence.xml or specified during EntityManagerFactory creation controls the behaviour of schema generation.

Property Name
Purpose
Values
javax.persistence.schema-generation.database.action
Specifies the action to be taken by the persistence provider with regard to the database artifacts Per.book "none", "create", "drop-and-create", "drop"
javax.persistence.schema-generation.scripts.action
Specifies which scripts are to be generated by the persistence provider Per.book "none", "create", "drop-and-create", "drop"
javax.persistence.schema-generation.create-source
javax.persistence.schema-generation.drop-source
Specifies whether the creation/dropping of database artifacts is to occur on the basis of the object/relational mapping metadata, DDL script, or a combination of the two.
"metadata", "script", "metadata-then-script", "script-then-metadata"
javax.persistence.schema-generation.create-database-schemas
Specifies whether the persistence provider is to create the database schema(s) in addi- tion to creating database objects such as tables, sequences, constraints, etc.
"true", "false"
javax.persistence.schema-generation.scripts.create-target
javax.persistence.schema-generation.scripts.drop-target
If scripts are to be generated, controls target locations for writing of scripts. Writers are pre-configured for the persistence provider. Need to be specified only if scripts are to be generated.
java.io.Writer (e.g. MyWriter.class) or URL strings
javax.persistence.database-product-name,
javax.persistence.database-major-version, javax.persistence.database-minor-version
Needed if scripts are to be generated and no connection to target database. Values are those obtained from JDBC DatabaseMetaData.

javax.persistence.schema-generation.scripts.create-script-source
javax.persistence.schema-generation.scripts.drop-script-source
Specifies locations from which DDL scripts are to be read. Readers are pre-configured for the persistence provider.
java.io.Reader (e.g. MyReader.class) or URL strings
javax.persistence.schema-generation.connection
JDBC connection to be used for schema generation

javax.persistence.sql-load-script-source
Specifies location of SQL bulk load script.
java.io.Reader (e.g. MyReader.class) or URL string

Section 11.2 in the JPA 2.1 specification defines the annotations used for schema generation process. For example, @Table, @Column, @CollectionTable, @JoinTable, @JoinColumn, are used to define the generated schema. Several layers of defaulting may be involved. For example, the table name is defaulted from entity name and entity name (which can be specified explicitly as well) is defaulted from the class name. However annotations may be used to override or customize the values.

The following entity class:

@Entity public class Employee {
    @Id private int id;
    private String name;
    . . .
    @ManyToOne     private Department dept; }

is generated in the database with the following attributes:

  • Maps to EMPLOYEE table in default schema
  • "id" field is mapped to ID column as primary key
  • "name" is mapped to NAME column with a default VARCHAR(255). The length of this field can be easily tuned using @Column.
  • @ManyToOne is mapped to DEPT_ID foreign key column. Can be customized using JOIN_COLUMN.

In addition to these properties, couple of new annotations are added to JPA 2.1:

  • @Index - An index for the primary key is generated by default in a database. This new annotation will allow to define additional indexes, over a single or multiple columns, for a better performance. This is specified as part of @Table, @SecondaryTable, @CollectionTable, @JoinTable, and @TableGenerator. For example:

    @Table(indexes = {@Index(columnList="NAME"), @Index(columnList="DEPT_ID DESC")})
    @Entity public class Employee {
        . . .
    }

    The generated table will have a default index on the primary key. In addition, two new indexes are defined on the NAME column (default ascending) and the foreign key that maps to the department in descending order.
  • @ForeignKey - It is used to define foreign key constraint or to otherwise override or disable the persistence provider's default foreign key definition. Can be specified as part of JoinColumn(s), MapKeyJoinColumn(s), PrimaryKeyJoinColumn(s). For example:

    @Entity public class Employee {
        @Id private int id;
        private String name;

        @ManyToOne
        @JoinColumn(foreignKey=@ForeignKey(foreignKeyDefinition="FOREIGN KEY (MANAGER_ID) REFERENCES MANAGER"))
        private Manager manager;
        . . .
    }

    In this entity, the employee's manager is mapped by MANAGER_ID column in the MANAGER table. The value of foreignKeyDefinition would be a database specific string.

A complete replay of Linda's talk at JavaOne 2012 can be seen here (click on CON4212_mp4_4212_001 in Media).

These features will be available in GlassFish 4 promoted builds in the near future. The development in EclipseLink is tracked here.

JPA 2.1 will be delivered as part of Java EE 7. The different components in the Java EE 7 platform are tracked here.

JPA 2.1 Expert Group has released Early Draft 2 of the specification. Section 9.4 and 11.2 provide all details about Schema Generation. The latest javadocs can be obtained from here. And the JPA EG would appreciate feedback.

Thursday Nov 15, 2012

Custom Text and Binary Payloads using WebSocket (TOTD #186)


TOTD #185 explained how to process text and binary payloads in a WebSocket endpoint. In summary, a text payload may be received as

public void receiveTextMessage(String message) {
    . . .
}

And binary payload may be received as:

public void recieveBinaryMessage(ByteBuffer message) {
    . . .
}

As you realize, both of these methods receive the text and binary data in raw format. However you may like to receive and send the data using a POJO. This marshaling and unmarshaling can be done in the method implementation but JSR 356 API provides a cleaner way. For encoding and decoding text payload into POJO, Decoder.Text (for inbound payload) and Encoder.Text (for outbound payload) interfaces need to be implemented.

A sample implementation below shows how text payload consisting of JSON structures can be encoded and decoded.
public class MyMessage implements Decoder.Text<MyMessage>, Encoder.Text<MyMessage> {
    private JsonObject jsonObject;

    @Override
    public MyMessage decode(String string) throws DecodeException {
        this.jsonObject = new JsonReader(new StringReader(string)).readObject();      
        return this;
    }

    @Override
    public boolean willDecode(String string) {
        return true;
    }

    @Override
    public String encode(MyMessage myMessage) throws EncodeException {
        return myMessage.jsonObject.toString();
    }

public JsonObject getObject() { return jsonObject; }
}
In this implementation, the decode method decodes incoming text payload to MyMessage, the encode method encodes MyMessage for the outgoing text payload, and the willDecode method returns true or false if the message can be decoded.

The encoder and decoder implementation classes need to be specified in the WebSocket endpoint as:
@WebSocketEndpoint(value="/endpoint",
encoders={MyMessage.class},
decoders={MyMessage.class}) public class MyEndpoint { public MyMessage receiveMessage(MyMessage message) { . . . } }
Notice the updated method signature where the application is working with MyMessage instead of the raw string.

Note that the encoder and decoder implementations just illustrate the point and provide no validation or exception handling. Similarly Encooder.Binary and Decoder.Binary interfaces need to be implemented for encoding and decoding binary payload.

Here are some references for you:
Subsequent blogs will discuss the following topics (not necessary in that order) ...
  • Error handling
  • Interface-driven WebSocket endpoint
  • Java client API
  • Client and Server configuration
  • Security
  • Subprotocols
  • Extensions
  • Other topics from the API

Sunday Nov 11, 2012

Processing Text and Binary (Blob, ArrayBuffer, ArrayBufferView) Payload in WebSocket - (TOTD #185)


The WebSocket API defines different send(xxx) methods that can be used to send text and binary data. This Tip Of The Day (TOTD) will show how to send and receive text and binary data using WebSocket.

TOTD #183 explains how to get started with a WebSocket endpoint using GlassFish 4. A simple endpoint from that blog looks like:
@WebSocketEndpoint("/endpoint")
public class MyEndpoint {
public void receiveTextMessage(String message) {
. . .
}
}
A message with the first parameter of the type String is invoked when a text payload is received. The payload of the incoming WebSocket frame is mapped to this first parameter.

An optional second parameter, Session, can be specified to map to the "other end" of this conversation. For example:
public void receiveTextMessage(String message, Session session) {
    . . .
}
The return type is void and that means no response is returned to the client that invoked this endpoint. A response may be returned to the client in two different ways. First, set the return type to the expected type, such as:
public String receiveTextMessage(String message) {
String response = . . .
. . .
return response; }
In this case a text payload is returned back to the invoking endpoint.

The second way to send a response back is to use the mapped session to send response using one of the sendXXX methods in Session, when and if needed.
public void receiveTextMessage(String message, Session session) {
    . . .
    RemoteEndpoint remote = session.getRemote();
    remote.sendString(...);
    . . .
    remote.sendString(...);
   . . .
   remote.sendString(...);
}
This shows how duplex and asynchronous communication between the two endpoints can be achieved. This can be used to define different message exchange patterns between the client and server.

The WebSocket client can send the message as:
websocket.send(myTextField.value);
where myTextField is a text field in the web page.

Binary payload in the incoming WebSocket frame can be received if ByteBuffer is used as the first parameter of the method signature. The endpoint method signature in that case would look like:
public void receiveBinaryMessage(ByteBuffer message) {
    . . .
}
From the client side, the binary data can be sent using Blob, ArrayBuffer, and ArrayBufferView. Blob is a just raw data and the actual interpretation is left to the application. ArrayBuffer and ArrayBufferView are defined in the TypedArray specification and are designed to send binary data using WebSocket. In short, ArrayBuffer is a fixed-length binary buffer with no format and no mechanism for accessing its contents. These buffers are manipulated using one of the views defined by one of the subclasses of ArrayBufferView listed below:
  • Int8Array (signed 8-bit integer or char)
  • Uint8Array (unsigned 8-bit integer or unsigned char)
  • Int16Array (signed 16-bit integer or short)
  • Uint16Array (unsigned 16-bit integer or unsigned short)
  • Int32Array (signed 32-bit integer or int)
  • Uint32Array (unsigned 16-bit integer or unsigned int)
  • Float32Array (signed 32-bit float or float)
  • Float64Array (signed 64-bit float or double)
WebSocket can send binary data using ArrayBuffer with a view defined by a subclass of ArrayBufferView or a subclass of ArrayBufferView itself.

The WebSocket client can send the message using Blob as:

blob = new Blob([myField2.value]);
websocket.send(blob);

where myField2 is a text field in the web page.

The WebSocket client can send the message using ArrayBuffer as:

var buffer = new ArrayBuffer(10);
var bytes = new Uint8Array(buffer);
for (var i=0; i<bytes.length; i++) {
bytes[i] = i;
}
websocket.send(buffer);
A concrete implementation of receiving the binary message may look like:

@WebSocketMessage
public void echoBinary(ByteBuffer data, Session session) throws IOException {
    System.out.println("echoBinary: " + data);
    for (byte b : data.array()) {
        System.out.print(b);
    }
    session.getRemote().sendBytes(data);
}

This method is just printing the binary data for verification but you may actually be storing it in a database or converting to an image or something more meaningful.

Be aware of TYRUS-51 if you are trying to send binary data from server to client using method return type.

Here are some references for you:
Subsequent blogs will discuss the following topics (not necessary in that order) ...
  • Error handling
  • Custom payloads using encoder/decoder
  • Interface-driven WebSocket endpoint
  • Java client API
  • Client and Server configuration
  • Security
  • Subprotocols
  • Extensions
  • Other topics from the API

Wednesday Nov 07, 2012

Logging WebSocket Frames using Chrome Developer Tools, Net-internals and Wireshark (TOTD #184)


TOTD #183 explained how to build a WebSocket-driven application using GlassFish 4. This Tip Of The Day (TOTD) will explain how do view/debug on-the-wire messages, or frames as they are called in WebSocket parlance, over this upgraded connection. This blog will use the application built in TOTD #183.

First of all, make sure you are using a browser that supports WebSocket. If you recall from TOTD #183 then WebSocket is combination of Protocol and JavaScript API. A browser supporting WebSocket, or not, means they understand your web pages with the WebSocket JavaScript. caniuse.com/websockets provide a current status of WebSocket support in different browsers. Most of the major browsers such as Chrome, Firefox, Safari already support WebSocket for the past few versions. As of this writing, IE still does not support WebSocket however its planned for a future release.

Viewing WebSocket farmes require special settings because all the communication happens over an upgraded HTTP connection over a single TCP connection. If you are building your application using Java, then there are two common ways to debug WebSocket messages today. Other language libraries provide different mechanisms to log the messages.

Lets get started!

Chrome Developer Tools provide information about the initial handshake only. This can be viewed in the Network tab and selecting the endpoint hosting the WebSocket endpoint.



You can also click on "WebSockets" on the bottom-right to show only the WebSocket endpoints.

Click on "Frames" in the right panel to view the actual frames being exchanged between the client and server.



The frames are not refreshed when new messages are sent or received. You need to refresh the panel by clicking on the endpoint again.

To see more detailed information about the WebSocket frames, you need to type "chrome://net-internals" in a new tab. Click on "Sockets" in the left navigation bar and then on "View live sockets" to see the page.



Select the box with the address to your WebSocket endpoint and see some basic information about connection and bytes exchanged between the client and the endpoint.



Clicking on the blue text "source dependency ..." shows more details about the handshake.




If you are interested in viewing the exact payload of WebSocket messages then you need a network sniffer. These tools are used to snoop network traffic and provide a lot more details about the raw messages exchanged over the network. However because they provide lot more information so they need to be configured in order to view the relevant information.

Wireshark (nee Ethereal) is a pretty standard tool for sniffing network traffic and will be used here. For this blog purpose, we'll assume that the WebSocket endpoint is hosted on the local machine. These tools do allow to sniff traffic across the network though. Wireshark is quite a comprehensive tool and we'll capture traffic on the loopback address.

Start wireshark, select "loopback" and click on "Start".



By default, all traffic information on the loopback address is displayed. That includes tons of TCP protocol messages, applications running on your local machines (like GlassFish or Dropbox on mine), and many others. Specify "http" as the filter in the top-left. Invoke the application built in TOTD #183 and click on "Say Hello" button once. The output in wireshark looks like



Here is a description of the messages exchanged:
  • Message #4: Initial HTTP request of the JSP page
  • Message #6: Response returning the JSP page
  • Message #16: HTTP Upgrade request



  • Message #18: Upgrade request accepted

  • Message #20: Request favicon
  • Message #22: Responding with favicon not found
  • Message #24: Browser making a WebSocket request to the endpoint


  • Message #26: WebSocket endpoint responding back

You can also use Fiddler to debug your WebSocket messages.

How are you viewing your WebSocket messages ?

Here are some references for you:
Subsequent blogs will discuss the following topics (not necessary in that order) ...
  • Binary data as payload
  • Custom payloads using encoder/decoder
  • Error handling
  • Interface-driven WebSocket endpoint
  • Java client API
  • Client and Server configuration
  • Security
  • Subprotocols
  • Extensions
  • Other topics from the API

Sunday Nov 04, 2012

JMaghreb 2012 Trip Report



JMaghreb is the inaugural Java conference organized by Morocco JUG. It is the biggest Java conference in Maghreb (5 countries in North West Africa).

Oracle was the exclusive platinum sponsor with several others. The registrations had to be closed at 1412 for the free conference and several folks were already on the waiting list. Rabat with 531 registrations and Casablanca with 426 were the top cities. Some statistics ...
  • 850+ attendees over 2 days, 500+ every day
  • 30 sessions were delivered by 18 speakers from 10 different countries
  • 10 sessions in French and 20 in English
    • 6 of the speakers spoke at JavaOne 2012
    • 8 will be at Devoxx
  • Attendees from 5 different countries and 57 cities in Morocco
  • 40.9% qualified them as professional and rest as students
  • Topics ranged from HTML5, Java EE 7, ADF, JavaFX, MySQL, JCP, Vaadin, Android, Community, JCP
  • Java EE 6 hands-on lab was sold out within 7 minutes and JavaFX in 12 minutes
I gave the keynote along with Simon Ritter which was basically a recap of the Strategy and Technical keynotes presented at JavaOne 2012. An informal survey during the keynote showed the following numbers:
  • 25% using NetBeans, 90% on Eclipse, 3 on JDeveloper, 1 on IntelliJ
  • About 10 subscribers to free online Java magazine. This digital magazine is a comprehensive source of information for everything Java - subscribe for free!!
  • About 10-15% using Java SE 7. Download JDK 7 and get started today! Even JDK 8 builds have been available for a while now.
My second talk explained the core concepts of WebSocket and how JSR 356 is providing a standard API to build WebSocket-driven applications in Java EE 7. TOTD #183 explains how you can easily get started with WebSocket in GlassFish 4. The complete slide deck is available:


Next day started with a community keynote by Sonya Barry. Some of us live the life of JCP, JSR, EG, EC, RI, etc every day, but not every body is. To address that, Sonya prepared an excellent introductory presentation providing an explanation of these terms and how java.net infrastructure supports Java development.

The registration for the lab showed there is a definite demand for these technologies in this part of the world. I delivered the Java EE 6 hands-on lab to a packed room of about 120 attendees. Most of the attendees were able to progress and follow the lab instructions. Some of the attendees did not have a laptop but were taking extensive notes on paper notepads. Several attendees were already using Java EE 6 in their projects and typically they are the ones asking deep dive questions. Also gave out three copies of my recently released Java EE 6 Pocket Guide and new GlassFish t-shirts. Definitely feels happy to coach ~120 more Java developers learn standards-based enterprise Java programming.

I also participated in a JCP BoF along with Werner, Sonya, and Badr. Adotp-a-JSR, java.net infrastructure, how to file a JSR, what is an RI, and other similar topics were discussed in a candid manner.

You can follow @JMaghrebConf or check out their facebook page. java.net published a timely conversation with Badr El Houari - the fearless leader of the Morocco JUG team. Did you know that Morocco JUG stood for JCP EC elections (ADD LINK) ? Even though they did not get elected but did fairly well.

Now some sample tweets from #JMaghreb ...

#JMaghreb is over. Impressive for a first edition! Thanks @badrelhouari and all the @MoroccoJUG team !
Since you @speakjava : System.out.println("Thank you so much dear Tech Evangelist ! The JavaFX was pretty amazing !!! "); #JMaghreb
@YounesVendetta @arungupta @JMaghrebConf Right ! hope he will be back to morocco again and again .. :)
@Alji_ @arungupta @JMaghrebConf That dude is a genius ;) Put it on your wall :p
@arungupta rocking Java EE 6 at @JMaghrebConf #Java #JavaEE #JMaghreb http://t.co/isl0Iq5p
@sonyabarry you are an awesome speaker ;-)
#JMaghreb rich more than 550 attendees in day one. Expecting more tomorrow!
ongratulations @badrelhouari the organisation was great! The talks were pretty interesting, and the turnout was surprising at #JMaghreb!
#JMaghreb is truly awesome... The speakers are unbelievable !
#JavaFX... Just amazing #JMaghreb
Charmed by the talk about #javaFX ( nodes architecture, MVC, Lazy loading, binding... ) gotta start using it intead of SWT. #JMaghreb
JavaFX is killing JFreeChart. It supports Charts a lot of kind of them ... #JMaghreb
The british man is back #JMaghreb I do like him!!
#JMaghreb @arungupta rocking @JMaghrebConf. pic.twitter.com/CNohA3PE
@arungupta Great talk about the future of Java EE (JEE 7 & JEE 8) Thank you. #JMaghreb
JEE7 more mooore power , leeess less code !! #JMaghreb
They are simplifying the existing API for Java Message Service 2.0 #JMaghreb good to know , the more the code is simplified the better !
The Glassdoor guy #arungupta is doing it RIGHT ! #JMaghreb
Great presentation of The Future of the Java Platform: Java EE 7, Java SE 8 & Beyond #jMaghreb
@arungupta is a great Guy apparently #JMaghreb

On a personal front, the hotel (Soiftel Jardin des Roses) was pretty nice and the location was perfect. There was a 1.8 mile loop dirt trail right next to it so I managed to squeeze some runs before my upcoming marathon. Also enjoyed some great Moroccan cuisine - Couscous, Tajine, mint tea, and moroccan salad. Visit to Kasbah of the Udayas, Hassan II (one of the tallest mosque in the world), and eating in a restaurant in a kasbah are some of the exciting local experiences.

Now some pictures from the event (and around the city) ...







And the complete album:



Many thanks to Badr, Faisal, and rest of the team for organizing a great conference. They are already thinking about how to improve the content, logisitics, and flow for the next year. I'm certainly looking forward to JMaghreb 2.0 :-)

Thursday Nov 01, 2012

Java EE 7 Status Update - November 2012

Here is a quick status update on different components that are targeted to be included in the Java EE 7 Platform.

UPDATE: Latest status tracked here. As evident, all the components have released at least an Early Draft specification. Some have released second Early Draft and some even have a Public Review in different stages. Several implementations are already integrated in GlassFish 4. Promoted Builds.

Which ones are you tracking or contributing ?

Make sure to file an issue so that your usecase and needs are addressed. Download GlassFish 4. Promoted Build and provide feedback.  


About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« November 2012 »
SunMonTueWedThuFriSat
    
2
3
5
6
8
9
10
12
13
14
16
17
18
19
20
22
23
24
25
28
30
 
       
Today