Friday, June 11, 2010

log4j ... Dynamic Log File Name


Background:
We developed a Bulk Loader component using core Java api's and used log4j for writing all the developer debugs, info, warn etc messages to a log file. The Bulk Loader, as the name suggests, sent bulk requests to application which enabled Load Testing. The Bulk Loader was developed in such a way that multiple instances could run on the same machine : this enabled controlling the load pushed to the application from various Bulk Loader instances.


Problem scenario:
During testing, if was found that all the Bulk Loader instances running on one machine, used the same log file for writing their messages to. This made the log file illegible. Messages from different instances were interwoven into a single log file which made debugging a very tough job. A solution was needed for each instance to create and write to its own log file.

Method 1: Modify the java code for setting the correct log file name to the FileAppender
  1. Get hold of the all Appenders  from the Logger object
  2. Loop through each and find the Appender of interest. This will typically be the FileAppender
  3. Call the setFile( String fileName ) api for setting desired log file name
  4. Call the activateOptions for Log4j framework to pick the newly set log file name
Though most of us would like and prefer to use the above method, there are two stark limitations :
  1. There can be multiple File Appenders defined in the log4j.xml. For example, my log4j.xml has two RollingFileAppenders; one with name as Process the other with Audit. In such cases, the logic of setting the log file name dynamically starts getting complex if lot of conditional checks
  2. If the source code of api responsible for initializing the Logger is not available (this could be due to the fact that you, as a part of Services team, have the ability to invoke an exposed log( String message, int level ) method and initialization and configuration of the Logger is taken care by the Product team), then you definitely cannot get hold to any of the Appenders and change the log file name.
Method 2: Modify the log4j.xml and Use -D switch
This method does not require any code changes and hence no need to recompile. This method is only related to configuration of log4j.xml and the start command of java program.
  • Open the log4j.xml and introduce a variable in front of the log file name definition. The variable name should be wrapped with special characters as follows: ${variable name}
  • Following is the snippet from my log4j.xml

         <appender name="Process" class="org.apache.log4j.DailyRollingFileAppender">

             <param name="File" value="./logs/${log_file_name}_Log.txt"/>

         <appender name="AuditAppender" class="org.apache.log4j.RollingFileAppender">

         <param name="File" value="./logs/${log_file_name}_Audit_log.txt"/>
  • Modify the start command of java application as below:

           java -Dlog_file_name=Items -cp %CLASSPATH% HelloWorld
  • This will create two log files by the name Items_Log.txt and Items_Audit.txt in the logs folder
Hope this post was helpful. Happy Logging !

Saturday, April 3, 2010

A Webservice that WORKS !!!


I faintly recollect the last webservice which I deployed on Tomcat in the year 2005. That was an achievement for me as no one in our team knew how to develop and deploy one. Four years and counting, I was facing the same challenge again. Unfortunately, I lost the reference project from year 2005 and here I was back to square one.
Searching on Google indeed returned lot of results; but; I doubt if anybody has been able to get them work. Samples from sun-java tutorials always talk about using ant scripts to compile and prepare the target war files. Seldom do we use Sun's J2EE server in our projects; most of the times the application server used is WebSphere or Weblogic or JBOSS. The next problem is to build the component for successful deployment on Weblogic or JBOSS etc.
I am being candid here. I tried a lot and hit many obstacles on the way. After breaking my head during leisure time, I managed to successfully expose and consume a webservice. The following section is my attempt to help folks who are in similar situation. I have tried to explain the following things:

Steps to develop a simple webservice
  1. Most of the webservices tutorials use simple types while passing and return from the service. Frankly speaking, a webservice accepting an int and returning a String is of no use to anyone of us. We always have complex types i.e. custom objects which are used as request (i.e. input argument to the webservice) and response (i.e. return parameter from the webservice).
  2. Deployment on JBoss 4.0.5 GA
  3. Deployment on Weblogic 9.2
  4. Test Client Standalone
  5. Test Client Weblogic
  6. Important points to remember
Hope you are successful too !

Software versions: Jboss 4.0.5 GA, Weblogic 9.2, JDK 1.5.0.*, JWSDP 2.0 (very important)

Steps:

1. Create the folder structure
The final folder from which the deployment ear/war/jar will be created is as follows:
 
 
2. 2. Create the remote interface, implementation class and the input & output valueobjects. An important point to be considered is the nomenclature of the implementation class. When using servlets to masquerade the webservice, we are inclined to put the name as XYZServlet. This works fine when deploying the webservice in Weblogic. But Jboss has a problem; if the name of the servlet class has 'Servlet' in it, then that class is ignored during webservice deployment and is treated as a valid Servlet instead.
Hence I recommend sticking to the XYZService nomenclature. XYZ will be remote interface a.k.a service end point and XYZService will be the implementation of the service.

Adjust your IDE settings such that the ouput from compilation of the below mentioned java files, results into creation of class files under webapp\web-services\WEB-INF\classes folder

Interceptor.java
=================
package org.jboss.webservices.queuing;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.jboss.webservices.valueobjects.InterceptorRequest;
import org.jboss.webservices.valueobjects.InterceptorResponse;


