Tuesday, March 25, 2008

Status Report for 02/27/2008 -- 03/12/2008

Progress

Implementation of one user registering and monitoring one sensor WITH displaying history data is done.

1. User interface

Based on the previous version that allows user to register and monitor any one of IUMSC sensors with displaying only most recent data, the current version can display history data and current data in real time.

2. Implementation

The previous version was improved in following aspects:

(1) Server side:

(a) Using ArrayList to store parcel data instead of File

  • Read parcel (a parcel is in XML format) data into DOM;
  • Parse the parcel, and get values of SensorName,TimeStamp and DoubleData;
  • Encapsulate the parcel data to a user-defined Parcel class, and write it to an ArrayList.

Note: this implementation is synchronized.

(b) Using JSON to represent parcel data instead of XML

Definition of Parcel class:

public class Parcel {

public String sensorName;

public String timeStamp;

public String doubleData;

public int parcelID;

public Parcel(String sensorName, String timeStamp, String doubleData, int parcelID) {

this.sensorName = sensorName;

this.timeStamp = timeStamp;

this.doubleData = doubleData;

this.parcelID = parcelID;

}

public JSONObject toJSON() throws JSONException {

JSONObject JObj = new JSONObject();

JObj.put("sensorName", sensorName);

JObj.put("timeStamp", timeStamp);

JObj.put("doubleData", doubleData);

JObj.put("parcelID", parcelID);

return JObj;

}

}

getparcels.jsp is responsible for:

  • Handle HTTP request from the client;
  • Each parcel data(element in the ArrayList) is converted to a JSON object, and added to a JSONArray which is used to hold a JavaScript representation all the parcels we’ll return;
  • Writes representation to client.

Note: Choosing JSON as means of transferring data in our application[4]

Disadvantage of XML:

  • We must ensure the XML is sent with the correct header if it is sent from the server. But if the XML is being generated on the fly by a server-side programming language, it is easy to miss this requirement, then responseXML property would be empty;
  • It often takes quite a few lines of JavaScript just to generate a small chunk of markup even if the DOM is eminently suited to parsing XML once it reaches the browser.

JSON is designed to store data, and it is lightweight alternative to XML. Anything that can be stored in XML can also be stored in JSON. Both are text-based representations of data, but while XML requires opening and closing tags, JSON just uses colons, commas, and curly braces.

JSON isn’t a data format that needs to be interpreted by JavaScript: JSON is JavaScript.

(2) Client side

The client side is responsible for querying the server for parcels and displaying them on a page. We define a ParcelManager class object-oriented JavaScript with Prototype to handle the fetching, caching and displaying of the parcels.

new Ajax.PeriodicalUpdater({failure:'error'}, "fetchparcels.jsp?start=" + start + "&pageSize=" + pageSize,

{

method: "get",

frequency: monitorRate,

decay: 2,

onSuccess: function(response) {

cacheParcelData(response);

drawParcelDIV(start, pageSize, div, false);

},

on404: function(response) {

alert('Server Status: 404: ' + response.statusText);

},

onFailure: function(response) {

alert('Server Status: ' + response.status + ' - ' + response.statusText);

}

}

);

The core part of the client side is Prototype Ajax.PeriodicalUpdater class which schedules the automatic updates without having to code any scheduling logic or writing timeout handlers.[3]

(a) When the client wants to monitor the parcel data, an Ajax.PeriodicalUpdater object is created, and getparcels.jsp is employed to fetch data on the server side;

(b) onSuccess event handler takes resposiblility to cache the parcel data and display them.

  • cacheParcelData()function is invoked only after we’ve fetched parcels from the server. It gets the JSON text we’ve received from the server and creates a JavaScript array out of it;
  • drawParcelDIV()function takes the cached parcel data and creates a list in the
    that we specify.

Discussion & Future work

1. One user can register and monitor multiple sensors;

The hard part is how to tell which data (parcel) belongs to which registration request when the user is allowed to register the same sensor with different data interval.

2. The problem with the interface of unregistering a sensor

Reference

[1] JSP : the complete reference. Hanna, Phil.

[2] Core servlets and JavaServer pages. Hall, Marty; Brown, Larry

