I am very new to REST services .. I want to create a WADL which I will be converting to Java interface to create and expose a Rest web service .. So .. I need to create a WADL to get the following java interface :-
#Path("/getData")
public interface MainData {
#GET
#Produces("application/json")
#Path("/retrieve/")
public DataResponse retrieveDataOperation(#QueryParam("id") int id);
#POST
#Produces("application/json")
#Path("/insert/")
public DataResponse insertDataOperation(String message);
#PUT
#Produces("application/json")
#Path("/update/")
public DataResponse updateDataOperation(String message);
#DELETE
#Produces("application/json")
#Path("/delete/")
public DataResponse deleteDataOperation(#QueryParam("id") int id);
}
So far I tried to create the following WADL to get the above interface :-
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://wadl.dev.java.net/2009/02 wadl.xsd"
xmlns:ns1="http://services.test.com/schema/bs/bom/v01/GetAllTypeDesignators"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://wadl.dev.java.net/2009/02">
<grammars>
<include href="MainData.xsd" />
</grammars>
<resources base="http://localhost:8082">
<resource path="getData" id="com.test.services.schema.maindata.v1.MainData">
<resource path="/retrieve/" >
<method name="GET" id="retrieveDataOperation">
<request>
<param type="xs:int" style="query" name="id"/>
</request>
<response>
<representation mediaType="application/json" element="ns1:DataResponse"/>
</response>
</method>
</resource>
<resource path="/delete/" >
<method name="DELETE" id="deleteDataOperation">
<request>
<param type="xs:int" style="query" name="id"/>
</request>
<response>
<representation mediaType="application/json" element="ns1:DataResponse"/>
</response>
</method>
</resource>
<resource path="/insert/" >
<method name="POST" id="insertDataOperation">
<request>
<param name="message" type="xs:string" />
</request>
<response>
<representation mediaType="application/json" element="ns1:DataResponse"/>
</response>
</method>
</resource>
<resource path="/update/" >
<method name="PUT" id="updateDataOperation">
<request>
<param name="message" type="xs:string" />
</request>
<response>
<representation mediaType="application/json" element="ns1:DataResponse"/>
</response>
</method>
</resource>
</resource>
</resources>
</application>
But I am not able to get the Java interface above after converting this WADL to Java .. While converting in Apache CXF it also shows following exception :- WADLToJava Error: java.lang.NullPointerException
Please help me to to modify the WADL to get the exact java interface above .. Am I doing in right way .. Please help ..
I have just check your WADL and it looks ok, few minor mistakes but nothing which point to your error. Also, I have used command line tool wadl2java;
wadl2java -d /output/dir -interface /input/wadl/application.wadl
Here is corrected WADL;
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:ns1="http://services.test.com/schema/bs/bom/v01/GetAllTypeDesignators">
<grammars>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://services.test.com/schema/bs/bom/v01/GetAllTypeDesignators">
<xs:element name="dataResponse" type="ns1:dataResponse"/>
<xs:complexType name="dataResponse">
<xs:sequence>
<xs:element name="param1" type="xs:int"/>
<xs:element name="param2" type="xs:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</grammars>
<resources base="http://localhost:8082">
<resource path="getData" id="com.test.services.schema.maindata.v1.MainData">
<resource path="/retrieve/" >
<method name="GET" id="retrieveDataOperation">
<request>
<param type="xs:int" style="query" name="id"/>
</request>
<response>
<representation mediaType="application/json" element="ns1:dataResponse"/>
</response>
</method>
</resource>
<resource path="/delete/" >
<method name="DELETE" id="deleteDataOperation">
<request>
<param type="xs:int" style="query" name="id"/>
</request>
<response>
<representation mediaType="application/json" element="ns1:dataResponse"/>
</response>
</method>
</resource>
<resource path="/insert/" >
<method name="POST" id="insertDataOperation">
<request>
<representation mediaType="*/*">
<param name="message" style="plain" type="xs:string" />
</representation>
</request>
<response>
<representation mediaType="application/json" element="ns1:dataResponse"/>
</response>
</method>
</resource>
<resource path="/update/" >
<method name="PUT" id="updateDataOperation">
<request>
<representation mediaType="*/*">
<param name="message" style="plain" type="xs:string" />
</representation>
</request>
<response>
<representation mediaType="application/json" element="ns1:dataResponse"/>
</response>
</method>
</resource>
</resource>
</resources>
</application>
You should post your MainData.xsd, I'll bet that inside your XSD relies your error.
UPDATE:
It appears that param name must be lowerCase of the param type if it used in "representation". I have just check the source code of the wadl2java (cxf-tools-wadlto-jaxrs-3.0.1-sources.jar) and concluded that modification of generator is required. Problematic line is in class org.apache.cxf.tools.wadlto.jaxrs.SourceGenerator:1044 which looks like elementParamName = elementParamType.toLowerCase(); You should report that on Apache CXF jira or modify code by yourself.
Alternative is to set your message param as #QueryParam, you can do that by replacing;
<representation mediaType="*/*">
<param name="message" style="plain" type="xs:string" />
</representation>
with this;
<param name="message" style="query" type="xs:string" />
but in that case your interface method will look like;
#POST
#Produces("application/json")
#Path("/insert/")
DataResponse insertDataOperation(#QueryParam("message") String message);
Hope it helps.
Related
Using JAXB to generate Java classes.
I'm using the following XSD scheme.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://schemas.microsoft.com/developer/msbuild/2003" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msb="http://schemas.microsoft.com/developer/msbuild/2003" elementFormDefault="qualified">
<!-- Working -->
<xs:complexType name="MetaTypeSimpleContent">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="Name" />
<xs:attribute type="xs:string" name="Scheme" />
<xs:attribute type="xs:string" name="Value" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<!-- Not Working -->
<xs:complexType name="MetaTypeComplexContent">
<xs:complexContent>
<xs:extension base="msb:BaseType">
<xs:attribute name="MyName" type="xs:string" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="BaseType">
<xs:attribute name="MyName" type="xs:string" />
</xs:complexType>
</xs:schema>
..and the following Binding definition
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.1">
<bindings schemaLocation="Test.xsd" version="1.0">
<!-- Customise the package name -->
<schemaBindings>
<package name="com.example.schema" />
</schemaBindings>
<!-- Working -->
<bindings node="//xs:complexType[#name='MetaTypeSimpleContent']">
<bindings node=".//xs:attribute[#name='Value']">
<property name="ValueAttribute" />
</bindings>
</bindings>
<!-- Not Working -->
<bindings node="//xs:complexType[#name='MetaTypeComplexContent']/xs:complexContent/xs:extension/xs:attribute[#name='MyName']">
<property name="MyName3" />
</bindings>
</bindings>
</bindings>
The binding for the complextType MetaTypeSimpleContent with the simpleContent works fine. But the binding for the complexType MetaTypeComplexContent with the complexContent doesn't. Why?
I got the following Error:
[ERROR] ct-props-correct.4: Error with type 'MetaTypeComplexContent'. Duplicate attribute usages were specified with the same name and target namespace. The name of the duplicate attribute is 'MyName'.
Line 19 of file: / D: /temp/Stackoverflow/Test.xsd
A schema could not be parsed.
The error message seems to be pointing out the problem quite clearly:
[ERROR] ct-props-correct.4: Error with type 'MetaTypeComplexContent'. Duplicate attribute usages were specified with the same name and target namespace. The name of the duplicate attribute is 'MyName'.
When extending a complex type, you should not re-declare the inherited content. Maybe you intended to add a new attribute in the extended complex type, but you forgot to change the name?
To fix the error, do one of the following:
delete the complex type extension
change the name or namespace of the attribute in the complex type extension
I need to query some endpoints for their WADLs, and test all the endpoints contained in the WADL. I'm using JaxB to unmarshal the WADL into POJOs (tried Jackson too, but got another error).
Here's the beginning of the XML:
<application>
<grammars/>
<resources base="https://gatewaydsapdev1.company.com/v2">
<resource path="/contents">
<resource path="/labels">
<method name="GET">
<request>
<param name="include" style="query" type="string"/>
<param name="q" style="query" type="string"/>
<param name="offset" style="query" type="string"/>
<param name="limit" style="query" type="string"/>
<param name="flush" style="query" type="boolean"/>
</request>
<response>
<representation element="Response" mediaType="application/json;charset=utf-8"/>
</response>
</method>
</resource>
....
And here's the unmarshalling code:
JAXBContext jaxbContext = JAXBContext.newInstance(WadlApplication.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(xml);
WadlApplication application = (WadlApplication) unmarshaller.unmarshal(reader);
But I get this exception:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"application"). Expected elements are <{http://wadl.dev.java.net/2009/02}application>,<{http://wadl.dev.java.net/2009/02}doc>,<{http://wadl.dev.java.net/2009/02}grammars>,<{http://wadl.dev.java.net/2009/02}include>,<{http://wadl.dev.java.net/2009/02}link>,<{http://wadl.dev.java.net/2009/02}method>,<{http://wadl.dev.java.net/2009/02}option>,<{http://wadl.dev.java.net/2009/02}param>,<{http://wadl.dev.java.net/2009/02}representation>,<{http://wadl.dev.java.net/2009/02}request>,<{http://wadl.dev.java.net/2009/02}resource>,<{http://wadl.dev.java.net/2009/02}resource_type>,<{http://wadl.dev.java.net/2009/02}resources>,<{http://wadl.dev.java.net/2009/02}response>
I don't know how to give the ObjectFactory the data it says is missing. Does anyone have any suggestions? TIA!
Your XML does not have a namespace whereas your JAXB classes do have the namespace http://wadl.dev.java.net/2009/02.
Either add namespace to the XML or drop it from your JAXB classes.
This is my input structure to the API,'search serves'
<structure name="SearchServesInput" >
<member name="ClientUser" target="Username" />
<member name="OwnerUser" target="Username" />
<member name="ServiceName" target="String" />
<member name="EnableSearch" target="Boolean" />
<member name="PanControls" target="PanControls" /> </structure>
At least 1 of the first three fields is required. How do I implement that?
You will have to declare a schema, here is a small example:
<?xml version="1.0"?>
<xs:schema>
<xs:attribute name="test" type="xs:string" use="required"/>
</xs:schema>
You can check here some tutorials.
I have an xml document which looks like this:
<document>
<primitive name="password" type="xs:string" path="" mandatory="false" />
<structure name="username" mandatory="true">
<primitive name="first-name" type="xs:string" path="" mandatory="true" />
<primitive name="last-name" type="xs:string" path="" mandatory="true" />
</structure>
<list name="addresses" path="" mandatory="true">
<structure name="address" mandatory="true">
<primitive name="country" type="xs:string" path="" mandatory="true" default-value="HU"/>
<primitive name="po-box" type="xs:string" path="" mandatory="true" />
</structure>
</list>
<list name="owned-phones" path="" mandatory="true">
<structure name="phone" mandatory="true">
<primitive name="number" type="xs:int" path="" mandatory="true" />
<primitive name="device-name" type="xs:string" path="" mandatory="true" />
<list name="similar-devices" path="" mandatory="true">
<structure name="device" mandatory="true">
<primitive name="device-name" type="xs:string" path="" mandatory="true" />
</structure>
</list>
</structure>
</list>
<list name="aliases" path="" mandatory="true">
<primitive name="alias" type="xs:string" path="" mandatory="true" />
</list>
<template name="tou">
<![CDATA[
wombat
]]>
</template>
This describes rules for a data structure which looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<password>ajshakjsdh</password>
<username>
<first-name>Kevin</first-name>
<last-name>Smith</last-name>
</username>
<addresses>
<address>
<country>HU</country>
<po-box>12234</po-box>
</address>
<address>
<country>US</country>
<po-box>666</po-box>
</address>
</addresses>
<owned-phones>
<phone>
<number>2431241</number>
<device-name>Nokia</device-name>
<similar-devices>
<device>
<device-name>Windozfon</device-name>
</device>
</similar-devices>
</phone>
<phone>
<number>68741</number>
<device-name>Samsung</device-name>
<similar-devices>
<device>
<device-name>Android</device-name>
</device>
<device>
<device-name>Blackberry</device-name>
</device>
</similar-devices>
</phone>
</owned-phones>
<aliases>
<alias>Alias1</alias>
<alias>Alias2</alias>
</aliases>
<!-- tou is missing but not mandatory -->
</document>
I have a set of transformation rules which can be used to convert the first xml file to an xsd document which can be used to validate the data structure (second code block):
<primitive name="$primitive_name" type="$primitive_type" mandatory="$primitive_mandatory" />
transforms to
<xs:element name="$primitive_name" type="$primitive_type" minOccurs="$primitive_mandatory ? 1 : 0" maxOccurs="1" />
<structure name="$structure_name" mandatory="$structure_mandatory">
<!-- anything inside recursively transformed -->
</structure>
transforms to
<xs:element name="$structure_name" minOccurs="$structure_mandatory ? 1 : 0" maxOccurs="1">
<xs:complexType>
<xs:all>
<!-- anything inside recursively transformed -->
</xs:all>
</xs:complexType>
</xs:element>
<list name="$list_name" mandatory="$list_mandatory">
<!-- anything inside recursively transformed -->
</list>
transforms to
<xs:element name="$list_name" minOccurs="$list_mandatory ? 1 : 0">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<!-- anything inside recursively transformed -->
</xs:sequence>
</xs:complexType>
</xs:element>
My question is what tool should I use for these simple transformations? I've heard that XSLT is the way to go here. I did a little research about it and it seems overkill to me. At least I was not able to find the correct transformation rules in XSLT. Can you provide a few pointers where should I start?
XSLT is very a good solution for your problem. You can easily map your structure to individual templates which will be called recursively.
Here is an example of a XSLT 2.0 stylesheet with templates for just the the examples you provided. It should provide a good starting point.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="document">
<xs:schema elementFormDefault="qualified">
<xsl:apply-templates/>
</xs:schema>
</xsl:template>
<xsl:template match="primitive">
<xs:element name="{#name}" type="{#type}" minOccurs="{if(#mandatory eq 'true') then 1 else 0}" maxOccurs="1" />
</xsl:template>
<xsl:template match="structure">
<xs:element name="{#name}" minOccurs="{if(#mandatory eq 'true') then 1 else 0}" maxOccurs="1">
<xs:complexType>
<xs:all>
<xsl:apply-templates/>
</xs:all>
</xs:complexType>
</xs:element>
</xsl:template>
<xsl:template match="list">
<xs:element name="{#name}" minOccurs="{if(#mandatory eq 'true') then 1 else 0}">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xsl:apply-templates/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsl:template>
</xsl:stylesheet>
There are many ways to achieve the same results. Look for a good XSLT tutorial that makes efficient use of XSLT templates. Avoid the ones that focus on single-template solutions using for-each. You can achieve everything you need using templates (and not using <xsl:for-each> which will make it excessively more complicated).
In case your support is limited to XSLT 1.0, you won't be able to use the (XPath 2.0) code in the minOccurs attributes, but you can generate the attribute with a nested <xsl:attribute> and use <xsl:choose> to calculate its contents.
The stylesheet above could be rewritten in XSLT 1.0 as below:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="document">
<xs:schema elementFormDefault="qualified">
<xsl:apply-templates/>
</xs:schema>
</xsl:template>
<xsl:template match="primitive">
<xs:element name="{#name}" type="{#type}" maxOccurs="1">
<xsl:attribute name="minOccurs">
<xsl:choose>
<xsl:when test="#mandatory = 'true'">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xs:element>
</xsl:template>
<xsl:template match="structure">
<xs:element name="{#name}" maxOccurs="1">
<xsl:attribute name="minOccurs">
<xsl:choose>
<xsl:when test="#mandatory = 'true'">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xs:complexType>
<xs:all>
<xsl:apply-templates/>
</xs:all>
</xs:complexType>
</xs:element>
</xsl:template>
<xsl:template match="list">
<xs:element name="{#name}">
<xsl:attribute name="minOccurs">
<xsl:choose>
<xsl:when test="#mandatory = 'true'">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xsl:apply-templates/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsl:template>
</xsl:stylesheet>
you are right, XSLT is the tool to use.
For your case it should be quite fast to create your xsl file as you don't have to much statements to convert.
You will need XSL and XPATH (Xml query language) to do the job
To start with, I suggest to go here http://www.w3schools.com/xsl/
and you will find the reference doc to XSLT there: http://www.w3.org/TR/xslt
For XPATH: http://www.w3.org/TR/xpath/ and http://www.w3schools.com/XPath/
Hope it will help.
Enjoy ;)
Yann
How do I an XSD date value which is optional? Is there a way I could escape from using nillable?
For instance, both
<element attribute="attribute">optional-value</element>
<element attribute="attribute"/>
are valid types, where "optional-value" must be defined as an xsd:date type.
Yes, but not with something that tools like:
XSD:
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="EmptyDate">
<xsd:attribute name="attribute" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="EmptyDate">
<xsd:union memberTypes="xsd:date emptyString"/>
</xsd:simpleType>
<xsd:simpleType name="emptyString">
<xsd:restriction base="xsd:string">
<xsd:length value="0"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Invalid XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attribute="attribute1" xmlns="http://tempuri.org/XMLSchema.xsd"> </root>
Valid XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attribute="attribute1" xmlns="http://tempuri.org/XMLSchema.xsd"/>