public interface Interceptor extends Remote {
  public InterceptorResponse addToQueue( InterceptorRequest req ) throws RemoteException;
  public String removeFromQueue( int positionNumber ) throws RemoteException;
}
InterceptorService.java
=======================
package org.jboss.webservices.queuing;
import java.rmi.RemoteException;
import org.jboss.webservices.valueobjects.InterceptorRequest;
import org.jboss.webservices.valueobjects.InterceptorResponse;
public class InterceptorService {
  public InterceptorResponse addToQueue( InterceptorRequest req ) throws RemoteException {
    System.out.println( "Interceptor request received is : " + req );


    InterceptorResponse res = new InterceptorResponse();
    String[] result = new String[ 3 ];
    result[ 0 ] = "First element";
    result[ 1 ] = "Second element";
    result[ 2 ] = "Third element";
    res.setResult( result );
    return res;
  }
  public String removeFromQueue( int positionNumber ) throws RemoteException {
    String retString = "Removed element at position " + positionNumber;
    System.out.println( retString );
    return retString;
  }
}
InterceptorRequest.java
=======================
package org.jboss.webservices.valueobjects;
import java.io.Serializable;
public class InterceptorRequest implements Serializable {
  private String _soapMsg = null;
  private int _demuxId = -1;
  private long _entryTimeInMillis = 0;
  private String[] _tcgsUrls = null;


  public String getSoapMsg() {
    return _soapMsg;
  }
  public void setSoapMsg(String soapMsg) {
    this._soapMsg = soapMsg;
  }
  public int getDemuxId() {
    return _demuxId;
  }
  public void setDemuxId(int demuxId) {
    this._demuxId = demuxId;
  }


and so on ... create getter and setter for each property
}
InterceptorResponse.java
========================
package org.jboss.webservices.valueobjects;


import java.io.Serializable;
public class InterceptorResponse implements Serializable {


  private String[] _result = null;
  public String[] getResult() {
    return _result;
  }
  public void setResult(String[] result) {
    this._result = result;
  }
}
3. Masquerade the webservice as a servlet: For this, we will add a web.xml with entries similar to the ones required while defining the servlet. The web.xml will reside at the following location : webapp\web-services\WEB-INF
web.xml
=======
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">


<servlet>
<servlet-name>InterceptorService</servlet-name>
<servlet-class>org.jboss.webservices.queuing.InterceptorService</servlet-class>
</servlet>


<servlet-mapping>
<servlet-name>InterceptorService</servlet-name>
<url-pattern>/Intercept</url-pattern>
</servlet-mapping>


</web-app>

Important points while developing the web xml:
  1. The servlet name should match in the servlet and servlet-mapping tag.
  2. The servlet class holds the fully qualified class name of the service implementation class.
  3. The url-pattern should be unique and not used anywhere else in the web xml.
4. Build the configuration descriptor for webservice. Place this in a file called as interceptor_config.xml.
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<service name="InterceptorService"
targetNamespace="http://queuing.webservice.jboss.org/"
typeNamespace="http://queuing.webservice.jboss.org/types"
packageName="org.jboss.webservices.queuing">
<interface name="org.jboss.webservices.queuing.Interceptor"/>
</service>
</configuration>

Important points while developing the configuration descriptor:

The interface name is fully qualified class name of the service endpoint i.e. the remote interface
As a rule of thumb, I put the target namespace and type namespace in reverse order of the pakcage name of the service endpoint

5. Build the service using wscompile.bat file available in the jwsdp2-0\jaxrpc\bin folder. The command is as below:

wscompile -verbose -classpath webapp/web-services/WEB-INF/classes -gen:server -f:rpcliteral -f:unwrap -d webapp/web-services/WEB-INF/classes -nd webapp/web-services/WEB-INF/wsdl -mapping webapp/web-services/WEB-INF/interceptor_mapping.xml interceptor_config.xml

The wscompile command line arguments explanation is :

-verbose : gives the detailed console output of wscompile
-classpath : represents the folder holding classes from which the webservice needs to be generated
-d : represents the destination where the service classes need to be generated
-nd : represents the destination where all the non class need to be generated
-mapping : represents the destination where the jaxrpc mapping xml needs to be generated.

On successful execution of wscompile, you should find Interceptor Stub, TIE, Literal Serializer and Deserializer class files generated in the folder given against the -d operator. You should also have an InterceptorService.wsdl file generated in the wsdl folder under WEB-INF. Given below are the classes generated on my machine along with the wsdl and jaxrpc-mapping file.

classes generated by javac
==========================
Interceptor.class
InterceptorService.class

classes generated by wscompile
==========================
InterceptorService_SerializerRegistry.class
Interceptor_addToQueue_RequestStruct.class
Interceptor_addToQueue_RequestStruct_LiteralSerializer.class
Interceptor_addToQueue_ResponseStruct.class
Interceptor_addToQueue_ResponseStruct_LiteralSerializer.class
Interceptor_removeFromQueue_RequestStruct.class
Interceptor_removeFromQueue_RequestStruct_LiteralSerializer.class
Interceptor_removeFromQueue_ResponseStruct.class
Interceptor_removeFromQueue_ResponseStruct_LiteralSerializer.class
Interceptor_Tie.class

