How to document contract-last (via jaxb schemagen) webservice? - java

I've developed a webservice and rightfully my users would like to see documentation. I'd prefer to simply document my code, either with javadoc comments or with an explicit annotation, e.g.
#XmlComment("This is used to [blah blah]")
#XmlElement(name = "referenceDate", namespace = NAMESPACE, type = Date.class)
public void setReferenceDate(Date referenceDate) {
this.referenceDate = referenceDate;
}
or
/**
* This is used to [blah blah]
*/
#XmlElement(name = "referenceDate", namespace = NAMESPACE, type = Date.class)
public void setReferenceDate(Date referenceDate) {
this.referenceDate = referenceDate;
}
The above aren't supported, as evidenced here:
JAXB-273 - 2006 request to make xs:documentation elements from annotations
JAXB-369 - 2007 request to make xs:documentation elements from comments
SO-470001 - "You can't do that" stackoverflow question
So I understand I can't use the above to I comment my service. But... Surely there's still a way to do so in a non-manual fashion. Must I hand-craft all my XML just for this? If that is the answer, why isn't there more attention on getting this feature into JAXB? Seems downright mandatory for an enterprise-grade webservice, right?

You're right it's poor. Most focus these days is on contract-first, so I guess it's not been prioritized. You could use XSLT to add in the comments to the WSDL from a separate XML doc. Not as good as generating it from the Java code, but better than nothing. Here's an ancient posting doing it http://www.gridlab.org/WorkPackages/wp-5/guide/wsdltips.html

Related

Auto display of list of enums in spring auto rest docs isn't explanatory

I've generated a document using spring auto rest docs. This uses capital.scalable libraries combined with java docs and spring rest docs.
My issue is with the List of enums while describing the request fields.
Type column generates a value as Array[Object]. Also, the description column doesn't generate the must be one of statement with the enum values, as it does when only Enum is the field and not the list of enums.
public enum Discipline {
ECONOMICS("economics"),
SOCIOLOGYANTHROPOLOGY("sociologyanthropology");
private final String discipline;
Discipline(final String discipline) {
this.discipline = discipline;
}
public String getId() {
return discipline;
}
}
Above is the enum that I have. It uses tostring correctly to display in the description when the field is used only as enum. But if list of enums i.e.
List<Discipline>
is the field, then it doesn't describe properly as mentioned above.
Please let me know what should be done to generate the document more effectively?
You are right that lists of enums are not properly supported yet.
If you have a request/response like:
class SomeRequest {
public enum EnumTest {
ONE, TWO
}
/**
* List of enums
*/
private List<EnumTest> enumTestList;
}
it is documented as
with Spring Auto REST Docs at the moment.
It would be good if the type would be Array[String] and the description would list the elements of the enum, e.g. "Elements must be one of [...]".
Spring Auto REST Docs 1.0.11 fixes the type issue and thus Array[String] will be shown with this version.
I opened an issue to improve the documentation of lists of enums: https://github.com/ScaCap/spring-auto-restdocs/issues/194. Until this issue is resolved, one can manually add "Elements must be one of [...]" to the Javadoc of the list as a workaround.

How to make changes in marshalled output in Java web service client

