Friday, May 10, 2013

JAX WS client call web services with WS-security name token - java command line version

I have an OSB proxy service running on http://localhost:8011/OWSM_Demo/fooPS?wsdl with WS name token security policy enabled. I need to call the service with the proper security header from Java.There are two scenarios: 1. call from command line Java app 2. call from Weblogic web app.

This post covers the command line verion. Web app version will be covered in the next post.

I followed this link: http://middlewaremagic.com/weblogic/?p=18. I first made the sample works as-is. I literrally followed the instructions with variations of my local environment. I have the SOA suite installed locally, i tested adminServer as well as the osb_server1 server. Here is what I did for osb_server1:
  1. In build.xml file, I just changed the weblogic/password, then changed following line for the server:<property name="wls.server.name" value="osb_server1"/> and http://localhost:8011/SecureHelloWorldImpl/SecureHelloWorldService?WSDL
  2. I ran setDomainEnv.cmd under C:\Oracle\Middleware\user_projects\domains\soa_domain\bin
  3. Then I just ran "ant" (the default target is "all").
The default target "all" compiles and deploys a sample web service to the weblogic server (AdminServer or osb_server1). Then generates the client stubs and finally compiles client code and runs the client.

The default build process first creates a web service with WSS name token security policy enabled. Then it generates the client classes based on the WSDL (very import point). Finally, it just invokes the service.This is all good.

Now I need to adapt the same sample to invoke my own OSB fooPS. Keep in mind, if you are only interested in creating a client that can call the OSB proxy fooPS, you only need do "ant client run" (skipping the server tasks).

If you read the build.xml file carefully, you'll see the "client" target is essentially independent of the actual sever implementation. It mostly generates the client classes based on the WSDL. From that I assume I can merely change the WSDL URL and make it work for my own OSB proxy service. Here is how I did it:

I changed WSDL URL in build.xml to point my service http://localhost1:8011/OWSM_Demo/fooPS?wsdl (see end of this post), then I ran "ant client" (I manully cleaned out the "webservicesSecurity_client" directory, you can use ant "clean" task to do it).

Of course, the build would fail because SecureHelloWorldClient.java can't find the original java classes from the original sample. But it did generate the client classes based on the new OSB WSDL, they are:
  • FooBPEL.java - interface
  • FooBPELAsyncHandler.java - I didn't do anything with this one
  • FoobpelClientEp.java - this one extends Service
  • ObjectFactory.java - didn't do anything
  • package-info.java - didn't do anything
  • Process.java - this is based on the only "operation" from the wsdl
  • ProcessResponse.java - operation response based on the WSDL
Now, change SecureHelloWorldClient.java from
  • SecureHelloWorldService service=new SecureHelloWorldService();
  • SecureHelloWorldPortType port=service.getSecureHelloWorldPortTypePort();
 to
  •  FoobpelClientEp service=new FoobpelClientEp();
  •  FooBPEL port=service.getFooBPELPt();
There you go. You can just type in "ant client run". It will invoke your OSB fooPS proxy! If you run into problems, try use TPCMon to debug the issue.

Of couse, you need to change your user/pass accordingly. Also, I didn't bother to change the client package name etc. This is just a proof of concept thing.

The meat part of the client program is to use BindingPort to set the WSS security header.

With the command line success under my belt, i started to migrate the solution to Web app. Of couse, it would be too easy it simply worked. And that's going to be covered in another post (http://yuanmengblog.blogspot.com/2013/05/eclise-creates-java-web-service-client.html).

I can't seem to find a way to add attachment, so here is the wsdl along with the xsd.

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="fooBPEL" targetNamespace="http://xmlns.oracle.com/cis/foo/fooBPEL" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:client="http://xmlns.oracle.com/cis/foo/fooBPEL" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:WL5G3N0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <plnk:partnerLinkType name="fooBPEL">
        <plnk:role name="fooBPELProvider" portType="client:fooBPEL"/>
    </plnk:partnerLinkType>
<wsp:Policy wsu:Id="wss_username_token_service_policy" xmlns="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<sp:SupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:Policy>
    <wsdl:types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema">
            <import namespace="http://xmlns.oracle.com/cis/foo/fooBPEL" schemaLocation="http://localhost:8011/OWSM_Demo/fooPS?SCHEMA%2FOWSM+Demo%2FfooBPEL"/>
        </schema>
    </wsdl:types>
    <wsdl:message name="fooBPELRequestMessage">
        <wsdl:part name="payload" element="client:process"/>
    </wsdl:message>
    <wsdl:message name="fooBPELResponseMessage">
        <wsdl:part name="payload" element="client:processResponse"/>
    </wsdl:message>
    <wsdl:portType name="fooBPEL">
        <wsdl:operation name="process">
            <wsdl:input message="client:fooBPELRequestMessage"/>
            <wsdl:output message="client:fooBPELResponseMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="fooBPELBinding" type="client:fooBPEL">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsp:PolicyReference URI="#wss_username_token_service_policy" wsdl:required="false"/>
        <wsdl:operation name="process">
            <soap:operation style="document" soapAction="process"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="foobpel_client_ep">
        <wsdl:port name="fooBPEL_pt" binding="client:fooBPELBinding">
            <soap:address location="http://thinkpad01:8011/OWSM_Demo/fooPS"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

<?xml version="1.0" encoding="UTF-8"?>
<schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://xmlns.oracle.com/cis/foo/fooBPEL" xmlns="http://www.w3.org/2001/XMLSchema">
 <element name="process">
  <complexType>
   <sequence>
    <element name="input" type="string"/>
   </sequence>
  </complexType>
 </element>
 <element name="processResponse">
  <complexType>
   <sequence>
    <element name="result" type="string"/>
   </sequence>
  </complexType>
 </element>
</schema>

1 comment: