Archive for jax-rpc

Revist Axis 1.4

We have a legacy Axis1 1.4 (not the Axis2 1.4) web services implementation and it's causing interoperability issues. So we need a revisit :(

Overview
-It's a SOAP-RPC implementation and implements jaxrpc.jar and saaj.jar (SOAP with attachment API)
-Implemented as a chain of message handlers
-Defaults to RPC/Encoded (SOAP section 5 encoding rules) so NOT WS-I compliant?!
-Architecture guide is here
-It's compiled in axis.jar file

Install
-Download and unzip Axis 1.4 (axis-bin-1_4.zip)
-Download and install Tomcat (I used apache-tomcat-4.1.39.zip)
-Copy the axis directory from axis distribution's webapps directory into Tomcat's webapps directory
-Start Tomcat
-Point browser to http://127.0.0.1:8080/axis/ (should see the Axis welcome page)
-Click Validation link (should see no errors)
-Test a SOAP endpoint: http://localhost:8080/axis/services/Version?method=getVersion
-Test a JWS endpoint: http://localhost:8080/axis/EchoHeaders.jws?method=list

Deploy Stock Sample Web Services
-Create a deploy.bat file in sample directory (i.e. samples/stock):

set AXIS_HOME=C:\jml\sw\org\apache\axis\axis-1_4
set AXIS_LIB=%AXIS_HOME%\lib
set AXISCLASSPATH=%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery-0.2.jar;%AXIS_LIB%\commons-logging-1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar;%AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar;%AXIS_LIB%\wsdl4j-1.5.1.jar
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient -lhttp://localhost:8080/axis/services/AdminService deploy.wsdd

-Run deploy.bat to deploy
-Restart Tomcat

WSDD

 
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <!-- define the logging handler configuration -->
 <handler name="track" type="java:samples.userguide.example4.LogHandler">
<parameter name="filename" value="MyService.log"/>
 </handler>
 
 <!-- define the service, using the log handler we just defined -->
 <service name="LogTestService" provider="java:RPC">
  <requestFlow>
   <handler type="track"/>
  </requestFlow>
<parameter name="className" value="samples.userguide.example4.Service"/>
<parameter name="allowedMethods" value="*"/>
 </service>
</deployment>
 

Test Stock Sample Web Services
-Create a test script in the %AXIS_HOME% directory

set AXIS_HOME=C:\jml\sw\org\apache\axis\axis-1_4
set AXIS_LIB=%AXIS_HOME%\lib
set AXISCLASSPATH=%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery-0.2.jar;%AXIS_LIB%\commons-logging-1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar;%AXIS_LIB%\wsdl4j-1.5.1.jar
java -cp .;%AXISCLASSPATH% samples.stock.GetQuote -lhttp://localhost:8080/axis/servlet/AxisServlet -uuser2 XXX
 
#!/bin/ksh
export AXIS_LIB=$AXIS_HOME/lib
echo $AXIS_LIB
export AXISCLASSPATH=$AXIS_LIB/axis.jar:$AXIS_LIB/commons-discovery-0.2.jar:$AXIS_LIB/commons-logging-1.0.4.jar:$AXIS_LIB/jaxrpc.jar:$AXIS_LIB/saaj.jar:$AXIS_LIB/log4j-1.2.8.jar:$AXIS_LIB/xml-apis.jar:$AXIS_LIB/xercesImpl.jar:$AXIS_LIB/wsdl4j-1.5.1.jar
echo $AXISCLASSPATH
$JAVA_HOME/bin/java -cp $AXISCLASSPATH org.apache.axis.client.AdminClient -lhttp://localhost:9980/axis/services/AdminService deploy.wsdd

-Run it. Should get "XXX: 55.25"
-Alternatively, use SoapUI to test
*WSDL URL: http://localhost:8080/axis/services/urn:xmltoday-delayed-quotes?wsdl

Test Stock Sample Web Services Using Java Code

public void testVersion() throws ServiceException, AxisFault{
  String endpoint = "http://localhost:8888/axis/services/Version";
  Service service = new Service();
  Call call = (Call)service.createCall();
 
  call.setTargetEndpointAddress(endpoint);
 
  String result = (String)call.invoke("getVersion", null);
  System.out.println(result);
}
 
public void testStockGetQuote() throws ServiceException, AxisFault{
  String endpoint = "http://localhost:8888/axis/services/urn:xmltoday-delayed-quotes";
  Service service = new Service();
  Call call = (Call)service.createCall();
 
  call.setTargetEndpointAddress(endpoint);
  call.setUsername("user1");
  call.setPassword("pass1");
 
  String result = (String)call.invoke("test", null);
  System.out.println(result);
 
  Float quote = (Float)call.invoke("getQuote", new Object[]{"XXX"});
  System.out.println(quote);
}

