Friday, 8 April 2011

Using Getopt in java to give command line options in java program

Wouldn't it be nice if we have command line argument processing in Java with options. I mean using flags and all that stuff for my argumens. Example syntax in Student Database Program:-
java myClassName -c Insert -s John -i 7635425 -b CS
-l {Java|C|C++|nothing} -a []
Flags Explanation:-
'c' may have the following options:-Insert, Delete, Update,Search 's' Student name(compulsory)
'i' Student id(compulsory)
'b' Stuent Major(compulsory)
'l' Student Computer Language Proficiency(choice)
'a' Student Achievements(optional)

So this is where Getopt comes handy.
public static void main(String[] args)
{

//string to hold values for the flags -c,-s,-i,-b,-l and -a
String c,s,i,b,l,a;

for(int count=0;args.length;count+)
{
if(!args[count].startsWith("-"))
{
//even numbered arguments should begin with -
System.out.println("improper suntax");
return;
}
//if args[count]==any flag then args[count+1] contains the
//value for that flag
if(args[count].equals("-c")) c=args[++count];
if(args[count].equals("-s")) s=args[++count];
if(args[count].equals("-i")) i=args[++count];
if(args[count].equals("-b")) b=args[++count];
if(args[count].equals("-l")) l=args[++count];
if(args[count].equals("-a")) a=args[++count];
}
//check for compulsory flags
if(c==null | | s==null | | i==null | | b==null | | l==null)
{
System.out.pritnln("Compulsory flags must be given");
return;
}

int id;
try{
id=Interger.parseInt(i);
}catch(NumberFormatException nfe)
{
Sytem.out.println("Id must be numeric");
return;
}
if(c.equalsIgnoreCase("Insert"))
{
.....
}
if(c.equalsIgnoreCase("Delete"))
{
.....
}
//and so on
...
....
}

Thanks

Creating a soap message in java using SAAJ

Installation issues
Setting up the Java Web Services Developer Pack 1.2 is easy -- as long as you send your messages through the included Tomcat Web server. To send messages through a standalone application, as I do here, you need to take the following steps:
  1. Download the JWSDP 1.2 from http://java.sun.com/webservices/downloads/webservicespack.html.
  2. Follow the instructions and install.
Example of soap message to be created : 

<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Header />
<SOAP-ENV:Body>
<ns1:Price xmlns:ns1="urn:xmethods-BNPriceCheck" >340
</ns1:Price>
         <AuthorName>
<FirstName>Rajesh</FirstName>
<LastName>Thakur</LastName>
</AuthorName>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Now it has 2 parts - name and price , which it wants to submit to the service.
Notice the structure of the message. The Envelope contains the Header and Body elements, and all three are part of the http://schemas.xmlsoap.org/soap/envelope/ namespace. The application sends the message using a SOAPConnection.

Creating the message object
//Next, create the actual message
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage();

//Create objects for the message parts
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPBody body = envelope.getBody();

First, you create the message itself by using the MessageFactory. This message already contains empty versions of the basic parts, such as the envelope and header. The SOAPPart contains the envelope, and the envelope contains the body. Create references to the needed objects, such as the SOAPBody.

Populating the body:
The body of the SOAP message is just like any other XML element in that you can add a child element, such as Price.
//Populate the body
//Create the main element and namespace
SOAPElement bodyElement =
body.addChildElement(envelope.createName("Price" ,
"ns1",
"urn:xmethods-BNPriceCheck")).addTextNode("340");