WSDL
====
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="InterceptorService" targetNamespace="http://queuing.webservice.jboss.org/" xmlns:tns="http://queuing.webservice.jboss.org/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:ns2="http://queuing.webservice.jboss.org/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<schema targetNamespace="http://queuing.webservice.jboss.org/types" xmlns:tns="http://queuing.webservice.jboss.org/types" xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://www.w3.org/2001/XMLSchema">
<complexType name="InterceptorRequest">
<sequence>
<element name="demuxId" type="int"/>
<element name="entryTimeInMillis" type="long"/>
<element name="soapMsg" type="string" nillable="true"/>
<element name="tcgsUrls" type="string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="InterceptorResponse">
<sequence>
<element name="result" type="string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
</schema>
</types>
<message name="Interceptor_addToQueue">
<part name="InterceptorRequest_1" type="ns2:InterceptorRequest"/>
</message>
<message name="Interceptor_addToQueueResponse">
<part name="result" type="ns2:InterceptorResponse"/>
</message>
<message name="Interceptor_removeFromQueue">
<part name="int_1" type="xsd:int"/>
</message>
<message name="Interceptor_removeFromQueueResponse">
<part name="result" type="xsd:string"/>
</message>
<portType name="Interceptor">
<operation name="addToQueue" parameterOrder="InterceptorRequest_1">
<input message="tns:Interceptor_addToQueue"/>
<output message="tns:Interceptor_addToQueueResponse"/></operation>
<operation name="removeFromQueue" parameterOrder="int_1">
<input message="tns:Interceptor_removeFromQueue"/>
<output message="tns:Interceptor_removeFromQueueResponse"/>
</operation>
</portType>
<binding name="InterceptorBinding" type="tns:Interceptor">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
<operation name="addToQueue">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal" namespace="http://queuing.webservice.jboss.org/"/></input>
<output>
<soap:body use="literal" namespace="http://queuing.webservice.jboss.org/"/></output></operation>
<operation name="removeFromQueue">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal" namespace="http://queuing.webservice.jboss.org/"/>
</input>
<output>
<soap:body use="literal" namespace="http://queuing.webservice.jboss.org/"/>
</output>
</operation>
</binding>
<service name="InterceptorService">
<port name="InterceptorPort" binding="tns:InterceptorBinding">
<soap:address location="REPLACE_WITH_ACTUAL_URL"/>
</port>
</service>
</definitions>


interceptor_mapping.xml i.e. jaxrpc mapping
===========================================
<?xml version="1.0" encoding="UTF-8"?>
<java-wsdl-mapping xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd">
<package-mapping>
<package-type>org.jboss.webservices.queuing</package-type>
<namespaceURI>http://queuing.webservice.jboss.org/types</namespaceURI>
</package-mapping>
<package-mapping>
<package-type>org.jboss.webservices.queuing</package-type>
<namespaceURI>http://queuing.webservice.jboss.org/</namespaceURI>
</package-mapping>
<java-xml-type-mapping>
<java-type>org.jboss.webservices.valueobjects.InterceptorResponse</java-type>
<root-type-qname xmlns:typeNS="http://queuing.webservice.jboss.org/types">typeNS:InterceptorResponse</root-type-qname>
<qname-scope>complexType</qname-scope>
<variable-mapping>
<java-variable-name>result</java-variable-name>
<xml-element-name>result</xml-element-name>
</variable-mapping>
</java-xml-type-mapping>
<java-xml-type-mapping>
<java-type>org.jboss.webservices.valueobjects.InterceptorRequest</java-type>
<root-type-qname xmlns:typeNS="http://queuing.webservice.jboss.org/types">typeNS:InterceptorRequest</root-type-qname>
<qname-scope>complexType</qname-scope>
<variable-mapping>
<java-variable-name>demuxId</java-variable-name>
<xml-element-name>demuxId</xml-element-name>
</variable-mapping>
<variable-mapping>
<java-variable-name>entryTimeInMillis</java-variable-name>
<xml-element-name>entryTimeInMillis</xml-element-name>
</variable-mapping>
<variable-mapping>
<java-variable-name>soapMsg</java-variable-name>
<xml-element-name>soapMsg</xml-element-name>
</variable-mapping>
<variable-mapping>
<java-variable-name>tcgsUrls</java-variable-name>
<xml-element-name>tcgsUrls</xml-element-name>
</variable-mapping>
</java-xml-type-mapping>
<service-interface-mapping>
<service-interface>org.jboss.webservices.queuing.InterceptorService</service-interface>
<wsdl-service-name xmlns:serviceNS="http://queuing.webservice.jboss.org/">serviceNS:InterceptorService</wsdl-service-name>
<port-mapping>
<port-name>InterceptorPort</port-name>
<java-port-name>InterceptorPort</java-port-name>
</port-mapping>
</service-interface-mapping>
<service-endpoint-interface-mapping>
<service-endpoint-interface>org.jboss.webservices.queuing.Interceptor</service-endpoint-interface>
<wsdl-port-type xmlns:portTypeNS="http://queuing.webservice.jboss.org/">portTypeNS:Interceptor</wsdl-port-type>
<wsdl-binding xmlns:bindingNS="http://queuing.webservice.jboss.org/">bindingNS:InterceptorBinding</wsdl-binding>
<service-endpoint-method-mapping>
<java-method-name>addToQueue</java-method-name>
<wsdl-operation>addToQueue</wsdl-operation>
<method-param-parts-mapping>
<param-position>0</param-position>
<param-type>org.jboss.webservices.valueobjects.InterceptorRequest</param-type>
<wsdl-message-mapping>
<wsdl-message xmlns:wsdlMsgNS="http://queuing.webservice.jboss.org/">wsdlMsgNS:Interceptor_addToQueue</wsdl-message>
<wsdl-message-part-name>InterceptorRequest_1</wsdl-message-part-name>
<parameter-mode>IN</parameter-mode>
</wsdl-message-mapping>
</method-param-parts-mapping>
<wsdl-return-value-mapping>
<method-return-value>org.jboss.webservices.valueobjects.InterceptorResponse</method-return-value>
<wsdl-message xmlns:wsdlMsgNS="http://queuing.webservice.jboss.org/">wsdlMsgNS:Interceptor_addToQueueResponse</wsdl-message>
<wsdl-message-part-name>result</wsdl-message-part-name>
</wsdl-return-value-mapping>
</service-endpoint-method-mapping>
<service-endpoint-method-mapping>
<java-method-name>removeFromQueue</java-method-name>
<wsdl-operation>removeFromQueue</wsdl-operation>
<method-param-parts-mapping>
<param-position>0</param-position>
<param-type>int</param-type>
<wsdl-message-mapping>
<wsdl-message xmlns:wsdlMsgNS="http://queuing.webservice.jboss.org/">wsdlMsgNS:Interceptor_removeFromQueue</wsdl-message>
<wsdl-message-part-name>int_1</wsdl-message-part-name>
<parameter-mode>IN</parameter-mode>
</wsdl-message-mapping>
</method-param-parts-mapping>
<wsdl-return-value-mapping>
<method-return-value>java.lang.String</method-return-value>
<wsdl-message xmlns:wsdlMsgNS="http://queuing.webservice.jboss.org/">wsdlMsgNS:Interceptor_removeFromQueueResponse</wsdl-message>
<wsdl-message-part-name>result</wsdl-message-part-name>
</wsdl-return-value-mapping>
</service-endpoint-method-mapping>
</service-endpoint-interface-mapping>
</java-wsdl-mapping>