I am trying to interact with a third party web service, who requires me to send a security token as a part of each request. The token is a node by itself, and I acquire it from the response of an initial call.
The web service endpoint is dotNet, and I have a Java client.
Apparently, the server side expects me to send the security token exactly like it was provided to me: literally the same string: so it won't do if its content has a different size, order, etc.
So, in SoapUI, everything works fine. There is a token in the response of the initial 'startSession' call, which I copy into the request of a next call.
But in Java (I tried JAX-WS and CXF generated code, both rely on JAXB) it doesn't work. I receive the token as an object after it is unmarshalled, and I use this object in the next call.
When marshalled and send, it is missing a namespace attribute in a subnode. The server side says it won't continue because the token is incorrect.
So, by using JAXB outbound logical handler functionality, I am able to add the missing namespace without any problems in the DOM source (I was also able to achieve this with a CXF interceptor).
The problem now is, that the attributes, when marshalled, are ordered in such a way that the result still not matches the provided token as it was before it was unmarshalled. Alhough it should not matter, the order of these attributes is crucial.
I have no idea how to solve this, unless it is possible to actually modify the output XML string. I even tried a dirty hack by removing all attributes from the subnode and replacing them with one attribute that visually looks the same; but then the outer two double quotes become single quotes...
I hope anyone has an idea. Because I have none.
Cheers.
UPDATE:
I should have mentioned that the attributes in question are namespace(d) attributes. The node should look like this:
<HawanedoSessionInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c">
However, after using outbound JAXB handler to add the missing xmlns="...", my result looks like this:
<HawanedoSessionInfo xmlns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
In the HawanedoSessionInfo class, I used XmlType.proporder and #XmlAttribute like so:
#XmlType(name = "HawanedoSessionInfo", propOrder = {
"xsd",
"xsi",
"xmlns",
and some other non-attribute sub-elements..
private String xsd;
private String xsi;
private String xmlns;
#XmlAttribute(ns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c")
public String getXsd() {
return xsd;
}
public void setXsd(final String xsd) {
this.xsd = xsd;
}
#XmlAttribute(ns="http://schemas.thecompany.com/Hawanedo/Business/v2.0c")
public String getXsi() {
return xsi;
}
public void setXsi(final String xsi) {
this.xsi = xsi;
}
#XmlAttribute
public String getXmlns() {
return xmlns;
}
public void setXmlns(final String xmlns) {
this.xmlns = xmlns;
}
So apparently the proporder option does not help in this case?
UPDATE 2:
Like I wrote in my answer, it now works. Based on this LINK,
in the HawanedoSessionInfo class I added:
#XmlCustomizer(HawanedoSessionInfoCustomizer.class)
I created the customizer class exactly as described in the linked page, and I added the jaxb.properties.
So I did two things:
1) I added my attributes to (the top of the already existing) propOrder attribute. I added the attributes as instance variables and created the getters/setters. I annotated the getters with XmlAttribute.
2) I implemented the XmlCustomizer solution.
Now comes the strange part. According to Fiddler, the order of the attributes is still not changed! But I must stress that this is now working, ONLY after implementing the Customizer. What is happening here? :)
So in principle you cannot control order of attributes in a standard way, but ....
Depending on jaxb /java version the order can be determined by alphabetical order of the names, the order of declaration.
You could try in your code if a) moving the fields around changes anything, b) renaming the fields (the XMLAttribute than have to map to original name).
If you are lucky, it will work. But of course it is a hack and will work till next jaxb/java update.
The JAXB providers (the actuall implementation can have extra features), that can be used to customized the marshalling process). For example I found that: https://community.oracle.com/thread/977397 abut eclipselink.
I am sure there was a way of intercepting the soap body before it is send or governing the data serialization before it is send. I can think how it was called but try to google the jaxws client customization. If you capture the whole soap message simple xslt transforamation could fix the attributes order.
I feel your pain. The whole point of using xml, jaxws and such is to make our life easier and then someone providers decide not to follow standards and you end up with a mess that you were trying to clean for few days. Good luck and maybe try to contact xml gurus from Eclipse Moxy
I am so happy right now, because I got it working and it only cost me a full week to do so...:) With help of #Zielu, I was pointed to this link with the EclipseLink XMLCustomizer solution as suggested by Blaise Doughan: XMLCustomizer solution
I took the code in my original question (underneath 'UPDATE') and added the exact solution as suggested. Not sure if it is all necessary, but it works. Thanks guys.
It's possible you can control the order by using,
#XmlType (propOrder={"prop1","prop2",..."propN"})

Java: reading Xml configuration and applying to an object, what's a lightweight, simple solution

