set soapaction header in a java client - java

i have created a java client in netbeans 7.2 from a wsdl
the issue is that the header send Soapaction but the server is expecting to receive SOAPAction
i try to overwrite the properties using this code
BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, false);
prov.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, "http://www.microsoft.com");
but again in the server it receives Soapaction instead of receiving SOAPAction
can someone tell me how can i overright this value?
thank you

I think you try to add it in a wrong place.
BindingProvider is only the stub object, "provides access to the protocol binding and associated context objects for request and response message processing."
What you really need here is an SOAP message interceptor, which you can use to customize your SOAP messages generated by your WS library.
In case you use JAX-WS, you can use for example SOAPHandlers to do this.
Here is an example:
http://www.mkyong.com/webservices/jax-ws/jax-ws-soap-handler-in-client-side/
If this is not your case, please provide more details about your application (what kind of project it is, what kind of WS implementation you are using etc).

Related

How to add a body to a GET request in JAX-RS

I'm trying to consume a REST API that requires a body with a GET request. But as a GET usually doesn't have a body, I can't find a way to attach a body in my request. I am also building the REST API, but the professor won't allow us to change the method to POST (he gave us a list of the endpoints we are to create, no more, no less).
I'm trying to do it like this:
Response r = target.request().method(method, Entity.text(body));
Where I set the method to GET and the body to my get body. However, using this approach I get an exception:
javax.ws.rs.ProcessingException: RESTEASY004565: A GET request cannot have a body.
Is there any way to do this with JAX-RS? We learned to use JAX-RS so I would prefer a solution using this, as I'm not sure my professor would allow us to use any other REST client. I'm currently using RESTEasy, provided by the WildFly server.
(This is not a duplicate of HTTP GET with request body because I'm asking on how to create a GET request with body in JAX-RS, not if it should be done.)
This depends on what is your JAX-RS implementation. This check can be disabled in Jersey 2.25 using SUPPRESS_HTTP_COMPLIANCE_VALIDATION property:
ClientConfig config = new ClientConfig();
config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
JerseyClient client = JerseyClientBuilder.createClient(config);
WebTarget target = client.target(URI.create("https://www.stackoverflow.com"));
Response response = target.request().method("GET", Entity.text("BODY HERE"));
Instead of exception you will get an INFO log
INFO: Detected non-empty entity on a HTTP GET request. The underlying HTTP transport connector may decide to change the request method to POST.
However in RESTEasy 3.5.0.Final there is a hardcoded check in both URLConnectionEngine and ApacheHttpClient4Engine:
if (request.getEntity() != null)
{
if (request.getMethod().equals("GET")) throw new ProcessingException(Messages.MESSAGES.getRequestCannotHaveBody());
You would have to create your own implementation of the ClientHttpEngine to skip this. Then you need to supply it when building the client:
ClientHttpEngine engine = new MyEngine();
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();

JAX WS async client: capture WS-Addressing 202 accepted

I have to invoke several webservices using WS-Addressing.
When invoking a webservice, the ReplyTo is set to a callback endpoint implemented by me.
The client is generated from the target WSDL using async with
<enableAsyncMapping>true</enableAsyncMapping>
which generates the Async version for each webservice with the following signature:
javax.xml.ws.Response<SampleWebServiceOutput> sampleWebService(SampleWebServiceInput input)
When invoking sampleWebService like,
Response<SampleWebServiceOutput> response = clientWsPort.sampleWebService(input);
if the request is sucessful, the server will return 202 Accepted however I can't figure out how to get it.
If I use response.get(), it will block forever since the response is sent to my callback url (WSA-Addressing Reply To)
Any clues how to know for sure if the server successfully accepted the request ?
Thank you.
Apparently the response returned when you set a different reply-to address results in a null response, which could explain why it is hanging when you call response.get().
The recommended solution is to use something like getResponseContext(), which is called from the binding.

Adding soap header authentication to wsdl2java generated code

I'm in the process of creating a Java web services client from a wsdl. I used Eclipses's Dynamic Web Project and new Web Services Client to generate the code with wsdl2java with Apache Axis 1.4. I need to add SOAP authentication to this code in order for it to work with the service. I couldn't find a place to do that in the generated code. After copious research I found this, which I've used as the backbone for my code so far.
Adding ws-security to wsdl2java generated classes
Before I was getting a "Error occurred while processing security for the message" or something along those lines. Now I am getting
"Exception: Did not understand "MustUnderstand" header(s):{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security Message: null"
I've tried many things to get past this exception. This is the code I've arrived at now.
javax.xml.namespace.QName headerName = new javax.xml.namespace.QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security");
org.apache.axis.message.SOAPHeaderElement header = new org.apache.axis.message.SOAPHeaderElement(headerName);
header.setActor(null);
header.setMustUnderstand(true);
// Add the UsernameToken element to the WS-Security header
javax.xml.soap.SOAPElement utElem = header.addChildElement("UsernameToken");
utElem.setAttribute("Id", "uuid-3453f017-d595-4a5b-bc16-da53e5831cd1-1");
javax.xml.soap.SOAPElement userNameElem = utElem.addChildElement("Username");
userNameElem.setValue("username");
javax.xml.soap.SOAPElement passwordElem = utElem.addChildElement("Password");
passwordElem.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
passwordElem.setValue("password");
header.setProcessed(true);
// Finally, attach the header to the binding.
setHeader(header)
This code is located in my Binding_ServiceStub class (in its' createCall method).
We have created clients in both C# and VB with this wsdl, and there it's as easy as just changing the ClientCredentials variable which is an extension of the proxy class generated. I was hoping for something similar here.
Here's the security policy from the wsdl code as well.
<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>
Does anyone know what else I can do here? Why this exception is happening? I've tried many different combinations of prefixes and setProcesses and setMustUnderstand values all in vain (and based on my research of this exception).
And if anyone knows a way in which to add Soap header authentication to wsdl2java code I would take that too. Just need this to work and you would think something like this would be a little more straightforward or at least have more examples out there.
Update-
Confirmed that the same header passed using SOAPUI works fine. Must be something with the framework? I created a custom handler to process the SOAP Message but that didn't help. Is Axis 1.4 and JAX-RPC the problem? (I know they're outdated but still...)
Cool. I decided to just use Apache CXF as my framework and using this it's as easy as adding
javax.xml.ws.BindingProvider bp = (javax.xml.ws.BindingProvider) port;
bp.getRequestContext().put("ws-security.username", username);
bp.getRequestContext().put("ws-security.password", password);
Wow that's much better. Don't use Axis 1.4 lesson learned.

Transport level information does not match with SOAP Message namespace URI

I'm getting the error "Transport level information does not match with SOAP Message namespace URI". Request you provide the details to fix the issue.
I have set the below in the client side.
HttpTransportProperties.ProxyProperties proxyProperties = new HttpTransportProperties.ProxyProperties();
proxyProperties.setProxyName(proxyAddress);
proxyProperties.setProxyPort(proxyPort);
stub._getServiceClient().getOptions().setProperty(HTTPConstants.CHUNKED,Boolean.FALSE);
stub._getServiceClient().getOptions().setProperty(HTTPConstants.PROXY, proxyProperties);
stub._getServiceClient().getOptions().setProperty(HTTPConstants.HEADER_CONTENT_TYPE,"application/soap+xml");
stub._getServiceClient().getOptions().setProperty("type","application/soap+xml");
stub._getServiceClient().getOptions().setProperty(HTTPConstants.HEADER_SOAP_ACTION, Action_URL);
stub._getServiceClient().getOptions().setProperty ( HTTPConstants.HTTP_PROTOCOL_VERSION, HTTPConstants.HEADER_PROTOCOL_11 ) ;
stub._getServiceClient().getOptions().setProperty ( "Transfer-Encoding", "chunked" ) ;
stub._getServiceClient().getOptions().setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "true");
Can you please help to solve the issue?
That error occurs if there is a mismatch between the content type and the SOAP version (as determined by the namespace URI of the SOAP envelope) of the received message. E.g. if Axis2 receives a SOAP 1.2 message with content type text/xml, it will trigger that error.
Joe - If you are getting this error, then I am assuming that you are trying to access a service that is really old and you might be using Axis that is version 2.0 . You will not be able to call the service by creating client using Axis or CXF. I have spent days trying to figure this out. Eventually I ended up using SAAJ API to create the request WSDL and post it to the service.
It is very easy and keeps you away from trying to figure out RPC/Literal/Document style etc.
See this post - Post

How to remove header attribute from Axis2 SOAP response

I am trying to remove the header attributes from a SOAP response.
I have searched and ran across the idea that setting the mustUnderstand option too false will remove the header attribute element, but not the header tag.
How do I remove the header tag from an Axis2 SOAP response? Is it possible?
You can write SoapHandler that intercepts all your soap requests. Inside SoapHandler you have access to SoapMessageContext than obtain SoapMessage.getEnvelope().getHeader() and play with header in all ways (remove/add header elements). This approach good because you introduce new layer in your api and can preprocess inbound and outbound messages without impact on your main code.
Maybe following link will help you http://java.dzone.com/articles/creating-soap-message-handlers

Categories