[3] Ajax in practice Crane, Dave.

[4] Bulletproof Ajax, Keith, Jeremy

Friday, February 29, 2008

Status Report for 02/13/2008 -- 02/27/2008

Progress

Implementation of one user registering and monitoring one sensor is done.

1. User interface

Now user can register and monitor any one of IUMSC sensors via application “CIMA Sensor Monitor” .

(1) Choose a sensor name, which is a CIMA service data source name, e.g “Bay1 Temperature”, from one of twelve IUMSC sensors;

(2) Type a data interval, which is CIMA service data reporting interval in seconds;

(3) Click button “Register”;

(4) After getting response from server “Successfully registered some sensor”, type a Monitor Rate, which is the frequency in seconds the user wants to send the polling requests to the server, and then click button “Monitor”, the most recent data will be shown on the screen continuously.

2. Implementation

(1) Client side[3]

Prototype provides a number of easy ways to make asynchronous requests via Ajax. We are using Ajax.Request class to register a sensor and Ajax.PeriodicalUpdater class to poll a periodical request to get the new real time data.

new Ajax.Request(

"httpcimagateway.jsp?type="+encodeURI(type)+"&"+"source="+encodeURI(source)+"&"+"dataInterval="+encodeURI(dataInterval),

{

method:"get",

onComplete:function(xhr){

document.getElementById('fileUrl').value=xhr.responseText;

}

onFailure: function(xhr){

throw new Error('Registration failed: ' + xhr.statusText);

}

}

);

The asynchronous request itself is triggered by constructing a new instance of Ajax.Request, passing two parameters: the URL for the request, and a hash object containing properties that specify the options of the request. The URL specifies a JSP file that we will start CIMA service and register a sensor, and it passed the value of parcel type, CIMA service data source and CIMA service data reporting interval. In the options parameters object, we specify the HTTP method as a GET with the method property, and provide function reference for completion and failure handlers with onComplete and onFailure, respectively.

The completion handler is just to get the URL of the file which stores the data of the registed sensor. The failure handler, which is passed a reference to the XHR instance, throws an error depicting the failure status.

new Ajax.PeriodicalUpdater({success: 'details'}, fileUrl,

{

method: 'get',

frequency: monitorRate,

decay: 2,

onSuccess:function(xhr) {

eval(xhr.responseText);

}

}

);

This class can satisfy our needs to obtain and display data from the server at periodic intervals. First, we create an instance of Ajax.PeriodicalUpdater that refers to a new JSP page in the request URL(Note: for simplicity, currently this URL is just a file containing sensor data and this will be improved in next step). Second, frequency property in the parameters object controls the number of seconds between updates, and decay property controls the rate at which the request interval grows when the response is unchanged.

(2) Server side

  • httpcimagateway.jsp

a. Handle HTTP request from the client;

b. If the parameter check passes, then do the service in the request, e.g. Register/Unregister/……

c. Return the URL of the file which contains the data

  • do_Register
    • Set up the embedded axis server and client listener;
    • Set up the call to the CIMA service;
    • Invoke the service
  • do_Unregister

The procedure is similar with do_Register.

Discussion & Future work

  1. Change the storage of the data from file to queue;
  2. One user can register and monitor multiple sensors;

According to the requirement, users are allowed to

(a) register the different sensors, and/or

(b) register the same sensor with different data interval.

For one user, all registered sensors’ data will come to the same port, so

for (a), we only need to filter different data to different requests based on different sensors’ name, and this can be done easily; But

for (b), the current web service just outputs the “pure” data without any extra information to web service client. So the client cannot tell which data (parcel) belongs to which registration request.

  1. The problem with the interface of unregistering a sensor

Reference

[1] JSP : the complete reference. Hanna, Phil.

[2] Core servlets and JavaServer pages. Hall, Marty; Brown, Larry

[3] Ajax in practice Crane, Dave.

Status Report for 01/30/2008 -- 02/13/2008

Progress

Based on my previous post, I found that invoking/starting a web service by using Axis1.4 API is not type safe, so I turned my work to newly introduced Axis2 for the project.

1. Brief introduction

