Nov 17, 2009

Using Axis2 Dynamic Client to invoke Secured Web Services

When invoking a secured web service with Axis2, usually we tend to use Axis2 ServiceClient at the service consumer's end. This is mainly due to the simplicity of the API of the ServiceClient. Since we are invoking a secured service, we have to point the ServiceClient to the security policy which is applied to the service. Usually this policy is stored in the file system and a policy object created by reading that file is added to the ServiceClient options. Following code snippets depicts the above mentioned procedure.
options.setProperty(RampartMessageData.KEY_RAMPART_POLICY, loadPolicy(policyPath));

With this approach, whenever the service policy is changed, the changes should be introduced to the client side policy file manually. This is not manageable in a scenario where a large number of clients access the same secured service which is subjected to frequent changes in the policy. In such cases, Axis2 Dynamic Client comes in handy.

RPCServiceClient or Axis2 Dynamic Client is an extension to the Axis2 ServiceClient. When instantiating a RPCServiceClient, the URL of the WSDL of the service, the QName of the service in the WSDL and the intended port name should be passed as parameters in addition to the Configuration Context.
RPCServiceClient dynamicClient = new RPCServiceClient(confContext, new URL("http://127.0.0.1:9763/services/HelloService?wsdl"),
new QName("http://www.wso2.org/types", "HelloService"), "HelloServiceHttpSoap12Endpoint");

During this instantiation, the policy which is appearing in the WSDL is extracted and applied to the web service client. So when the policy is changed, always the changes get reflected in the client side.

Then you can engage modules in same way as with ServiceClient. Since RPCServiceClient is extending ServiceClinet, engage(String moduleName) method is inherited.
dynamicClient.engageModule("rampart");

Now we have passed the service policy and engaged the Rampart module. What else is missing here? Yes. It is the rampart-config which is used to pass the client-side configuration data for Rampart. In this case, we can construct the rampart-config element programmatically and append it to the policy derived from the WSDL.

Constructing rampart-config programmatically is straight forward. Following code snipped demonstrates how to construct the rampart-config corresponding to a Username Token based Security Scenario.
RampartConfig rampartConfig = new RampartConfig();
rampartConfig.setUser("admin");
rampartConfig.setPwCbClass("org.wso2.training.wsas.security.PasswordCallbackHandler");

Then append this rampart-config to the policy derived from the WSDL.
Map endPoints = dynamicClient.getAxisService().getEndpoints();
AxisBinding axisBinding = ((AxisEndpoint) endPoints.values().iterator().next()).getBinding();
Policy policy = axisBinding.getEffectivePolicy();
policy.addAssertion(rampartConfig);
axisBinding.applyPolicy(policy);

Here we are taking the effective policy and append the rampart-config and overriding the existing policy using the updated policy.

Now we can invoke the service.
Object[] returnArray = dynamicClient.invokeBlocking(new QName("http://www.wso2.org/types","greet"),
new Object[]{"Alice"}, new Class[]{String.class});

We are using the blocking invocation here. The QName of the operation in WSDL file, an array of objects with the parameters and an array of Class objects for the return types are passed into this method.

With the successful completion of that method, we have invoked a service securely using an Axis2 Dynamic Client.

References : http://www.nandana.org/2008/11/how-to-write-dynamic-client-for-web.html

2 comments:

Afkham Azeez said...

You can also use the Axis2 ServiceClient directly.

You must use this constructor:

public ServiceClient(ConfigurationContext configContext, URL wsdlURL,
QName wsdlServiceName, String portName) throws AxisFault

Twitted by samindaw said...

[...] This post was Twitted by samindaw [...]

Post a Comment