Friday, June 24, 2011

Time to change Java main method - Paper

Cairo, Egypt On May, 2011

I. Abstract
Main method in Java (which is inherited from C) have the String[] as input parameter to the main method, now it is time to enforce Object Oriented in this method as well, and enable Object passing as a parameters[1]
In the same time, class can't have more than one main method, so we enabled more than one main method and enabled the dynamic selection of it based on the parameter list.
We have tried some approaches to enable passing objects to the main method using the Java language [2].
We will see how we will use the JSON representation of the object in this paper and pass-by-content or pass-by-representation new methodology in passing objects as parameters.
We proposed some of the new signatures to the main method and passing the arguments as (Object[] args) , (CustomClass[] myData) and (CustomClass[] myData, String[] args).

II. Introduction
Java and all command line parametrized languages accept only String array of arguments which make sense as our ability to call using command line gives us the ability to enter text that could be represented by String object in Java or char* in C.
This is how we used to have a method like[3]:

public static void main (String[] args) {
for (String s: args) {
System.out.println(s);
}
}

java Echo Drink Hot Java
Drink
Hot
Java
If we enclosed them with double quotation “, this will result in a single parameter:
java Echo "Drink Hot Java"
Drink Hot Java

If we need to pass integer value, we need to use parsing method to obtain the numeric value from it:
try {
firstArg = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.err.println("Argument must be an integer");
}

What if we need to pass a whole object as an argument to the class?
There are some solutions for this, including 1) passing the Object fields as a separate parameters then in our main method construct this Object and fill its fields. 2) Use Java serialization and save the object to the file system and pass the filename to it to deserialize it back to an object [4].

// Serialize the original class object
FileOutputStream fo = new FileOutputStream("cde.tmp");
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(corg);
so.flush();
so.close();
// Deserialize in to new class object
FileInputStream fi = new FileInputStream("cde.tmp");
ObjectInputStream si = new ObjectInputStream(fi);
cnew = (CustomDataExample) si.readObject();
si.close();

Our proposed solution is to use JSON as a passing String represents this object.

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999.[5]
JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.[5]

JSON is built on two structures:
* A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
* An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
We have selected Google JSON named Gson which is a Java library that can be used to convert Java Objects into their JSON representation.[6]
It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of.[6]
There are a few open-source projects that can convert Java objects to JSON. However, most of them require that you place Java annotations in your classes something that you can not do if you do not have access to the source-code. Most also do not fully support the use of Java Generics. Gson considers both of these as very important design goals. [6]

This is example of JSON object:
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address":
{
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
}
}


III. New main method signature
Now let's see how we can build a new main method signature, our target is to have the main method public static void main(Object[] args) instead of public static void main (String[] args)

public static void main(String[] args) {
if(args!=null && args.length>0){
Vector parametersObjects=new Vector();
for(int i=0;i<args.length;i++){
if(args[i].startsWith("{") && args[i].endsWith("}")){
args[i]=args[i].replaceAll("~", "\"");
parametersObjects.add(param);
}else{
parametersObjects.add(args[i]);
}
}
Object[] params=null;
if(parametersObjects.size()>0){
params=parametersObjects.toArray();
}
main(params);
}
}
We will back to the line (args[i]=args[i].replaceAll("~", "\"");) later on to explain why we have added it.
Our main method will utilize the parameters now as objects:
public static void main(Object[] args) {
if(args!=null && args.length>0){
for(int i=0;i<args.length;i++){
if(args[i] instanceof EmpData){
//…
}else{
//…
}
}
}
}

If we can inject the code in main(String[] args) into the JVM we would only have the ability to code any one of these 2 methods with String[] and Object[] according to our needs.
Now we can call our class and send mixed parameters of String and JSON objects:

java -jar JSON-Param.jar {"id":0,"name":"Osama Oransa","location":"Cairo, Egypt","isSupported":false}

Now we are facing the following problems:
1. Spaces inside the JSON object string representation.
2. Double quotes inside the parameter which will be removed automatically from the arguments
We have fixed this by ensuring no spaces inside the JSON object string representation except inside the literal values of string field(s), this literal values are already surrounded by double quotes so it won't break the parameter so this will fix the 1st issue, 2nd issue will need a special parameter to proceed every double quote, in this research we have used the symbol ~.