Apache Axis2 is built on Apache AXIOM a new high performance, pull-based XML object model. Axis2 comes with many new features, enhancements and industry specification implementations. Axis 2 has five primary strengths: better performance, messaging support, synchronous support, better support for WS-extensions, and better deployment support. The strength of Axis 2 lies in the flexibility and the functionality that Axis 2 provides; migration can be justified for the cases where few of those functionalities are vital. Future articles will provide examples on using Axis 2.

2. A test Web Services via Apache Axis2 in Eclipse

We create a bottom up JAVA bean Web service and Web service client using Axis2 WTP Tools. It shows how to create a simple Web service and Web service client from a JAVA class. The JAVA class in this scenario converts between the Celsius and Fahrenheit temperature scales and its the same class that used in the Axis web services tutorials.

(1) Download the latest Axis2 runtime and extract it;

(2) Point Eclipse WTP to downloaded Axis2 Runtime;

(3) Create a project with the support of Axis2 feature;

(4) Select the Axis2 Web service facet;

(5) Import the wtp/Converter.java class into Axis2WSTest/src (be sure to preserve the package);

package wtp;
public class Converter {
  public float celsiusToFarenheit ( float celsius ){
    return (celsius * 9 / 5) + 32;
  }
 
  public float farenheitToCelsius ( float farenheit ){
    return (farenheit - 32) * 5 / 9;
  }
}

(6) Create a web service based on the above java class;

(7) Generate the client for the newly created service by referring the ?wsdl generated by the Axis2 Server;

(8) The Clients stubs will be generated to above Dynamic Web project;

(9) Write Java main program to invoke the client stub. Import the ConverterClient.java file to the workspace into the wtp package in the src folder of the web service client;

package wtp;
 
import java.rmi.RemoteException;
 
import org.apache.axis2.AxisFault;
 
import wtp.ConverterConverterSOAP11Port_httpStub.CelsiusToFarenheit;
import wtp.ConverterConverterSOAP11Port_httpStub.CelsiusToFarenheitResponse;
 
public class ConverterClient {
 
  public static void main(String[] args) {
    try {
      float celsiusValue = 100;
      ConverterConverterSOAP11Port_httpStub stub = new ConverterConverterSOAP11Port_httpStub();
      CelsiusToFarenheit c2f = new CelsiusToFarenheit();
      c2f.setCelsius(celsiusValue);
      CelsiusToFarenheitResponse res = stub.celsiusToFarenheit(c2f);
      System.out.println("Celsius : "+celsiusValue+" = "+"Farenheit : "+res.get_return());
    } catch (AxisFault e) {
      e.printStackTrace();
    } catch (RemoteException e) {
      e.printStackTrace();
    }
  }
}
 

Discussion

Now I am working on how to start a web service dynamically based on the feather of the project and the existing web service. I will state it in more detail later.

Reference

·         http://ws.apache.org/axis2/
·         http://www.developer.com/services/article.php/3525481
·         http://www.eclipse.org/webtools/jst/components/ws/1.0/tutorials/WebServiceExplorer/WebServiceExplorer.html
·         http://www.eclipse.org/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html
·         http://www.eclipse.org/webtools/jst/components/ws/1.5/tutorials/BottomUpWebService/BottomUpWebService.html
·         http://www.eclipse.org/webtools/jst/components/ws/1.5/tutorials/TopDownWebService/TopDownWebService.html
·         http://www.eclipse.org/webtools/jst/components/ws/1.5/tutorials/WebServiceClient/WebServiceClient.html
 

Thursday, January 31, 2008

Status Report for 01/23/2008 -- 01/30/2008

Progress

Based on the discussion in my previous posts, I did some work on Axis 1.4 for the project.

1. Install and Deploy Apache Axis 1.4

(1) Make sure that we have

· J2SE SDK 1.5

· A Servlet Container: Tomcat 5.5.17

(2) Download axis-bin-1.4.zip from http://apache.oc1.mirrors.redwire.net/ws/axis/1_4/

(3) Unzip it and look at the dir. tree. Note that Axis runs as a Servlet.

(4) Deploy Axis.

