Spring Framework – Accessing web services using JAX-RPC (with Authentication)

In my previous post, I never mention about authentication. So, based on what I did in last post, I will show you how to provide the username and password from client.

You only need to put 2 extra properties in applicationContext.xml of your client.


<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
 "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
 <bean id="myService">
 <property name="serviceInterface" value="com.client.ImsWebservice.JaxRpcMyService" />
 <property name="wsdlDocumentUrl" value="http://localhost:8080/test/webservice/MyService?wsdl" />
 <property name="namespaceUri" value="http://ImsWebservice/" />
 <property name="serviceName" value="JaxRpcMyServiceService" />
 <property name="portName" value="MyService" />
 <property name="servicePostProcessors">
 <list>
 <bean/>
 </list>
 </property>
 <!-- two properties added for authentication: -->
 <property name="username" value="wsuser"/>
 <property name="password" value="wspwd"/>
 </bean>
</beans>

Done!

-HADZRUL-

Spring Framework – Exposing servlet-based web services using JAX-RPC (with Authentication)

In my previous post, I never mention about authentication. Here, I will show you how to do a simple authentication provided by Axis.

In our server-config.wsdd, we had initialized 1 handler called “Authenticate”. We will use this handler for our web services.

First, you need to add <requestFlow> to your service in server-config.wsdd.

<service name="MyService" provider="java:RPC">
<parameter name="allowedMethods" value="*" />
<parameter name="className" value="com.JaxRpcMyService" />
<beanMapping qname="imsWs:MyResponse" xmlns:imsWs="urn:ImsWebservice" languageSpecificType="java:com.MyResponse" />
<namespace>http://ImsWebservice/</namespace>
<requestFlow>
<handler type="Authenticate" />
</requestFlow>
</service>

Then, you need to create 1 file named as “user.lst” that will contain your username and password. Place this file in WEB-INF folder.


username  password

That’s it!

- HADZRUL -

Spring Framework – Accessing web services using JAX-RPC

Let’s say you have a Spring web application and you need to access another system via web services. Mostly, you will be provided with WSDL (either file or URL).

First, you need to generate all the java classes from WSDL. You can follow THIS tutorial on how to generate them.

After all the java classes are ready, compile it and put in a jar. Or you can put the source code directly inside your source folder.

Then, you need to create a class that implement JaxRpcServicePostProcessor. Below is my example of this class.

//BeanMappingServicePostProcessor.java

import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.encoding.TypeMapping;
import javax.xml.rpc.encoding.TypeMappingRegistry;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.springframework.remoting.jaxrpc.JaxRpcServicePostProcessor;
import com.client.ImsWebservice.MyResponse;

public class BeanMappingServicePostProcessor implements JaxRpcServicePostProcessor {

 public static final String DEFAULT_ENCODING_STYLE_URI = "http://schemas.xmlsoap.org/soap/encoding/";
 public static final String DEFAULT_TYPE_NAMESPACE_URI = "urn:ImsWebservice";
 private String encodingStyleUri = DEFAULT_ENCODING_STYLE_URI;
 private String typeNamespaceUri = DEFAULT_TYPE_NAMESPACE_URI;

 public void setEncodingStyleUri(String encodingStyleUri) {
     this.encodingStyleUri = encodingStyleUri;
 }

 public void setTypeNamespaceUri(String typeNamespaceUri) {
     this.typeNamespaceUri = typeNamespaceUri;
 }

 public void postProcessJaxRpcService(Service service) {
     TypeMappingRegistry registry = service.getTypeMappingRegistry();
     TypeMapping mapping = registry.createTypeMapping();
     registerBeanMapping(mapping, MyResponse.class, "MyResponse");
     registry.register(this.encodingStyleUri, mapping);
 }

 protected void registerBeanMapping(TypeMapping mapping, Class type, String name) {
     QName xmlType = new QName(this.typeNamespaceUri, name);
     mapping.register(type, xmlType,
     new BeanSerializerFactory(type, xmlType),
     new BeanDeserializerFactory(type, xmlType));
 }
}

Inside this class, you need to register all the beans from WSDL (see line 30). Based on my previous TUTORIAL, I only have 1 bean to map that called “MyResponse”.

How to configure the web services? It’s easy. Inside your applicationContext.xml, you need to put all the settings. Below is my example.

 <bean id="myService">
     <property name="serviceInterface" value="com.client.ImsWebservice.JaxRpcMyService" />
     <property name="wsdlDocumentUrl" value="http://localhost:8080/test/webservice/MyService?wsdl" />
     <property name="namespaceUri" value="http://ImsWebservice/" />
     <property name="serviceName" value="JaxRpcMyServiceService" />
     <property name="portName" value="MyService" />
     <property name="servicePostProcessors">
       <list>
         <bean class="com.client.BeanMappingServicePostProcessor"/>
       </list>
     </property>
 </bean>

Done! Now you can test your client. You can do a simple class with a main method to test it. For example:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.client.ImsWebservice.JaxRpcMyService;
import com.client.ImsWebservice.MyResponse;

public class Client {
  public static void main(String[] args) {
     ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/client/clientContext.xml");
     try {
         JaxRpcMyService myService = (JaxRpcMyService)applicationContext.getBean("myService");
         MyResponse response = myService.getInfo("Hello World!");

         if(response != null){
             System.out.println("Response code: " + response.getCode());
             System.out.println("Response message: " + response.getMessage());
         }
     } catch (Exception e) {
         e.printStackTrace();
     }
  }
}

