So a guy send me a xsd and xpdl and told me to make requests to a SOAP gateway using this in Java.
What am I supposed to do with this? Load it or something? Can someone explain?
Any advice?
You should receive a WSDL as well. Using WSDL then you can generate soap client in java.
Soap client is like a library which act as local set of classes and methods. You can use those to call operations to execute on SOAP gateway. Its like you are calling a function locally but when executed, it will run on the SOAP gateway (remote server) where this function logic is implemented and hosted.
wsdl contains SOAP endpoints and xsd for data validation and description. Suppose you have a SOAP request like this
<message name = "SayHelloRequest">
<part name = "firstName" type = "xsd:string"/>
</message>
<message name = "SayHelloResponse">
<part name = "greeting" type = "xsd:string"/>
</message>
<portType name = "Hello_PortType">
<operation name = "sayHello">
<input message = "tns:SayHelloRequest"/>
<output message = "tns:SayHelloResponse"/>
</operation>
</portType>
here SayHelloRequest is request definition and SayHelloResponse is response defination. and Now suppose you have an Java Plain Object and then you need to define this on XSD like below code
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
you can define in XSD datatypes and its validation.
For simplicity xsd validate document and metadata anotherway WSDL is to describe the webservice location and operations. you can generate java classes from wsdl and yu can follow this link
https://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jst.ws.cxf.doc.user%2Ftasks%2Fcreate_client.html
Related
I have a WSDL file which also contains all types used in it (via <wsdl:types>
tag). When defining the types, I have something like this:
<wsdl:definitions name="service"
targetNamespace="http://www.xxx.yyy/reg/definitions" xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tax="http://www.xxx.yyy/reg/definitions" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
.............
<xs:complexType name="CompanyName">
<xs:sequence>
<xs:element name="Name" type="xs:string" />
<xs:element name="ShortName" type="xs:string" minOccurs="0" />
</xs:sequence>
<xs:attribute name="Language" type="tax:LanguageType" use="required"/>
<xs:assert test="ShortName or #Language != 'Language1'"/>
</xs:complexType>
.............
</wsdl:definitions>
Unfortunately, it doesn't work giving the following exception when I try to start the application on Tomcat:
javax.xml.ws.WebServiceException: org.xml.sax.SAXParseException; s4s-elt-invalid-content.1: The content of 'CompanyName' is invalid. Element 'assert' is invalid, misplaced, or occurs too often.
The WSDL version is 1.2 and I don't know which version of xsd it uses when types are described in it, so I don't know if it is a xsd version (1.0 vs. 1.1) issue or something else.
Can someone help me in finding the real issue?
EDIT: I have added the header of the wsdl.
I have added the version attribute (version="1.1") to <xs:schema>
definition but that didn't help either:
<xs:schema targetNamespace="http://www.xxx.yyy/reg/definitions" elementFormDefault="qualified" version="1.1">
Looks like assertions were introduced with XML Schema v1.1 when the XMLSchema definition moved over to w3.org.
Sample header:
<wsdl:description
targetNamespace="http://www.w3.org/2002/ws/sawsdl/spec/wsdl/order#"
xmlns="http://www.w3.org/2002/ws/sawsdl/spec/wsdl/order#"
xmlns:wsdl="http://www.w3.org/ns/wsdl"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:sawsdl="http://www.w3.org/ns/sawsdl">
I'm trying to wrap my head around Apache Camel using Jboss Fuse 6.2.1 and I don't understand how SOAP headers are being processed.
I have a WSDL from which I have generated classes for my input and output messages. The input consists of a header and a body while the output only consists of a body.
WSDL
<wsdl:types>
<xs:schema targetNamespace="http://cxftestserver.blueprint.me.com">
<xs:element name="input">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="Id" />
<xs:element type="xs:string" name="Name" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="output">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="Code" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schema targetNamespace="http://cxftestserver.blueprint.me.com/authentication">
<xs:element name="authHeader">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="username" />
<xs:element type="xs:string" name="password" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="inputTest">
<wsdl:part name="header" element="tns1:authHeader" />
<wsdl:part name="body" element="tns:input" />
</wsdl:message>
<wsdl:message name="outputTest">
<wsdl:part name="out" element="tns:output" />
</wsdl:message>
Blueprint
<bean id="myProcessor" class="com.me.blueprint.cxftestserver.MyProcessor" />
<cxf:cxfEndpoint id="test-ws" address="/Test" serviceClass="com.me.blueprint.cxftestserver.TestEndpoint" />
<camel:camelContext>
<camel:route>
<camel:from uri="cxf:bean:test-ws" />
<camel:process ref="myProcessor" />
</camel:route>
</camel:camelContext>
What I don't understand now is why the Message-body inside of the Exchange contains both the authHeader and the input? Every example I've read in the docs suggest that I should be able to extract the header by doing:
exchange.getIn().getHeaders(//insert your favorite parameter here);
but whenever I've tried that it would always return null. I wasted several hours looking in all the wrong places when I finally found that the Message-body contained the MessageContentsList-object holding both my SOAP-header and my SOAP-body.
Message inMessage = e.getIn();
AuthHeader header = inMessage.getBody(AuthHeader.class);
Input body = inMessage.getBody(Input.class);
Can someone please explain to me why and when this happens?
All depends on what dataFormat you prefer to use, for eg: if you use dataFormat=MESSAGE. Then you will be able to see the whole incoming message in your exchange, basically the whole message including headers will come in as a string. You can handle it straight away using xpath.
Refer this example for dataFormats -
https://github.com/gnanagurus/camel-guru-projects/blob/master/camel-cxf-geocoder-example/src/main/resources/META-INF/spring/beans-config.xml
But whatever they have suggested is also right, You can extract it using getHeaders(). Can you try configuring the CXF endpoint as mentioned in this example & make the dataFormat to be 'PAYLOAD'. (Basically in PAYLOAD you will get the soap body as a exchange body, rest in headers) I am sure, you will be able to read your headers using getHeaders().
Also, is there a reason why you have defined your CXF endpoint using your service class / why you have to generate your classes. If you have a reason ignore it, I tend to avoid classes in camel projects, rather I try the best to use the framework capabilities in XML itself. If you want to expose a SOAP based web service endpoint using camel, You don't have to generate any classes yourself - this example can lead/help you:
https://github.com/gnanagurus/camel-guru-projects/tree/master/camel-cxf-geocoder-example
Description about the above example:
http://bushorn.com/camel-web-services-expose-them/
Good luck
I believe I've found the answer to my initial question:
According to the documentation I've now come to understand that, when using POJO as data format, the consumer-endpoint looks at what parameters the requested method has in my SEI (Service Endpoint Interface (to which the serviceClass-attribute points.))
These parameters are then invoked into the Message-body (MessageContentsList-object) which would explain why both the header and the body are present.
I'm following this example to build a web service with Soap. Is there a way to remove the targetNamespace for the Soap response? With SoapUI I get this response:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:getAllResponse xmlns:ns2="http://spring.io/guides/gs-producing-web-service">
<ns2:timestamp>12/18/2015 10:51:02 AM</ns2:timestamp>
<ns2:MyItem>
<ns2:class>myClass</ns2:class>
<ns2:name>MyItemName</ns2:name>
</ns2:MyItem>
</ns2:getAllResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And would like to get it without the target namespace, e.g. like:
...
<MyItem>
<MyItem>
<class>myClass</class>
<name>MyItemName</name>
</MyItem>
I'm sending an empty request to get a list of MyItems. My xsd looks like this:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:tns="http://spring.io/guides/gs-producing-web-service"
targetNamespace="http://spring.io/guides/gs-producing-web-service">
<xs:element name="getAllRequest">
<xs:complexType>
<xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getAllResponse">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="1" name="timestamp" type="xs:string"/>
<xs:element maxOccurs="unbounded" name="MyItem" type="tns:MyItem"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="MyItem">
<xs:sequence>
<xs:element name="class" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
The MyItem class will be generated automatically and gets annotated with this:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "MyItem", propOrder = {
"class",
"name",
})
public class MyItem { //....
Is there any way to get a response without the target namespace? I know its purpose and that it's actually quite useful. But it happened that it can't be processed any further by another tool with this target namespace and looks like this:
<MyItem xmlns="http://spring.io/guides/gs-producing-web-service"> ...
Thanks in advance!
Is there any way to get a response without the target namespace?
I hope not. A SOAP web service should have a well-defined, published interface and every response that it sends should conform to that interface. Usually, the interface is described by a WSDL document.
And would like to get it without the target namespace
<MyItem>
<class>myClass</class>
<name>MyItemName</name>
</MyItem>
Being pedantic, but the absence of a namespace prefix does not mean that there is no namespace. There might be a default namespace in force. So you could achieve XML that looks exactly like the above and the MyItem, class and name tags might still have a non-empty namespace.
I know its purpose and that it's actually quite useful.
The purpose of a namespace in an XML document ( whether a web service response, or any other XML ) is to avoid polluting the global namespace. Do you really want 'name' and 'class' to have exactly one meaning in your applications? Or would it be better if each schema could define its own version of those?
But it happened that it can't be processed any further by another tool with this target namespace and looks like this:
<MyItem xmlns="http://spring.io/guides/gs-producing-web-service"> ...
That looks like valid XML, so what's the problem? Is that output produced by the 'other tool'? Or is it something that the 'other tool' cannot handle?
Here is the simple and easiest solution for that problem. Create Package-Info.Java file in your model package and add the below script to that.
#javax.xml.bind.annotation.XmlSchema(namespace = "http://spring.io/guides/gs-producing-web-service", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = { #javax.xml.bind.annotation.XmlNs(namespaceURI = "http://spring.io/guides/gs-producing-web-service", prefix = "") })
package my.com.scicom.stars.model;
And add elementFormDefault as "qualified" in your xsd or wsdl file.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://spring.io/guides/gs-producing-web-service"
targetNamespace="http://spring.io/guides/gs-producing-web-service"
elementFormDefault="qualified">
Trying to implement a SOAP Webservice for a client and I need a wsdl file to test the service by soapUI. But as you can see below, this xsd has no Request and Response methods, all requests and responses are defined as a a "type" in a base ServiceProvider element. So when I try to auto generate my wsdl file by spring-ws it does not generate a proper wsdl, because Spring-ws requires all requests and responses element names should end with "Request" "Response".
What can I do?
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified" targetNamespace="http://myurl" xmlns="http://myurl">
<xs:element name="ServiceProviderT" nillable="false">
<xs:annotation>
<xs:documentation>ServiceProviderT is the message spec for data sent between TechX and service providers or
vendors</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="Version" type="xs:string" nillable="false"/>
<xs:choice>
<xs:element name="Request" type="RequestType" nillable="false"/>
<xs:element name="Response" type="ResponseType" nillable="false"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
....
And this how I generate wsdl file
<sws:dynamic-wsdl id="myservice"
portTypeName="MyService"
locationUri="/myService"
targetNamespace="http://myurl">
<sws:xsd location="/schemas/my.xsd"/>
</sws:dynamic-wsdl>
There is no such requirement those are just the defaults. This is explained here in the Spring-WS reference guide. It also explains which properties to set to override those defaults.
The default request suffix is Request; the default response suffix is Response, though these can be changed by setting the requestSuffix and responseSuffix attributes on <dynamic-wsdl />, respectively.
<sws:dynamic-wsdl id="myservice"
portTypeName="MyService"
locationUri="/myService"
requestSuffix="YourRequestSuffixHere"
responseSuffix="YourResponseSuffixHere"
targetNamespace="http://myurl">
<sws:xsd location="/schemas/my.xsd"/>
</sws:dynamic-wsdl>
We have a POJO web service implemented in AXIS2 v1.5.2 running in Tomcat 6 behind Apache2 webserver.
For demonstration purposes, I will focus on the validateUser message and corresponding method.
All of the messages are behaving in a similar fashion.
I have seen this as well as a couple of other related questions but they do not seem to get to the bottom of the issue.
When requests are sent to the service, the parameters are being passed to the POJA as null and blank.
First the WSDL:
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns="http://service.icomet.com" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:ax21="http://util.java/xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://service.icomet.com">
<wsdl:types>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://util.java/xsd">
<xs:complexType name="Map">
<xs:sequence>
<xs:element minOccurs="0" name="empty" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:ax22="http://util.java/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://service.icomet.com">
<xs:import namespace="http://util.java/xsd"/>
<xs:element name="validateUser">
<xs:complexType>
<xs:sequence>
<xs:element name="user" nillable="true" type="xs:string"/>
<xs:element name="userPassword" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="validateUserRequest">
<wsdl:part name="parameters" element="ns:validateUser"/>
</wsdl:message>
After following along in the code of org.apache.axis2.rpc.receivers.RPCMessageReceiver, org.apache.axis2.rpc.receivers.RPCUtil and org.apache.axis2.databinding.utils.BeanUtil
what I see is the service getting my request with the params intact.
The OMElement printed in the log from:
BeanUtil.deserialize(OMElement response,
Object[] javaTypes,
ObjectSupplier objectSupplier) looks like this:
deserialize(OMElement response,
Object[] javaTypes,
ObjectSupplier objectSupplier)
looks like this:
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<ns:validateUser xmlns:ns="http://service.icomet.com">
<ns:user>test</ns:user>
<ns:userPassword>values</ns:userPassword>
</ns:validateUser>
After a call to get the children of the OMElement and looking at the first child of the above OMElement I see this:
<ns:validateUser xmlns:ns="http://service.icomet.com">
<ns:user>test</ns:user>
<ns:userPassword>values</ns:userPassword>
</ns:validateUser>
Calling getText() on the above OMElement returns multiple blank lines in the log.
I added the following method:
private static void showElement(OMElement omElement) {
System.out.println("onElement class:" + omElement.getClass().getName());
System.out.println("omElement:" + omElement);
System.out.println("omElement.getText:" + omElement.getText());
for (Iterator it = omElement.getChildElements(); it.hasNext();) {
Object object = it.next();
System.out.println("child class name:" + object.getClass().getName());
System.out.println("child to string:" + object);
}
for (Iterator it = omElement.getAllAttributes(); it.hasNext();) {
OMAttribute object = (OMAttribute) it.next();
System.out.println("OMAttribute:" + object.getAttributeValue());
}
}
to the BeanUtil class to have better look at this OMElement. This code returns the following:
onElement class:org.apache.axiom.om.impl.llom.OMElementImpl
omElement:<ns:validateUser xmlns:ns="http://service.icomet.com">
<ns:user>test</ns:user>
<ns:userPassword>values</ns:userPassword>
</ns:validateUser
omElement.getText:
child class name:org.apache.axiom.om.impl.llom.OMElementImpl
child to string:<ns:user xmlns:ns="http://service.icomet.com">test</ns:user>
child class name:org.apache.axiom.om.impl.llom.OMElementImpl
child to string:<ns:userPassword xmlns:ns="http://service.icomet.com">values</ns:userPassword>
So, I am seeing the values. They are arriving and getting in the door so to speak. However, due to the fact that org.apache.axis2.databinding.typemapping.SimpleTypeMapper.getSimpleTypeObject calls getText on the OMElement and returns an empty string, the RPCUtil.processRequest method is returning an object array with an empty string and a null object and this gets passed on to the POJO.
I know its a long question, but I figured I might as well add all this info up front.
Turns out to be a bug in AXIS2 1.5.
Some of the details to be found here
Defect was addressed in nightly build on 1/6/2011. Still waiting for confirmation as to what exactly was done to fix the issue. There were a couple of solutions discussed in the thread.
I used the most obvious answer for the moment and patched the code myself.