JAX-WS client for WSO2 Admin service.

In my previous blog post, we understood about Admin services in WSO2 products. We have implemented a web service client for RemoteUserStoreManagerService. We used Axis2 client for that. Today, we are going to look, how we can implement a JAX-WS cleint for invoking admin services.

I am using the RemoteUserStoreManagerService as sample admin service.

Step 1. Generating stub class using wsimport

>wsimport

Due to issue of java2wsdl tool which is used in the WSO2 severs, generated WSDL file does not contain output message element for void return types with faults. Therefore wsimport would be failed with errors. However, you can modify the WSDL and use wsimport command to generated the stubs.  Basically we need to consider the these operations as two way operations as they are returning an application level exceptions.

How to modify the WSDL ?

1. Download the original WSDL by pointing to correct url of the server

2. Update it by adding <output> element if element is not presented under the <operation>.  You must do to it for all the operations elements which contains a <fault>

As an example,  “addUser” operation of the default WSDL would be as follows

<wsdl:operation name="addUser">
<wsdl:input message="ns:addUserRequest" wsaw:Action="urn:addUser"/>
<wsdl:fault message="ns:RemoteUserStoreManagerServiceUserStoreException" name="RemoteUserStoreManagerServiceUserStoreException" wsaw:Action="urn:addUserRemoteUserStoreManagerServiceUserStoreException"/>
</wsdl:operation>

You can modify it by adding output element… Just add following

<wsdl:output message="ns:addUserRequest" wsaw:Action="urn:addUserResponse"/>

Then complete element would be as follows.

<wsdl:operation name="addUser">
<wsdl:input message="ns:addUserRequest" wsaw:Action="urn:addUser"/>
<wsdl:output message="ns:addUserRequest" wsaw:Action="urn:addUserResponse"/>
<wsdl:fault message="ns:RemoteUserStoreManagerServiceUserStoreException" name="RemoteUserStoreManagerServiceUserStoreException" wsaw:Action="urn:addUserRemoteUserStoreManagerServiceUserStoreException"/>
</wsdl:operation>

Also, you need to configure following element as well.

<wsdl:operation name="addUser">
<soap12:operation soapAction="urn:addUser" style="document"></soap12:operation>
<wsdl:input>
<soap12:body use="literal"></soap12:body>
</wsdl:input>
<wsdl:fault name="RemoteUserStoreManagerServiceUserStoreException">
<soap12:fault use="literal" name="RemoteUserStoreManagerServiceUserStoreException"></soap12:fault>
</wsdl:fault>
</wsdl:operation>

You can modify it by adding output element… Just add following

<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>

Then complete element would be as follows.

<wsdl:operation name="addUser">
<soap:operation soapAction="urn:addUser" style="document"></soap:operation>
<wsdl:input>
<soap:body use="literal"></soap:body>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="RemoteUserStoreManagerServiceUserStoreException">
<soap:fault use="literal" name="RemoteUserStoreManagerServiceUserStoreException"></soap:fault>
</wsdl:fault>
</wsdl:operation>

You no need to much worry about the content of the <output> element, as we are just adding it for code generation purpose.

You can find the updated WSDL from here

Step 2. Create a jar file using generated stub class. I just used the jar command for it. You can find the created jar file from here.

 >jar cvf remote-user-mgt-stub.jar *

Step 3. Create your java project by adding above stub jar file in to the class path

Sample java client side code for listuser() operation would be as following.

//set the trust store which contains the WSO2IS server's certificate
System.setProperty("javax.net.ssl.trustStore", "/home/asela/is/wso2is-5.0.0/repository/resources/security/client-truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
RemoteUserStoreManagerService managerService = new RemoteUserStoreManagerService();
RemoteUserStoreManagerServicePortType portType = managerService.getRemoteUserStoreManagerServiceHttpSoap11Endpoint();
BindingProvider bindingProvider = (BindingProvider) portType;
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://localhost:9443/services/RemoteUserStoreManagerService");
bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "admin");
bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "admin");
try {
List<String> users = portType.listUsers("*", 100);
for(String user: users){
System.out.println("User : " + user);
}
} catch (RemoteUserStoreManagerServiceUserStoreException_Exception e) {
e.printStackTrace();
}

Step 4 (Optional). If you check the code generation class, you will see JAXBElement elements which make difficult to implement the client side code . Therefore, when you are code generating, you can ignore the JAXBElement element as follows.

1. Please create binding file as follows

<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings generateElementProperty="false">
<xjc:simple />
</jaxb:globalBindings>
</jaxb:bindings>

2. Run wsimport by pointing to the binding file.

>wsimport -b simple-binding.xml

Thanks for reading.!!!