In our various applications, we have a hodge-podge of different methods used to read Xml configuration info and apply it to a Java object.
I am looking for a utility that, when given some Xml element, will automatically take any child element and set a corresponding property on the object to be configured (and of course handle any data conversion from String to correct standard Java data type).
I realize I am describing something a lot like JAXB (which I've used only a little, as part of a project to serialize/deserialize objects to Xml), so maybe it's the best solution? I just don't particularly want to be required to add the annotations to the class, and would rather it be assumed that any setter corresponds to any similarly named Xml element.
Any recommendations on what should be a standard way to do this would be appreciated. (And I'm fine if people say go back and read the JAXB docs, because that's the best solution.)
Thanks in advance.
Update: I did end up with JAXB, although it wasn't exactly painless. The main downside is that it is not case-insensitive (when you are dealing with config files, it's best not to require match by case). One other downsides are that you need to deploy 3 additional jars. I ended up with this code (maybe there is something more elegant):
public class JAXBConfigurator<T> {
private String filePath;
private Class<T> clazz;
public JAXBConfigurator(Class<T> toConfigure, String xmlFilePath) {
this.clazz = toConfigure;
this.filePath = xmlFilePath;
}
/**
* #return Parses Xml and reads configuration from Document element. Using this method assumes that the
* configuration xml starts at the top of the xml document.
* #throws Exception
*/
public T createAndConfigure() throws Exception {
return createAndConfigure(null);
}
/**
* Selects specified element from the parsed Xml document to use as the base
* for reading the configuration.
*
* #param tagName
* #return
*/
public T createAndConfigure(String tagName) throws Exception {
Document doc = XmlUtils.parse(filePath);
Node startNode;
if (tagName == null) {
startNode = doc;
} else {
startNode = XmlUtils.findFirstElement(doc, tagName);
}
return readConfigFromNode(startNode);
}
private T readConfigFromNode(Node startNode) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = context.createUnmarshaller();
JAXBElement<T> configElement = unmarshaller.unmarshal(startNode, clazz);
return configElement.getValue();
}
}
The class gets used like this:
JAXBConfigurator<MyConfig> configurator = new JAXBConfigurator<Config>(MyConfig.class, xmlfilePath);
instance = configurator.createAndConfigure("MyXmlStartTag");
...which seems reusable enough for most scenarios. Thanks again to everyone who responded.
JAXB (JSR-222) is configuration by exception. This means that no annotations are required. You just need to add metadata to override the default rules:
For an Example
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics
Pick one of these: Castor, XMLBeans, JiBX, XStream and JAXB. I'd recommend JAXB or JiBX. And in case you use Spring for other purpose, you can also check out Spring Object/XML mapping, which is basically a wrapper around aforementioned implementations and provides a consistent API.

How to create an ontology in Java?

