I tend to use external JAXB bindings files for my Schema-to-Java compilation. This works just fine, but I did notice one thing that I've started wondering about. It's not really JAXB-specific, more like an XPath question, but the context helps.
Suppose we have this schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:test="www.acme.com"
targetNamespace="www.acme.com"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="el1"/>
<xs:complexType name="testType">
<xs:sequence>
<xs:element ref="test:el1"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
The element reference in the complex type requires the prefix "test", bound to our target namespace, to find the element definition. If we omitted the prefix, a schema processor would complain that it can't find the element it refers. So obviously the reference is a qualified name and a schema processor is aware of this.
Now take the following bindings file extract for XJC:
<bindings node="//xs:complexType[#name='testType']">
<bindings node=".//xs:element[#ref='test:el1']">
<property name="element1"/>
</bindings>
</bindings>
The binding for the complex type is clear. We select it by name, and the xs prefix is bound in the bindings file's root (not shown here). It might as well be xsd.
What bugs me is the nested binding. In the context of our complex type node, we select an xs:element node for which attribute ref has value test:el1. But that value is simply regarded as text. The XML processor has no knowledge of the fact that it's supposed to be a qualified name and test: is actually a prefix declaration bound to a namespace.
Now I know I'm nitpicking, but the actual prefix string should have no importance, only the namespace URI itself. Someone could change the test prefix in the schema to acme and it would still be the same schema semantically. However, my bindings file would no longer work.
So, is there any way to construct the XPath expression without relying on knowledge of the prefix, only the namespace URI? It's obviously not a big problem, but I'm curious about this.
Is there any way to construct the
XPath expression without relying on
knowledge of the prefix, only the
namespace URI?
If you talk about an attribute value, this is XPath 1.0
.//xs:element[
namespace::*[
. = 'www.acme.com'
][
susbtring-before(
../#ref,
':'
)
= name()
]
and
substring(
concat(':', #ref),
string-length(#ref) - 1
)
= 'el1'
]
In XPath 2.0 is much more simple:
.//xs:element[resolve-QName(#ref,.) eq QName('www.acme.com','el1')]
Related
Currently I am using the Basic resource type for coding test cases like this:
<!-- https://simplifier.net/validate?scope=eRezeptAbrechnungsdaten#current&fhirVersion=R4 -->
<Basic xmlns="http://hl7.org/fhir">
<code>
<coding>
<system value="http://terminology.hl7.org/CodeSystem/basic-resource-type"/>
<code value="study"/>
</coding>
</code>
<!-- "http://fhir.de/CodeSystem/ifa/pzn" is 'preferred' ... -->
<extension url="https://fhir.gkvsv.de/StructureDefinition/GKVSV_EX_ERP_Import_PZN">
<valueCoding>
<system value="http://fhir.de/CodeSystem/ifa/pzn" />
<code value="." />
</valueCoding>
</extension>
<!-- ... but not mandatory -->
<extension url="https://fhir.gkvsv.de/StructureDefinition/GKVSV_EX_ERP_Import_PZN">
<valueCoding>
<system value="http://fhir.de/NamingSystem/arge-ik/iknr"/>
<code value="." />
</valueCoding>
</extension>
</Basic>
These are test cases for validating FHIR validators, in case anyone wondered. ;-)
The block for the mandatory Basic.code element detracts a bit from the actual payload. Is there some other resource type that could be used in a similar fashion and which does not have any mandatory fields?
If you would want an actual resource type, and not be limited by Parameters, you could look at using Patient. That has no mandatory fields, and can be persisted etc.
The Parameters resource type has no required top-level fields if you just want to use it for extensions.
The purpose of Basic.code is to allow tools to disambiguate instances of Basic, given that Basic can be used for anything. Basic.code is the only element required and it allows non-customized implementations to still be able to filter and search Basic instances to a limited extent without needing to support custom search parameters. In many systems, it determines whether they can accept the Basic resource at all and/or where it gets mapped within their system.
Basic is the only resource that is intended to be created, updated, searched and otherwise handled that is 'generic' and can be used for any purpose.
With jaxb I want to generate pojos from xsd.
But the xsd is provided by external vendor, where element have meaninful names,
but types are weird. Just an example:
<xs:element name="PersonAddress" type="PerAdr" />
<xs:complexType name="PerAdr">
<xs:sequence>
<xs:element name="street" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
<xs:element name="house" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
So generated class is called PerAdr.
How to make it generating classes where their names are element names, not type so it would generate in this case class PersonAddress.
I have a huge xsd, so thinking about a clever way of doing it, not just writing hundreds of lines in .xjb file
I am not exactly a professional in JAXB. But I've looked at JAXB specification (here: http://download.oracle.com/otn-pub/jcp/jaxb-2.0-fr-oth-JSpec/jaxb-2_0-fr-spec.pdf) and found the following:
The characteristics of the schema-derived Element class are derived in
terms of the properties of the “Element Declaration Schema Component” on
page 349 as follows:
The name of the generated Java Element class is derived from the
element declaration {name} using the XML Name to Java identifier
mapping algorithm for class names.
Each generated Element class must extend the Java value class javax.xml.bind.JAXBElement<T>. The next bullet specifies the
schema-derived Java class name to use for generic parameter T.
If the element declaration’s {type definition} is
Anonymous: Generic parameter T from the second bullet is set to the schema-derived class represented the anonymous type definition generated as specified
in Section 6.7.3.
Named: Generic parameter T from the second bullet is set to the Java class representing the element declaration’s {type definition}.
So, one may conclude from that: Once you have an XSD element with a named XSD type, you've got to deal with a Java class representing that type and named after it. That's logical. After all, you may have different XSD elements with the same global type. That's the default mapping.
However, JAXB allows for customizations (of the XML schema), with which you can override certain things. For instance, you can modify the name of the Java class generated by the XSD type, e.g:
<xs:complexType name="USAddress">
<xs:annotation> <xs:appinfo>
<jaxb:class name="MyAddress" />
</xs:appinfo></xs:annotation>
<xs:sequence>...</xs:sequence>
<xs:attribute name="country" type="xs:string"/>
</xs:complexType>
So, instead of USAddress, the result Java class will be named MyAddress. This looks like a solution to your problem, but to take advantage of it, you will need to modify every type definition in your XSD, which sounds daunting because your schema is huge.
So, what can you do?
First of all, you need to make sure that each XSD element in your schema and its (globally defined) type uniquely correspond each other. If there happen to be several different XSD elements with the same type, obviously the type name cannot be equal to all of them. In that case, if you don't like the original type names, you just need to edit that schema manually and give those types different names as it better fits to you.
Any automation is possible only when the relation XSD element <-> its XSD type is unique! In that case, you can derive the type name from the element name: make it the same or add, for instance, T prefix: TPersonAddress.
That is typically called refactoring and can be done automatically. The question is how?
Well, since XSD is XML, you can write an XSLT script that does the necessary transformation. But that may be not so straightforward, because you will have to parse the schema a bit. That is, to recognize every XSD element there and find the corresponding XSD type, and then to change the type name at both locations. Alternatively, you can insert those customization directives (<jaxb:...> elements) within the definition of each XSD type, as mentioned above. I don't know how much it would take to program such things. That will definitely come down to the creation of an index (with <xsl:key> construct) and iterating by it.
Alternatively, I can suggest you some unorthodox approach. We have developed a tool called FlexDoc/XML. Essentially, it is a transformer of XML files into anything. The transformation is programmed using some templates that work similar to XSLT.
The original idea was to extend that XSLT-like approach to any kind of Java based data-sources provided via various APIs. For instance, we have a similar product called
FlexDoc/Javadoc that mimics standard Javadoc. But then we realized that XML itself is also a good field full of various heavy-lifting tasks, for which XSLT is too lightweight. For instance, the generation of easily navigable single documentation by hundreds of XSD and WSDL files, for which we have two template sets now: XSDDoc and WSDLDoc. (We are working also on a similar thing for JSON Schemas).
Using FlexDoc/XML it is possible to create a template that does what you need (renaming those XSD types). That can be accomplished in a matter of a hour, and we will do it for you, if you purchase eventually a "FlexDoc/XML SDK" license. (People typically buy the SDK license to customize XSDDoc/WSDLDoc templates. But it can be equally used as a separate tool for the tasks like yours.)
I have developed a web service that accepts and responds with a common message structure. Meaning, this message structure is made to be generic. The way we made it generic is using the following XML schema:
<xs:complexType name="HeaderType">
<xs:complexType name="MessageType">
<xs:complexType name="PayloadType">
where PayloadType is the following:
<xs:complexType name="PayloadType">
<xs:annotation>
<xs:documentation>Payload container</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice>
<xs:element name="CreateExceptionSeverity" type="cmsmsg:ExceptionSeverity" minOccurs="0">
<xs:annotation>
<xs:documentation>CreateExceptionSeverity is a hello world operation that takes in a app id, id, name, and description where the web service creates a new entry in EXCEPTIONSEVERITY table.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="OperationSet" type="cmsmsg:OperationSet" minOccurs="0">
<xs:annotation>
<xs:documentation>Each operation set is a collection of operations that may require operational-integrity and/or sequence control.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Compressed" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>For compressed and/or binary, uuencoded payloads</xs:documentation>
</xs:annotation>
</xs:element>
**<xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other">**
<xs:annotation>
<xs:documentation>For XML payloads, usually CIM profiles defined using an XSD in a profile-specific namespace.</xs:documentation>
</xs:annotation>
</xs:any>
</xs:choice>
<xs:element name="Format" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>Hint as to format of payload, e.g. XML, RDF, SVF, BINARY, PDF, ...</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
So, the line:
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##other">
makes this structure flexible enough to send data when invoking the web service and when the web service sends back the response. This web service is deployed on a TIBCO server (uses Tomcat) and will be invoked through way of SOAP/HTTP.
The client for this web service is a Java Spring web app. My question is: how can the Java code deal with this Any element because it requires a concrete XML type like integer, string, or a complex type? Any direction here will be much appreciated.
Please don't do this. I've worked with these sort of "generic" web services before and they are the equivalent of having a java API where every method has the signature
public Object methodName(Object o);
Yes, it's all very generic, but it conveys no information on how to use it (A well designed interface conveys how it should be used, the same way the handle of a tea pot suggests that the tea pot should be picked up by the handle). When someone wants to develop an application that consumes your service, how do they figure out what to send and what they'll get back? If it's in some other document, then you've basically created your own bespoke web service description language, which won't integrate with any tooling (like Spring or Axis-2) and will require a lot of extra manual code to be written.
Additionally, you're going to have to write extra code in your service implementation to validate the content of the payloads. This means extra work to maintain and higher chance of defects.
Please use concrete XML inputs and responses for your Web Service operations and get rid of the any's. Not only will it make your code simpler and the code of your consumers simpler, it will also get rid of the question you've ask on how to consume it from Spring.
The fact that you've had to come here to ask how to consume a web service you've created should be setting off alarm bells in your head. When creating any sort of interface, if it's hard for you to use, then it's going to be extremely hard for anyone else to use. To ensure my web services are easy to consume, the first thing I do (before I create the WSDL or the implementation) is create a simple program that invokes the service as part of a test(e.g., JUnit or Cucumber-JVM, etc), passing in only the data that's needed (and nothing more) and only checking for the response data that it needs (and nothing more). I then work on the web service implementation until the test passed. This always results in nice easy and simple to use services, rather than big heavy bloated services with highly complex schemas, of which only 1% is used (I'm sure they put the other 99% of the schema there and don't use it, just to lead new users of the service astray).
In terms of the meta-data you want to include in the message (i.e. the messageType and headerType information), consider using SOAP Headers as per the Messaging Metadata SOA Pattern. They allow you to include extra information, without polluting your message body.
Lastly, if you need to apply some sort of consistency over the message structure (because for some strange reason the SOAP envelope is not enough and you need your own bespoke envelope to put in the SOAP envelope), please consider using abstract base types, which you then extend to suite the particular needs of the method. This will allow you to apply consistency, without requiring your service consumers to guess what the "any" might actually be.
Side note. One client I worked at had a generic message structure such as yours. One of the reasons was they wanted a consistent way to report success or error in their web service responses. So in the to of their bespoke response envelope was a element to indicate success or failure and all was good...
...except for the consumers of the service, who now needed to write extra code no only checking for SOAP faults, but also checking if the bespoke error flag was set.
...and except for when we wanted to put a load balancer in front of our services, because it didn't natively support our bespoke error element. It did however support SOAP faults and http status codes :/
UPDATE
A simpler way to put it. The operation violates the Liskov substitution principle.
If an operation accepts "Any", I should expect that any valid xml element I pass to the operation will work. However only certain XML elements are allowed. The only way to know which types are allowed is to know the details of the operation. In other words, the operation is less flexible than advertised.
The above update was modified from the excellent answer at https://softwareengineering.stackexchange.com/a/198100/37491
I have seen everywhere using tx namespace in springconfig.xml.Can we use tx1 instead of tx? i mean is it kind of hardcoded when xml is processed during parsing?
Since Spring configuration files are just XML files and the parsing of them happens at the infoset level (where it should happen, of course) you can indeed change the prefix to anything you want with an appropriate xmlns:… declaration. What you can't change is the namespace URI that the arbitrary prefix is bound to; that must be correct.
But I suggest using tx if at all possible: it makes it easier for other people (or yourself in a few months time) to come to your config file and read it quickly. No point in making things deliberately obscure after all, since Spring is complex enough without.
If you want to use a xml namespace prefix, you have to define it. The first element of an spring appliction context file has often this attribute:
xmlns:tx="http://www.springframework.org/schema/tx"
This means that all elements having the tx prefix belong to the http://www.springframework.org/schema/tx namespace. If you want to use another prefix you have to change the above attribute:
xmlns:tx1="http://www.springframework.org/schema/tx"
Now every element starting with tx1: belongs to the mentioned namespace.
This is not specific to spring but belongs to the XML schema definition language (xsd).
I'm trying to use a generic list as a property of the users profile. I'll admit this is probably just making my life harder than it needs to be but I don't want to change the programming model just because the data store struggles.
I have this in my web.config
</providers>
<properties>
.....
<add name="AListProperty" type="System.Collections.Generic.List`1[[System.Int32]]"/>
<add name="AnotherListProperty" type="System.Collections.Generic.List`1[[MyNamespace.Web.UI.MyReallySimpleClass]]">
</properties>
</profile>
The first property, "AListProperty" works fine. The second one throws a variety of exceptions depending on how I delcare it in the web.config. MyReallySimpleClass is public, serializable and consists of 2 public fields (at present)
So, my questions are
1. Does anyone know where the format for declaring these types in the web.config is documented.
2. What I'm doing wrong? It looks fine, I can't see any semantic difference between the two declarations.
Thanks
It would help if you could also give some details about the exception types and message you are experiencing. Otherwise my guess would be that you may need to qualify MyNamespace.Web.UI.MyReallySimpleClass with the assembly where the type lives, as in MyNamespace.Web.UI.MyReallySimpleClass, MyAssembly. The assembly qualification is not be needed unless the type lives in mscorlib, as System.Int32 does, under App_Code or in one of the assemblies listed in the system.web/compilation/assemblies section of the configuration.
Does anyone know where the format for declaring these types in the
web.config is documented.
See Specifying Fully Qualified Type Names in MSDN.
Try to specify the assembly of YourReallySimpleClass:
...type="System.Collections.Generic.List`1[[MyNamespace.Web.UI.MyReallySimpleClass, MyAssemblyName]]"