I have a system that returns SOAP envelope message
<soap:Envelope>
<soap:Body>
<ns2:myResponse>
And i have classes generated from WADL and XSD files (by cxf-wadl2java-plugin and JAXB), also i have an interface generated (imports from javax.ws.rs ):
#Path("/case/{id}")
public interface MyService {
#GET
#Produces("application/xml")
Response getCase(#PathParam("id") String id);
How should the client looks like ?
I've tried with Jersey:
com.sun.jersey.api.client.Client client = Client.create();
WebResource resource = client.resource("http://localhost:8080/case");
and CXF:
MyService service = JAXRSClientFactory.create("http://localhost:8080", MyService.class, providers);
but during a call i have (i'm not surprised) a problem with unmarshalling:
unexpected element (uri:"http://www.w3.org/2003/05/soap-envelope", local:"Envelope"). Expected elements are <{}myResponse>
how to create working client for this?
it was a WS before (with WSDL, binding file and XSDs with cxf-codegen-plugin plugin)
Related
I'm building a service that sends a POST request to UPS track package API. In PostMan, this call returns a 200 with this URL and these POST params
URL: https://onlinetools.ups.com/ups.app/xml/Track
Body: form-data
Params:
UPSSecurity
<?xml version="1.0"?> <AccessRequest xml:lang="en-US"> <AccessLicenseNumber>REDACTED</AccessLicenseNumber> <UserId>REDACTED</UserId> <Password>REDACTED</Password> </AccessRequest>
Body
<?xml version="1.0"?> <TrackRequest xml:lang="en-US"> <Request> <TransactionReference> <CustomerContext>Your Test Case Summary Description</CustomerContext> <XpciVersion>1.0</XpciVersion> </TransactionReference> <RequestAction>Track</RequestAction> <RequestOption>activity</RequestOption> </Request> <TrackingNumber>REDACTED</TrackingNumber> </TrackRequest>
Our application defines clients using OpenFeign and Spring annotations. The solution I'm going to try is to define my FeignClient like this:
interface UPSClient {
#Headers({"SOAPAction: http://onlinetools.ups.com/webservices/TrackBinding/v2.0","Content-Type: application/xml"})
#PostMapping(
value = "/Track",
consumes = MediaType.TEXT_XML_VALUE,
produces = MediaType.TEXT_XML_VALUE
)
ResponseEntity<TrackResponse> getTrackResponse(#RequestBody UPSRequest upsRequest);
and define MyRequestObject as
public class UPSRequest {
String UPSSecurity; // UPSSecurity is a POJO generated from UPS wsdl and marshalled into an XML String
String Body; // Body is a POJO generated from UPS wsdl and marshalled into an XML String
}
Is there a cleaner approach that anyone could recommend? The TrackResponse returned from the UPS endpoint can be handled by a custom SOAPDecoder and shouldn't be an issue
Currently, I created a project webservice which I provide 2 webservices endpoint corresponding with 2 versions is MyWebserviceV1 and MyWebserviceV2.
However, I would like to have only one access url and I will forward the request base on targetNamspace.
URL example: localhost:8080/my-project/MyWebservice
I have 2 files wsdl for these versions, each file wsdl I have different targetNamespace:
- MyWebserviceV1: the targetNamespace com.test/myservice-v1.0
- MyWebserviceV2: the targetNamespace com.test/myservice-v2.0
My idea is that: When I receive the SOAP request, base on the targetNamespace (QName from client request) attribute, I will forward to corresponding endpoint.
I intended to use the javax.servlet.Filter for pre-process request but I could not get the target targetNamspace.
How can I get the targetNamespace from SOAP request message, or any configuration available to use for my case.
I am using Camel in our project and requesting WebServices, the dataFormat is POJO. I was able to request when my SOAP message did not contain SOAP headers, but when it had Headers, I was unable to set those. I looked at the documentation but was not able to understand and have several questions.
I want to create a message like the below:
<soapenv:Envelope`enter code here`
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<platformMsgs:documentInfo
xmlns:platformMsgs="urn:messages_2015_1.platform.webservices.netsuite.com">
<platformMsgs:nsId>WEBSERVICES_3479023</platformMsgs:nsId>
</platformMsgs:documentInfo>
</soapenv:Header>
<soapenv:Body>
<addListResponse
xmlns="">
<platformMsgs:writeResponseList
xmlns:platformMsgs="urn:messages_2015_1.platform.webservices.netsuite.com">
<platformCore:status isSuccess="true"
xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com"/>
<platformMsgs:writeResponse>
<platformCore:status isSuccess="false"
xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com">
<platformCore:statusDetail type="ERROR">
<platformCore:code>DUP_ENTITY</platformCore:code>
<platformCore:message>This entity already exists.</platformCore:message>
</platformCore:statusDetail>
</platformCore:status>
</platformMsgs:writeResponse>
</platformMsgs:writeResponseList>
</addListResponse>`enter code here`
</soapenv:Body>
</soapenv:Envelope>
I will be able to send the message if there was only Body, but can someone give me a code snippet for including the header section? The dataFormat is POJO.
When using CXF endpoint with dataFormat as POJO, body in Camel Exchange object is an object of org.apache.cxf.message.MessageContentsList. It is an extension of java.util.ArrayList<Object> and it contains parts of SOAP Message in order as defined in WSDL and corresponding method in WebService class.
Element 0 there is a Body.
So, one way to do that with Java is to create a Processor class implementing org.apache.camel.Processor interface and in its process method set your SOAP header. Something like:
#Override
public void process(Exchange camelExchange) throws Exception {
MessageContentsList messageBody = (MessageContentsList) camelExchange.getIn().getBody();
DocumentInfo docInfoHeader = new DocumentInfo();
... set docInfoHeader properties ...
messageBody.add(docInfoHeader);
}
(sample is not tested. It is just an idea, how to handle that...)
Other answer on similar question you can find here: Setting Custom Soap Header-To Pojo Message In Camel Cxf
It describes how to use Camel Exchange headers as SOAP Headers.
I'm not sure for 100% which way will work for you and which one is better...
I guess, it depends on WSDL you use.
UPD: second choice is to use pure CXF solution by using CxfMessageSoapHeaderOutInterceptor custom implementation.
It may look like:
public class MyCxfInterceptor extends CxfMessageSoapHeaderOutInterceptor {
#Override
public void handleMessage( org.apache.cxf.binding.soap.SoapMessage message) {
org.apache.cxf.binding.soap.SoapHeader myCustomHeader = new org.apache.cxf.binding.soap.SoapHeader(new QName(
{custom name space}, {custom local name}), {Custom content object}));
myCustomHeader.setMustUnderstand(true);
message.getHeaders().add(myCustomHeader);
}
and set Interceptor in Camel Cxf Endpoint as :
<cxfEndpoint ...>
<outInterceptors>
<spring:bean class="MyCxfInterceptor"/>
</outInterceptors>
...
Well suppose I request the Web Service and it failed, a Fault message is generated. Will I get the Fault object at position 0 of MessageContentsList then too? Or will I get only the response object at position 0?
I'm using eBay notification API, i'm getting a SOAP web request that contains XML inside.
I would like to use jersey framework in order to deserialize the request into an object.
Is there any easy way to generate a bean class from the SOAP request that will be used in a simpler way that I'm using json? for an example :
#POST
#Path("/path")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response methodName(Item bean)
{
...
}
You can generate bean class from xml response using JAXB library.
Read More about this
Situation: jax-ws web service on Weblogic appserver; wsdl first development, jaxb customizations in external binding file.
I would like to get a handle to the actual jaxb context that will process the incoming soap xml message, before it has been unmarshalled into java objects.
Then I would like to get the unmarshaller of this jaxb context - the one that actually will be used during the unmarshalling. And then setup some properties of this unmarshaller (e.g. listener and idresolver).
The new #UsesJAXBContex annotation JAXBContextFactoryin jaxws 2.1.5 - jaxb 2.2 is probably what I need for that.
However weblogic 10.3.1 uses jaxws 2.1.1, jaxb 2.1.3.
Another solution is to use:
#WebServiceProvider(portName = "Port", serviceName = "Service", targetNamespace = "tns", wsdlLocation = "/wsdls/x.wsdl")
#BindingType(value = "http://schemas.xmlsoap.org/wsdl/soap/http")
#ServiceMode(value = javax.xml.ws.Service.Mode.MESSAGE)
public class ServiceProvider implements Provider<SOAPMessage>
This gives access to the soap xml message. I still have to figure out where the method name can be found.
Instead of:
#WebService(portName = "Port", serviceName = "Service", targetNamespace = "tns",
wsdlLocation = "/wsdls/x.wsdl", endpointInterface = "tns.PortType")
#BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
public class ServicePort implements PortType