WSDL2Java
-wsdl2java command options
-Sample client-side generation commands

@echo off
set JAVA_CMD="%JAVA_HOME%\bin\java"
set AXIS_HOME=C:\jml\sw\org\apache\axis\axis-1_4
set JAVA_OPTIONS=-Djava.ext.dirs=%AXIS_HOME%\lib\
set CLASS_PATH=.

%JAVA_CMD% %JAVA_OPTIONS% -cp %CLASS_PATH% org.apache.axis.wsdl.WSDL2Java stock.wsdl

-Generated client side classes
+For each entry in the type section
*A java class
*A holder if this type is used as an inout/out parameter
+For each portType
*A java interface
+For each binding
*A stub class
+For each service
*A service interface
*A service implementation (the locator)
-Test code

 
public void testStockGetQuote2() throws ServiceException, RemoteException{
  StockQuoteServiceService service = new StockQuoteServiceServiceLocator();
  StockQuoteService port = service.getGetQuote();
  ((org.apache.axis.client.Stub) port).setUsername("user1");
  ((org.apache.axis.client.Stub) port).setPassword("pass1");
 
  String test = port.test();
  System.out.println(test);
 
  float quote = port.getQuote("XXX");
  System.out.println(quote);
}

-Server side binding with option "--server-side --skeletonDeploy true" or "-s -S true"
%JAVA_CMD% %JAVA_OPTIONS% org.apache.axis.wsdl.WSDL2Java -s -S true stock.wsdl
-Generated server side classes
+For each binding
*A skeleton class
*An implementation template class
+For all services
*One deploy.wsdd file
*One undeploy.wsdd file

Java2WSDL
-Create WSDL from Java interface
-From Java Interface

 
package java2wsdl;
 
public interface WidgetPrice {
	String getWidgetPrice(String widgetName);
	void setWidgetPrice(String widgetName, String widgetPrice);
}
 

-Command

@echo off
echo JAVA_HOME: %JAVA_HOME%
set JAVA_CMD="%JAVA_HOME%\bin\java"
rem set JAVAC_CMD="%JAVA_HOME%\bin\javac"

rem setting up axis1 env...
set AXIS_HOME=C:\jml\sw\org\apache\axis\axis-1_4

set JAVA_OPTIONS=-Djava.ext.dirs=%AXIS_HOME%\lib\
echo JAVA_OPTIONS: %JAVA_OPTIONS%

set CLASS_PATH=..\..\bin

%JAVA_CMD% %JAVA_OPTIONS% -cp %CLASS_PATH% org.apache.axis.wsdl.Java2WSDL -o widget.wsdl -l"http://localhost:8080/axis/services/WidgetPrice" -n"urn:WidgetPrice" -p"widget" "urn:WidgetPrice" widget.WidgetPrice

-Got

 
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:WidgetPrice" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="urn:WidgetPrice" xmlns:intf="urn:WidgetPrice" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)-->
   <wsdl:message name="setWidgetPriceRequest">
      <wsdl:part name="in0" type="soapenc:string"/>
      <wsdl:part name="in1" type="soapenc:string"/>
   </wsdl:message>
   <wsdl:message name="getWidgetPriceResponse">
      <wsdl:part name="getWidgetPriceReturn" type="soapenc:string"/>
   </wsdl:message>
   <wsdl:message name="setWidgetPriceResponse">
   </wsdl:message>
   <wsdl:message name="getWidgetPriceRequest">
      <wsdl:part name="in0" type="soapenc:string"/>
   </wsdl:message>
   <wsdl:portType name="WidgetPrice">
      <wsdl:operation name="getWidgetPrice" parameterOrder="in0">
         <wsdl:input message="impl:getWidgetPriceRequest" name="getWidgetPriceRequest"/>
         <wsdl:output message="impl:getWidgetPriceResponse" name="getWidgetPriceResponse"/>
      </wsdl:operation>
      <wsdl:operation name="setWidgetPrice" parameterOrder="in0 in1">
         <wsdl:input message="impl:setWidgetPriceRequest" name="setWidgetPriceRequest"/>
         <wsdl:output message="impl:setWidgetPriceResponse" name="setWidgetPriceResponse"/>
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="WidgetPriceSoapBinding" type="impl:WidgetPrice">
      <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name="getWidgetPrice">
         <wsdlsoap:operation soapAction=""/>
         <wsdl:input name="getWidgetPriceRequest">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:WidgetPrice" use="encoded"/>
         </wsdl:input>
         <wsdl:output name="getWidgetPriceResponse">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:WidgetPrice" use="encoded"/>
         </wsdl:output>
      </wsdl:operation>
      <wsdl:operation name="setWidgetPrice">
         <wsdlsoap:operation soapAction=""/>
         <wsdl:input name="setWidgetPriceRequest">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:WidgetPrice" use="encoded"/>
         </wsdl:input>
         <wsdl:output name="setWidgetPriceResponse">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:WidgetPrice" use="encoded"/>
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="WidgetPriceService">
      <wsdl:port binding="impl:WidgetPriceSoapBinding" name="WidgetPrice">
         <wsdlsoap:address location="http://localhost:8080/axis/services/WidgetPrice"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