java -jar JSON-Param.jar {~"id~":0,~"name~":~"Osama Oransa~",~"location~":~"Cairo, Egypt~",~"isSupported~":false}

This is why we have added this line in the main method to construct our JSON object correctly:
args[i]=args[i].replaceAll("~", "\"");

To construct JSON object representation like what we have modified:
String jSonAsParameter=new Gson().toJson(object).replaceAll("\"","~\"");

Of course this has a drawback of preventing us to use ~ symbol inside the string literal values so we need to search for a better symbol.

Another way to fix this is to add all the parameters into a single String then start to parse it and only respect String if there is no current JSON object is opened (i.e. no matched closing bracket reached yet), this way is simple and granted to work but it need to be implemented from the JVM as it will need complex logic and will consume time in processing.

IV. Pass-by-Content
According to Sebesta in his book Concepts.of.Programing.Languages passing parameters in programming languages take different types like pass-by-value, pass-by-result, pass-by-value-result, pass-by-reference and pass-by-name [7].

If we looked at what we did so far, we have pass the object content itself so this is some sort of pass-by-value but we can name it pass-by-content or pass-by-representation as we didn't pass the object instead we passed a content to a new object that would be created and constructed from this content.

To fully support JSON in Java as content representation we can add a new method toJson() that produce JSON representation of this class object, in the same time we need to add a static method that accept String of JSON representation and return the object that represents these content.

public class EmpData {
private int id;
private String name;
private String location;
private boolean isSupported;
public String toJson(){
return new Gson().toJson(this);
}
public static EmpData getInstanceFromJson(String jSonString){
return (EmpData)new Gson().fromJson(jSonString, EmpData.class);
}

......setters and getters of instance variables
}

V. Many main methods concept
Now we can have one main method to start the Java application regardless of its signature String[], Object[] or mixed String[], Object[] or even direct child of Object like EmpData[] and the JVM is responsible for invoking the correct method or we can have many main methods and one is selected upon parameter types.
This is similar to have more than one door per application and selection of the door is by the keys given.
If we modified our code a little we can have something like this:
public static void main(String[] args) {
if(args!=null && args.length>0){
Vector parametersObjects=new Vector();
Vector<EmpData> parametersEmpData=new Vector<EmpData>();
Vector<String> parametersString=new Vector<String>();
for(int i=0;i<args.length;i++){
if(args[i].startsWith("{") && args[i].endsWith("}")){
args[i]=args[i].replaceAll("~", "\"");
//System.out.println("Param "+i+" ="+args[i]);
EmpData param=EmpData.getInstanceFromJson(args[i]);
parametersEmpData.add(param);
parametersObjects.add(param);
}else{
parametersString.add(args[i]);
parametersObjects.add(args[i]);
}
}
EmpData[] empParams=null;
String[] stringParams=null;
Object[] objectParams=null;
if(parametersObjects.size()>0){
objectParams=parametersObjects.toArray();
}
if(parametersEmpData.size()>0){
empParams=parametersEmpData.toArray(new EmpData[0]);
}
if(parametersString.size()>0){
stringParams=parametersString.toArray(new String[0]);
}
if(empParams!=null && stringParams!=null){
main(empParams,stringParams);
}else{
main(objectParams);
}
}
If no main method can selected, compilation ambiguity exception must be detected.

VI. Future work
Incorporate parameters detection and main method selection into the Java Development Kit (JDK) and Java Virtual Machine (JVM), this will reduce the effort needed by the programmer and will enhance the speed as well.
Adding toJson() and getInstanceFromJson(String jSonString) methods could be added to the Object class to be inherited by all the objects.

VII. References
[1] www.java-tips.org/java-se-tips/java.lang/what-is-the-main-method.html (Retrieved on 1st of May,2011)
[2] http://download.oracle.com/javase/tutorial/deployment/jar/appman.html (Retrieved on 1st of May,2011)
[3] http://download.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html(Retrieved on 1st of May,2011)
[4] http://download.oracle.com/javase/6/docs/technotes/guides/serialization/examples/custom/index3.html(Retrieved on 1st of May,2011)
[5] http://www.json.org/(Retrieved on 1st of May,2011)
[6] http://code.google.com/p/google-gson/ (Retrieved on 1st of May,2011)
[7] Sebesta.R.W.Concepts.of.Programing.Languages.7th.ED-ISBN_0321330250

No comments:

Post a Comment