· Copy webapps/axis tree to webapps directory of Tomcat.

· Alternatively, modify server.xml of Tomcat.

(5) Run Tomcat: issue bin/startup from Tomcat home.

Direcotry Structure:

axis-1_0

docs

lib

samples

webapps

axis

WEB-INF

lib

classes

web.xml

(6) Test the Deployment

(a) Point my browser to http://localhost:8080/axis

(b) Click the link "Validate", an error message and two warnings were shown on the next page.

Error: could not find class javax.activation.DataHandler from file activation.jar

Axis will not work

See http://java.sun.com/products/javabeans/glasgow/jaf.html

Optional Components

Warning: could not find class javax.mail.internet.MimeMessage from file mail.jar

Attachments will not work

See http://java.sun.com/products/javamail/

Warning: could not find class org.apache.xml.security.Init from file xmlsec.jar

XML Security is not supported

See http://xml.apache.org/security/

The core axis libraries are present. 2 optional axis libraries are missing

(7) Shutdown Tomcat, and follow the instructions above to

(a) download the zip files;

(b) unzip these files;

(c) find the jar files;

(d) copy them to $CATALINA_HOME/webapps/axis/WEB-INF/lib

activation.jar, mail.jar, xmlsec-1.4.1.jar are in jaf-1_1_1.zip, javamail-1_4_1.zip, xml-security-bin-1_4_1.zip respectively.

(8) Startup Tomcat, and run http://localhost:8080/axis

2. A test Web Services Using Apache Axis

The easiest way is to simply copy any independent Java class into our Axis web application directory and access it via SOAP remotely.

(a) developing the Java class,

(b) deploying it,

(c) building and running a client to access it.

(1) Developing a Java class

Try out a Hello World -style class which has one method, called greet() that takes someone's name as a parameter and returns a nice greeting message with that person's name.

(a) Locate the $AXIS_HOME/samples directory;

(b) Create a new subdirectory called "hello";

(c) In this subdirectory, create the file Hello.java, and include the following code;

public class Hello {

public String greet(String a_name) {

return "Nice to meet you, "+a_name;

}

}

(d) Copy it into $TOMCAT_HOME/webapps/axis and name it Hello.jws

(2) Building a client to access our service.

Develop the client code in the file HelloClient.java, which we will store at $AXIS_HOME/samples/hello. HelloClient.java needs to do the following:

· Connect to the our Hello service (a SOAP endpoint)

· Invoke the service method remotely, marshalling parameters in and out.

· Print out the reply from the service.

Below is code for HelloClient.java that enables this:

package samples.hello;

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

import org.apache.axis.utils.Options;

import javax.xml.rpc.ParameterMode;

public class HelloClient

{

public static void main(String [] args) throws Exception {

Options options = new Options(args);

String endpoint = "http://localhost:" + options.getPort() + "/axis/Hello.jws";

args = options.getRemainingArgs();

if (args == null || args.length != 1) {

System.err.println("Usage: Hello ");

return;

}

Service service = new Service();

Call call = (Call) service.createCall();

call.setTargetEndpointAddress(new java.net.URL(endpoint));

call.setOperationName("greet");

call.addParameter("name", XMLType.XSD_STRING, ParameterMode.IN);

call.setReturnType(XMLType.XSD_STRING);

String msg = (String)call.invoke(new Object[] {args[0]});

System.out.println("Reply: " + msg);

}

}

Compile this client: javac samples/hello/HelloClient.java

Run the client: java samples.hello.HelloClient -p8080 Greg

which returns the message:

Nice to meet you, Greg!

Discussion

Based on the previous discussion, it is necessary to remove SimpleAxisServer and just use Axis as an engine to invoke the web service.

http://ws.apache.org/axis/java/apiDocs/org/apache/axis/transport/http/SimpleAxisServer.html

Reference

·         http://www.javaranch.com/journal/2002/05/axis.html
http://ws.apache.org/axis/java/user-guide.html#CustomDeploymentIntroducingWS

 

Status Report for 01/09/2008 -- 01/23/2008

Progress

1. Design for server side (JSP/Java servlet)

Based on the discussion on my previous blog, remove the embedded Jetty and make everything run in Tomcat.

