Is it possible to extract an attribute (as in XML attribute value) from a RequestWrapper object?
In my implementation, I'd like to use the value of the attribute, but can't reference it with #WebParam, as that is only for elements (I believe)
#SOAPBinding is defined "Document/Literal/Wrapped"
WSDL (relevant sections, target attribute at **):
<s:element name="GetStatus">
<s:complexType>
<s:element minOccurs="0" maxOccurs="1" name="Entity" type="s0:Entity"/>
**<s:attribute name="Handle" type="s:string"/>
</s:complexType>
</s:element>
<s:element name="GetStatusResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="StatusCode" type="s0:StatusCode"/>
<s:element minOccurs="0" maxOccurs="1" name="Server" type="s0:Server"/>
</s:sequence>
</s:complexType>
</s:element>
<message name="GetStatusIn">
<part name="parameters" element="s0:GetStatus"/>
</message>
<message name="GetStatusOut">
<part name="parameters" element="s0:GetStatusResponse"/>
</message>
<portType name="Service">
<operation name="GetStatus">
<input message="s0:GetStatusIn"/>
<output message="s0:GetStatusOut"/>
</operation>
</portType>
SEI abstract method (able to specify XML elements with WebParam):
#WebMethod(operationName="GetStatus")
#RequestWrapper(localName=“GetStatus",className="com.example.GetStatus")
#ResponseWrapper(localName=“GetStatusResponse",className="com.example.GetStatusResponse")
public void getStatus(
#WebParam(name="Entity”)Entity entity,
#WebParam(name="StatusCode",mode=WebParam.Mode.OUT)Holder<StatusCode> statusCode,
#WebParam(name="Server", mode=WebParam.Mode.OUT)Holder<Server> server
);
Implementation:
#Override
public void getStatus(
Entity entity,
Holder<StatusCode> statusCode,
Holder<Server> server
) { ... }
It’s obvious how I can read the value of the #RequestWrapper bean Status (Entity via #WebParam), but is there any way to access the value (Handle) within Status. WebParam, as far as I understand, does not support attributes, only elements.
An alternate way to ask/seek solution might be asking how to access the full bean being referenced by RequestWrapper, in this case GetStatus.
I know if I transition to Document/Literal/Bare I can simply have the parameters and return value reflect the bean, but I'd prefer to solve this using wrapped as all information points to this being the most widely preferred binding.
Self-answered for posterity.
No. To qualify as wrapped style, only elements must be present.
Was reviewing the JAX-WS specification overnight
2.3.1.2 Wrapper Style
A WSDL operation qualifies for wrapper style mapping only if the following criteria are met:
(i) The operation’s input and output messages (if present) each contain only a single part
(ii) The input message part refers to a global element declaration whose localname is equal to the operation name
(iii) The output message (if present) part refers to a global element declaration
(iv) The elements referred to by the input and output message (if present) parts (henceforth referred to as
wrapper elements) are both complex types defined using the xsd:sequence compositor
(v) The wrapper elements only contain child elements, they MUST not contain other structures such
as wildcards (element or attribute), xsd:choice, substitution groups (element references are not
permitted) or attributes; furthermore, they MUST not be nillable.
Non-elements can be present too, as long as they are contained inside an javax.xml.ws.Holder object.
Related
I have a SOAP URL with one of the input parameters of enumerated type as below. With SOAPUI I'm just able to remove the ? mark and able to execute the request successfully. <urn:Comm_Source></urn:Comm_Source>
I created client code using wsimport and it creates the input method parameter as CommSourceType object. If I pass null for this value the web service fails.
<xsd:element maxOccurs="1" minOccurs="0" name="Comm_Source" nillable="false" type="s0:Comm_SourceType"/>
There is a lack of information for the complete answer (eg the whole wsdl/xsd or what means: If I pass null for this value the web service fails.).
In general:
null is not the same as an empty string.
<urn:Comm_Source></urn:Comm_Source> - is an empty string
<urn:Comm_Source xsi:nil="true" /> - is a null value (xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance")
the specified element <xsd:element maxOccurs="1" minOccurs="0" name="Comm_Source" nillable="false" type="s0:Comm_SourceType" /> does not support null because there is nillable="false".
The element can either be omitted or an empty string can be written in it.
I have schema where I want either of element is mandatory and they should not repeat.
EDITED -- Here valid request can contain both query and id in request or with only query or id element is also valid.
e.g:
<soapenv:Body>
<ws:SomeOperation>
<SoapOperation>
<query>test</query>
<id>1</id>
</SoapOperation>
</ws:SomeOperation>
</soapenv:Body>
Valid Requests:
with query and id element.
with only query element.
with only id element.
Invalid Requests:
without query and id element.
with multiple query element.
with multiple id element.
I want query or id must be present. One of them is mandatory.
I tried below things:
<xs:sequence>
<xs:element minOccurs="0" name="id">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="query">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
Here the problem is none of them is mandatory and making any one as minoccurs=1 will make that field mandatory ( e.g. if i mark id as minoccurs=1 then id field is mandatory but my valid request can have only query and not id) and there can be possibility of both tags to be present as well.
Also I tried choice tag.
Using simple choice with will make these tags repeat which also i do not want. The tag should not repeat.
I'm using Sparx Enterprise Architect v10 to generate XSD schema from XML Schema graphic model.
Basically, I created 2 different XSDschema : 1 main XSDshema with my entities that are complexType :
<xs:complexType name="EntitytXT">
<xs:annotation>
<xs:documentation>This is the definition of an EntitytXT</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="element1" type="shared:StringXT" minOccurs="1" maxOccurs="1"/>
<xs:element name="element2" type="shared:StringXT" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
The other created XSDschema is the "shared one" and is simple with just the type StringXT; composed of things like that :
<xs:simpleType name="StringXT">
<xs:restriction base="xs:string">
<xs:maxLength value="5" />
</xs:restriction>
</xs:simpleType>`
What I want to do is :
Whenever I generate the first main XSD with EA, that the imported xsd "shared" path
xmlns:v1shared="http://xxxx/common/v1/shared" AND that the tag
<xs:import namespace="http://xxxx/shared" schemaLocation="http:/xx/xx/common/shared.xsd" />
are present in my generated resulting XSD.
Many thanks.
So, after almost a day, it ended up to be fairly obvious.
I didn't find any specific answer to this practical import procedure for different XSDschema in EA.
The thing is : you have 2 XSDschema as 2 different packages. To ensure the "shared" one to be imported into the main one (with the tag <xs:import explicitly in the xsd header, you must :
Enter 2 different target Namespace, one concerning each XSDschema package
Add the "shared" (+its namespace) in the XMLNS tab within the main XSDschema properties
Double check the SchemaLocation Tagged value for each XSDschema package
And last, but not least, in the xs sequence for your main complexTypes <xs:element name="element1" type="shared:StringXT" the "type" tag must be just :StringXT (without the 'shared') in order to 'link' the main XSDschema and the shared one. You can go to the XSDschema attributes and check their tagged values. You should see something like +Attributes +from StringXT
hope it helps!
I am a SOAP newb assigned to resurrecting an old soap interface. I've ported the soap service onto a new tomcat at a new path (and left the client unchanged). I send the request:
http://myserver:8181/soap/SoapTest?wsdl
and I get back:
<wsdl:definitions xmlns:ns1="http://webservices.mycompany.com"
xmlns:ns3="http://schemas.xmlsoap.org/wsdl/soap/http"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mycompany.com/SoapTest"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="SoapTestService"
targetNamespace="http://www.mycompany.com/SoapTest">
<wsdl:import location="http://myserver:8181/soap/SoapTest?wsdl=SoapTest.wsdl"
namespace="http://webservices.mycompany.com"></wsdl:import>
<wsdl:binding name="SoapTestServiceSoapBinding" type="ns1:SoapTest">...</wsdl:binding>
<wsdl:service name="SoapTestService">...</wsdl:service>
</wsdl:definitions>
Seems promising. A request to the import location SoapTest?wsdl=SoapTest.wsdl returns:
<wsdl:definitions xmlns:ns1="http://webservices.mycompany.com"
xmlns:ns2="http://jaxb.dev.java.net/array" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="SoapTest"
targetNamespace="http://webservices.mycompany.com">
<wsdl:types>
<xs:schema xmlns:tns="http://webservices.mycompany.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://webservices.mycompany.com" version="1.0">
<xs:complexType name="sessionObj">
<xs:sequence>
<xs:element name="code" type="xs:int"/>
<xs:element name="id" type="xs:long"/>
<xs:element minOccurs="0" name="role" type="xs:string"/>
<xs:element minOccurs="0" name="username" type="xs:string"/>
</xs:sequence>
</xs:complexType>
... (and so on)
So the client can receive member xs name:type associations but seems not to be - or not to be applying them. That is ...
HUH.. upon review, I see xs being used as a namespace but xmlns:xsd defined?? How might this happen?
ZSI client queries (from Windows, if that makes any difference) to this interface (Linux) receive responses containing the expected data payload but then map each data item into an individual "property" - resulting in a list of generic properties.
I was expecting a list of typed members, with each property cast to its xs type (e.g. int, long, string, string for the above), right?
Thanks in advance for any clues.
Given that you've not provided enough information for the real issue at hand, I will base this on the basis of you been a newb, and therefore wrap my answer around portions I find relevant to your question.
Your main web service is described in the WSDL http://myserver:8181/soap/SoapTest?wsdl, which holds an import to a parent WSDL. This parent WSDL holds service definitions which can be bind by your main service.
Seems promising. A request to the import location
SoapTest?wsdl=SoapTest.wsdl returns:
..
From the document definition provided above, the import:
<wsdl:import location="http://myserver:8181/soap/SoapTest?wsdl=SoapTest.wsdl"
namespace="http://webservices.mycompany.com">
</wsdl:import>
injects the parent WSDL file which holds the schema defintion for all elements and attributes relevant for your service. Meaning a standalone call to it, will reveal the xs namespace definition. See here for more on schema and datatypes.
HUH.. upon review, I see xs being used as a namespace but xmlns:xsd
defined?? How might this happen?
Yes, the schema is defined not as a separate file, but as part of the WSDL. It is defined between <wsdl:types> tags:
<wsdl:types>
<xs:schema xmlns:tns="http://webservices.mycompany.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://webservices.mycompany.com" version="1.0">
[..]
</wsdl:types>
See here also for more on ZSI binding and stub generation.
From ZSI documentation:
If the operation invoked returns a ComplexType, typecode information must be provided in order to tell ZSI how to deserialize the response.
In order for ZSI to transparently deserialize the returned complex type into a Person instance, a module defining the class and its typecode must be appended to the ZSI.Path list. It is also possible to explicitly tell ZSI what class and typecode to use by passing the class as a parameter to the Binding.Receive() method. The first method is often preferred, particularly for publically-distributed libraries.
Code Generation from WSDL and XML Schema is the second way ZSI provides to access WSDL services. Given the path to a WSDL service, two files are generated, a 'service' file and a 'types' file, that one can then use to access the service.
I use Hyperjaxb3 to generate JPA entities from XSD schema. I have a xsd:string type that I want to use for description text (text area in the UI):
<xsd:complexType name="Description">
<xsd:simpleContent>
<xsd:extension base="**xsd:string**">
<xsd:attribute name="abc" type="xsd:NCName" use="optional" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
Hyperjaxb3 generates class (entity) Description with attribute value, annotated like this:
#Basic
#Column(name = "VALUE_", **length = 255**)
public String getValue() {
return value;
}
The questions I have:
I saw that if I put xsd:maxLength restriction on xsd:simpleType, JPA #Column.length has the value of maxLength. How can I set xsd:rescriction on xsd:simpleContent that is xsd:extension of xsd:string? Do I have to define a complexType with xsd:resctriction that I will extend? And if yes, will Hyperjaxb generate #Column.length by my restriction. I tried following:
<xsd:simpleType name="DescriptionParent">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="4096" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="Description">
<xsd:simpleContent>
<xsd:extension base="DescriptionParent">
<xsd:attribute name="abc" type="xsd:NCName" use="optional" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
But the JPA column length is still 255.
Is it also possible to set in my JAXB customization (*.xjb file) the lenght of the column for given type (somehow let hyperjaxb know that this is the orm I want to use for my specific type)? Or is it totally out of the way and xsd:maxLength should be used (above) I managed to set it globally for Hyperjaxb customization:
Thanks for your help.
Second question: yes, you can configure global type mappings for simple types.
See Per-type customization for single properties.
First question: it seems to be a bug/missing feature, please file an issue here.