Wednesday, October 31, 2007

Install JDK, Tomcat and Axis2 on Ubuntu

Previously, I deployed all java related stuff on my windows machine. Now, I would like to deploy on linux.
My environment:
Operating System: Ubuntu 6.06.1 LTS f
JDK 6 installation
In Ubuntu, an open source Java environment has been included. It is Gcj(http://gcc.gnu.org/java/). It is a GNU project. However, I prefer Sun JDK.
(1) download and install Sun JDK 1.6
Ubuntu is a branch of Debian, so it naturally inherits the great package management tool -- apt-get. It is an easy job to install packages on Ubuntu.
First, you should add "universe" and "multiverse" repositories to your /etc/apt/sources.list file. Then, execute following command:
   sudo apt-get install sun-java6-jdkBy default, it will be installed to /usr/lib/jvm/.
(2) configure it
Because now we have two Java compilers/interpreters installed, to make it work in the way I expect configuration is a must. In directory /usr/lib/jvm/, there are several *.jinfo files which contains information about installed jdk/jre packages. You can change jdk/jre alternatives by using command:update-java-alternatives.   
   sudo update-java-alternatives -l
  //list all available jre/jdk installations
   sudo update-java-alternatives -s java-6-sun  //set sun's jdk to be used
Or, you can use:
   sudo update-alternatives --config java
Then a list of available jdk/jre installations is displayed. In my case, it is:
There are 3 alternatives which provide `java'.

  Selection    Alternative
-----------------------------------------------
          1    /usr/bin/gij-wrapper-4.1
 +        2    /usr/lib/jvm/java-gcj/jre/bin/java
*         3    /usr/lib/jvm/java-6-sun/jre/bin/java

Press enter to keep the default[*], or type selection number: 
Then, set environment vaiable. Add following two lines:  
   JAVA_HOME="/usr/lib/jvm/java-6-sun"
to file /etc/environment.
(3) test
Type:
javac -version
java -version
to see whether your configuration works.
Install Tomcat 5.5
(1) Download and install
sudo apt-get install tomcat5.5 tomcat5.5-admin tomcat5.5-webapps
Note: here I installed three packages. Tomcat 5.5 contains basic implementation of Servlet and JSP specifications. Tomcat 5.5-admin contains two web-based management interface. Tomcat 5.5-webapps contains documents and some sample web applications.
(2)Configure
I installed webapps and admin.
Set CATALINA_HOME environmen variable. In my case, CATALINA_HOME=/usr/share/tomcat5.5.
The example apps are installed to "/usr/share/tomcat5.5/webapps/".
Global configuration files (server.xml and web.xml) are located in "/etc/tomcat5.5".
To make use of the web-based management tool, you need an account. You can set up your account by modifying file /usr/share/tomcat5.5/conf/tomcat-users.xml. Add the following line:
   <user username="username"  password="password" roles="manager,admin" />
Then, restart tomcat
   sudo /etc/init.d/tomcat5.5 restart
Note: "admin" and "manger" are two different roles.
(3)Start/Stop server
Script used to start/stop tomcat server is /etc/init.d/tomcat5.5.
sudo /etc/init.d/tomcat5.5 start
sudo /etc/init.d/tomcat5.5 stop
sudo /etc/init.d/tomcat5.5 restart
sudo /etc/init.d/tomcat5.5 force-reload
sudo /etc/init.d/tomcat5.5 status
However, you had better use script in directory /usr/share/tomcat5.5/bin/. I guess /etc/init.d/tomcat5.5 is intended to be used internally.
      /usr/shar/share/tomcat5.5/bin/startup.sh
      /usr/shar/share/tomcat5.5/bin/shutdown.sh
(4)Test
Tomcat by default listens to port 8180. In windows, it listens to 8080. Strange...
You can visit http://localhost:8180 to check whether your installation succeeds.
(5) Deploy your own web app
Your application should be put into directory "/usr/share/tomcat5.5/webapps/". You can use a .war file or just regular file system tree.

Problem:

   After installing Tomcat 5.5, I typed http://localhost:8180 to do test. Everything seemed to work well -- management, administration ... However, when I tried the JSP example at http://156.56.104.196:8180/jsp-examples/, error occurred!
Error message is:

HTTP Status 500 -


type Exception

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException: Unable to load class for JSP
 org.apache.jasper.JspCompilationContext.load(JspCompilationContext.java:598)
 org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:147)
 org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:315)
 org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
 org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

root cause
......

I made sure that all related .jar files were positioned correctly. What was weird was that servlet example could run correctly while JSP example always incurred error. I wrote a simple JSP file:
   <% out.println("Hello,world"); %>
After deploying it, I found that it worked!!!

Solution
After search by Google, finally I found this page http://forum.java.sun.com/thread.jspa?threadID=693082&messageID=4028997 which gave solution. The reason is incorrect configuration in Tomcat 5.5 distribution!!! I repeat the solution simply here:
Edit /usr/share/tomcat5.5/webapps/jsp-example/WEB-INF/tagPlugins.xml.
Original one is:

<tag-plugins>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.rt.core.IfTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.If</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.common.core.ChooseTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.Choose</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.rt.core.WhenTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.When</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.common.core.OtherwiseTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.Otherwise</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.rt.core.ForEachTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.ForEach</plugin-class>
  </tag-plugin>
</tag-plugins>
Note, those orange lines are not correct!! Altered copy is:
<tag-plugins>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.rt.core.IfTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.core.If</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.common.core.ChooseTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.core.Choose</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.rt.core.WhenTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.core.When</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.common.core.OtherwiseTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.core.Otherwise</plugin-class>
  </tag-plugin>
  <tag-plugin>
    <tag-class>org.apache.taglibs.standard.tag.rt.core.ForEachTag</tag-class>
    <plugin-class>org.apache.jasper.tagplugins.jstl.core.ForEach</plugin-class>
  </tag-plugin>
</tag-plugins>
Install Axis2 1.3 in Tomcat 5.5
(1) Download Axis2 1.3 Release
I chose to download .war file which would be deployed in tomcat 5.5
Command:
   wget http://www.eng.lsu.edu/mirrors/apache/ws/axis2/1_3/axis2-1.3-war.zip
(2) Deploy axis2.
Copy the downloaded axis2.war to /usr/share/tomcat5.5/webapps/. Then restart Tomcat. Tomcat automatically extracts and deploys the .war file.
(3) Test
Go to http://localhost:8180/axis2/. You should see the welcome page of Axis2.
Axis2 provides a user-friendly web-based interface to view all available services, validate the installation, upload new service (actually what are uploaded are .aar files)...
Standard binary distribution of Axis2 1.3
In fact, if you want to develop web service by using Axis2, you should download standard binary distribution which contains complete version of Axis2.
The most important part of Axis2 are those tools under directory bin. These tools include axis2.sh/axis2.bat, axis2server.bat/axis2server.sh, java2wsdl.bat/java2wsdl.sh, wsdl2java.sh/wsdl2.bat.  I described usage of these tools in my last post.

Tuesday, October 30, 2007

Web Service Development and Deployment using Axis2

Goal
Develop and deploy web service in Apache Tomcat by using Axis2 1.2/1.3.
Prerequisite:
(1) Install JDK, Tomcat and Axis2.
      Keys:
         (a) Versions of these packages must match.
         (b) JDK is recommended. Though JRE works most of the time, some features of the additional libraries/packages may not work well.
(2) Configure JDK. I think the most important part is to set the environment.
     There are already lots of tutorials around the internet. Typically, you should set environment variables : JAVA_HOME and CLASSPATH.
(3) Configure Tomcat
     Tomcat must be run on JVM. So path of JVM needs to be configured correctly.
(4) Deploy Axis2
     Axis2 is deployed in Tomcat. You can put the axis2.war file to webapps directory of Tomcat. Tomcat automatically unextracts and deploys it.
     In addition, you should set AXIS2_HOME environment variable to point to the location of axis2.
Procedure
Now, let's start to write our service prototype.
(1) Define interface in Java.
My sample interface:
File Add.java
package test;
interface Add{
   int addoperation( int op1, int op2 ) ;
}
(2) Now, compile Add.java to .class file. Command:
     javac Add.java
(3) Then, we will generate WSDL document based on the interface defined above.
     The tool is Java2WSDL which is included in Axis2 package.  My command used to generate WSDL document is:
          Java2WSDL -cn test.Add
     The newly generated WSDL document is Add.wsdl.
     Note: (1) Java2WSDL generates WSDL document based on .class file, not .java source file. So step (2) is necessary.
              (2) Java2WSDL command must be invoked in right directory. You must obey that package name must match
                   the directory hierarchy. In my case,directory tree is: D:/apps/demo/test/Add.java. When I invoke Java2WSDL,
                   current working directory is D:/apps/demo/.
(4) Use WSDL2Java (included in Axis2 package) to generate stub Java functions based on WSDL document.
There are two parts: client side and server side.
Detailed information about WSDL2Java/Java2WSDL is here: http://ws.apache.org/axis/java/user-guide.html#UsingWSDLWithAxis
(4.1) Server side
First you need to copy the generated Add.wsdl to the machine where service is to be located. In my case, the Add.wsdl is stored at D:/apps/demo/service.
(4.1.1) Generate stub functions
Again, WSDL2Java is used. Command is:    WSDL2Java -uri C:/apps/demo/test/Add.wsdl -p test -d adb -s -ss -sd -ssi
After excution of this command, directory tree looks like:
D:/apps/demo/service/
   Add.wsdl 
   resource
      Add.wsdl
      services.xml
   src
      test
         AddMessageReceiverInOut.java
         Addoperation.java
         AddoperationResponse.java
         AddSkeleton.java
         AddSkeletonInterface.java
         ExtensionMapper.java
   build.xml
(4.1.2) Add functionality of your service to generated methods
File AddSkeleton.java contains code directly related to your web service implementation. Initial content of AddSkeleton.java is:
/**
 * AddSkeleton.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis2 version: 1.3  Built on : Aug 10, 2007 (04:45:47 LKT)
 */
package test;

/**
 *  AddSkeleton java skeleton for the axisService
 */
public class AddSkeleton implements AddSkeletonInterface {
    /**
     * Auto generated method signature
     * @param addoperation0
     */
    public test.AddoperationResponse addoperation(
        test.Addoperation addoperation0) {
        //TODO : fill this with the necessary business logic
        throw new java.lang.UnsupportedOperationException("Please implement " +
            this.getClass().getName() + "#addoperation");
    }
}

I modify AddSkeleton.java to add my web service implementation. New content is:
package test;

public class AddSkeleton implements AddSkeletonInterface {
    public test.AddoperationResponse addoperation(
        test.Addoperation addoperation0) {
         //first, get two parameters
         int op1 = addoperation0.getParam0();
         int op2 = addoperation0.getParam1();
         int sum = op1 + op2; //calculate summation
         AddoperationResponse resp = new AddoperationResponse();//construct response object
         resp.set_return( sum );//set the return value
         return resp;
    }
}
(4.1.3) Build a service
Change directory to D:/apps/demo/service/, then execute the following command:
ant jar.server
After execution, directory tree looks like:
D:/apps/demo/service/
   Add.wsdl 
   resource
      Add.wsdl
      services.xml
   src
      test
         AddMessageReceiverInOut.java
         Addoperation.java
         AddoperationResponse.java
         AddSkeleton.java
         AddSkeletonInterface.java
         ExtensionMapper.java
   build.xml
   build
      classes
         META-INF
            Add.wsdl
            services.xml
         test
            some .class files
      lib
         Add.aar
Note: Add.aar is the the archive.
(4.1.4) Deploy the service
Copy Add.arr to the "services" directory (Tomcat_directory/webapps/axis2/WEB-INF/services) of deployed axis2. Axis2 provides a web-based interface to manage the deployed services. You can use that interface to upload your .arr file.
(4.2) Client side
(4.2.1) Generate stub functions
My command used to generate client-side Web service stub functions is:
    WSDL2Java -uri Add.wsdl -p test.axis2.add -d adb -s
After execution of this command, directory tree should look like:
D:/apps/demo/ 
   Add.wsdl 
   test
      Add.java 
      Add.class
   src
      test
         AddStub.java
   build.xml
The file AddStub.java contains the newly generated client-side stub functions.
(4.2.2) develop your code to use web service
(4.2.2.1) Write source code to invoke remote web service
Create a new file called Client.java (Actually, you can use any name you like) in the directory D:/apps/demo/src/test/.
Content of the file:
package test;

import java.io.*;
import test.AddStub.Addoperation;
import test.AddStub.AddoperationResponse;

public class Client {
 public static int op1 = 0;
 public static int op2 = 0;
    public static void main(java.lang.String[] args) {
        try {
            AddStub stub = new AddStub("http://localhost:8080/axis2/services/Add");
            BufferedReader   in=new   BufferedReader(new  InputStreamReader System.in));  
            System.out.println("Please input the first operand:");
            String input = in.readLine();
            op1 = Integer.parseInt( input );
            System.out.println("Please input the second operand:");
            input = in.readLine();
            op2 = Integer.parseInt( input );
            add(stub);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("\n\n\n");
        }
    }

    /* invoke the 'add' web service */
    public static int add(AddStub stub) {
        try {
            Addoperation req = new Addoperation();
            req.setParam0(op1);
            req.setParam1(op2);
            AddoperationResponse resp = new AddoperationResponse();
            resp = stub.addoperation(req);//invoke the web service
            System.out.println("done");
            System.out.println(op1 + "+"+ op2 + " is " + resp.get_return());
            return resp.get_return();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("\n\n\n");
        }
        return 0;
    }
}
Note: In axis2 1.4, the generated code is different from code generated by axis2 1.3.
In axis2 1.3, parameters of a request are set using setParam0, setParam1,...
In axis2 1.4, parameters of a request are set using setter functions of those properties, e.g. setName, setId.
Also the method to get return value is different. There may be some other changes I don't know, so I encourage to consult official Axis2 document.
(4.2.2.2) compile the source file and execute it.
Change your current working directory to: C:/apps/demo/, then execute following command:
    ant jar.client
Then, a new directory "build" is created. Now the directory looks like:
D:/apps/demo/ 
   Add.wsdl 
   test
      Add.java 
      Add.class
   src
      test
         AddStub.java
   build.xml
   build
      classes
         test
            some .class files
      lib
         Add-test-client.jar
Now, you can use java command to execute the program.
Remeber: first you must set CLASSPATH to include axis2 .jar libraries and newly created Add-test-client.jar. One alternative way is to use option -cp of command java. Command to execute your program is:
    java test.Client      #with CLASSPATH being set
or
  java -cp <axis2_jars>:./Add-test-client.jar test.Client      #without CLASSPATH being set
To relieve programmers from these fussy stuff, axis2 provides a tool axis2.bat/axis2.sh. This script automatically set CLASSPATH to include all the .jar files of axis2. How can the script know where your axis2 is installed? Ha, you must create a new environment variable called AXIS2_HOME which contains the path where axis2 is installed. However, the newly created Add-test-client.jar is not included in the classpath by the axis2.bat/axis2.sh script. So you still need to add it to CLASSPATH. Execute your program using command:
    axis2.sh -cp ./Add-test-client.jar test.Client
In fact, I wrote my own script to ease invocation of that program. Now, I don't need to set long CLASSPATH or input long command line with -cp option.

Tuesday, October 23, 2007

A problem of JavaCOG

I submit an execution task. The COG program seems to wait forever. But the task actually is executed by the remote server.
The reason seems to be that: COG program expects response from remote server (Globus server or others), but the remote server does not return any response even if the task is completed successfully.
I don't know whether my understanding is correct. I tried different ways to submit a task.
(1) by using command line tool
    task 1: transfer a local file to remote machine using gridftp.
    cog-file-transfer.bat -s file:///E:/my_program/web_app/CogTest/bin/testkarajan.xml -d gsiftp://gf1.ucs.indiana.edu/home/zhguo/testkarajan.xml
    This can be completed successfully.
    task 2: execute a command on remote machine
    cog-job-submit.bat -s gf1.ucs.indiana.edu -e /bin/ls -stdout list.txt -d /home/zhguo -provider gt2
    This command hangs up forever and does not return control to user until it is terminated forcibly. But the corresponding command ( in this case, it is /bin/ls ") can be executed on remote machine and the result is written into the specified file.
    cog-job-submit.bat -s gf1.ucs.indiana.edu -e /bin/ls -stdout list.txt -d /home/zhguo -provider gt2 -b
    This works well.
    So, what is difference between batch mode and regular mode?
(2) by using GUI tool
     The same results as above.
(3) by using API
    I wrote a program which utilized the karajan engine to handle the karajan workflow related stuff.
    All kinds of invocation do not work well.

How to solve it? Is there anything I missed ?

XML-RPC Usage

Currently, I am focusing on building client and server programs which communicate with each other by using XML-RPC.
Client
To support XML-RPC at client side, there are two choices. I write javascript functions that handle XML-RPC related stuff --encoding, decoding, escape ... I read the XML-RPC specification. It is not long, just a few pages. However, to implement a robust and steady xml-rpc javascript library is not so easy as it looks. I don't have so much time to do this. So, I chose to make use of existing library. I surveyed many XML-RPC javascript libraries. Shortly afterwards, I found that most of the libraries were not satisfying. For example, some libraries even don't escape the parameters passed to a method. If a parameter is a string and it contains '<' characters, those '<' characters must be escaped in order not to confuse the server because '<' marks start of a tag!! After trying lots of times, I found two good libraries. One is mozilla xml-rpc javascript library which is used by Firefox. However, it requires additional javascript libraries which are basis of Firefox javascript libraries. To use it, lots of libraries are needed and obviously this is cumbersome.  The other good library is Javascript O Lait which builds generic architecture to allow users to create and import module. In addition to support of modularity, it provides many useful modules, such as Codec, JSON-RPC, XML-RPC, String extension ... At last I decided to use Jsolait. Key code is:
var url = "http://127.0.0.1:8080/sample/xmlrpc";//The path must comply with configuration at server side
var methods = ["zhguo.handler.inBound"];//This is the full qualified name of the method you want to invoke. 
     //Note: this must comply with the configuration at service side
var xmlrpc=null;
try{
    xmlrpc = imprt("xmlrpc"); //import the needed module
}catch(e){
    throw "importing of xmlrpc module failed.";
}
 
try{
 var service = new xmlrpc.ServiceProxy( url, methods );
 var from = "home", to = "rpc";
 service.zhguo.handler.inBound( from, to );//directly call the method by using service object
}catch(e){
 alert( e );
} 
Server

I make use of Apache XML-RPC Java library. There is no detailed document on the web. Official website has some description on how to quickly build application based on XML-RPC. There are several ways you can use the XML-RPC service. I chose to embed it in Tomcat container. Key procedure is:
(1) Edit the web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">
  <display-name>Test for XML-RPC</display-name>
  <description>This is a test for XML-RPC</description>
 <servlet>
  <servlet-name>XmlRpcServlet</servlet-name>
  <servlet-class>org.apache.xmlrpc.webserver.XmlRpcServlet</servlet-class>
  <init-param>
   <param-name>enabledForExtensions</param-name>
   <param-value>true</param-value>
   <description>Sets, whether the servlet supports vendor extensions.</description>
  </init-param>
 </servlet> 
 <servlet-mapping>
  <servlet-name>XmlRpcServlet</servlet-name>
  <url-pattern>/xmlrpc</url-pattern>
 </servlet-mapping>
</web-app>
(2) Create your service. My sample class is:
package zhguo.test;
public class SimpleHandler{
 public SimpleHandler(){}
 public String inBound( String from, String to ){
  return "thank you, " + from +", for calling " + to;
 }
}
And put the corresponding .class file in the directory WEB-INF/classes/zhguo/test/.
(3) Add a file called XmlRpcServlet.properties under directory WEB-INF/classes/org/apache/xmlrpc/webserver/. Content of the file is
zhguo.handler=zhguo.test.SimpleHandler
Note: zhguo.test.SimpleHandler is the class which provides service to XML-RPC client. The public functions in this class are exposed by Apache XML-RPC framework to clients. In other words, clients can invoke public functions defined in class zhguo.test.SimpleHandler. The property name is an arbitrary string. It represents the corresponding service class (In this case it is zhguo.test.SimpleHandler). Clients use this name to access the service. So, in javascript above, one statement is 'var methods = ["zhguo.handler.inBound"]'. Upon receiving the request, the server looks up the class corresponding to "zhguo.handler", invokes inBound function of that class and returns the result.
(4) Put the necessary libraries(XML-RPC .jar files) in the lib directory
(5) Starts the tomcat.
Finally, the directory layout is:
WEB-INF/lib/
WEB-INF/classes/org/apache/xmlrpc/webserver/XmlRpcServlet.properties
WEB-INF/classes/zhguo/test/SimpleHandler.class
WEB-INF/web.xml

Tuesday, October 16, 2007

JSON-RPC-Java

Site: http://oss.metaparadigm.com/jsonrpc
It is a piece of middleware which allows client-side JavaScript to invoke server-side Java method. It uses xmlhttprequest to send requests to server.

Example
function onLoad()
{
    jsonrpc = new JSONRpcClient("JSON-RPC");
}

function clickHello()
{
    var whoNode = document.getElementById("who");
    var result = jsonrpc.hello.sayHello(whoNode.value);
    alert("The server replied: " + result);
}
Procedure
Every time a new JSONRpcClient object is created, the system automatically asks the server for the method list. Then all these methods are added to this newly created instance. When the user program invokes a certain method, the system marshalls the parameters and method names and then send a message to server. The server unmarshalls the received message and invokes the corresponding function at server side. After the function is executed, the result is marshalled and sent to client. At server side, the library provides a bridge which can be used by a class to expose its methods to clients.
Improvement
To improve performance, that Javascript library maintains a pool of xmlhttprequest instances. Every time a new xmlhttprequest object is required, the pool is searched at first. If there is available xmlhttprequest instance, it is used. Or else, new xmlhttprequest instance is created.

Sunday, October 14, 2007

Dummy Functions of Javascript Library

Currently, I have built all dummy javascript functions based on JavaCOG. The classes in JavaCOG are mapped to objects in javascript and all methods are mapped as well. However, there is a problem. In Java, a function can be defined multiply times so long as the function signatures are different. In javascript, function overriding is not supported. As a result, in the future we must distinguish the different cases by passing specified parameters.

Current focus is how to make javascript interact with the server. I have several ideas:

(1) Using xmlhttprequest in Javascript
   When a user needs to send request to server, we can use xmlhttprequestobject. However, for security reason, xmlhttprequest has limitations. For example, xmlhttprequest can only send requests to the domain from which the javascript comes. If a javascript program from google.com wants to send requests to a host in microsoft.com domain by using xmlhttprequest object, it is prohibited by default. Of course, uses can allow the access by modifying their browser security configurations. However, I don't think lots of users are willing to do that. As a result, only one server can exist to provide service.
    Advantages: programmers can choose any format they like to encode the requests. JSON is a choice which is better than XML.

(2) Using IFrame element
   By dynamically modifying the source URL of IFrame element, clients can send http GET requests to server. If form is embedded in the IFrame element, clients can send HTTP POST requests. If GET method is used, we can customize query part of the URL so that request parameters are included. If POST method is used, we can specify parameters by setting values of fields.
   Advantages: it does not have the domain access limitation described above.
   Disadvantages: If we use GET method, there are some limitations imposed on the URL such as length, characters.... If we use POST method, we can not control the encoding of the submitted data.

    Of course, we can use basic form to submit the requests. However, we want to build a Web 2.0 Javascript library, so ...

    Actually, javascript at client side invokes the corresponding functions at server side. So I call it Javascript RPC. There exist two main formats of messages transmitted between client and server: XML-RPC and JSON-RPC.
    Ajax Pattern(http://ajaxpatterns.org/wiki/index.php?title=AJAXFrameworks) lists many Ajax-related frameworks among which some satisfy our requirements.

(1) XML-RPC
    http://www.xmlrpc.com/
    I found serveral javascript libraries which support XML-RPC.
    xml-rpc http://www.scottandrew.com/xml-rpc/
    @tomic http://atomic.jbrisbin.com/ Actually, it is a Web 2.x Ajax Framework.
    vcXMLRPC: http://www.vcdn.org/Public/XMLRPC/ The latest version was released in 2001.
    jsxmlrpc:  http://kuriositaet.de/javascript/jsxmlrpc.html

(2) JSON-RPC

http://json-rpc.org/  On this website, there is a specification about JSON-RPC. In addition, some implementations written in different languages are listed.
Besides the client-side support of JSON-RPC, some frameworks go further to provide server-side support.
    JSON-RPC-Java:  http://oss.metaparadigm.com/jsonrpc/
    "JSON-RPC-Java is a key piece of Java web application middleware that allows JavaScript DHTML web applications to call remote methods in a Java Application Server without the need for page reloading (now refered to as AJAX)."
    Now, JSON-RPC-Java has been merged with Jabsorb http://code.google.com/p/jabsorb/.

Some libraries implement both XML-RPC and JSON-RPC:
    JSXML-RPC: http://phpxmlrpc.sourceforge.net/jsxmlrpc/
    JS o lait: http://jsolait.net/. Actually, this library provides more than RPC. It provides codec, crypto, HTML forms ...  Part of JSON-RPC-Java is based on Js o lait.

I have not investigated what format the following frameworks use:
    JSRS -- Javascript Remote Scripting http://www.ashleyit.com/rs/main.htm 
    DWR -- Direct Web Remoting https://dwr.dev.java.net/

Saturday, October 13, 2007

Prototype --- A javascript Framework

 
Recently, I read through the source code of Prototype -- a Javascript framework.  Its purpose it to extend basic Javascript language to provide more useful and  powerful functionalities which make programmers work easily. Basic extension is to simulate object-oriented programming model.
 
  • Class
    Class creation:
          The only feature of classes defined this way was that the constructor called a method called initialize automatically. In other words, every time a user creates a new class by calling Class.create function, the initialize is invoked automatically. So users can put initialization code in initialize function.
    var Class = {
     create: function() { 
      return function() {
       this.initialize.apply(this, arguments);

    } } }
    Typical usage:
    var person = Class.create();
    person = {
     initialize : function( arguments ){},
     function2 : function(){},
     ...
    }
    

    Class inheritance:
    Object.extend = function(destination, source) {
     for (var property in source) {    
      destination[property] = source[property];
     }
     return destination;
    }
    
    You can see that it just copies all properties from source object to destination object.

  • Ajax
    Prototype wraps basic xmlhttprequest object. It provides several useful objects: Ajax.Request, Ajax.Responders, Ajax.Updater and Ajax.PeriodicalUpdater.
    By using Ajax.Requestr, users can send requests to a destination host. By installing callback funtions, when operation succeeds or fails, corresponding function is invoked automatically.
    By using Ajax.Updater, users can associate an request with a specified html element. When requested data comes, content in that element is automatically updated.
    By using Ajax.PeriodicalUpdater, users can set the frequency and decay of executing update operations.

  • JSON
    JSON - Javascript Object Notation is representation of javascript object. Of course, the javascript can be described in XML. However, parsing of JSON is faster than that of XML.
    Parse JSON
    var data = str.evalJSON(true);//where str is the string you want to be parsed.
    Encode JSON:
    Object.toJSON( dataobj );
    where dataobj is the object you want to convert to JSON. Object automatically invokes toJSON functions of different objects based on the type. So, you can write a customized toJSON function for your object.
    objname.toJSON(); where objname is the object which will be converted.

  • DOM extension
    Prototype adds many convenient methods to elements returned by the $() function. For example
    $('title').addClassName('css-title').show()
    Magic? Let me reveal the secret. Prototype implements Element.extend(obj) funtion which extends the specified object by copying all those methods (addClassName ...) directly. In addition, the Element.extend function can guarantee that the same element is not extended twice.
    Or you can use following syntax:
    Element.function_name( element_name, property_value );
    Programmers can write their own element functions, encapsulate them in a an object and pass the object to Element.addMethods function.
    (Note: the element object which is passed to the new element funtions must be returned at the end).

Sunday, October 07, 2007

First COG program

Recently, I wrote a simple JavaCOG program which makes use of the globus middleware installed on gridfarm001. Four kinds of objects in the program are important:
  • Task--abstraction of the work you want to execute on remote machines.
  • JobSpecification
  • Service--local representation of remote service.
  • TaskHandler
To appropriately set Service object, other two objects are necessary:
  • ServiceContact -- specifies endpoint (host and port) you want to interact with.
  • SecurityContext--specifies the credential you will use to do the authentication by server.
Because Service is local representation of remote grid service, provider must be specified to complete the translation between upper abstraction and underlying infrastructure. In my case, the underlying infrastructure is Globus. However I don't know the version of Globus. At first, I used provider GT4. However, the program seemed not to have effect before being terminated antomatically. I added additional debugging and logging statements, but nothing was generated. I debugged it step by step, I found that the program was terminated when the handler submitted the task. Then I tried the command line tool provided by JavaCOG and it worked. So I ensured that some configurations in my program were incorrect. Finally, I found that it was because of the version of Globus. Gridfarm installs GT2. I didn't know that and assumed it was GT4. So I used GT4 as the service provider. Then you know the result... One bad thing is that my program didn't give any useful information before being terminated. No exception could be caught. I don't know why.

Tuesday, October 02, 2007

JavaCOG Abstraction

Java COG Abstraction

Java COGSpecification. 1

Basic Description. 1

General Abstraction Classes: 2

Additional Abstraction. 3

Basic Description

(from http://wiki.cogkit.org/index.php/Java_CoG_Kit_Abstraction_Guide):

“Every Grid job (remoteexecution, file transfer, file operation) is represented as a Grid task. All job-specific details arerepresented as a task specification.Further, the remote execution and file servers are locally represented as service objects. Every service has a provider attribute associated with it thatsignifies the technology in which the service is implemented. In order toexecute the Grid job, a user needs to create an abstract Grid task andassociate a specification and service to it. The task is then submitted to atask-handler. The task-handler extracts the specification details and dependingon the provider attribute of the service translates them into the protocolspecific constructs expected by the backend service. The task is submitted andexecuted by the handler in an asynchronous mode. Hence, the client need notwait (block) for the task to be completed by the remote service. Instead, oncethe task is submitted to the task-handler, the client is free to continue withother activities and gets asynchronously notified once the task is done(completed or failed).”

General Abstraction Classes:

1          Executable Object:

       AnExecutableObject provides a high-level abstraction for artifacts that can beexecuted on the Grid. It can be specialized as a Grid Task or a TaskGraph.

1.1         Task:

A Task is an atomic unit of execution in cog-abstractions. Itrepresents a generic Grid functionality including remote job execution, filetransfer request, file operation, or information query. It has a uniqueidentity, name, execution status, specification, and set of services (forremote execution).

1.2         TaskGraph

A TaskGraph provides a building block for expressing complexdependencies between tasks. Advanced applications require mechanisms to executeclient-side workflows that process the tasks based on user-defined controldependencies. Hence, the data structure representing the TaskGraph aggregates aset of ExecutableObjects (Tasks and TaskGraphs) and allows the user to definedependencies between these tasks.

2          Specification

Every Grid Taskhas an associated Specification that dictates the objective of the task and theenvironment required to achieve the objective. This class just provides basicattributes which are common to almost all kinds of tasks.

Following three classes are subclasses ofSpecification:

JobSpecification:

The JobSpecification mentions the common parameters needed for theremote job execution independent of the low-level implementation.Implementation-specific parameters can be added to the specification asadditional attributes.

FileTransferSpecification:

    TheFileTransferSpecification provides the commonly used attributes for ?letransfers between Grid resources.

FileOperationSpecification:

The FileOperationSpecification offers the functionality to invokeimportant operations on files hosted on remote Grid resources.

3          Service

Every Grid Taskhas a set of remote Services that support the actual execution of the task. Theservice interface is a local representation of the remote Grid service. Everyservice has a provider attribute that specifies the technology andprovider supported by that service. It also has a service contact and a securitycontext specific to that provider.

4          Handler

Cog-abstractionscontains the TaskHandler and the TaskGraphHandler,to process a Task and a TaskGraph respectively. Once a Task or a TaskGraph issubmitted to the appropriate handler, the handler interacts with the desiredGrid implementation and accomplishes the necessary tasks. The handlers incog-abstractions can be viewed as adaptors that translate the abstract definitionsof a Task and TaskGraph into implementation-specific constructs understood bythe backend Grid services.

5          Status

Every ExecutableObject (Task or TaskGraph) has an associated execution status.

6          Permission

The permissionsinterface provides a means to get and set permissions for a class of usersalong with GridFile and FileResource abstractions.

7          GridFile

A GridFile is anabstract representation of a remote file or directory. It represents the basicproperties of a file such as size, name, modification date, access permissionsetc. This abstraction is a passive information carrier and cannot be used tomodify the properties or contents of a remote resource directly. It can be usedas an input to the file resource abstraction to change access permissions of aremote resource.

Additional Abstraction

If what a userwants to do is manipulate file resources ( read, write, delete, copy …),JavaCOG provides an additional abstraction class which makes the task easier. Inthis case, the user does not need to use task model.

1          FileResource

An alternatemodel of abstraction for file operations, bypassing the task model, isalso available for applications that desire direct interactions with the filehosting Grid servers. A FileResource provides all the necessaryfunctionality to directly invoke remote file operations.

 

CSS

I have been updating my blog since last year. To make the content more readable, I manually edit the html/css source code. I modified the template of my blog to add some css rules which can be used repetitively in my blog posts. This saves lots of duplicate typing work. However, it is still a painful task to edit the html/css source code in google blotspot. No syntax highlight, so small a area where edit takes place, manually html escape ... Of course, I can first edit the html/css code in an external editor (notepad, ultraedit...) and then copy and paste the code. But, what is important to me is the pure content of the blog posts. In other words, the decoration and formatting of the content should take as little time as possible. So, I prefer to use rich text editor in which formatting of text/image... can be controlled conveniently. In addition, the editor must have the ability to convert the rich text into html/css format. In my case, I chose MS Word because I can get it easily. Now, I can edit my document in MS Word which I am familiar with and then convert the document into html. But, one problem pops up now. The converted html document contains css <style></style> section in head section which contains various css rules. I CANNOT copy and paste the document directly into google blogspot because the <style> element CANNOT be defined in bodysection. What I type in the text area(blogspot editing) is finally put into body section of the final web page by google server. So, I thought of changing the css rules into inline mode by using the style attribute.
Originally:
<html>
    <head>
        <style>
        .css{
            color:blue;
        }
        </style>
    </head>
    <body>
        <div class=\"css\">test text</div>
    </body>
</html>
Formatted:
<html>
    <head> </head>
    <body>
        <div style=\"color:blue;\">test text</div>
    </body>
</html>
If all the work is done manually, I believe it is a test of one's patience and carefulness. As a computer major student, I would like it to be done programmatically. I need a CSS parser to parse the css rules and know which element refers to which css rule. After that, the remaining work is just to insert the css rules into corresponding places.
After searching in Google, I found W3 Simple API for CSS and Cypress.
SAC is a standard interface for CSS parser and supposed to work with CSS1, CSS2, CSS3 (currently under development) and other CSS derived languages.
Cypress is an open source CSS parser.
Actually, at first I checked well-known layout engines - Mozilla Gecko, Trident, WebCore(currently WebKit). But I did not find an independent css parsing module in those engines.
Now, I decide to use Cypress to write a simple program to do the work I mentioned above.

Monday, October 01, 2007

Java Cog Setup

Today, I downloaded and installed JavaCog. Detailed Information:
Prerequisite
To use grid services, one must obtain the certificate/credential from administrator of the grid. Generally, public/private key mechanism is used. There are two files:
usercert.pem
This file contains the certificate which is requested by server to authenticate the user.
userkey.pem
This file contains the private key which should be kept secretly by user. Usually, this file is encrypted based on the passphase provided by user so that a attacker cannot get useful information even if he gets this file.
Note: the names of those two files do not matter. What you must do is correctly configure the JavaCOG so that it can find those two files. File cog.properties contains corresponding information. Usercert.pem and userkey.pem are default names for those two files.
Setup Steps:
(1) download JavaCOG 4.1.5
Note: I installed the binary archive. If you prefer to install it from the source code, consult the documentation.
(2) unpack the tarball( .tar.gz or .zip)
Suppose the unpacked files are put into directory COGDIR.
(3) cd COGDIR/bin
(4) run cog-setup(under linux/unix) or cog-setup.bat(under windows)
Then a GUI is displayed to guide you to set up JavaCOG step by step. This GUI is just an auxiliary tool to make the setup easier. Actually, all configuration is written into a file called cog.properties. This file is located under directory $(HOME)/.globus.Suppose username is USER1:
In Linux, $(HOME) is /home/USER1.
In Windows, $(HOME) is C:\Documents and Settings\USER1\ (if operating system is installed into partition C)
(5)Put the certificate of the grid service under directory $(HOME)/.globus/cog-certificates.
(6) Modify the file cog.properties to indicate that the newly added certificate should be trusted by JavaCOG and JavaCOG can use the certificate to authenticate the grid server. Actually, more options can be specified. In my case, those two files are 84ff0685.0 and 84ff0685.signing_policy.
So, related lines in cog.properties are:
cacert=C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\84ff0685.0
A sample cog.properties file:
#Java CoG Kit Configuration File
#Mon Oct 01 16:20:20 EDT 2007
usercert=C\:\\Documents and Settings\\gerald\\.globus\\usercert.pem
userkey=C\:\\Documents and Settings\\gerald\\.globus\\userkey.pem
proxy=C\:\\DOCUME~1\\gerald\\LOCALS~1\\Temp\\x509up_u_gerald
cacert=C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\44879c16.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\1c3f2ca8.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\84ff0685.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\aaaddcdf.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\4a6cd8b1.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\5aba75cb.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\3deda549.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\b89793e4.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\9a1da9f9.0,C\:\\Documents and Settings\\gerald\\.globus\\cog-certificates\\2c7969d0.0
ip=xxx.xxx.xxx.xxx
Note: Generally, you want to change the passphase which is used to encrypt/decrypt your private key file. You can use command: grid-change-pass-phase
JavaCOG toolkit
In addition to cog-setup, JavaCOG provides many more tools which makes configuration/execution easier. These tools are under directory bin. Here you can find the documentation about those tools. However, the documentation does not cover all those tools.
Credential Management
If you have several computers, you must save credentials (certificates/private keys) on these different machines. It is a boring work. You can use a credential management server to relieve the burden. Myproxy is a popular credential repository. You can store your credentials in a MyProxy repository and retrieve a proxy credential from the MyProxy repository when needed. The actual work is the user generates a proxy certificate and then uploads it to Myproxy server.
MyProxy commands:
  • myproxy-init - Store a proxy credential for later retrieval
    The myproxy-init command uploads a credential to a myproxy-server for later retrieval. In the default mode, the command first prompts for the user's Grid pass phrase (if needed), which is used to create a proxy credential. The command then prompts for a MyProxy pass phrase, which will be required to later retrieve the credential. By default, myproxy-init will create a proxy credential from the user's end-entity credentials at ~/.globus/usercert.pem and ~/.globus/userkey.pem to delegate to the myproxy-server.
  • myproxy-store - Store end-entity credential for later retrieval
    Unlike myproxy-init, this command transfers the private key over the network (over a private channel). In the default mode, the command will take the credentials found in ~/.globus/usercert.pem and ~/.globus/userkey.pem and store them in the myproxy-server repository.
  • myproxy-logon - Retrieve a credential
    The myproxy-logon command retrieves a credential from the myproxy-server that was previously stored using myproxy-init. In the default mode, the command prompts for the MyProxy pass phrase associated with the credential to be retrieved and stores the retrieved credential in the standard location (/tmp/x509up_u).
  • myproxy-retrieve - Retrieve an end-entity credential
    The myproxy-retrieve command retrieves a credential directly from the myproxy-server(8) that was previously stored using myproxy-init(1) or myproxy-store(1). Unlike myproxy-logon(1), this command transfers the private key in the repository over the network (over a private channel). To obtain a proxy credential, we recommend using myproxy-logon(1) instead.
    In the default mode, the command prompts for the pass phrase associated with the credential to be retrieved and stores the retrieved credential in the standard location ( ~/.globus/usercert.pem and ~/.globus/userkey.pem). You could then run grid-proxy-init to create a proxy credential from the retrieved credentials.
  • myproxy-info - Display information about credentials
  • myproxy-destroy - Remove a credential from the repository
  • myproxy-change-pass-phrase - Change a credential's passphrase
  • myproxy-admin-adduser - Add a new user credential
  • myproxy-admin-change-pass - Change credential passphrase
  • myproxy-admin-query - Query repository contents
  • myproxy-admin-load-credential - Directly load repository
  • myproxy-server - Store credentials in an online repository
COG command:
However, the related command in JavaCOG is
cog-myproxy
This command is similar to the myproxy-init/myproxy-logon/myproxy-store/myproxy-store commands in Myproxy client. In other words, you can store/retrieve credentials(proxy credentials or original certificates/keys).
Some typical examples:
cog-myproxy -h gf1.ucs.indiana.edu put #upload the certificate to the myproxy server.
cog-myproxy -h gf1.ucs.indiana.edu get #download the certificate from myproxy server
Proxy Credential
Every time the service you are interacting with needs your certificate to do authentication, you must input the pass phase. GSI provides a delegation capability: an extension of the standard SSL protocol which reduces the number of times the user must enter his passphrase. If a Grid computation requires that several Grid resources be used (each requiring mutual authentication), or if there is a need to have agents (local or remote) requesting services on behalf of a user, the need to re-enter the user's passphrase can be avoided by creating a proxy.
A proxy consists of a new certificate and a private key. The key pair that is used for the proxy, i.e. the public key embedded in the certificate and the private key, may either be regenerated for each proxy or obtained by other means. The new certificate contains the owner's identity, modified slightly to indicate that it is a proxy. The new certificate is signed by the owner, rather than a CA. The certificate also includes a time notation after which the proxy should no longer be accepted by others. Proxies have limited lifetimes.
When proxies are used, the mutual authentication process differs slightly. The remote party receives not only the proxy's certificate (signed by the owner), but also the owner's certificate. During mutual authentication, the owner's public key (obtained from her certificate) is used to validate the signature on the proxy certificate. The CA's public key is then used to validate the signature on the owner's certificate. This establishes a chain of trust from the CA to the proxy through the owner.
cog-proxy-init
It provides a GUI to generate the proxy certificate. The default name of the proxy file is x509up_u_username which is stored in the temporary directory. (Of course, you can change it by modifying the configuration file.). During the generation, you can specify some options: proxy lifetime, key strength...

If you prefer command line tool to generate the proxy certificate, you should use grid-proxy-init command. Roughly, grid-proxy-init and cog-proxy-init provide the same functionality except the user interface. You can choose either one you like.
grid-proxy-init - Generate a new proxy certificate
grid-proxy-destroy - Destroy the current proxy certificate
grid-proxy-info - Display information obtained from a proxy certificate