SOAPElement authorElement = body.addChildElement(envelope.createName("AuthorName");
authorElement.addChildElement("FirstName").addTextNode("Rajesh");
authorElement.addChildElement("LastName").addTextNode("Thakur");

//Save the message
message.saveChanges();


//Check the input
System.out.println("\nREQUEST:\n");
message.writeTo(System.out);
System.out.println();
So this is how our message is prepared and now we can send it as request.

Thursday, 7 April 2011

Create JAR file using Java commands

Following are few commands that can be used to create/view/modify/execute a JAR file using Java command line utilities and JVM.

Create a JAR file

jar cf JAR_FILE_NAME FILE_NAMES_OR_DIRECTORY_NAME
e.g.
jar cf MyApp1.jar C:\JavaProject\MyApp

View contents of a JAR file

jar tf JAR_FILE_NAME
e.g.
jar tf MyApp1.jar

View contents with detail of a JAR file


jar tvf JAR_FILE_NAME
e.g.
jar tvf MyApp1.jar
Note that we have used v (verbose) option to see the detail of JAR.

Extract content of JAR file

jar xf JAR_FILE_NAME
e.g.
jar xf MyApp1.jar

Extract specific file from JAR file

jar xf JAR_FILE_NAME FILE_NAME(S)_FROM_JAR_FILE
e.g.
jar xf MyApp1.jar Test1.class

Update a JAR file


jar uf JAR_FILE_NAME FILE_NAMES_FROM_JAR_FILE
e.g.
jar uf MyApp1.jar Test1.class

Executing a JAR file


java -jar JAR_FILE_NAME
e.g.
java -jar MyApp.jar

Create an executable JAR file

In order to create an executable JAR, one of the classes that we include in our JAR must be a main class.
Create a text file called MANIFEST.MF using any text editor and copy following content in it.

Manifest-Version: 1.0
Main-Class: MyMainClass
Where MyMainClass is the name of the class that contents main method. Also note that you have to specify fully qualified class name here.
Use following command to create an executable JAR file.

jar cvfm MyApp.jar MANIFEST.MF FILE_NAMES_OR_DIRECTORY_NAME

Friday, 1 April 2011

Logging resources

Formatting or rendering via logging

Each handlers output can be configured with a formatter
Available formatter
  • SimpleFormatter Generate all messages as text
  • XMLFormatter Generates XML output for the log messages 
Log entries can be sent to these destinations, as either simple text or as XML :
  • the console
  • a file
  • a stream
  • memory
  • a TCP socket on a remote host
class MyHtmlFormatter extends Formatter{

//this method is called for every log records
public String format(LogRecord record)
{
StringBuffer buf = new StringBuffer(1000);
//if level is greater than warning, bold the content
if (record.getLevel().intValue() >= Level.WARNING.intValue()){
buf.append("<b>");
buf.append(record.getLevel());
buf.append("</b>");
}
//else do something else
//and so on
return buf.toString();
}

Java Logging API tutorial (step by step)

The JDK contains the "Java Logging API". Via a Logger one can save text to a central place to report on errors, provide additional information about your program, even the finest detail to errors depending on the priorities. See here for what is java logging API.

Creating a Logger


The package java.util.logging provides the logging capabilities via the class Logger.
Java code:
import java.util.logging.Logger;

private final static Logger LOGGER = Logger.getLogger(MyClass.class .getName());


Logging Levels



Once the logger created, (above we have created logger per class, so its static.) we can use it to log errors, or simple info or even the lowest detail of the user program.

So the levels are divided as follows:
Log Levels in descending order are:




  • SEVERE (highest)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

In addition to that you have also the levels OFF and ALL to turn the logging of or to log everything.
Java code to set logging level:


LOGGER.setLevel(Level.DEBUG);

Example:

package logging.example;
import java.util.logging.Logger;

public class HelloLogging {
private static Logger theLogger =
Logger.getLogger(HelloLogging.class.getName());

private String aMessage;

public HelloWorld(String message) {
aMessage = message;
}

public void sayHello() {
// use the 'least important' type of message, one at
// the 'finest' level.
theLogger.finest("Hello logging!");
System.err.println(aMessage);
}
}


Now in main simply call this class:

public static void main(String[] args) {
HelloLogger helloLog = new HelloLogger("Hello world logger!");
helloLog.sayHello();
}


As we have done logger level to finest we cannot get "Hello logging" on console. For this in sayHello we can write this:


theLogger.INFO("Hello logging!");


This will log "INFO" or higher level logs to the console.

 

Handler



Now we can handle these logs. By handling I mean is that we get the log message and export it to certain target accordingly. See Log handlers in Java APIs for this.

 

Formatter


Each handlers output can be configured with a formatter, which format the output in custom way before sent to display. See here for more.

 

Logger Inheritance


Loggers inherit certain characteristics from their parents when they are created, Typically a Logger will inherit the following:


  • If a Logger is created with no Level set it will inherit the first Level it finds set in a Logger as it walks up the tree.
  • The default setting is to use parent handlers so if you don't specify a handler explicitly LogRecords may still be published by parent Loggers.
  • If a Logger has a null ResourceBundle name it will use the name given to its parent and so on.

Logging Convenience Methods


The default Logger implimentation has numerous convenience logging methods that can save a great deal of time when adding log messages to code. The convenience methods take one of two forms. Either "void info( String message )" or "void info( String sourceClass, String sourceMethod, String message )". The first version is sold to developers that want quick logging the second is to developers that want accurate logging. The second is more "accurate" because it explicitly names the source class and method, information that may be lost when the class is JITed. In reality I have never seen the first version turn out the wrong result (or no result which is more likely).

 

Logging Configuration


This section will have a bit of a Tomcat twist to it towards the end because most of my work is done with Tomcat. This is another area where Sun seem to have dropped the ball a little. There is no way using the basic Java logging framework to distinguish between different web applications in the same container if they use the same Logger. This means that if you had the same code deployed twice you wouldn't be able to tell where the log messages were coming from. Log4j solves that problem but for now we will stick to the default Java logging API and later I will show you a way round the problem.

Configuring Java Logging

Logging can be configured in three different ways: you can supply a properties file that describes the logging setup (by default this is called logging.properties and lives in JRE/lib/), you can provide a class that can be instantiated at VM initialisation that will configure the logging or you can roll your own logging configuration. I include rolling you own because I don't like either of the other two solutions much. The first means you have to play with a file that lives in one of hte VM distribution directories which, to my mind, is a bad thing. The second means adding another argument to the invocation of the VM which, IMHO, leads to screw ups. Either way, those are your options. I will focus mostly on the properties file as that is more commonly used. The class configuration technique is useful of you need to configure loggers from a database or other source but if you need something that complex you probably have enough time to "do it right".

The logging.properties file simply defines a number of Loggers, Handlers, Formatters and Filters that are constructed and ready to go shortly after the VM has loaded. Normally the top portion of the file is devoted to setting up Handlers for the root logger. The set up for the root Logger is a little different to the other Loggers because it doesn't have a name. To add handlers to the root logger include a line that begins handlers and then lists the handlers to add to the root logger. For instance this

handlers = java.util.logging.ConsoleHandler,
java.util.logging.FileHandler


will add a ConsoleHandler and FileHandler to the root logger. Next set the logging level of the root logger which is done with the name .level. To set it to all use

.level = ALL


To set the logging levels for the two handlers created add lines like this

java.util.logging.ConsoleHandler.level = INFO
java.util.logging.FileHandler.level = ALL


and finally to set a formatter simply specify its name like this

java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter


It is possible to set any of the instance variables on the Loggers, Handlers, Formatters and Filters in a similar manner by specifying its name followed by the property name you want to set. To set handlers on other loggers use the syntax loggerName.handlers=list_of_handler_class_names.

You can probably see the limitation in the default Java logging setup now. There is no way to separatly configure the handlers for different loggers because you have no way to seperate the names of the handlers - you have to refer to them by their class name.

Log handlers or appenders in Java APIs

Each logger can have access to several handler.
The handler receives the log message from the logger and exports it to a certain target
A handler can be turn off with setLevel(Level.OFF) and turned on with setLevel(...)
You have several standard handler, e.g.

  • ConsoleHandler: Write the log message to console
  • FileHandler: Writes the log message to file
Log Levels INFO and higher will be automatically written to the console.
Handler[] handlers = Logger.getLogger( "" ).getHandlers();

//Now you can set individual handler level like this: 
handlers[index].setLevel( Level.FINE );

See log formatter.