On server side:

(1) JSP/servlet gets the parameters in the request from client;

(2) Start SimpleAxisServer(SAS) to call a CIMA web service;

(3) Receive the data at a listener of SAS;

(4) Write the data to a file;

(5) Send the URL of file back to client

On client side:

(1) Send the request to server;

(2) Receive the URL of the file;

(3) Parse the file content and display them on the browser

2. Implementation

(1) Server side

(a) Using Java servlet

Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException

in class

public class Main extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet

(b) Using JSP

In a JSP page,

  • Get the parameters from request;
  • Call a Java method to invoke the CIMA web service and another method to write data to a file;
  • Return the URL of the file to client

(2) Client side

In Ajax, make a request either to the Java servlet or the JSP. Parse the file content and show the data on the browser via an Ajax function.

Discussion

(1) Comparison between Java servlets and JSP in this project.

Both Java servlets and JSP have an extensive infrastructure for automatically parsing and decoding HTML form data, reading and setting HTTP headers, handling cookies, tracking sessions, and many other such high-level utilities. But as for outputting the result to the client, we need to write a zillion println statements to generate HTML. Plus, by separating the presentation from the content, we can separate the tasks on Web page design and servlet programming. In this project, it involves some static HTML content, and the client only needs the URL of the file, so use of a combination of JSP and servlets would simplifies the creation and maintenance of the HTML.

(2) Currently, we invoke CIMA web service by start a SimpleAxisServer, but in SimpleAxisServer API, there is a note -- This is a simple implementation of an HTTP server for processing SOAP requests via Apache's xml-axis. This is not intended for production use. Its intended uses are for demos, debugging, and performance profiling. Note this classes uses static objects to provide a thread pool, so you should not use multiple instances of this class in the same JVM/classloader unless you want bad things to happen at shutdown.

So it is necessary to remove SimpleAxisServer and just use Axis as an engine to invoke the web service

http://ws.apache.org/axis/java/apiDocs/org/apache/axis/transport/http/SimpleAxisServer.html

Reference

  • JSP : the complete reference. Hanna, Phil.
  • Core servlets and JavaServer pages. Hall, Marty; Brown, Larry

Status Report for 12/26/2007 -- 01/09/2008

Progress

1. Design for server side (Embedded Jetty)

In this design, we embedded Jetty into our Java applications and used it as the core HttpServer, an HTTP server with the ability to serve static content and servlets.

The basic idea is to implement a handler in the servlet and start a jetty server with it. Once the jetty server gets a request from the jetty port, the handler will get the parameters and start SimpleAxisServer(SAS) to call a CIMA web service and then get the data at a listener of SAS.

2. Implementation

(1) Create an instance of the Jetty server (org.mortbay.jetty.Server) listening at some port, but does not start the server.

Server server = new Server();

Connector connector=new SelectChannelConnector();

connector.setPort(some port);

server.setConnectors(new connector[]{connector});

(2) Add resource handlers which will get the parameters from the client’s request and start the web service.

Handler param = new ParamHandler();
Handler rqst = new RqstHandler();
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{rqst, param});

server.setHandler(handlers);

(3) Start the Jetty server.

server.start();

server.join();

(4) Set up the embedded axis server with deployment descriptor generated by WSDL2Java

SimpleAxisServer server = new SimpleAxisServer();

ServerSocket WSserverSocket = new ServerSocket(someport);

WSserverSocketPort = WSserverSocket.getLocalPort();

server.setServerSocket(WSserverSocket);

server.setMyConfig(wsdddoc.getDeployment());

server.start();

set up the call to the CIMA service


String endpointURL = new String(some IP address);
Call call = new Call(endpointURL);
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
call.setOperationName(somename);
call.addParameter(……);

call.invokeOneWay(……);

Discussion

On the client side, Ajax is being used for this web application. In a standard way, making a request to a servlet/JSP page on the server in Tomcat would be much easier and convenient. So instead of using embedded Jetty, we can just use servlet/JSP page to get the parameter and call a web service and send the response to client. In that case, everything on the server is running in the Tomcat, and just one port is necessary.