I've some data triplets that I want to write in some sort of basic OWL ontology. I've triplets like:
Delhi is part of India
or
India is an Asian country
Note that I've relations like "is-a", "part-of", or "related-to". What's the simplest way to build an ontology? Any working example or a reference to an example website will be great help!
There are a lot of different things mixed up in your question, I strongly suggest you take a bit of time (away from the keyboard!) to think through what you're trying to achieve here.
Firstly, geographic ontologies can get quite complex, and a lot of work has already been done in this area. Probably the obvious starting point is the GeoNames ontology, which gives names to geographic features, including cities like Dehli and countries like India. At the very least you should re-use those names for the places in your application, as that will maximise the chances that your data can be successfully joined with other available linked-data sources.
However, you probably don't want the whole of GeoNames in your application (I'm guessing), so you also need to be clear why you need an ontology at all. A good way to approach this is from the outside of your application: rather than worry about which kind of Jena model to use, start by thinking through ways to complete the sentence "using the ontology, a user of my application will be able to ...". That should then lead you on to establishing some competency questions (see, for example, section 3 of this guide) for your ontology. Once you know what kinds of information you want to represent, and what kinds of queries you need to apply to it, your technology choices will be much clearer. I realise that these applications are typically developed iteratively, and you'll want to try some code out fairly early on, but I still advocate getting your destination more clearly in mind before you start your coding journey.
You imply that you want to use Jena to drive a web site. There are many choices here. Don't be mislead by the term semantic web - this actually means bringing web-like qualities to interlined data sets, rather than putting semantics into human readable web pages per se. While you can do so, and many people do, you'll need some additional layers in your architecture. We typically use one of two approaches: using Jena with a templating engine, such as Velocity, in a servlets container, or using a Ruby web framework and driving Jena via JRuby. There are many other ways to solve this particular problem: Jena doesn't address web publishing directly, but it can be used within any Java-based web framework.
Finally, regarding namespaces, you should really re-use existing vocabularies, and hence namespaces, where possible. Don't make up new names for things which already have representations on the web of data somewhere. Use GeoNames, or DbPedia, or any of the many other published vocabularies where they fit. If they don't fit, then you should create a new name rather than use an existing name in a non-compatible way. In this case, you should use the web domain of your application (e.g. your company or university) as the basis for the namespace. Ideally, you should publish your ontology at the base URL of the namespace, but this can sometimes be hard to arrange depending on local web policies.
I suggest OWL API from Manchester University. In this way you can start to create your ontology "on the fly" in Java, and with a single method invocation you can serialize it in your preferred format (RDF, Manchester Syntax etc) if you need, or directly working on the in-memory representation. In this way you can rapidly prototype and experiment your ontology in the context of your program.
For an overview of the library and its main componenets I suggest the tutorial (code tutorial) provided by the creator of the library, it covers 90% of the basic needs.
PS: Protégé is based on OWL Api, you can also try it as suggested, but expecially in the beginning I preferred to rapidly play with ontologies and switch to some engineering environment like Protege when my mind was clear enough. In addition, with an external ontology you would need to learn how to navigate it, that IMHO it is really not worth in the very beginning.
Have a look at Stanford's Protege. It's an ontology editor.
You'd just declare a triplet class consisting of a subject, object, and predicate. "has-a" is a predicate, so your ontology elements would look like:
"Dehli", "is-in", "India"
"India", "is-in", "Asia"
"India", "is-a", "country"
This doesn't address queries, of course, but given a decent data store (even a database would do) you could start to build a flexible ontology with a decent query mechanism.
JENA is far, far more capable than what this would create, of course; it does provide the semantic query stuff, as well as far better resource definition and resolution. However, it's a lot more involved than a simple triplet structure; it all depends on what you need.
/**
- This is maven dependencies for owl-api
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>owlapi-api</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>owlapi-apibinding</artifactId>
</dependency>
* First of all you need to initialize ontology:
**/
private OWLDataFactory factory;
private PrefixManager pm;
private OWLOntology ontology;
private String pmString = "#";
private OWLOntologyManager manager;
private OWLReasoner reasoner;
private ShortFormEntityChecker entityChecker;
private BidirectionalShortFormProviderAdapter bidirectionalShortFormProviderAdapter;
private void initializeOntology(String fileContent)
throws OWLOntologyCreationException {
InputStream bstream = new ByteArrayInputStream(fileContent.getBytes());
this.manager = OWLManager.createOWLOntologyManager();
this.ontology = this.manager.loadOntologyFromOntologyDocument(bstream);
IRI ontologyIRI = this.ontology.getOntologyID().getOntologyIRI();
this.pm = new DefaultPrefixManager(ontologyIRI.toString()
+ this.pmString);
this.factory = this.manager.getOWLDataFactory();
ReasonerFactory factory = new ReasonerFactory();
this.reasoner = factory.createReasoner(this.ontology);
Set<OWLOntology> onts = new HashSet<>();
onts.add(this.ontology);
DefaultPrefixManager defaultPrefixManager = new DefaultPrefixManager(
this.pm);
ShortFormProvider shortFormProvider = new ManchesterOWLSyntaxPrefixNameShortFormProvider(
defaultPrefixManager);
this.bidirectionalShortFormProviderAdapter = new BidirectionalShortFormProviderAdapter(
this.manager, onts, shortFormProvider);
this.entityChecker = new ShortFormEntityChecker(
this.bidirectionalShortFormProviderAdapter);
}
/*
After that you need to define your classes and the relations of the classes. These relations calls as object properties in ontology. Instance of each ontology class calls as individual and the attributies of the classes (for person name, age , adress) calls as data-property.
*/
// To create a new individual of an ontology class :
public OWLClass getClass(String className) {
return this.factory.getOWLClass(":" + className, this.pm);
}
public OWLNamedIndividual createInvidual(String cls, String invname) {
OWLNamedIndividual res = this.factory.getOWLNamedIndividual(":"
+ invname, this.pm);
this.manager.addAxiom(this.ontology,
this.factory.getOWLDeclarationAxiom(res));
OWLClassAssertionAxiom axiom = this.factory.getOWLClassAssertionAxiom(
getClass(cls), res);
this.manager.addAxiom(this.ontology, axiom);
return res;
}
// To create an object property :
// This method will create an object property named prop if it is not exist.
public OWLObjectProperty getObjectProperty(String prop) {
return this.factory.getOWLObjectProperty(":" + prop, this.pm);
}
public void addObjectProperty(String propname, OWLNamedIndividual prop,
OWLNamedIndividual obj) {
OWLObjectPropertyAssertionAxiom axiom = this.factory
.getOWLObjectPropertyAssertionAxiom(
getObjectProperty(propname), obj, prop);
this.manager.addAxiom(this.ontology, axiom);
}
// And finally , to add a data-property to individuals :
public OWLDataProperty getDataProperty(String prop) {
return this.factory.getOWLDataProperty(":" + prop, this.pm);
}
public void addDataProperty(String propname, boolean propvalue,
OWLNamedIndividual inv) {
OWLAxiom axiom = this.factory.getOWLDataPropertyAssertionAxiom(
getDataProperty(propname), inv, propvalue);
this.manager.addAxiom(this.ontology, axiom);
}

