Is there a way of handling multiple xsd versions with xmlBeans? - java

I know that I can compile multiple xsd files in a single jar. I've tried using different namespaces which only takes me half way through my goal. This way I can parse the correct schema but I want this to be transparent to my users which will receive the xmlBeans object that I've parsed.
They don't have to know which version of xml file is currently present on the system. I would need a super class for every xsd version to achieve this.
Could this be done with xmlBeans?

My understanding is, if you have a com namespace and a com.v1 and com.v2 namespace and you have an xsd element called EmployeeV1 in com.v1 and EmployeeV2 in com.v2.
You want to a super class called Employee in the com namespace which you want to return to your caller?
Do you think EmployeeV1 and EmployeeV2 could extend from Employee in your xsd? Then maybe when you generate you will get the class hierarchy that represents your xsd.
If that doesn't work, (i haven't used xmlbeans in years now), you might have to create your own domain object and make your callers consume that. That might be worth the effort, since to me it looks like you handle the parsing of an XML that other people rely on, you could abstract all other users from the structure of the XML (which is in flux) by having an intermediary domain object.

Related

Selecting an XSD schema during SAX parsing

Assume the following:
I have a set of XSD schemas S, each with distinct namespace URIs.
I know that I'm going to be receiving an XML document containing a root element that contains exactly one namespace declaration that refers to a member of S. I can abort parsing immediately with an error if I don't receive exactly one namespace declaration, or if the received namespace doesn't refer to any schema in S.
I want to parse the incoming XML document with a SAX parser, and I want to validate the incoming document during parsing against one of the schemas in S. I know from the above that the first call I'm going to see in the ContentHandler that I give to the parser will be a call to startPrefixMapping when the parser encounters the namespace declaration.
Is it possible to, in the startPrefixMapping call, pick one of the schemas in S for validation once I know which one I need?
It seems that I could maybe call setSchema on the parser inside the startPrefixMapping call, but I get the feeling from the API documentation that I'm not supposed to do this (and that it may be too late to call the method at that point anyway).
Is there some other way to supply a set of schemas to the parser and perhaps have it pick the right one itself based on the namespace declaration it receives?
Edit: I was wrong, it's not just inadvisable to call setSchema on a parser once parsing has started - it's actually impossible. Parsers don't expose a setSchema call, only parser factories do. This means that my options are limited to those that can allow the parser to select a schema for itself. Unfortunately, that has its own problems: It's not possible for an XML document to merely specify a namespace, it also has to specify a filename for the intended schema (which in my opinion is an implementation detail on the parser side and should not be required of the incoming data) and the parser has to intercept the request for this filename to supply a member of S for validation.
Edit: I've solved this. I've put together some heavily-commented public domain example code here that looks up schemas based on pre-specified systemIds, and the schemas are delivered programatically (so they can be served from databases, class resources, etc). It correctly rejects any document that specifies an unknown schema, specifies no schema, or tries to specify its own schemaLocation to try to fool the validator.
https://github.com/io7m/xml-schema-lookup-example

JAXB issue with missing namespace definition