Thank you.

-HADZRUL-

How to generate java class from WSDL using Axis2

If you Google about this, most of the results will guide you to use Ant script. Here, I will show you how to generate java class using batch file (I’m using Windows to execute this). First, you need all necessary libs from Axis2. Download it and put in a folder.

Then, create your first batch file. For example, axis-cp.bat. Set the path to your lib folder (that contains all the Axis2 libs) and the path of your java folder.

SET lib=C:\sample\lib
SET AXIS=%lib%\EXML-PLUS.jar;%lib%\axis.jar;%lib%\commons-discovery.jar;%lib%\commons-logging.jar;%lib%\jaxrpc.jar;%lib%\log4j.jar;%lib%\saaj.jar;%lib%\wsdl4j.jar;%lib%\xml-apis.jar;%lib%\xercesImpl.jar
SET JAVA_HOME=C:\Progra~1\Java\jdk1.5.0_09

Next, create your second batch file. For example, wsdl2java.bat. You will write a command to generate java class from WSDL. Put in a valid URL of your WSDL.

call axis-cp.bat

%JAVA_HOME%\bin\java -cp %AXIS% org.apache.axis.wsdl.WSDL2Java -o src -v -a -d Session http://localhost:8080/test/webservice/MyService?wsdl

pause

Now, you are able to run wsdl2java.bat by double-click it.

You can download my example HERE

Spring Framework – Exposing servlet-based web services using JAX-RPC

Let’s say you have a service in your Spring web application and this service need to be accessible via web services. So, how to expose your service? In this post, I will show you how to expose a servlet-based web services using JAX-RPC.

As an example, below is our service that need to be exposed. We will use a simple service that have a method to return the response as an object (MyResponse).

// MyService.java

public interface MyService {
 public MyResponse getInfo(String value);
}
// MyServiceImpl.java

public class MyServiceImpl implements MyService{
 public MyResponse getInfo(String value) {
 return new MyResponse("1", value);
 }
}

Based on Spring Reference, Spring provides a convenience base class for JAX-RPC servlet endpoint implementations, which is ServletEndpointSupport. So, to expose our service, we need to create a class that will extend Spring’s ServletEndpointSupport class and implement our business logic inside, usually delegating the call to the business layer (which means our implementation class).

// JaxRpcMyService.java
import org.springframework.remoting.jaxrpc.ServletEndpointSupport;

public class JaxRpcMyService extends ServletEndpointSupport implements MyService{

 private MyService myService;

 protected void onInit() {
 this.myService = (MyService) getWebApplicationContext().getBean("myService");
 }

 public MyResponse getInfo(String value) {
 return myService.getInfo(value);
 }
}

Take note that inside this JaxRpcMyService class, we have 1 delegate method; getInfo( ). This is the only class that we need to expose our service. Simple right?

Ok, now let’s move to configurations. First, you need to add AxisServlet in your web.xml.

<servlet>
 <servlet-name>axis</servlet-name>
 <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
 <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
 <servlet-name>axis</servlet-name>
 <url-pattern>/webservice/*</url-pattern>
</servlet-mapping>

Then, you need to have a configuration for Axis (server-config.wsdd) to setup the endpoint. Take a look at <service name=”MyService”>. You need to define your className, beanMapping for all your related beans and namespace (optional). That is the configuration for your service. If you want to know more about Axis configuration, you can refer on Axis website.

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
 xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 <globalConfiguration>
 <parameter name="adminPassword" value="admin" />
 <parameter name="sendXsiTypes" value="true" />
 <parameter name="sendMultiRefs" value="true" />
 <parameter name="sendXMLDeclaration" value="true" />
 <parameter name="axis.sendMinimizedElements" value="true" />
 <requestFlow>
 <handler type="java:org.apache.axis.handlers.JWSHandler">
 <parameter name="scope" value="session" />
 </handler>
 <handler type="java:org.apache.axis.handlers.JWSHandler">
 <parameter name="scope" value="request" />
 <parameter name="extension" value=".jwr" />
 </handler>
 </requestFlow>
 </globalConfiguration>
 <handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" />
 <handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder" />
 <handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper" />
 <service name="AdminService" provider="java:MSG">
 <parameter name="allowedMethods" value="AdminService" />
 <parameter name="enableRemoteAdmin" value="false" />
 <parameter name="className" value="org.apache.axis.utils.Admin" />
 <namespace>http://xml.apache.org/axis/wsdd/</namespace>
 </service>

 <service name="MyService" provider="java:RPC">
 <parameter name="allowedMethods" value="*" />
 <parameter name="className" value="JaxRpcMyService" />
 <beanMapping qname="imsWs:MyResponse" xmlns:imsWs="urn:ImsWebservice" languageSpecificType="java:MyResponse" />
 <namespace>http://ImsWebservice/</namespace>
 </service>

 <service name="Version" provider="java:RPC">
 <parameter name="allowedMethods" value="getVersion" />
 <parameter name="className" value="org.apache.axis.Version" />
 </service>
 <transport name="http">
 <requestFlow>
 <handler type="URLMapper" />
 <handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler" />
 </requestFlow>
 </transport>
 <transport name="local">
 <responseFlow>
 <handler type="LocalResponder" />
 </responseFlow>
 </transport>
</deployment>

By this point, you had setup everything you need for your web service. You can run your web application and go to

http://localhost:8080/<context_name>/webservice/MyService?wsdl to see the wsdl.

Thank you.

-HADZRUL-