XML serialization in Java? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
What is the Java analogue of .NET's XML serialization?
2008 Answer
The "Official" Java API for this is now JAXB - Java API for XML Binding. See Tutorial by Oracle. The reference implementation lives at http://jaxb.java.net/
2018 Update
Note that the Java EE and CORBA Modules are deprecated in SE in JDK9 and to be removed from SE in JDK11. Therefore, to use JAXB it will either need to be in your existing enterprise class environment bundled by your e.g. app server, or you will need to bring it in manually.
XStream is pretty good at serializing object to XML without much configuration and money! (it's under BSD license).
We used it in one of our project to replace the plain old java-serialization and it worked almost out of the box.
"Simple XML Serialization" Project
You may want to look at the Simple XML Serialization project. It is the closest thing I've found to the System.Xml.Serialization in .Net.
JAXB is part of JDK standard edition version 1.6+. So it is FREE and no extra libraries to download and manage.
A simple example can be found here
XStream seems to be dead. Last update was on Dec 6 2008.
Simple seems as easy and simpler as JAXB but I could not find any licensing information to evaluate it for enterprise use.
Worth mentioning that since version 1.4, Java had the classes java.beans.XMLEncoder and java.beans.XMLDecoder. These classes perform XML encoding which is at least very comparable to XML Serialization and in some circumstances might do the trick for you.
If your class sticks to the JavaBeans specification for its getters and setters, this method is straightforward to use and you don't need a schema. With the following caveats:
As with normal Java serialization
coding and decoding run over a InputStream and OutputStream
the process uses the familar writeObject and readObject methods
In contrast to normal Java serialization
the encoding but also decoding causes constructors and initializers to be invoked
encoding and decoding work regardless if your class implements Serializable or not
transient modifiers are not taken into account
works only for public classes, that have public constructors
For example, take the following declaration:
public class NPair {
public NPair() { }
int number1 = 0;
int number2 = 0;
public void setNumber1(int value) { number1 = value;}
public int getNumber1() { return number1; }
public void setNumber2(int value) { number2 = value; }
public int getNumber2() {return number2;}
}
Executing this code:
NPair fe = new NPair();
fe.setNumber1(12);
fe.setNumber2(13);
FileOutputStream fos1 = new FileOutputStream("d:\\ser.xml");
java.beans.XMLEncoder xe1 = new java.beans.XMLEncoder(fos1);
xe1.writeObject(fe);
xe1.close();
Would result in the following file:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_02" class="java.beans.XMLDecoder">
<object class="NPair">
<void property="number1">
<int>12</int>
</void>
<void property="number2">
<int>13</int>
</void>
</object>
</java>
XMLBeans works great if you have a schema for your XML. It creates Java objects for the schema and creates easy to use parse methods.
If you're talking about automatic XML serialization of objects, check out Castor:
Castor is an Open Source data binding framework for Java[tm]. It's the shortest path between Java objects, XML documents and relational tables. Castor provides Java-to-XML binding, Java-to-SQL persistence, and more.
Usually I use jaxb or XMLBeans if I need to create objects serializable to XML. Now, I can see that XStream might be very useful as it's nonintrusive and has really simple api. I'll play with it soon and probably use it. The only drawback I noticed is that I can't create object's id on my own for cross referencing.
#Barak Schiller
Thanks for posting link to XStream!
Don't forget JiBX.
if you want a structured solution (like ORM) then JAXB2 is a good solution.
If you want a serialization like DOT NET then you could use Long Term Persistence of JavaBeans Components
The choice depends on use of serialization.
public static String genXmlTag(String tagName, String innerXml, String properties )
{
return String.format("<%s %s>%s</%s>", tagName, properties, innerXml, tagName);
}
public static String genXmlTag(String tagName, String innerXml )
{
return genXmlTag(tagName, innerXml, "");
}
public static <T> String serializeXML(List<T> list)
{
String result = "";
if (list.size() > 0)
{
T tmp = list.get(0);
String clsName = tmp.getClass().getName();
String[] splitCls = clsName.split("\\.");
clsName = splitCls[splitCls.length - 1];
Field[] fields = tmp.getClass().getFields();
for (T t : list)
{
String row = "";
try {
for (Field f : fields)
{
Object value = f.get(t);
row += genXmlTag(f.getName(), value == null ? "" : value.toString());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
row = genXmlTag(clsName, row);
result += row;
}
}
result = genXmlTag("root", result);
return result;
}

Categories