Active IQ Unified Manager Discussions
Active IQ Unified Manager Discussions
I am trying to invoke WFA Webservices from java using CXF. After generating JAX-WS stubs, the call is straight-forward.
public class WFAServiceTestClient {
private static final QName SERVICE_NAME = new QName("http://ws.wfa.netapp.com/","WorkflowService");
public static void main(String[] args) {
URL wsdlURL=null;
try {
wsdlURL = new URL( "http://10.72.64.247/wfa-ws/WorkflowService_doc?wsdl");
} catch (MalformedURLException e) {
e.printStackTrace();
}
WorkflowService ss = new WorkflowService(wsdlURL, SERVICE_NAME);
WorkflowServiceDoc port = ss.getWorkflowServiceDocPort();
// Set request context property.
java.util.Map<String, Object> requestContext = ((javax.xml.ws.BindingProvider)port).getRequestContext();
requestContext.put("ws-security.username", "admin");
requestContext.put("ws-security.password", "admin");
List returnList = port.getAllWorkflows();
}
}
But this code does not set the correct credentials and the call fails with :
com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 401: Unauthorized
What should be the correct method of setting the credentials ? I tried setting up a callback handler as per WS-Security UsernameToken spec 1.0, but it seems that WFA is not using it.
My request (from wireshark sniff) -
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getAllWorkflows xmlns:ns2="http://ws.wfa.netapp.com/"/></S:Body></S:Envelope>
Solved! See The Solution
Following is the class we use internally for testing:
/**
* Note that in order for this wrapper to run from TeamCity, the agent must have in its environment:<ul>
* <li> path=%path%;c:\work\tools\jdk\bin
* <li> JAVA_HOME=c:\work\tools\JDK
* </ul>
* Also, the "maven runner" should be configured to use JAVA_HOME.
*/
public class WebServiceWrapper {
private static final String TIMEOUT_MS = "120000";
private JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
private String hostIp;
private String userName;
private String password;
private Map<String, CachedClient> clientCache = new HashMap<String, CachedClient>();
public WebServiceWrapper(String hostIp, String userName, String password) {
this.hostIp = hostIp;
this.userName = userName;
this.password = password;
}
public Object[] invokeWebService(String serviceName, String operationName, Object... params) {
ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
CachedClient cachedClient = getClient("http://" + hostIp + "/wfa-ws/" + serviceName + "?wsdl");
try {
return cachedClient.client.invoke(operationName, params);
} catch (Exception e) {
throw new EndToEndException("Web-service invocation failed invoking " + serviceName + "." + operationName, e);
} finally {
// Restore the original class loader
Thread.currentThread().setContextClassLoader(prevClassLoader);
}
}
@Override
public String toString() {
return "WebServiceWrapper{" +
"hostIp='" + hostIp + '\'' +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
public String getHostIp() {
return hostIp;
}
Map<String, CachedClient> getClientCache() {
return Collections.unmodifiableMap(clientCache);
}
private CachedClient getClient(String wsdlUrl) {
CachedClient cachedClient = clientCache.get(wsdlUrl);
if (cachedClient == null) {
cachedClient = new CachedClient(dcf.createClient(wsdlUrl));
cachedClient.classLoader = Thread.currentThread().getContextClassLoader();
AuthorizationPolicy authorization = ((HTTPConduit) cachedClient.client.getConduit()).getAuthorization();
authorization.setUserName(userName);
authorization.setPassword(password);
cachedClient.client.getRequestContext().put("javax.xml.ws.client.receiveTimeout", TIMEOUT_MS);// 120 seconds
cachedClient.client.getRequestContext().put("javax.xml.ws.client.connectionTimeout", TIMEOUT_MS);// 120 seconds
clientCache.put(wsdlUrl, cachedClient);
}
else {
// for existing client, restore's the client's class loader
Thread.currentThread().setContextClassLoader(cachedClient.classLoader);
}
return cachedClient;
}
public class CachedClient {
Client client;
ClassLoader classLoader;
public CachedClient(Client client) {
this.client = client;
}
public Client getClient() {
return client;
}
}
}
Example for using this utility:
webServiceWrapper = new WebServiceWrapper("10.68.66.170", "admin", "<some password>");
webServiceWrapper.invokeWebService("ValidationService", "validateConfiguration");
You should be using the AuthorizationPolicy capability as illustrated below:
private JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
.
.
.
client = dcf.createClient(wsdlUrl);
AuthorizationPolicy authorization = ((HTTPConduit) client.getConduit()).getAuthorization();
authorization.setUserName(userName);
authorization.setPassword(password);
client.getRequestContext().put("javax.xml.ws.client.receiveTimeout", TIMEOUT_MS);// 120 seconds
client.getRequestContext().put("javax.xml.ws.client.connectionTimeout", TIMEOUT_MS);// 120 seconds
.
.
.
client.invoke(operationName, params)
Thanks, is there some sample code that I can take a look at ?
Following is the class we use internally for testing:
/**
* Note that in order for this wrapper to run from TeamCity, the agent must have in its environment:<ul>
* <li> path=%path%;c:\work\tools\jdk\bin
* <li> JAVA_HOME=c:\work\tools\JDK
* </ul>
* Also, the "maven runner" should be configured to use JAVA_HOME.
*/
public class WebServiceWrapper {
private static final String TIMEOUT_MS = "120000";
private JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
private String hostIp;
private String userName;
private String password;
private Map<String, CachedClient> clientCache = new HashMap<String, CachedClient>();
public WebServiceWrapper(String hostIp, String userName, String password) {
this.hostIp = hostIp;
this.userName = userName;
this.password = password;
}
public Object[] invokeWebService(String serviceName, String operationName, Object... params) {
ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
CachedClient cachedClient = getClient("http://" + hostIp + "/wfa-ws/" + serviceName + "?wsdl");
try {
return cachedClient.client.invoke(operationName, params);
} catch (Exception e) {
throw new EndToEndException("Web-service invocation failed invoking " + serviceName + "." + operationName, e);
} finally {
// Restore the original class loader
Thread.currentThread().setContextClassLoader(prevClassLoader);
}
}
@Override
public String toString() {
return "WebServiceWrapper{" +
"hostIp='" + hostIp + '\'' +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
public String getHostIp() {
return hostIp;
}
Map<String, CachedClient> getClientCache() {
return Collections.unmodifiableMap(clientCache);
}
private CachedClient getClient(String wsdlUrl) {
CachedClient cachedClient = clientCache.get(wsdlUrl);
if (cachedClient == null) {
cachedClient = new CachedClient(dcf.createClient(wsdlUrl));
cachedClient.classLoader = Thread.currentThread().getContextClassLoader();
AuthorizationPolicy authorization = ((HTTPConduit) cachedClient.client.getConduit()).getAuthorization();
authorization.setUserName(userName);
authorization.setPassword(password);
cachedClient.client.getRequestContext().put("javax.xml.ws.client.receiveTimeout", TIMEOUT_MS);// 120 seconds
cachedClient.client.getRequestContext().put("javax.xml.ws.client.connectionTimeout", TIMEOUT_MS);// 120 seconds
clientCache.put(wsdlUrl, cachedClient);
}
else {
// for existing client, restore's the client's class loader
Thread.currentThread().setContextClassLoader(cachedClient.classLoader);
}
return cachedClient;
}
public class CachedClient {
Client client;
ClassLoader classLoader;
public CachedClient(Client client) {
this.client = client;
}
public Client getClient() {
return client;
}
}
}
Example for using this utility:
webServiceWrapper = new WebServiceWrapper("10.68.66.170", "admin", "<some password>");
webServiceWrapper.invokeWebService("ValidationService", "validateConfiguration");