6. Link the webservice and servlet through the webservice.xml. Place the webservices.xml under webapp\web-services\WEB-INF
webservices.xml
===============
<webservices xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd" version="1.1">
<webservice-description>
<webservice-description-name>InterceptorService</webservice-description-name>
<wsdl-file>WEB-INF/wsdl/InterceptorService.wsdl</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/interceptor_mapping.xml</jaxrpc-mapping-file>
<port-component>
<port-component-name xmlns:sns="http://queuing.webservice.jboss.org/">sns:Interceptor</port-component-name>
<wsdl-port xmlns:sns="http://queuing.webservice.jboss.org/">sns:InterceptorPort</wsdl-port>
<service-endpoint-interface>org.jboss.webservices.queuing.Interceptor</service-endpoint-interface>
<service-impl-bean>
<servlet-link>InterceptorService</servlet-link>
</service-impl-bean>
</port-component>
</webservice-description>
</webservices>

Important points:
  1. The webservice description name and the servlet name should match.
  2. The wsdl file name along with relative path from WEB-INF folder should be crrect
  3. The jaxrpc mapping file should point to the interceptor_mapping xml file
  4. The port component name should match the value of the portType tag's name attribute in the wsdl file
  5. The wsdl port should match the value of the port tags name attribute in the wsdl file
  6. The service endpont interface holds the fully qualified name of our remote interface
  7. The service impl bean holds a link to the servlet name.

7. The finalstructure of the webapp folder:
8. Open command prompt. Navigate inside the webapp/web-services folder. Create a war file of all contents in the web-services folder. Command for creating the war file is :
jar -cvf web-services.war *
This creates a web-services.war file. Copy the web-services war file in the %JBOSS_HOME%\server\default\deploy folder. Start jboss and check the console. You should find the following lines:


Navigate to the %JBOSS_HOME%\server\default\data\wsdl folder. You should see a web-services.war folder in there. Inside this folder, you should find the InterceptorService.wsdl file. This means that the webservice is successfully deployed. In order to consume the webservice, a manual change in the deployed wsdl is necessary. This is shortcoming of JBOSS 4.0.5 GA. Open the InterceptorService.wsdl file and go to the end where the service is defined as follows:

<service name="InterceptorService">
<port name="InterceptorPort" binding="tns:InterceptorBinding">
<soap:address location="http://pni3p103:8080/web-services/Intercept"/>
</port>
</service>

Change the port number in the URL of the location attribute of the address tag. The port number is defaulted to 8080 by JBOSS. Change this to the appropriate port number which JBOSS is listening too. In my case, I have changed it to 7001. In case the editor flags a "sharing or access violation" while saving the modified wsdl; don't panic. This means that the app server has successfully loaded the wsdl and you need not explicitly change the ports. My Jboss allowed me to change the wsdl most of the times; but I did observe this file being locked by the appserver which did not allow modification to the port number. But I was able to access the wsdl successfully though !

<service name="InterceptorService">
<port name="InterceptorPort" binding="tns:InterceptorBinding">
<soap:address location="http://pni3p103:7001/web-services/Intercept"/>
</port>
</service>

Try accessing the url by suffixing ?WSDL to it : http://pni3p103:7001/web-services/Intercept?WSDL This should render the wsdl on your internet browser. Your webservice is successfully deployed !

9. Deploy in Weblogic:
Weblogic gives us ability to deploy the folder instead of packaging it into a war file; we will use this feature. I recommend making a copy of the webapp folder so that weblogic files do not meddle with jboss files. Create a folder Weblogic and copy the webapp folder under this. Start your Weblogic server; remember to shutdown JBoss in case you have both on a single machine. I typically make all the app servers listen to the same port due to which I can have only one instance running at a time. Once the Weblogic server has started, log into the administration console. The url is http://machine-name:port-number/console Login to the application. Click on Lock and Edit button --> click on Deployments --> click on Install button. Browse to the Weblogic\webapps\web-services. Select web-services folder and deploy as an application by clicking Next and selecting all others as defaults. Finally click on the Activate changes green button. Restart Weblogic instance and login to the administration console again.

In the Deployments, you should see web-services application in the Active state. If it is in prepared state, select the web-service application and click on Start --> Start servicing all requests. Click on the plus sign beside the web-service application and it will display the InterceptorService. Now there are couple of additional steps required by Weblogic. Click on the InterceptorService --> Click on the Configuration tab --> Select View Dynamic WSL Enabled and click Save. This will bring up a Deployment Plan Assistance. Select WEB-INF radio button and click Finish. Activate the Changes and restart Weblogic instance. Try to access the URL for the WSDL. If your Jboss and Weblogic listen the same port, the URL will remain same.
10. Test from standalone client

