I can call NetDocuments SOAP API by C# as following:
// Authenticate to the NetDocuments directory service
ndDir.Directory ndDirectory = new ndDir.Directory();
ndDirectory.CookieContainer = new System.Net.CookieContainer(); // enable cookie handling
ndDirectory.Login( username, password );
// Connect to the NetDocuments storage service
ndStor.storage ndStorage = new ndStor.storage();
ndStorage.CookieContainer = ndDirectory.CookieContainer; // share cookies with the directory service
XmlNode searchRes = ndStorage.Search( criteria, attrList );
However, when I call NetDocuments SOAP API by java with Axis 1.4, I receive error: "No authentication session. The authentication session has timed out or was not established prior to this call."
DirectorySoapStub stubDir = new DirectorySoapStub(new URL("https://vault.netvoyage.com/ndApi/directory.asmx"), new DirectoryLocator());
StorageSoapStub stubSto = new StorageSoapStub(new URL("https://vault.netvoyage.com/ndApi/storage.asmx"), new StorageLocator());
stubSto.setMaintainSession(true);
stubDir.login(username, password);
javax.xml.soap.MimeHeaders mhds = stubDir._getCall().getMessageContext().getCurrentMessage().getMimeHeaders();
java.util.Iterator iterator = mhds.getAllHeaders();
while (iterator.hasNext()) {
javax.xml.soap.MimeHeader mhd = (javax.xml.soap.MimeHeader)iterator.next();
if ("set-cookie".indexOf(mhd.getName()) >= 0) {
stubSto._setProperty(mhd.getName(), mhd.getValue());
}
}
stubSto.search(criteria, attrList);
Is there similar thing of CookieContainer in Java? How can I call NetDocuments SOAP API by java with Axis 1.4?
I realise this question was posted a while ago, but I've been able to get this working in the past by using the JAX-RPC plugin that comes with NetBeans. The version of NetBeans I used was v6.8 (I think that the JAX-RPC plugin is not included in newer versions of NetBeans as JAX-RPC isn't widely used anymore). I remember struggling to get anything working when I tried to use Axis, though that was more than likely due to me not being familiar enough with it.
I can't remember all the steps necessary, but you can point the JAX-RPC plugin at the WSDL for NetDocuments and all the classes needed for calling the API are then set up for you.
To handle authentication correctly, it was necessary to set the SESSION_MAINTAIN_PROPERTY on the DirectorySoap_Stub and StorageSoap_Stub classes to true - this instructs them to maintain a session once you have logged in. See e.g. http://docs.oracle.com/cd/E19575-01/821-0177/fxybb/index.html for info on SESSION_MAINTAIN_PROPERTY
Additionally, when you login via the DirectorySoap object, if you then want to use the methods of StorageSoap you need to let the StorageSoap object know the cookie that you are using in the DirectorySoap session.
To do this I implemented a javax.xml.rpc.handler.Handler that stores the CookieJar from the DirectorySoap session (property "com.sun.xml.rpc.client.http.CookieJar" on the request MessageContext) and sets that CookieJar on the same property of requests of the StorageSoap session.
Hopefully that's useful to anyone with similar SOAP issues...
Cheers
Related
I'm trying to use Opentext Content Web Services(CWS) from my axis2-based web-service.
This is a piece of code that creates a proxy client to CWS and passes an authentication token in a header.
DocumentManagement_Service docManService = new DocumentManagement_Service();
DocumentManagement docManClient = docManService.getBasicHttpBindingDocumentManagement();
try
{
// The namespace of the OTAuthentication object
final String ECM_API_NAMESPACE = "urn:api.ecm.opentext.com";
// Create a SOAP header
SOAPHeader header = MessageFactory.newInstance().createMessage().getSOAPPart().getEnvelope().getHeader();
// Add the OTAuthentication SOAP header element
SOAPHeaderElement otAuthElement = header.addHeaderElement(new QName(ECM_API_NAMESPACE, "OTAuthentication"));
// Add the AuthenticationToken SOAP element
SOAPElement authTokenElement = otAuthElement.addChildElement(new QName(ECM_API_NAMESPACE, "AuthenticationToken"));
authTokenElement.addTextNode(authToken);
// Set the SOAP header on the docManClient
String ENDPOINT_ADDRESS_PROPERTY = WSBindingProvider.ENDPOINT_ADDRESS_PROPERTY;
((WSBindingProvider) docManClient).setOutboundHeaders(Headers.create(otAuthElement));
}
catch (SOAPException e)
{
System.out.println("Failed to set authentication SOAP header!\n");
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
return;
}
This code works fine when executed from simple java application. In that case docManClient is a SEIStub object and setOutboundHeaders method works after casting to WSBindingProvider.
But when this code is executed inside my axis2 webservice, docManClient is JAXWSProxyHandler object and it can not be casted into WSBindingProvider nor execute setOutboundHeaders method.
So my question is - How do I pass my header with AuthElement using JAXWSProxyHandler (do the same as setOutBoundHeaders method do) OR Can I somehow convert JAXWSProxyHandler object to SEIStub object?
The problem occurs because you are using an API that is specific to the JAX-WS implementation in the JRE. However, when running on Axis2, the JAX-WS implementation provided by Axis2 will be used instead. That implementation supports a different set of API extensions.
What this means is that your code is not portable across different JAX-WS implementations. You have two options:
Make it portable by only using standard APIs. In your case this would require implementing a JAX-WS handler that adds the header. To pass the authToken to the handler, you would cast the client to BindingProvider and add the data to the request context.
Remove the axis2-jaxws JAR from your Axis2 deployment so that your code will use the JAX-WS implementation from the JRE. Of course this won't work if the service itself is deployed as a JAX-WS service. Unfortunately the code snippet doesn't show whether that's the case or not.
I created the jar from the WSDL for my client using the wsdl2java command. Now, I need to know how I can authenticate my client in order to complete an operation?
I am using CXF 2.7.16. I created my service using the generated class MyApp_Service, I am struggling with this. Isn't there a simple way to tell my client the credentials it should use to gain access to the web service?
I read about the Spring configuration, however I am unable to figure out if it applies to my case and how if yes. I tried to cast the MyApp_Service class to BindingProvider in order to use the method which consist to put the USERNAME and PASSWORD properties in the context with a value. However, MyApp_Service cannot be cast to BindingProvider.
This is my first web service client application ever. So, any help will be welcomed.
Update 2015-05-28: I tried to define the AuthenticationPolicy but is seems not working. Here is the code:
Client client = JaxWsDynamicClientFactory.newInstance().createClient(wsdlUrl);
ClientImpl clt = (ClientImpl) client;
HTTPConduit cc = (HTTPConduit) clt.getConduit();
org.apache.cxf.configuration.security.ObjectFactory secOF = new org.apache.cxf.configuration.security.ObjectFactory();
AuthorizationPolicy ap = secOF.createAuthorizationPolicy();
ap.setUserName(usagerWS);
ap.setPassword(mdpWS);
ap.setAuthorizationType("Basic");
cc.setAuthorization(ap);
Sniffing with WireShark, the Authorization header is clearly missing in the HTTP request.
What is missing?
Problem solved, here is the solution:
MyApp_Service service = new MyApp_Service(wsdlUrl, new QName(namespace, serviceName));
MyApp port = service.getMyApp();
// Set credentials
Map<String, Object> reqCtxt = ((javax.xml.ws.BindingProvider) port).getRequestContext();
reqCtxt.put(javax.xml.ws.BindingProvider.USERNAME_PROPERTY, username);
reqCtxt.put(javax.xml.ws.BindingProvider.PASSWORD_PROPERTY, password);
No more usage of the dynamic client. Only the classes generated with wsdl2java are used.
I am implementing a TV listing service and I have decided to use ROVI as my data provider.
They provide me with an API that allows me to exchange data between my application and their servers by means of SOAP requests.
Since I am programming in Java, I used wsimport to generate the classes that would enable me to interact with their server.
//Connection
service = new ListingsService();
port = service.getListingsServiceSoap();
I have come across a problem which Google doesn't seem to have the answer for.
According to their API, whenever I want to make a call to a SOAP service I have to add my API Key to the end of url.
The problem is, I don't know how to do that. Using the stubs generated by wsimport, I can create a request object as it should be; however the URL is not displayed as per their specification. The url I currently get is: http://api.rovicorp.com/v9/listingsservice.asmx and what is required is: http://api.rovicorp.com/v9/listingsservice.asmx?apikey=myAPIkey. I obtained that by printing the following code:
System.out.println(port.toString());
Trying to run the following code:
GetServicesRS servicesRS = port.getServices(getServicesRQ, auth)
Yields the following error:
Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 403: Forbidden
What java method can I use to append this parameter into the SOAP request URL.
Thanks for your help.
Edit.
I am still struggling with this and haven't been lucky with responses, if anyone could point me in the direction of a framework or something that could facilitate this would be great!
Cheers
I manage to work around my problem using something called BindingProvider.
I added the following to my code:
//Connection
service = new ListingsService();
port = service.getListingsServiceSoap();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://api.rovicorp.com/v9/listingsservice.asmx?apikey=" + APIKey);
With the aforementioned code the call to the API is successful:
GetServicesRS servicesRS = port.getServices(getServicesRQ, auth)
Hope it helps someone in the future.
UPDATED
I have a Metro 2.1.1 WebService secured with the mechanism Transport Security (SSL). I want to access this service with a .NET 3.5+ WCF client. I found this link which solves the same problem problem, however I was still unable to make a working client. I think I'm mixing up stuff in the client config.
The WCF team has released a set of interoperability bindings at this link. This blog post provides details on how to use them. One of the supported bindings is specifically for Metro based service. Haven't tried to set this binding up but it seems this scenario is covered.
Client Code:
//IMPORTANT - THIS LINE IS ONLY FOR TESTING PURPOSES!
//This code is for accepting self-signed server certificate
ServicePointManager.ServerCertificateValidationCallback += (sender_ws, cert, chain, sslPolicyErrors) => true;
//instantiate transport binding element, leave the defaults
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
//instantiate message encoding element, where message version must be Soap11WSAddressing10 to match metro web service requirement.
TextMessageEncodingBindingElement text = new TextMessageEncodingBindingElement();
text.MessageVersion = MessageVersion.Soap11WSAddressing10;
//instantiate transport security binding element, with all the suggested values in app.config
TransportSecurityBindingElement b_element = new TransportSecurityBindingElement();
b_element.DefaultAlgorithmSuite = new Basic128SecurityAlgorithmSuite();
b_element.IncludeTimestamp = true;
b_element.KeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy;
b_element.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
b_element.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
//instantiate the custom binding and add the elements created above
CustomBinding customBinding = new CustomBinding();
customBinding.Name = "myOwnPersonalCustomBinding";
customBinding.Elements.Add(b_element);
customBinding.Elements.Add(text);
customBinding.Elements.Add(transport);
//instantiate the client
Uri uri = new Uri("https://localhost:8181/test/hello");
HelloWebServiceClient wsClient = new HelloWebServiceClient (customBinding, new EndpointAddress(uri));
//Call
richTextBox1.Text = wsClient.hello(textBox1.Text);
My problem is I get error while trying to get request token from Yahoo. The error says Im missing oauth_callback parameter and yes I miss it because I dont need it. Ive read I need to set it to "oob" value if I dont want to use it(desktop app). And I did that but to no avail. If I set it to null the same happens. Im using OAuth for java: http://oauth.googlecode.com/svn/code/java/core/
OAuthServiceProvider serviceProvider = new OAuthServiceProvider("https://api.login.yahoo.com/oauth/v2/get_request_token",
"https://api.login.yahoo.com/oauth/v2/request_auth",
"https://api.login.yahoo.com/oauth/v2/get_token");
OAuthConsumer consumer = new OAuthConsumer("oob", consumerKey, consumerSecret, serviceProvider);
OAuthAccessor accessor = new OAuthAccessor(consumer);
OAuthClient client = new OAuthClient(new HttpClient4());
OAuthMessage response = client.getRequestTokenResponse(accessor, OAuthMessage.POST, null);
System.out.println(response.getBodyAsStream());
Have you tried using Scribe?
I also had problems with OAuth java libs so I developed that one. It's pretty much cross provider and better documented than the one you're using.
If it does not work with Yahoo you can easily extend it creating your own Provider
Hope that helps!
there is a problem in the java OAuthMassage class, I resolved it by adding to addRequiredParameters method thie line
if (pMap.get(OAuth.OAUTH_CALLBACK) == null) {
addParameter(OAuth.OAUTH_CALLBACK, consumer.callbackURL);
}
if you still have this problem I can help you: rbouadjenek#gmail.com
I haven't used that library, but it looks like it isn't properly handling the callback URL. Since OAuth 1.0a (http://oauth.net/advisories/2009-1/ and http://oauth.net/core/1.0a/), the callback URL needs to be sent in the first call to get the request token (not in the client-side call to authorise it), and it seems that this library hasn't been updated to do this (at least from looking at the code). I assume that Yahoo requires the parameter to be there.
Not sure if the original problem was ever solved, but wanted to point to a new Java OAuth SDK that Yahoo released last week:
http://developer.yahoo.net/blog/archives/2010/07/yos_sdk_for_java.html
Developers trying to access Yahoo's services via OAuth with Java may find parts of this SDK helpful.