Thursday, June 26, 2014

What is Jaggery




Jaggeryjs is a cool javascript Framework that allows you to develop webbased application very easily, It reduce the development complexity by unifying the server side and client side development. You can tryout and and read all about Jaggery from http://jaggeryjs.org/


Downloading and running Jaggery

Since everything is well documented in the Jaggery website I won't be writing on these, So you can get all the details from here http://jaggeryjs.org/quickstart.jag#settingup


Developing Jaggery Application

Jaggery application has its old file structure, so if you want to easily create a Jaggery project then you can download WSO2 Developpder Studio, this can be also installed as a plugin to your existing Eclipse IDE. In this sample I will create necessary Folder structure and config files manually.

I will explain how to develop a simple Jageery Websocket server which will echo messages its receiving.

Ok Lets get started

Writing the WebSocket Server

Step 01

Create a Folder and lets name it "JaggeryWebsocket". In the folder create a new file "server.jag". This file will act as the server component of the websocket implementation.


Note : .jag is the extension used by Jaggery files.

Step 02

Now Add the following code segment to the server.jag file.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<%

webSocket.ontext = function (data) {
 var list = application.get('list');

 //broadcasting
 for(var i = list.length - 1; i >= 0; i--) {
  list[i].send(data);
 }
};

webSocket.onbinary = function (stream) {

};

webSocket.onopen = function () {

 var streamList=[];
 var list = application.get('list');
 if(list ==null){
  streamList.push(this);
  application.put('list', streamList);

 }
 else{
  var storedList = application.get('list');
  storedList.push(this);
  application.put('list', storedList);

 }
};

webSocket.onclose = function (status) {


 var list = application.get('list');

 for(var i = list.length - 1; i >= 0; i--) {
  if(list[i] === this) {
   list.splice(i, 1);
  }
 }

};

%>



Writing The Client

Step 01

Now Create another file called "index.jag" and add the following code to the file.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Jaggery WebSocket</title>
<script type="text/javascript">
 var websocket = new WebSocket(
   "ws://localhost:9763/JaggeryWebsocket/server.jag");

 websocket.onmessage = function processMessage(message) {

   messagesTextArea.value += message.data + "\n";

 }
 function sendMessage() {
  websocket.send(messageText.value);
  messageText.value = "";
 }
</script>
</head>
<body>

 <div>
  <br>
  <br>
  
  <h3>Output Console</h3>
    
  <textarea id="messagesTextArea" rows="8" cols="80"></textarea>
  <br>
  <input type="text" id="messageText" size="50" /> 
  <input id="button1" type="button" value="Connect" onclick="sendMessage();">

 </div>


</body>
</html>


Step 02

Now You can Add the project Folder into the Jagger y Server, You can place the Project folder in <JAGGERY_HOME>/apps directory ad start the server by going to the <JAGGERY_HOME>/bin directory. Now you can access the application from the flowing URL.

http://localhost:9764/JaggeryWebsocket/index.jag


Thank You for reading and comment below if you have any queries.



WebSockets

Websockets are mainly used for cross browser communication so in most cases the browser act as the client to connect to the socket server, But in some cases you might need a java client to send messages to a socket server. According to my research this area is not well documented. So I will try to implement a Java Client to access a websocket.


Prerequisites

For this sample application I will be Using a sample echo Websoket server located at "http://www.websocket.org/echo.html". You can also use wesocket server which I developed in a previous Blog post, You can Find it here.

I will be using Jetty for this implementation and Eclipse IDE for coding.

Developing the sample

Step 01

Create a new Java Project and lets call it "WebSocketJavaClient" and in the "src" directory create a new java Class with the following name in the mentioned package.



Step 02

Now add the following code segment to the newly created class.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package org.socket.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;

@WebSocket
public class WebSocketObject {
 
 public Session session;
 
 @OnWebSocketClose
 public void onClose(int statusCode, String reason) {
  System.out.printf("Connection closed: %d - %s%n", statusCode, reason);
  this.session = null;
 
 }

 @OnWebSocketConnect
 public void onConnect(Session session) {
  System.out.printf("Got connect: %s%n", session);
  this.session = session;
   
 }

 @OnWebSocketMessage
 public void onMessage(String msg) {
  System.out.println("Message Recieved : "+ msg.toString());
 }
 
 
 public void  sendMessage(String message){
  
  session.getRemote().sendStringByFuture(message);
  
 }
 
 public void closeConnection() {
  session.close(StatusCode.NORMAL, "[Consumer]Closing the session with the Server!!");
  
 }

}



Step 03

Now add the following Jar file as a External jar to your Class Path "jetty-all-9.2.1.v20140609.jar".

Note : I have tested it with the above version and you can use any other version and tryout, the above jar can be downloaded from here.


Step 04

Create a another java class with the following details.



Step 05

Now add the following Code snippet to the newly created class.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.socket.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.concurrent.TimeUnit;

import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
 
/**
 * Sample Websocket Client
 */
public class SocketClient {
 