Create a separate java project. Create an interceptor_client_config.xml file with the following entries
intercept_client_config.xml
===========================
<?xml version="1.0" encoding="UTF-8"?>
<configuration
xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<wsdl location="http://localhost:7001/web-services/Intercept?WSDL"
packageName="org.jboss.webservices.queuing"/>
</configuration>

Build client stubs using the wscompile. The command is:


wscompile -verbose -d . -gen:client intercept_client_config.xml



Create a WebservicesClient.java. Put the following code in it.
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import org.jboss.webservices.hello.Hello;
import org.jboss.webservices.hello.SayHello;
import org.jboss.webservices.queuing.Interceptor;
import org.jboss.webservices.queuing.InterceptorRequest;
import org.jboss.webservices.queuing.InterceptorResponse;


public class WebservicesClient
{
  public static void main(String[] args) throws Exception {
    addToQueue();
    removeFromQueue();
}


private static void removeFromQueue() throws Exception {
String urlstr = "http://localhost:7001/web-services/Intercept?WSDL";
System.out.println("Contacting webservice at " + urlstr);
URL url = new URL(urlstr);
QName qname = new QName("http://queuing.webservice.jboss.org/", "InterceptorService");
ServiceFactory factory = ServiceFactory.newInstance();
Service service = factory.createService(url, qname);
Interceptor intercept = ( Interceptor ) service.getPort( Interceptor.class );
System.out.println("Interceptor.removeFromQueue( 0 )");
Object o = intercept.removeFromQueue( 0 );
System.out.println( "Class ::>> " + o.getClass() );
System.out.println( "output : " + o );
}


private static void addToQueue() throws Exception {
String urlstr = "http://localhost:7001/web-services/Intercept?WSDL";
System.out.println("Contacting webservice at " + urlstr);
URL url = new URL(urlstr);
QName qname = new QName("http://queuing.webservice.jboss.org/", "InterceptorService");
ServiceFactory factory = ServiceFactory.newInstance();
Service service = factory.createService(url, qname);
Interceptor intercept = ( Interceptor ) service.getPort( Interceptor.class );
InterceptorRequest req = new InterceptorRequest();
req.setDemuxId( 1 );
req.setEntryTimeInMillis( 1000L );
req.setSoapMsg( "ameybhide soap msg" );
req.setTcgsUrls( new String[] { "a", "m", "e", "y" } );
System.out.println("Interceptor.addToQueue( " + req + " )");
Object o = intercept.addToQueue( req );
System.out.println( "Class ::>> " + o.getClass() );
InterceptorResponse res = ( InterceptorResponse )o;
System.out.println( "output ::>> [InterceptorResponse]: " );
if( res.getResult() != null && res.getResult().length > 0 ) {
System.out.println( "Elements ::>> " );
for ( int counter = 0; counter < res.getResult().length; counter++ ) {
System.out.println( res.getResult()[ counter ] );
}
} else {


System.out.println( "Empty" );
}
}
}

You will need the following jar files on your classpath before you run the above class file
- the stub classes generated as a result of the wscompile command
- jwsdp2-0/jaxrpc/lib/jaxrpc-api.jar
- jwsdp2-0/jaxrpc/lib/jaxrpc-impl.jar
- jwsdp2-0/jaxrpc/lib/jaxrpc-spi.jar
- jboss-4.0.5.GA/client/activation.jar
- jboss-4.0.5.GA/client/mail.jar
- jboss-4.0.5.GA/client/namespace.jar
- jwsdp2-0/saaj/lib/saaj-api.jar
- jwsdp2-0/saaj/lib/saaj-impl.jar
- jwsdp2-0/fastinfoset/lib/FastInfoset.jar
- jwsdp2-0/sjsxp/lib/jsr173_api.jar

Run the WebservicesClient. You should see the following output:
Contacting webservice at http://localhost:7001/web-services/Intercept?WSDL
Interceptor.addToQueue( org.jboss.webservices.queuing.InterceptorRequest@273686 )
Class ::>> class org.jboss.webservices.queuing.InterceptorResponse
output ::>> [InterceptorResponse]:

Elements ::>>
First element
Second element
Third element
Contacting webservice at http://localhost:7001/web-services/Intercept?WSDL
Interceptor.removeFromQueue( 0 )
Class ::>> class java.lang.String
output : Removed element at position 0
 
All the Best !!!

Friday, March 12, 2010

Remote Debugging with Eclipse


My eyes were glued to the monitor, fingers doing a tap dance on the F6 key periodically using F5 and F8 too. A colleague walked over to my cubicle and asked me what I was doing. After giving him a I-didn't-want-to-be-disturbed look, I told him I was debugging a server side Java code. He was surprized. He knew how to debug a stand alone Java application using Eclipse. It was as simple as running the application through the Debug mode, introducing a breakpoint and changing the perspective of Eclipse to Debug. He was not aware that we could do the same on a code getting executed inside an application server.

Simple ... I told him. The only change required is to setup a Remote Java application in Eclipse and modify the start up scripts of your application sever. Piece of cake !

We use Websphere, Weblogic and JBoss applicaiton servers the most in our projects. I have listed down steps for configuring Eclipse and these application servers for debugging your J2EE components. Hope it saves your time spent in restart, recompile, redeploy of J2EE components. Finding a problem is very easy when you have the power of debugger !