-Now generate server side binding classes

@echo off
echo JAVA_HOME: %JAVA_HOME%
set JAVA_CMD="%JAVA_HOME%\bin\java"
set AXIS_HOME=C:\jml\sw\org\apache\axis\axis-1_4
set JAVA_OPTIONS=-Djava.ext.dirs=%AXIS_HOME%\lib\
echo JAVA_OPTIONS: %JAVA_OPTIONS%
set CLASS_PATH=.

%JAVA_CMD% %JAVA_OPTIONS% -cp %CLASS_PATH% org.apache.axis.wsdl.WSDL2Java -o . -d session -s -S true -Nurn:WidgetPrice widget.wsdl2java widget.wsdl

-Implement/fill in "WidgetPriceSoapBindingImpl" class
-Compile widget package and copy to Tomcat webapps\axis\WEB-INF\classes
-Ran deploy

set AXIS_HOME=C:\jml\sw\org\apache\axis\axis-1_4
set AXIS_LIB=%AXIS_HOME%\lib
set AXISCLASSPATH=%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery-0.2.jar;%AXIS_LIB%\commons-logging-1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar;%AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar;%AXIS_LIB%\wsdl4j-1.5.1.jar
rem java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient -lhttp://localhost:8080/axis/services/AdminService deploy.wsdd
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient -lhttp://localhost:8080/axis/services/AdminService undeploy.wsdd

-Restart Tomcat
-Test service

 
	public void testGetWidgetPrice() throws ServiceException, AxisFault{
		String endpoint = "http://localhost:8888/axis/services/WidgetPrice";
		Service service = new Service();
		Call call = (Call)service.createCall();
 
		call.setTargetEndpointAddress(endpoint);
 
		String result = (String)call.invoke("getWidgetPrice", null);
		System.out.println(result);
	}

Remote Administration
Note that by default, the Axis server is configured to only accept administration requests from the machine on which it resides - if you wish to enable remote administration, you must set the "enableRemoteAdmin" property of the AdminService to true. To do this, find the "server-config.wsdd" file in your webapp's WEB-INF directory. In it, you'll see a deployment for the AdminService. Add an option as follows:

 
<service name="AdminService" provider="java:MSG">
<parameter name="className" value="org.apache.axis.util.Admin"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="enableRemoteAdmin" value="true"/>
</service>
 

JAX-WS RI 2.1/JAXB vs AXIS2/XMLBean

JAX-WS RI 2.1 benchmark details

Axis2

Deploy Axis2 into Tomcat
Download Axis2 standard binary distribution (axis2-1.4.1-bin.zip) from here

Download and install Ant (apache-ant-1.7.0-bin.zip) if it was not already installed

Create Axis2 war file

axis2-1.4.1\webapp>ant create.war

Generated: axis2-1.4.1\dist\axis2.war

Copy axis2-1.4.1\dist\axis2.war into the tomcat\webapps directory

Axis2 Home Page
URL: http://localhost:8080/axis2
Default admin login: admin/axis
Change admin user/pass: axis2.xml

Quick Start: StockQuoteService

Generate service

C:\Program Files\axis2-1.4.1\samples\quickstart>ant

Generated build\StockQuoteService.aar with the structure

META-INF\services.xml
samples\quickstart\service\pojo\StockQuoteService.class

services.xml:

 
<service name="StockQuoteService" scope="application" targetNamespace="http://quickstart.samples/">
    <description>
        Stock Quote Service
    </description>
    <messageReceivers>
        <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
                         class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
        <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                         class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
    </messageReceivers>
    <schema schemaNamespace="http://quickstart.samples/xsd"/>
<parameter name="ServiceClass">samples.quickstart.service.pojo.StockQuoteService</parameter>
</service>

Copy StockQuoteService.aar to C:\Program Files\apache-tomcat-5.5.27\webapps\axis2\WEB-INF\services

Creating Clients

Client generating methods
ADB (Axis databinding framework): simple but limited schema bindings. XML-->Java binding only.
XMLBeans: full schema binding support but more complex. XML-->Java binding only.
JiBX: full schema binding support, easy to use, two way XML <--> Java binding support. Can be complicated to setup.

I tried XMLBeans method and generated all Java classes but stumbled when creating client to communicate with web services. It doesn't seem intuitive at all on how to use the generated classes. I'm putting Axis2 on the back burner for now and favor JAX-WS reference implementation (Metro). Here is an interesting post lauding the Metro.