I have an existing Webservice with a complexType as a return value.
<xs:complexType name="dummy">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="A" type="xs:string" />
</xs:sequence>
</xs:complexType>
Later on (after a few clients are in Production) I want to extend my Webservice.
In Detail I want to add a new optional subelement of the complex type:
<xs:complexType name="dummy">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="A" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="B" type="xs:string" />
</xs:sequence>
</xs:complexType>
Am I breaking existing Clients? If yes, what is a correct/usual way to handle enhancements of existing Webservices?
Taking your question literary, the answer is yes.
Java clients are based on generated code, and they are validating if actual contract matches that from which the client is generated. I've broken contract for JAX-WS-generated Java client by adding new method - which theoretically should not be an issue. But I was setting endpoint address in initialization code.
Some clients that are not validating can work with changed contract as long as they do not meet unknown fields. In your case, as long as you optional new element won't show up, they will consume the message, but they will throw an error when such element will be existant in the message (our client has hmmm... well.. client, that was operating in such way, they've had old definition, but the new field was almost always null - and not present in XML).
Dynamically generated clients (such as in Python) are generating responses based on current contract, and because in that languages you can add new fields to existing objects, they will work without any problems in your case.
So the long answer is: it depends on what clients are using your contract.
How to manage such changes: it's not a nice way, but if you have no influence on what clients are used and when they are updated, leave the old web service and publish new version paralell under new URL.
Related
I am new to JAXB and dealing with XSDs. I am using the Maven JAXB2 plugin to marshall classes from them. I got them from the provider of a web service that I need to consume, but I am not sure if they have made an error in their documentation or if I just may not be dealing with the duplication correctly.
So I have two XSD file a.xsd and b.xsd, both of which reside in the same directory.
In a.xsd I have the decleration:
<xs:complexType name="AttributeType">
<xs:sequence>
<xs:element ref="AttributeValue" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="AttributeName" type="xs:string" use="required" />
<xs:attribute name="AttributeNamespace" type="xs:string"
use="required" />
</xs:complexType>
In b.xsd I have :
<xs:complexType name="AttributeType">
<xs:sequence>
<xs:element ref="AttributeValue" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="AttributeName" type="xs:string" use="required" />
<xs:attribute name="AttributeNamespace" type="xs:string"
use="required" />
</xs:complexType>
The error I am getting in Maven is
A class/interface with the same name "com.mycompany.voice.gcs.correspondenceservice.v1.AttributeType" is already in use. Use a class customization to resolve this conflict.
They look identical to me and it doesn't make sense to have them duplicated. But as I said, I'm new to this stuff so I wanted to make sure that I wasn't missing something.
Thanks. :)
As long as these two schemas have different namespaces, it is OK. Look for the targetNamespace attribite of the root schema element.
If target namespace is missing or if target namespaces are the same, this might be a problem.
This looks like a "copy-paste" schema design, not a preferred modular design, but it's hard to judge without seeing the schemas.
"Copy-paste" design is not atypical but is also not a good practice.
The service provider gave me the wrong files with duplicating complex types. As a result the duplicates were failing.
I would like to validate a custom XML document against a schema.
This document would include a structure with any number of elements, each having a specific attribute. Something like this:
<Root xmlns="http://tns">
<Records>
<FirstRecord attr='whatever'>content for first record</FirstRecord>
<SecondRecord attr='whatever'>content for first record</SecondRecord>
...
<LastRecord attr='whatever'>content for first record</LastRecord>
</Records>
</Root>
The author of the XML document can include any number of records, each with an arbitrary name of his or her choosing. How is this possible to validate this against an XML Schema ?
I have tried to specify the appropriate structure type in a schema, but I do not know how to reference it in the appropriate location:
<xs:schema xmlns="http://tns" targetNamespace="http://tns" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="RecordType"> <!-- This is my record type -->
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attr" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Records">
<!-- This is where records should go -->
<xs:complexType />
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
What you describe is possible in XSD 1.1, and something very similar is possible in XSD 1.0, which is not to say it's an advisable design.
In XML vocabularies, the element type normally conveys relevant information about the type of information, and it is the name of the element type that is used to drive validation in most XML schema languages; the design you describe is (some would say) a little bit like asking if I can define an object class in Java, or a struct in C, which obeys the constraints that the members can have arbitrary names, as long as one of them is an integer with the value 42. That, or something like it, may well be possible, but most experienced designers will feel strongly that this is almost certainly not the right way to go about solving any normal problem.
On the other hand, doing unusual and awkward things with a system can sometimes help in learning how to use the system effectively. (You never know a system well, said a friend of mine once, until you have thoroughly abused it.) So my answer has two parts: how to come as close as possible to the design you specify in XSD, and alternatives you might consider instead.
The simplest way to specify the language you seem to want in XSD 1.1 is to define an assertion on the Records element which says (1) that every child of Records has an 'attr' attribute and (2) that no child of Records has any children. You'll have something like this:
...
<xs:element minOccurs="1" maxOccurs="1" name="Records">
<xs:complexType>
<xs:sequence>
<xs:any/>
</xs:sequence>
<xs:assert
test="every $child in * satisfies $child/#attr"/>
<xs:assert
test="not(*/*)"/>
</xs:complexType>
</xs:element>
...
As you can see, this is very similar to what InfantPro'Aravind' has described; it avoids the problems identified by InfantPro'Aravind' by using assertion, not type assignment, to impose the constraints you impose.
In XSD 1.0, assertion is not available, and the only way I can think of to come close to the design you describe is define an abstract element, which I'll call Record, as the child of Records, and to require that the elements which actually occur as children of Records be declared as being substitutable for this abstract type (which in turn requires that their types be derived from type RecordType). Your schema might say something like this:
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Records">
<xs:complexType>
<xs:sequence>
<xs:element name="Record"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="RecordType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attr"
type="xs:string"
use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Record"
type="RecordType"
abstract="true"/>
Elsewhere in the schema (possibly in a separate schema document) you will need to declare FirstRecord, etc., and specify that they are substitutable for Record, thus:
<xs:element name="FirstRecord" substitutionGroup="Record"/>
<xs:element name="SecondRecord" substitutionGroup="Record"/>
<xs:element name="ThirdRecord" substitutionGroup="Record"/>
...
At some level, this matches your description, though I suspect you did not want to have to declare FirstRecord, SecondRecord, etc.
Having described ways in which XSD can do what you describe, I should also say that I wouldn't recommend either of these approaches. Instead, I'd design the XML vocabulary differently to work more naturally with XSD.
In the design as you specify it, every record appears to have the same type, but in addition to the content of the element they are allowed to convey a certain additional quantity of information by having a different name (FirstRecord, SecondRecord, etc.). This additional information could just as easily be conveyed in an attribute, which would allow you to specify Record as a concrete element, rather than an abstract element, giving it an extra "alternate-name" attribute. Your sample data would then take a form like this:
<Root xmlns="http://tns">
<Records>
<Record
alternate-name="FirstRecord"
attr='whatever'>content for first record</Record>
<Record
alternate-name="SecondRecord"
attr='whatever'>content for first record</Record>
...
<Record
alternate-name="LastRecord"
attr='whatever'>content for first record</Record>
</Records>
</Root>
This will be more or less acceptable depending on whether you or your data providers or tools in your tool chain attach some mystic or other significance to having the string "FirstRecord" be an element type name instead of an attribute value.
Alternatively, one could say that the point of the design is to allow Records to contain an arbitrary sequence of elements of arbitrary structure (on this account, the restriction to xs:string is just an artifact of your example and is not really desired in reality) as long as we have, for each record, the information recorded in the 'attr' attribute. Easy enough to specify this: define 'Record' as a concrete element with an 'attr' attribute, accepting one child which can be any XML element:
<xs:element name="Record">
<xs:complexType>
<xs:sequence>
<xs:any processContents="lax"/>
</xs:sequence>
<xs:attribute name="attr"
use="required"
type="xs:string"/>
</xs:complexType>
</xs:element>
The value of the 'processContents' attribute can be changed to 'strict' or 'skip' or kept at 'lax', depending on whether you want FirstRecord, SecondRecord, etc. to be validated (and declared) or not.
I guess this is not possible with XSD alone!
When you say
any number of records, each with an arbitrary name of his or her choosing.
That forces us to use <xs:any/> element but! Having an element declared as any doesn't allow you to validate attributes under it..
So .. the answer is NO!
Is it possible to have a combination of xs:all and xs:sequence?
I've have a xml structure with an element probenode which consist of the elements name, id, url, tags, priority, statuws_raw, active. And a combination of device and group.
device and group can occur zero or more times...
the solution below doesn't work because it is not allowed to use unbounded for an element. within an all group.
<xs:complexType name="probenodetype">
<xs:all>
<xs:element name="name" type="xs:string" />
<xs:element name="id" type="xs:unsignedInt" />
<xs:element name="url" type="xs:string" />
<xs:element name="tags" />
<xs:element name="priority" type="xs:unsignedInt" />
<xs:element name="status_raw" type="xs:unsignedInt" />
<xs:element name="active" type="xs:boolean" />
<xs:element name="device" type="devicetype" minOccurs="0" maxOccurs="unbounded">
<!-- zie devicetype -->
</xs:element>
<xs:element name="group" type="grouptype" minOccurs="0" maxOccurs="unbounded">
<!-- zie grouptype -->
</xs:element>
</xs:all>
<xs:attribute name="noaccess" type="xs:integer" use="optional" />
</xs:complexType>
In XSD 1.0, the children of xs:all must have maxOccurs set to 1.
In XSD 1.1 this constraint is lifted.
So your alternatives appear to be:
Use an XSD 1.1 processor (Saxon or Xerces-J).
Use XSD 1.0 and impose an order on the children of probenodetype. This is a problem if the order in which the children appear carries information (so id followed by url is different from url followed by id ...).
In some simple cases it's feasible to write a content model that accepts precisely what you suggest you want, using only choice and sequence, but with seven required elements the resulting content model is likely to be too long and complex to be useful.
At this point some users give up and write a complex type with a repeatable OR-group and move the responsibility for checking that name, id, url, etc. all occur at least once and at most once into the application; that allows the generator of the XML not to have to worry about a fixed order (and opens a side channel for information leakage, which matters to some people) but also renders the schema somewhat less useful as documentation of the contract between data provider and data consumer.
I would like to allow for an element to either contain an attribute OR define a more complex type.
Something like
<myElement someAttr="..."/>
or
<myElement>
<...>
</myElement>
That is, if someAttr exists then I do not want to allow sub elements and if it doesn't then I want to.
The reason for this is I want to have an "include" feature where I include a file which is essentially inserted into the element. But I don't want both. You can either include additional external xml code into the element or add your own BUT not both. (or also to have it inserted from a separate part of the xml)
This is mainly for simplifying a complex xml so that the structure is easily understood.
I doubt you will be able to express something like that in XML schema at this point.
You can make an attribute optional, e.g. it can be present or not. But you cannot express something like if the attribute is not present, then include other complex content with the current means.
You'll have to either check this programmatically yourself, or maybe investigate if other XML description languages like RelaxNG or Schematron might be able to help.
Perhaps with a static choice and you change the myElement name ?
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:choice>
<xs:element name="myElementWithAttrs">
<xs:complexType>
<xs:attribute name="someAttrs" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="myElementWithoutAttrs">
<xs:complexType>
<xs:sequence>
<xs:any processContents="skip"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
This XSD portion was obtained from: http://www.iana.org/assignments/xml-registry/schema/netconf.xsd
<xs:complexType name="rpcType">
<xs:sequence>
<xs:element ref="rpcOperation"/>
</xs:sequence>
<xs:attribute name="message-id" type="messageIdType" use="required"/>
<xs:anyAttribute processContents="lax"/>
</xs:complexType>
<xs:element name="rpc" type="rpcType"/>
And is the core to function calls in NETCONF being the node of an XML document. I am curious as to why it is not something like:
<xs:element name="rpcType">
<xs:complexType>
<xs:sequence>
<xs:element ref="rpcOperation"/>
</xs:sequence>
<xs:attribute name="message-id" type="messageIdType" use="required"/>
<xs:anyAttribute processContents="lax"/>
</xs:complexType>
</xs:element>
The reasoning is that in #1 when trying to marshall a bean (in jaxb2) I get the exception:
[com.sun.istack.SAXException2: unable to marshal type "netconf.RpcType" as an element because it is missing an #XmlRootElement annotation]
I have been reading this article over and over again, and really cant get a hold of the difference, and why it would be #1 vs #2...
It's not obvious, I'll grant you. It comes down to the type vs element decision.
When you have something like
<xs:element name="rpcType">
<xs:complexType>
This is essentially an "anonymous type", and is a type which can never occur anywhere other than inside the element rpcType. Because of this certainty, XJC knows that that type will always have the name rpcType, and so generates an #XmlRootElement annotation for it, with the rpcType name.
On the other hand, when you have
<xs:complexType name="rpcType">
then this defines a re-usable type which could potentially be referred to by several different elements. The fact that in your schema it is only referred to by one element is irrelevant. Because of this uncertainty, XJC hedges its bets and does not generate an #XmlRootElement.
The JAXB Reference Implementation has a proprietary XJC flag called "simple binding mode" which, among other things, assumes that the schema you're compiling will never be extended or combined with another. This allows it to make certain assumptions, so if it sees a named complexType only being used by one element, then it will often generate #XmlRootElement for it.
The reality is rather more subtle and complex than that, but in 90% of cases, this is a sufficient explanation.
Quite an involved question. There are many reasons to design schemas using types rather than elements (this approach is called the "venetian blind" approach versus "salami slice" for using global elements). One of the reasons is that types can be sub-typed, and another that it may be useful to only have elements global that can be root elements.
See this article for some more details on the schema side.
Now, as for the JAXB question in particular. The problem is that you created a class corresponding to a type and tried to serialise it. That means JAXB knows its content model, but not what the element name should be. You need to attach your RpcType to an element (JAXBElement), for example:
marshaller.marshal(new ObjectFactory().createRpc(myRpcType));
The ObjectFactory was placed into the package created by JAXB for you.
Advantages of Named Types
The advantage of a schema using global/named types is that child/sub types can be created that extend the parent type.
<xs:complexType name="rpcType">
<xs:sequence>
<xs:element ref="rpcOperation"/>
</xs:sequence>
<xs:attribute name="message-id" type="messageIdType" use="required"/>
<xs:anyAttribute processContents="lax"/>
</xs:complexType>
<xs:element name="rpc" type="rpcType"/>
The above fragment would allow the following child type to be created:
<xs:complexType name="myRPCType">
<xs:complexContent>
<xs:extension base="rpcType">
<xs:sequence>
<xs:element name="childProperty" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Impact on JAXB
Another aspect of named types is that they may be used by multiple elements:
<xs:element name="FOO" type="rpcType"/>
<xs:element name="BAR" type="rpcType"/>
This means that the schema to Java compiler cannot simply just pick one of the possible elements to be the #XmlRootElement for the class corresponding to "rpcType".