Weblogic 9.2:
  • Open the startWebLogic.cmd file present in the bin folder withing your user domain.
  • Search for text -Xrunjdwp in this cmd file. If you find one, stick to modifying it. If you don't find one, then you will need to add the following line:
         set JAVA_OPTIONS=%JAVA_OPTIONS% -Xdebug -Xrunjdwp:transport=dt_socket,address=1044,server=y,suspend=n      
  • Some advice to set the debug parameters in the DEBUG_OPTS variable. But I prefer sticking to the JAVA_OPTIONS as these are definitely put on the command for launching the weblogic application server.
  • The address=1044 tells the application server to connect the debugger over 1044 port. In case the port is in user, change it to some other port like 7002 or 9001  whichever is free.
  • The suspend=n tells the application server to continue with the startup and execution even if no debugger is attached
  • If the value of suspend attribute is changed to y i.e. suspend=y, then the application server's JVM starts in suspended mode and stays suspended till some debugger gets attached to it.
  • Start Weblogic. You should see the text highlighted in the image above on your console too.
JBoss 4.0.5 GA :
  • Open the run.bat file present in the bin directory of JBoss installation
  • Look for the following text :
         rem JPDA options. Uncomment and modify as appropriate to enable remote debugging.

         rem set JAVA_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y %JAVA_OPTS%
  • If you find it, then uncomment the set JAVA_OPTS by removing the rem keyword.
  • If you do not find the text, add the following text :
         set JAVA_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=1044,server=y,suspend=y %JAVA_OPTS%
  • The address=1044 tells the application server to connect the debugger over 1044 port. In case the port is in user, change it to some other port like 7002 or 9001 whichever is free.
  • The suspend=n tells the application server to continue with the startup and execution even if no debugger is attached.
  • If the value of suspend attribute is changed to y i.e. suspend=y, then the application server's JVM starts in suspended mode and stays suspended till some debugger gets attached to it

  • Start JBoss. You should see the text as shown in the image

Websphere 6.1.0.13:
  • Open the admin console of Websphere. This is generally https://machine-name:9043/ibm/console
  • Login using correct credentials
  • On the left navigation pane, open Servers --> Application Servers. On the right pane, click on your server name that needs to be started up in debug mode.
  • This takes you to the Configuration tab. Scroll to the botton to find a section for Additional Properties. Click on the Debugging Services link.
  • Change the JVM debug port to 1044.
  • Append the following text to the JVM debug arguments:
         -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044
  • The address=1044 tells the application server to connect the debugger over 1044 port. In case the port is in user, change it to some other port like 7002 or 9001 whichever is free
  • The suspend=n tells the application server to continue with the startup and execution even if no debugger is attached.
  • If the value of suspend attribute is changed to y i.e. suspend=y, then the application server's JVM starts in suspended mode and stays suspended till some debugger gets attached to it.
  • Click on OK button.
  • Restart the Websphere instance


Eclipse 3.3.0 :
  • Start one of the application server (Weblogic/Websphere/JBOSS)
  • Launch eclipse. Change to the Debug perspective. Open the Debug Dialog.
  • Select the Remote Java Application and Click on New Launch configuration (the button on the top left)
  • Give suitable name for this debug app ( I have given it same as application server name i.e. JBOSS)
  • Select the project which you want to debug. This could be your EJB, Webservice, Servlet etc
  • Give the hostname as the machine name where the application server is running. The port number should match the value of the address attribute set in the start up script off application server (we have provided the address in the above sections)

  • Click on apply. Then click on Debug. You should see multiple Java threads listed in the Debug perspective.


Now you can insert break points in the project and debug the J2EE components deployed in application server.

Happy debugging !

Wednesday, June 18, 2008

Persistence, Concurrency and RTTI


I got a request to write about Java tenets: Persistence, Concurrency and RTTI. My two cents ....

Persistence:
Object persistence (a.k.a Serialization in Java) is ability to read/write state of object on a stream. Persistence is useful/required in situations when object's state needs to be retained/stored across invocation of a program or when an object needs to be synchronized across JVM's. Examples of persistence are:
  1. Storing object state to a file - File input and output streams
  2. Storing object state to a database
  3. Sending/Receiving/Synchronizing object state across JVM - typically over sockets

Quoting -Carting applications generally use Persistence. A Quote object contains items that you wish to purchase from the online portal. Multiple Quote objects taken together make up a Cart object. The 'Save Cart' option actually serializes the entire Cart object into a Blob colum inside a database table. The Cart object can be reloaded from the db at a later instant to view the complete order.

This brings up two important aspects of Persistence:

  1. The entire object state is serialized to the stream (except for transient variables). Object's properties can be primitives or references to other Object's. Thus each such object also needs to be serialized. In a nutshell, serializing an object results into serialization of all objects contained in the current object till nth level.
  2. Reflections api is used to create a object by reading its state from the stream.

An object can be serialized only if it implements the marker interface 'Serializable'.

Concurrency:
Java supports MultiThreading. A Thread object is a lightweight process and multiple Threads execute concurrently in JVM. This brings up a potential problem of data corruption by simultaneous access via multiple Threads or in other words maintaining sanctity of data being accessed/mutated by various Threads. Use of synchronized keyword, wait() and notify() methods help us in solving the aforementioned issues. I will not go deep into implementation details of wait(), notify() and synchronized as these will be addressed in the Multi Threading blog.

Each object has a monitor associated with it. When a Thread comes across a synchronized method or block during its execution, it obtains the monitor on the object before entering the method or block. Only one Thread can obtain the monitor on an object. Thus in case a second Thread wants to execute another/same synchronized method/block of the same object, then it blocks till the first Thread release the previously obtained monitor.