    public static void main(String[] args) {
        
      //  String destUri = "ws://localhost:8080/webSocketSample/server";
        String destUri = "ws://echo.websocket.org";
        String message;
        
        WebSocketClient client = new WebSocketClient();
        WebSocketObject socket = new WebSocketObject();
        try {
            client.start();
        
            URI echoUri = new URI(destUri);
            ClientUpgradeRequest request = new ClientUpgradeRequest();
            client.connect(socket, echoUri, request);
            System.out.println("Connecting to :" +echoUri);
            Thread.sleep(1000);
            BufferedReader myReader = new BufferedReader(new InputStreamReader(System.in));
            
            while (true) {
             
    System.out.print("Enter Message : ");
    message = myReader.readLine();
    socket.sendMessage(message);
    Thread.sleep(1000);
    
   }
            
                       
          } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            try {
             socket.closeConnection();
                client.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Note : I have added a delay in order to synchronize the Outgoing and incoming messages viewed on console, It is not necessary

Step 06

Now run the "SocketClient.java". When You enter a message the messages will be echoed back by the server.




Note : The code can be improved alot and this is the simplest sample that I can come-up with, You can refer to Jetty documentation for more detailed information. Please fell free to comment below if you have any questions.

You cqan Fing the Code from following Location, https://github.com/ycrnet/WebSocketJavaClient.git

Thanks for reading.

What are Websockets


Websockets allow two way communication between the server and the Client resulting low latency communication between client and the server. It allows  full-duplex communications channels over a single TCP connection. It also allows to break free from the request/response paradigm on what the traditional web was based on. Websockets further enhances the AJAX capabilities, where AJAX communication is also steered by a Client.

WebSockets provide new protocol between client and server which runs over a persistent TCP connection. Through this open connection, bi-directional, full-duplex messages can be sent between the single TCP socket connection (simultaneously or back and forth).


WebSockets Diagram How do websockets work?


The sample

The Sample demonstrate a simple application that runs with web-sockets, the application will echo/ broadcast messages when the server receives it to all the active connections.

GlassFish server will be used with eclipse IDE to develop the sample.

How to Create the Application

Writing The Socket Server

Step 01

Open Eclipse and Create a new dynamic web project with the name "webSocketSample" and with all the default configurations.



Step 02

Add the Glassfish server to your Project, This can be done in many ways the easiest way is to first download the compatible version of GlassFish server and then add it. You can do this by Going to Servers Tab and Select Add new server as shown below.



Follow the wizard and make sure you add your project to configured project list so it will automatically get deployed when the server in starting.


Step 03

Expand the project and go to Javaresorces/src  directory and create a new Java class with the following Name and package.



Note : Make sure You have added all the Libraries to your Project as shown below. (The Glassfish System library contains some jars needed for this project) If not added you can these libraries manually.





Step 03

Add the following Code Snippets to your newly Created Class


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package org.socket.server;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonWriter;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.*;

@ServerEndpoint("/server")
public class SocketServer { 
 
 // Storing the sessions
 static Set <Session> clientUIs = Collections.synchronizedSet(new HashSet<Session>());
 @OnOpen
 public void handleOpened(Session clientSession) throws IOException {
  clientUIs.add(clientSession);
  
   clientSession.getBasicRemote().sendText(buildJsonData("System", "You are now connected to the Map Server!!!"));
 
  System.out.println("A New Client is Connected!!!!");
 }
 
 @OnMessage
 public void handleMessage(String message, Session clientSession) throws IOException{
   System.out.println("A Message Received!!!");
     
   Iterator<Session> iterator = clientUIs.iterator();
   while (iterator.hasNext()){
    
    iterator.next().getBasicRemote().sendText(buildJsonData("Message : ", message));
    
   }
 }
 
 @OnClose
 public void handleClose (Session id){
  
  clientUIs.remove(id);
 }

 private String buildJsonData(String id, String message) {
  // TODO Auto-generated method stub
  JsonObject json = Json.createObjectBuilder().add("message", id+ ": " +message).build();
  StringWriter strwriter = new StringWriter();
 
   try (JsonWriter jsonwriter = Json.createWriter(strwriter)) {jsonwriter.write(json);}
  
   System.out.println("The Jason : "+strwriter.toString());
  return strwriter.toString();
 }

}



Writing The Client To Access the Socket

Step 01

Now in your project go to webcontent  directory and create a file called "index.html"

And add the following code into that file. Note the Javascript code that initiate the websocket connection.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>The Map UI</title>
<script type="text/javascript">
 var websocket = new WebSocket(
   "ws://localhost:8080/webSocketSample/server");

 websocket.onmessage = function processMessage(message) {

  var jsonData = JSON.parse(message.data);
  if (jsonData != null) {
   messagesTextArea.value += jsonData.message + "\n";

  }
 }
 function sendMessage() {
  websocket.send(messageText.value);
  messageText.value = "";

 }
</script>
</head>
<body>

 <div>
  <br>
  <br>
  
  <h3>Output Console</h3>
    
  <textarea id="messagesTextArea" rows="8" cols="80"></textarea>
  <br>
  <input type="text" id="messageText" size="50" /> 
  <input id="button1" type="button" value="Send Message" onclick="sendMessage();">

 </div>


</body>
</html>


Step 02

Make sure that you don't have any errors in the code, and now start the glassfish server and go the following URL with two different browsers.

http://localhost:8080/webSocketSample/index.html 


If the application is successfully connected to the server the Output console will show a message "System: You are now connected to the Map Server!!!"

Now send a message with one browser and the message will be broadcast to all the application that are connected with the server.



You have successfully Implemented Simple Application with websockets, You can Find the Source Code at following guthub location

https://github.com/ycrnet/WEbSocketsWithGlassFish

Thank You!

Please Feel free to contact me anytime... :)


Subscribe to RSS Feed Follow me on Twitter!