So I searched around quite a bit for a solution to this particular issue and I am hoping someone can point me in a good direction.
We are receiving data as XML, and we only have XSD to validate the data. So I used JAXB to generate the Java classes. When I went to unmarshal a sample XML, I found that some attribute values are missing. It turns out that the schema expects those attributes to be QName, but the data provider didn't define the prefix in the XML.
For instance, one XML attribute value is "repository:<uuid>", but the namespace prefix "repository" is never defined in the dataset. (Never mind the provider's best practices suggest defining it!)
So when I went to unmarshal a sample set, the QName attributes with the specified prefix ("repository" in my sample above) are NULL! So it looks like JAXB is "throwing out" those attribute QName values which have undefined namespace prefix. I am surprised that it doesn't preserve even the local name.
Ideally, I would like to maintain the value as is, but it looks like I can't map the QName to a String at binding time (Schema to Java).
I tried "manually" inserting a namespace definition to the XML and it works like a charm. What would be the least complicated method to do this?
Is there a way to "insert" namespace mapping/definition at runtime? Or define it "globally" at binding time?
The simplest would be to use strings instead of QName. You can use the javaType customization to achieve this.
If you want to add prefix/namespace mappings in the runtime, there are quite a few ways to do it:
Similar to above, you could provide your own QName converter which would consider your prefixes.
You can put a SAX or StAX filter in between and declare additional prefixes in the startDocument.
What you actually need is to add your prefix mappings into the UnmarshallingContext.environmentNamespaceContext. I've checked the source code but could not find a direct and easy way to do it.
I personally would implement a SAX/StAX filter to "preprocess" your XML on the event level.

What Java XML API to use in my app - StAX or DOM?

I did some research, looked at the table at the bottom here (1) and I am trying to find out what kind of API I should use.
Let me introduce the problem my app in going to solve:
My application listens to some observer events fired from all places (e.g. events from CDI) in some observer class. In that class, there are methods which observes these events.
I need to construct XML file on-the-fly as these events are being observed. More concretely, when I observe event "start", I need to create this xml.
<start></start>
After that when I observe some other event, like "installed" (does not matter how it is called really), I need to have this structure:
<start><installed></installed><start>
Everytime I observe some event, I need to be able to write that XML representation to external file. Summing it up, it seems I can not use "SAX" because SAX just parses XML documents but I need to write them or construct them. Next, I am about to use StAX or DOM but StAX is "forward only" which I do not quite understand what it stands for, but when I take StAX API it behaves like this (2) and when it is "forward" I am "forced" to manually start and end elements but that is not applicable in my case. I do not know when I am about to end the document generation, I just need to have valid xml every time in order to write it.
However, there is this method (3) which says that when I call it, it automatically closes all elements. So e.g. when I have this:
<a>
<b></b>
<c>
<d>
</d>
and I call writeEndDocument(), does that mean that it automatically closes "c" and "a"?
(1) http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/SJSXP2.html
(2) http://docs.oracle.com/javase/tutorial/jaxp/stax/example.html#bnbgx
(3) http://docs.oracle.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html#writeEndDocument()
I recommend to use the following XML libraries (ordered by recommendation; only use the next one if the one before doesn't suit you needs):
JAXB (work with objects rather than XML)
StAX (lower level than JAXB)
SAX (only for reading; should be rarely used now with JAXB and StAX available)
DOM (should be rarely used now with JAXB and StAX available)
Do not use lower level XML techniques (either SAX or DOM) unless you really need them. I believe that this is not the case.
Use JAXB. Create class that represents your events. Every time you get event create instance of this class and populate fields. Every time you have to create XML just marshal the instance(s) to any stream you want (file, socket, whatever).

How to move to XML configurations

I am required to move some of our application configuration classes to XMLs. The classes mainly have enums, which are used by other classes. These enums are extensively used in our application.
For instance, we have classes like
enum ColumnType{
type1("Type1"),type2("type2"),type3("type3")
}
Also we need these types to instantiate classes.
for instance,
Processor p = new StringValueProcessor(ColumnType.type1);
How can I move this to an XML file without changing the dependecies in my application?
Edit:
It is not mandatory to keep these enums and I don't want to compile the code against the classes created from xml. The config needs to be dynamic, that's the whole point of moving to XML, so that we can configure things in XML and there is no need of compiling and re-deploying.
My main concern is to be able to restrict instances for all column types to one and make them accessible throughout my application.
Edit: After thinking over the design for some more time, I have narrowed down to two essential requirements.
1) I would define some xml tags with some properties and I would need to convert it to object
2) I would also define some tags (the way servlets are defined in web.xml) and I would need to initialise the corresponding class
3) I would further define some mapping tags which will map the objects created in step 1) to instances initialised in step 2). This should be converted to java HashMap, where there can be only one instance of objects defined in step 1) but there will be a new instance of objects defined in step 2) for each mapping.
Is there a framework which can provide this functionality out-of-the-box?
You can use the XML files to generate the enums. This has to be done at compile/build time, or you cannot use them in your code like the second example (as they don't exist at compile time)
Why do you want to migrate the enums to XML?
I think the answer your looking for is to use JAXB. It lets you turn XML into POJOs and vice-versa. It even has some functionality for using enums. All you have to do is add some annotations to your java and you can convert to and from XML.
By using annotations, you won't affect any existing functionality.

JAXB unmarshalling

Is it possible to unmarshall a class without knowing it's type (JAXBContext.newInstance(clazz)) , or what is proper way to test what is comming?
I do get messages for unmarshaling from plain text - String
Incomming classes doesn't implement any interface and can be in any package.
thanks
No, not really. The JAXB context needs some information about what classes should be bound to. if necessary, pass a list of every possible JAXB-annotated class to the context factory method.
This shouldn't be a limitation, though - your own code also needs to know what classes to expect. If your code doesn't know or care about the type of the bound classes, then JAXB isn't the tool for the job, you should just be unmarshalling into a generic DOM of some kind.
Try to locate your classes, which can come in xml in one package and then pass the list of it to JAXBContext.

Categories

Resources