RTTI (RunTime Type Identification):
RTTI helps us in identifying the object type at runtime as there may be a need to check the object type prior to executing a chunk of business logic. Implementing Polymorphism with interfaces to achieve extensibilty introduces use of base class reference when objects communicate with each other by sending messages. For example, consider the following hierarchy: Animal interface has implmentation classes Wild and Tame which are further extended by Lion, Tiger, Elephant, Deer, Snake, Dog, Cat etc

With appropriate OO design we will introduce api's like getNumberOfLegs in the Animal interface which will be implemented in the concrete derived classes. While passing a list of animals, each of the element in the list will be Animal reference. But what if we wanted to increment a counter for all animals that were Wild? We can add an isWild() api to Animal class and implement it in Wild and Tame classes. This will get automatically inherited into all the subclasses. The basic purpose of introducing Wild and Tame subclasses gets defeated because within Tame, we are implementing isWild() which returns false. Not a good design.

Instead, while iterating over the Animal list, we can use the instanceof operator, which is Java api for RTTI. We can check if the current element is an instance of Wild and then conditionally increment the counter. Having said this, use of instanceof operator is very heavy and affects the performance. A code having number of if .. else if .. else if ... statements involving instanceof operator suggests bad design.

Tuesday, June 17, 2008

Parameter Passing


Objects communicate with each other by sending messages. Sending a message basically means invoking one of the methods from the published contract of other object. Most of the methods will involve passing arguments back and forth between objects.

A method, in C/C++ or Java, can have only one return type, but the signature of method can have a number of arguments in it. For example, the following method declaration is valid:

public String getName( List myList, int count ) {

...
...
}

The above declaration says that the getName method accepts two parameters and returns a String. There is no syntactically legal construct that allows us to return two String objects.

C/C++ developers use a typical coding practice. The return from a method will always be an int. A return of zero indicates successful execution of the method whereas a non-zero return value indicates some error in method execution. This error code is then passed to another api to get the complete error report. A value that needs to be returned from the method is accepted as input argument itself which is subsequently modified in the method. A typical C/C++ api signature is as follows which clearly mentions input and output parameters.

/**
* This function will return all the views,
* for a given Item.
*/
extern C_API int ITEM_list_all_view_revs(

obj_o item, /** < (I) Tag of the item */
int* count, /** < (O) Number of views attached to the above Item */
obj_o** views /**< (OF) count objects of views for the Item */ );


This is where we have to be careful while passing arguments to ITEM_list_all_view_revs api. The obj_o is an input which will be read by the method to list the views. This will be pass by value. The int* count and obj_o** views will be mutated by the method. These have to be pass by reference.

Is it the same when we invoke methods in Java? Yes and No. Yes, we can pass arguments to methods and mutate the same in side the method body. No, there is no such thing as passing by reference in Java. All parameters/arguments in Java are always pass by value. Surprized?

Java does not have the concept of pointers. In case of primitives, the memory location at which the variable is defined holds the value of the variable. For example, writing int i = 5 creates a variable i at say memory location 100 which holds value 5. In case of objects, the object is created on the heap and its memory location address is stored as a value at the memory location where the reference to the object is created. For example, writing List myList = new ArrayList() creates an object of type ArrayList on the heap at say memory location 1000. A reference myList is created at a different memory location say 200 and the value stored at this memory location is 1000.

Suppose we were to call the above declared java method, the code fragment would be somthing like:


List myList = new ArrayList();
int count = 5;

ParameterPassing pp = new ParameterPassing();
pp.getName( myList, count );


Essentially what is getting passed is the value at the memory location of variables myList and count. myList is a reference to object and hence holds the address of the object created on heap whereas count is a primitive and directly holds the value. Thus in the getName method if we were to call the myList.add("xyz") method, then it will go and modify the object state on the heap. But if we do count++ within the getName method then the value is modified withing the method scope but not persisted back to the memory location where it originated from.

The crux of paramter passing in Java is as follows:
  1. Parameters/Arguments are always passed by value
  2. Objects are always mutated by reference


Another implementation detail to be kept in mind is that method invocation results into creation of local variables of the parameters passed to the method. Thus passing myList to getName method creates a local variable/reference to the ArrayList object created on the heap. Suppose in the method, we assign a different reference to the myList variable, myList = new ArrayList(), then this is valid only in the current method scope. This is because the locally created myList reference now points to a new object created on the heap.

A small program to explain the above concept:

import java.util.*;

public class ParameterPassing {

public String getName( List myList, int count ) {

myList.add("XYZ");
count++;

System.out.println(myList.get(0));
System.out.println(count);

myList = new ArrayList();

return "";
}

public static void main( String args[]) {

List myList = new ArrayList();
int count = 5;

ParameterPassing pp = new ParameterPassing();
pp.getName( myList, count );


System.out.println(myList.get(0));
System.out.println(count);
}
}

Following is the output:
XYZ
6
XYZ
5

The count in the main method holds the old value 5 because the count++ in getName method actually increments the local variable. Similarly myList = new ArrayList() points the local reference to the new object created on the heap.

Monday, June 16, 2008

OOPs ! I defined it again ....


All the interviews that I have given and conducted till date always had (and will continue to have) the usual suspect : 'Define concepts/principles of Object Oriented Programming". Most of the interviewers arrive at a fair enough conclusion about the interviewee depending upon his explanation on the aforementioned question. Before I dive into crisp definitions of each of the concept, I want to point out three important entities often misunderstood or misquoted or misconceived while reading books.

C&C (common and crap) answers:
"An Object is an instance of a class ..... Class is from which objects are created/derived". Practically i.e. looking from coding point of view it is a correct definition, but unfortunately doesn't explain much about the exact use of object and class. To put it in layman terms "X equals Y and Y equals X". When one gets to designing an application, this definition will not help.

"An interface is Java's solution to support multiple inheritance". Agreed, but that is use of interface and not the definition.

C&C answers again (this time crisp and correct) :
Object: An object is an entity that has the following four characteristics, viz: Identity, State, Behaviour and Properties

Class: A class provides an Identity to the object and models the state, behaviour and properties of the object. A class defines a skeleton for objects and acts as a blueprint from which object can be created.

Interface: Interface is a contract between a class and the outside world. The behaviour of an object i.e. the methods form the object's interface to outside world. By implementing an interface, a class promises to provide the behaviour published by the Interface. Interfaces help in extensibility.

The four Object Oriented Principles:

Inheritance: Mechanism to structure and organize our software. Provides an ability to a sub-calss to inherit the properties, state and behaviour of the base class. Inheritance enables us to define a more general class and derive specialized classes from it. This helps in better data analysis.

Encapsulation: Separating object's interface from its implementation. Hiding object data and allowing modification of object data by publishing method. Controlling the access to data and methods that manipulate the data using access modifiers.

Polymorphism: The ability of a reference of a base class to denote an object of its own class or any of its subclasses at runtime. This is a definition that many of you might be reading for the first time. The common definitions being "one name many forms" or "method overloading and overriding". But on deeper introspection, the above is possible when a reference of a base class can denote different objects at runtime. The only exeception being method overloading as this is compile time polymorphism i.e. which method will be executed can be determined at compile time itself.

Abstraction: Simplifying complexities by seggregating/breaking them into smaller units and modelling a structure/heirarchy chain by abstracting common behaviour into classes.

All the OOP principals work hand-in-hand. It is very difficult to write a code that just implements the Abstraction principal and so forth.

I hope you have a better perspective of the principles now. I will write more in the blogs-to-come. Till then ... happy digestion.

Friday, June 13, 2008

Hello Primitives


Java is not 100% object oriented because of two main constraints:

  1. int, float, char etc are primitives and not objects
  2. Multiple inheritance not supported.

Java has an answer/solution to the above mentioned constraints. Wrapper classes are provided which allow us to create an object even when dealing with simple numbers. Thus instead of using int, we can create an object of type Integer or a Float object instead of float primitive. Java's answer to multiple inheritance is Interfaces; a class can implement more than one interfaces.

Even with these solutions/workarounds, the main reason behind Java not being purely object oriented is that we can still write a Java program with the use of primitives. This introduces use of an entity that is not an object, which violates the principle of object oriented program. Java allows the use of primitives for performance reasons. If it weren't for primitives, our mundane loops would have caused a catastrophe. A simple program to illustrate the Power of Primitives:


import java.util.Calendar;

public class HelloPrimitives {

public static void main(String args[]) {

//Nested loops using primitives
long lTimeInMillis = Calendar.getInstance().getTimeInMillis();
int i = 0;
int j = 0;

for( int counter = 0; counter < 1000; counter++ ) {

for( int innerCounter = 0; innerCounter < 3000; innerCounter++ ) {

j = innerCounter;
}

i = counter;
}

lTimeInMillis = Calendar.getInstance().getTimeInMillis() - lTimeInMillis;

//Nested loops using wrapper classes
Long oTimeInMillis = new Long( Calendar.getInstance().getTimeInMillis( ) );
Integer objI = null;
Integer objJ = null;
Integer objCounter = new Integer( 0 );

for( ; objCounter.intValue() < 1000; ) {

Integer integerInnerCounter = new Integer( 0 );

for( ; objInnerCounter.intValue() < 3000; ) {

objJ = new Integer( objInnerCounter.intValue() );
objInnerCounter = new Integer( objInnerCounter.intValue() + 1 );
}

objI = new Integer( objCounter.intValue() );
objCounter = new Integer( objCounter.intValue() + 1 );
}

oTimeInMillis = new Long( Calendar.getInstance().getTimeInMillis() - oTimeInMillis.longValue() );

System.out.println( "Time taken by primitives = " + lTimeInMillis );
System.out.println( "Time taken by wrapper classes = " + oTimeInMillis.longValue() );

}
}

The following output is observed on my machine (numbers are machine specific):
D:\amey\blogs\java\progs\hello_primitives>java HelloPrimitives
Time taken by primitives = 15
Time taken by wrapper classes = 1219


It can be seen that use of primitives improves the performance significantly. Stark reasons for this are

  1. Memory allocation for a primitive and object is very different. For primitive datatype, the value is directly stored at the memory address of the reference. Whereas objects are created on heap, and the memory location of the reference holds the memory location of the object on the heap.
  2. The values can be directly accessed in case of primitives while for objects, we need to invoke a method using the dot ',' operator. This calls for pushing the current method on the stack and popping it back at later instance which is time consuming.

One more tip for increasing performance is controlling number of times a primitive or object gets created. In the above program, we are creating innerCounter and objInnerCounter within the inner loop. Try initializing them just once above the outermost for loop and see the difference in timings.

Also increase the inner loop to 30,000.

int innerCounter = 0; //initialize only once
for( int counter = 0; counter < 1000; counter++ ) {
for( ; innerCounter < 30000; ) {
.....
.....
}


.....
.....
Integer objCounter = new Integer( 0 );
Integer objInnerCounter = new Integer( 0 ); //initialize only once
for( ; objCounter.intValue() < 1000; ) {



for( ; objInnerCounter.intValue() < 30000; ) {
.....
.....
}
}
The output on my machine is:
D:\amey\blogs\java\progs\hello_primitives>java HelloPrimitives
Time taken by primitives = 0
Time taken by wrapper classes = 16

Wow !

Cheers,
Amey