undefined element declaration 'xs:schema' - java

I am completely new to web service stuff.
I have to write rest web service client for a web service. The web service runs fine on SoapUI. WSDL file for the URL is provided to me. But when I add the wsdl file in my Eclipse project, it gives compilation error
src-resolve.4.2: Error resolving component 'xs:schema'. It was detected that 'xs:schema' is in namespace 'http://www.w3.org/2001/XMLSchema', but components from this namespace are not referenceable from schema document 'file:///E:/Ashish%20Workspace/HATStoLSAMS%20Webservice/HATS2LSAMSWS/WebContent/WEB-INF/wsdl/CorpsiteService.svc.wsdl'. If this is the incorrect namespace, perhaps the prefix of 'xs:schema' needs to be changed. If this is the correct namespace, then an appropriate 'import' tag should be added to 'file:///E:/Ashish%20Workspace/HATStoLSAMS%20Webservice/HATS2LSAMSWS/WebContent/WEB-INF/wsdl/CorpsiteService.svc.wsdl'.
I googled a lot to get rid of these error but nothing worked.
If I ignore the errors and try creating stubs using wsimport as well as wsdl2java commands
it gives error
[ERROR] undefined element declaration 'xs:schema'
line 1 of http://chec.local/STAR.WCF/CorpsiteService.svc?singlewsdl
I am using below command to generate stubs
wsimport -d e:\test -s E:\wssrc http://chec.local/STAR.WCF/CorpsiteService.svc?singlewsdl -wsdllocation "../../../../../WEB-INF/wsdl/CorpsiteService.svc.wsdl"
I am stuck at this point and have been struggling on to this the whole day.
Any help regarding this would be really helpful

The solution to this appears to be supply alternate bindings for xs:schema as described in https://metro.java.net/2.1/guide/Dealing_with_schemas_that_are_not_referenced.html
Specifically, for the http://www.w3.org/2001/XMLSchema which is often imported into the namespace xs, there is some additional work that needs to be done.
The command would be: wsimport -b http://www.w3.org/2001/XMLSchema.xsd -b customization.xjb something.wsdl
customization.xjb linked from the above is at https://www.java.net//blog/kohsuke/archive/20070228/xsd.xjb or copied from below
This customization exists to handle some naming conflicts that might arise from using the schema Schema (which is imported as the same name space in multiple schemas).
customization.xjb
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
version="2.0">
<globalBindings>
<xjc:simple />
</globalBindings>
<bindings scd="~xsd:complexType">
<class name="ComplexTypeType"/>
</bindings>
<bindings scd="~xsd:simpleType">
<class name="SimpleTypeType"/>
</bindings>
<bindings scd="~xsd:group">
<class name="GroupType"/>
</bindings>
<bindings scd="~xsd:attributeGroup">
<class name="AttributeGroupType"/>
</bindings>
<bindings scd="~xsd:element">
<class name="ElementType"/>
</bindings>
<bindings scd="~xsd:attribute">
<class name="attributeType"/>
</bindings>
</bindings>
I have tried this with these files and the associated -b parameters to wsimport and have gotten (apparently) past this error (and on to other ones). That said, I'm not 100% certain that my new errors are not in part caused by this (and thus this wouldn't be a complete answer). Without the actual wsdl causing the problem, one can only take a reasonable guess as to solving the problem (and on to the next one).

If you are using maven-jaxb2-plugin instead -b provide needed URL as additional schema in schemas:
<schema>
<url>https://example.com/WebService.asmx?WSDL</url>
</schema>
<schema>
<url>http://www.w3.org/2001/XMLSchema.xsd</url>
</schema>
You can even save it in resources so it is picked up automatically

I was facing same issue, resolved by just adding one line into maven plugin
<args>
<arg>-b</arg>
<arg>http://www.w3.org/2001/XMLSchema.xsd</arg>
</args>
My maven plugin is given below
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>periodictableaccessws</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
<args>
<arg>-b</arg>
<arg>http://www.w3.org/2001/XMLSchema.xsd</arg>
</args>
<wsdlFiles>
<wsdlFile>doosdaas.wsdl</wsdlFile>
</wsdlFiles>
<packageName>com.dss.doosdaas</packageName>
<vmArgs>
<vmArg>-Djavax.xml.accessExternalDTD=all</vmArg>
<vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
</vmArgs>
<!-- <bindingDirectory>${basedir}/src/main/resources/jaxb</bindingDirectory>
<bindingFiles>
<bindingFile>jaxb_binding.xjb</bindingFile>
</bindingFiles>-->
</configuration>
</execution>
</executions>
</plugin>

I face this kind of error when I had to consume some of UE Taxations Customs web services. In previous projects I had used the solution proposed by user289086
But for recents projects I had used another solution also based in bindings but shorter, where I use the Wrapper-style rules described here Using JAXB Data Binding.
1- Create a binding file with the following content and add it to META-INF folder:
<jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
</jaxws:bindings>
2- Create Web service reference from wsdl using wsimport(in my case I use the Netbeans IDE WS Client Assistant that use wsimport in the background) for the following service for example:
UE CheckTinService
Note: First maybe the process of wsimport could be raise and error or not, but the difference of adding or not the previous binding is easy to check.
3- Add the binding reference to the corresponding jaxws-maven-plugin execution in the .pom file. For the example it stays like this:
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlFiles>
<wsdlFile>ec.europa.eu/taxation_customs/tin/checkTinService.wsdl</wsdlFile>
</wsdlFiles>
<packageName></packageName>
<vmArgs>
<vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
</vmArgs>
<wsdlLocation>https://ec.europa.eu/taxation_customs/tin/checkTinService.wsdl</wsdlLocation>
<staleFile>${project.build.directory}/jaxws/stale/checkTinService.stale</staleFile>
<bindingFiles>
<bindingFile>${basedir}/src/main/resources/META-INF/TaxationCustomsWsImportBindings.xml</bindingFile>
</bindingFiles>
</configuration>
<id>wsimport-generate-checkTinService</id>
<phase>generate-sources</phase>
</execution>
</executions>
...
You can see the exactly configuration for using the binding file created before:
<bindingFiles>
<bindingFile>${basedir}/src/main/resources/META-INF/TaxationCustomsWsImportBindings.xml</bindingFile>
</bindingFiles>
4- Finally turn to refresh de WS Reference and the changes will be applied to the process of wsimport.

Related

Dealing with duplicate classes with multiple maven-jaxb2-plugin executions using different schemas with the same base schema

I'm currently using maven-jaxb2-plugin v0.13.3.
The plugin config has multiple executions, each processing wsdl files. Several of them are completely independent, but several are simply different wsdls in the same enterprise, with schemas that import a common base schema.
Note that I cannot change the wsdls or the schemas.
The original code was using "forceRegenerate" set to true, along with all of them writing to the same target directory. This works fine with a command-line build, but as many people know by now, this causes an infinite build loop in Eclipse.
I'm working through the steps to fully resolve this. The easy steps are setting "forceRegenerate" to false and adding a suffix directory to the "generateDirectory" directory for each execution to make them unique. I then have to change the Eclipse project properties to remove the original source directory for the common place they were all writing to, and replace that with a single ref for each of the now unique source directories.
Up to now, this would work fine if all the executions referenced fully independent schemas.
If two or more of these executions specify a wsdl that has schemas that reference a common base schema, which is the case here, I get duplicate class errors at build time.
If it helps, here is some sample code from the pom that has been somewhat elided:
<execution>
<id>unifiedServices</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<specVersion>2.2</specVersion>
<schemaDirectory>src/main/resources/schemas/csi_UnifiedServices_240.0_schema</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
<generateDirectory>target/generated-sources/jaxb/us</generateDirectory>
<forceRegenerate>false</forceRegenerate>
</configuration>
</execution>
<execution>
<id>iuclp</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<specVersion>2.2</specVersion>
<schemaDirectory>src/main/resources/schemas/csi_OrderAndSubscriptionManagementMobility</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
<generateDirectory>target/generated-sources/jaxb/osmm</generateDirectory>
<forceRegenerate>false</forceRegenerate>
</configuration>
</execution>
I've seen many postings that talk about variations of this, many of which refer to older versions of the plugin.
What are some practical solutions to this that still fulfill my constraints (can't modify the wsdl/schema)?
Update:
I am proceeding to implement the bindings file, as suggested in the first answer. It's not quite working, and I'm not sure what I'm doing wrong.
This is the configuration block of the first execution (I've only changed one execution block, once I determine it's generating reasonable code, I'll work on the other execution blocks, and then change the references in the code).
<configuration>
<bindingDirectory>src/main/resources/bindings</bindingDirectory>
<bindingIncludes>
<bindingInclude>unifiedservices.xjb</bindingInclude>
</bindingIncludes>
<specVersion>2.2</specVersion>
<schemaDirectory>src/main/resources/schemas/csi_UnifiedServices_240.0_schema</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
<generateDirectory>target/generated-sources/jaxb/us</generateDirectory>
<forceRegenerate>false</forceRegenerate>
</configuration>
This is the slightly elided bindings file (unifiedservices.xjb):
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2000/10/XMLSchema-instance"
xs:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
jxb:version="2.0">
<jxb:bindings schemaLocation="http://.../Namespaces/UnifiedServices/Types/Public/CommonDataModel.xsd"
node="/xs:schema">
<jxb:schemaBindings>
<nameXmlTransform>
<typeName suffix="us"/>
</nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
This is the header of the slightly elided "CommonDataModel.xsd":
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
xmlns='http://.../Namespaces/UnifiedServices/Types/Public/CommonDataModel.xsd'
targetNamespace='http://.../Namespaces/UnifiedServices/Types/Public/CommonDataModel.xsd'
elementFormDefault='qualified'
version='240.0.03'>
When I run this build, I get this as the first error:
[ERROR] Error while parsing schema(s).Location [ file:/C:/.../src/main/resources/bindings/unifiedservices.xjb{8,37}].
com.sun.istack.SAXParseException2: "http://.../Namespaces/UnifiedServices/Types/Public/CommonDataModel.xsd" is not a part of this compilation. Is this a mistake for "file:/C:/.../src/main/resources/schemas/csi_UnifiedServices_240.0_schema/CommonDataModel.xsd"?
Update:
I updated the bindings file so that "schemaLocation" is just a relative path to the schema file in question, but now I just get a different error.
This is my new bindings file:
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2000/10/XMLSchema-instance"
xs:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
jxb:version="2.0">
<jxb:bindings schemaLocation="../schemas/csi_UnifiedServices_240.0_schema/CommonDataModel.xsd"
node="/xs:schema">
<jxb:schemaBindings>
<nameXmlTransform>
<typeName suffix="us"/>
</nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
When I build with this, I get:
[ERROR] Error while parsing schema(s).Location [ file:/C:/.../src/main/resources/bindings/unifiedservices.xjb{8,37}].
com.sun.istack.SAXParseException2: XPath evaluation of "/xs:schema" results in empty target node
This is the somewhat elided header of the "CommonDataModel.xsd" file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ... -->
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
xmlns='http://.../Namespaces/UnifiedServices/Types/Public/CommonDataModel.xsd'
targetNamespace='http://.../Namespaces/UnifiedServices/Types/Public/CommonDataModel.xsd'
elementFormDefault='qualified'
version='240.0.03'>
I had to ask myself whether that relative path is correct. I would think if it was wrong, I would get a more specific error message. For a little confirmation, I ran SysInternals ProcessMonitor, watching for "CommonDataModel.xsd", and they were all to that same file, and all were successful.
Update:
I think I found a possible cause for that last problem. The following pointed out an issue: XPath evaluation in JAXB binding file results in empty target node .
So, I made sure that the two "xs" namespaces were identical. This got rid of the xjc errors. However, it also didn't appear to do anything.
My current binding file is this:
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xs:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
jxb:version="2.0">
<jxb:bindings schemaLocation="../schemas/csi_UnifiedServices_240.0_schema/CommonDataModel.xsd"
node="/xs:schema">
<jxb:schemaBindings>
<jxb:nameXmlTransform>
<jxb:typeName suffix="us"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
When I run the build, I see blocks of output lines like this:
[INFO] --- maven-jaxb2-plugin:0.13.3:generate (unifiedServices) # UnifiedAccountMs ---
[INFO] Sources are not up-to-date, XJC will be executed.
[INFO] Episode file [C:\...\target\generated-sources\jaxb\us\META-INF\sun-jaxb.episode] was augmented with if-exists="true" attributes.
That looks fine, but it doesn't tell me anything. When it finally does the compile, I get errors like this:
[ERROR] /C:/.../target/generated-sources/jaxb/us/com/cingular/csi/csi/namespaces/unifiedservices/infrastructurecommon/types/_public/messageheader/ObjectFactory.java:[32,8] duplicate class: com.cingular.csi.csi.namespaces.unifiedservices.infrastructurecommon.types._public.messageheader.ObjectFactory
And when I searched for that fqcn, I did indeed find multiple occurrences of it (the elided portions are identical):
./target/generated-sources/jaxb/ausn/com/.../namespaces/unifiedservices/infrastructurecommon/types/_public/messageheader/ObjectFactory.java
./target/generated-sources/jaxb/us/com/.../namespaces/unifiedservices/infrastructurecommon/types/_public/messageheader/ObjectFactory.java
I may be misunderstanding what the "typeName" transformation is supposed to do, but it doesn't seem like it changed anything. In any case, I have a feeling that appending a suffix to the class name isn't exactly what I want. I think changing the package name is more appropriate, but I can't even get the typename transformation to do anything.
One solution could be to add a separate binding file (*.xjb) to each execution in order to generate specific classes (and avoiding name clash).
<configuration>
<bindingDirectory>src/main/bindings</bindingDirectory>
<bindingIncludes>
<include>unifiedServices.xjb</include>
</bindingIncludes>
See the XJC documentation , but it is for instance possible to add a suffix to all class names:
<schemaBindings>
<nameXmlTransform>
<typeName suffix="_SuffixA"/>
</nameXmlTransform>
</schemaBindings>
Doing so, if the same "Foo" type of namespace "company.com" is part of a same common schema imported by several wsdl, you could end up with distinct classes:
com.company.Foo_SuffixA (generated in "unifiedServices")
com.company.Foo_SuffixB (generated in "iuclp")

Duplicate NS in SOAP Message

Ive got a problem with my xml SOAP message - using java 1.8, Websphere 8.5.5.17, for generating class from wsdl Ive used jaxws-maven-plugin.
When I received SOAP message via WAS to my Java application, something duplicate my ns3 prefix (sometimes another), and unmarshaling to type Object is not work :(
<ns3:document xmlns:ns4="http://service.gggg.com/common/CommonMessage/v01" xmlns:ns3="http://service.gggg.com/RDS/datamodel/LAA/common/v01">
<ns3:outputChannels>
<ns3:archiveType>None</ns3:archiveType>
<ns3:publishingType>Signature</ns3:publishingType>
<ns3:printType>None</ns3:printType></ns3:document>
ns3 prefix is correctly defined upper and element "document" is anyType. The problem is in the inner atribute of document element -> the second definiton of xmlns:ns3, when I overide it manualy together with ns of childs it works.
<ns3:document xmlns:ns4="http://service.gggg.com/common/CommonMessage/v01" xmlns:ns9="http://service.gggg.com/RDS/datamodel/LAA/common/v01">
<ns9:outputChannels>
<ns9:archiveType>None</ns9:archiveType>
<ns9:publishingType>Signature</ns9:publishingType>
<ns9:printType>None</ns9:printType></ns3:document>
Ive just tried jaxb NamespacePrefixMapper, namespaces set in jaxb bindings, manualy overiding in Interceptor SOAPElement, add prefix namespace in package-info.java and a lot lot lot of more but without happy end :(
maven
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<genJWS>false</genJWS>
<extension>true</extension>
<wsdlFiles>
<wsdlFile>
${project.basedir}/src/main/resources/wsdl/ServiceWSDL.wsdl
</wsdlFile>
</wsdlFiles>
<target>2.0</target>
<xadditionalHeaders>true</xadditionalHeaders>
<bindingFiles>
<bindingFile>${project.basedir}/src/main/resources/jaxb/bindings.xml</bindingFile>
<bindingFile>${project.basedir}/src/jaxws/binding.xml</bindingFile>
</bindingFiles>
</configuration>
</execution>
</executions>
</plugin>
binding.xml
<jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle></jaxws:bindings>
bindings.xml
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
<jaxb:bindings>
<jaxb:globalBindings generateElementProperty="false" fixedAttributeAsConstantProperty="true"
choiceContentProperty="true"/>
</jaxb:bindings></jaxb:bindings>
Can someone help me ?
THX!

Generating client side code for wsdl with more parts in a body

I'm currently developing client app using official API of Polish Ministry of Finance to check NIP numbers. (https://sprawdz-status-vat.mf.gov.pl/?wsdl)
Unfortunately I have a problem with wsdl published by them. Namely there is a message with 2 parts.
<wsdl:message name="SprawdzNIPNaDzienZapytanie">
<wsdl:part name="NIP" element="tns:NIP"/>
<wsdl:part name="Data" element="tns:Data"/>
</wsdl:message>
I was trying to parse it by wsimport maven plugin but client side code didn't even generate, because of error
[ERROR] operation "SprawdzNIPNaDzien": more than one part bound to body[ERROR] operation "SprawdzNIPNaDzien": more than one part bound to body
I thought ok, I will try different tool for generating code. As I have already used cxf earlier I chose to use it. Code generated just fine but when I was trying to call the service I did get similar error as before.
SEI WeryfikacjaVAT has method sprawdzNIPNaDzien annotated as BARE but it has more than one parameter bound to body. This is invalid. Please annotate the method with annotation: #SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
Now I'm wondering. Is there a way to make it work without changing wsdl file? As it is official API which doesn't belong to me, I have no way to correct it. I guess there must by a way to operate with such wsdl as SoapUI handle it just fine and doesn't throw any errors.
#Update
I have tried to add cxf parameter mentioned by Khalid so my pom.xml looks as follows:
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<defaultOptions>
</defaultOptions>
<sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>other.xml</wsdl>
</wsdlOption>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/wsdl/my.wsdl</wsdl>
<bindingFiles>
<bindingFile>
${basedir}/src/main/resources/wsdl/bindings.xml
</bindingFile>
</bindingFiles>
<noAddressBinding>true</noAddressBinding>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
And bindings.xml file:
<jaxws:bindings
wsdlLocation="my.wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
<enableWrapperStyle>true</enableWrapperStyle>
</jaxws:bindings>
Unfortunately port is still generated with
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) instead of WRAPPED annotation.
When parameterStyle is Bare, web methods should only have 1 parameter.
With document style web services, the BP mandates that each message
have zero or one part.
Here is an example :
<message name = "SubmitPurchaseOrderMessage">
<part name="Order" element "sd:purchaseOrder"/>
</message>
So, that means the parameters are all inside element in the SOAP request.
When the parameter style is wrapped, that makes sense to have all
parameters wrapped inside element.
When the
parameter style is bare, all parameters are not wrapped inside any
element.
Therefore, that makes sense to have this under doc/lit/bare:
<message name="add">
<part name="parameter1" element="tns:a"/>
</message>
The schema will show something like this:
<add>
<element name="parameter1" type:int/>
</add>
But that won't make sense to have this message under doc/lit/bare:
<message name="add>
<part name = "parameter1" element="tns:a"/>
<part name = "parameter2" element="tns:b"/>
</message>
This is not valid as BP mandates that with document style web service, the message must have at most 1 element.
That's the reason your web method won't deploy. you have more than one part in message.
Reference :
https://coderanch.com/t/624936/certification/parameterStyle-Bare-web-methods-parameter
if you want to make it wrapped style without changing wsdl file then you use binding file with cxf to generate code.
Here is the bindings.xml
<jaxws:bindings
wsdlLocation="Your wsdl file path"
xmlns="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
<enableWrapperStyle>true</enableWrapperStyle>
</jaxws:bindings>
enableWrapperStyle = false to generate unwrapped style code.
and Here is the configuration you'll in pom.xml
<configuration>
<!-- Binding file for Wrapped style services -->
<defaultOptions>
<bindingFiles>
<bindingFile>
${basedir}/src/main/resources/bindings.xml
</bindingFile>
</bindingFiles>
<noAddressBinding>true</noAddressBinding>
</defaultOptions>
</configuration>

JAXB class generation for Amazon Product.xsd not working

When generating Java classes from the Products.xsd using JAXB and it's maven plugin I get the following warnings and errors
org.xml.sax.SAXParseException; systemId: https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/amzn-base.xsd; lineNumber: 956; columnNumber: 45; Simple type "ProcessorTypeValues" was not mapped to Enum due to EnumMemberSizeCap limit. Facets count: 744, current limit: 256. You can use customization attribute "typesafeEnumMaxMembers" to extend the limit.
at com.sun.tools.xjc.reader.xmlschema.ErrorReporter.warning(ErrorReporter.java:88)
...
Error while generating code.Location [ https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/SWVG.xsd{300,40}].
org.xml.sax.SAXParseException; systemId: https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/SWVG.xsd; lineNumber: 300; columnNumber: 40; A class/interface with the same name "generated.BBFCRatingType" is already in use. Use a class customization to resolve this conflict.
After I was able to fix this, I got errors like:
.../target/generated-sources/xjc/generated/Home.java:[2737,45] cannot find symbol
symbol: class Home
location: class generated.Home.ProductType
.../target/generated-sources/xjc/generated/Home.java:[2929,23] class generated.Home is already defined in package generated
I've seen many questions concerning this while googling, but no one proposed a proper solution.
After a day of analyzing the problems and solving them step by step I got it to work.
To my opinion the XSDs are not very consistent, they contain for example multiple element declarations that could be summarized in a common XSD and some elements have a hierachy which contain elements with the same name.
The XSDs are not invalid but do not comply to Java conventions in some ways, when using JAXBs default settings.
One solution is, to keep the XSDs locally and to just comment out the conflicting parts an then generate classes.
But I wanted to generate the classes using the provided URLs, so this did not work for me.
So I'll post my solution here, perhaps it helps somebody:
The generation is done via maven-jaxb2-plugin in the pom.xml, so this part reads (my target package is defined as com.amazon.product, you can change it to what you like):
<plugins>
...
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemas>
<schema>
<url>https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Product.xsd</url>
</schema>
</schemas>
</configuration>
<id>jaxb-generate-amazon</id>
</execution>
</executions>
<configuration>
<catalogResolver>org.jvnet.jaxb2.maven2.resolver.tools.ClasspathCatalogResolver</catalogResolver>
<generatePackage>com.amazon.product</generatePackage>
<generateDirectory>${project.build.directory}/generated-sources/xjc</generateDirectory>
<verbose>true</verbose>
<removeOldOutput>false</removeOldOutput>
<clearOutputDir>false</clearOutputDir>
<forceRegenerate>true</forceRegenerate>
</configuration>
</plugin>
...
<plugins>
My bindig.xjb in the resource folder reads:
<bindings
xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
version="2.1">
<globalBindings underscoreBinding="asCharInWord" typesafeEnumMaxMembers="9000" typesafeEnumMemberName="generateName"/>
<bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/FoodServiceAndJanSan.xsd" node="//xsd:element[#name='ProductType']/xsd:complexType/xsd:choice/xsd:element[#name='FoodServiceAndJanSan']/xsd:complexType">
<class name="FoodServiceAndJanSanSub"/>
</bindings>
<bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Home.xsd" node="//xsd:element[#name='ProductType']/xsd:complexType/xsd:choice/xsd:element[#name='Home']/xsd:complexType">
<class name="HomeSub"/>
</bindings>
<bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/GiftCards.xsd" node="//xsd:element[#name='ProductType']/xsd:complexType/xsd:choice/xsd:element[#name='GiftCard']/xsd:complexType">
<class name="GiftCardSub"/>
</bindings>
<bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/MechanicalFasteners.xsd" node="//xsd:element[#name='ProductType']/xsd:complexType/xsd:choice/xsd:element[#name='MechanicalFasteners']/xsd:complexType">
<class name="MechanicalFastenersSub"/>
</bindings>
</bindings>
Why do we need this bindings? I'll tell you:
Long enum types result in a WARNING
This is just a warning but it annoyed me.
Enums such as ´ProcessorTypeValues` have more entries than the default valid number of 256. You can configure this in the globalBindings:
<globalBindings ... typesafeEnumMaxMembers="1000" .../>
A class/interface with the same name "generated.BBFCRatingType" is already in use.
Amazon for example defines the element types like BBFCRatingType and BBFC_Rating_Type. Unforunately the default config will generate for both a Java class named BBFCRatingType. But two classes in a Java package cannot have the same name.
The solution is to tell JAXB to include the underscores:
<globalBindings ... underscoreBinding="asCharInWord" .../>
class generated.Home is already defined in package generated
For example the Home.xsd defines an element called Home as a subelement of ProductType which itself is located in another element, also called Home. The problem is the same as in the previous errors: Two classes with the same name in one package.
We have to give the second class a different name:
<bindings schemaLocation="https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/Home.xsd" node="//xsd:element[#name='ProductType']/xsd:complexType/xsd:choice/xsd:element[#name='Home']/xsd:complexType">
<class name="HomeSub"/>
</bindings>
Additional thoughts/improvements
If you want some enums, that cannot be generated automatically, to be real Java enums, you have to force this manually for each one.
For example for ProductClothing:
<bindings schemaLocation="xsd/ProductClothing.xsd">
<bindings node="//xsd:element[#name='VariationData']/xsd:complexType/xsd:sequence">
<bindings node="./xsd:element[#name='Parentage']/xsd:simpleType">
<typesafeEnumClass name="Parentage" />
</bindings>
<bindings node="./xsd:element[#name='VariationTheme']/xsd:simpleType">
<typesafeEnumClass name="VariationTheme" />
</bindings>
</bindings>
<bindings node="//xsd:element[#name='ClassificationData']/xsd:complexType/xsd:sequence">
<bindings node="./xsd:element[#name='ClothingType']/xsd:simpleType">
<typesafeEnumClass name="ClothingType" />
</bindings>
<bindings node="./xsd:element[#name='PerformanceRating']/xsd:simpleType">
<typesafeEnumClass name="PerformanceRating" />
</bindings>
<bindings node="./xsd:element[#name='CupSize']/xsd:simpleType">
<typesafeEnumClass name="CupSize" />
</bindings>
<bindings node="./xsd:element[#name='TargetGender']/xsd:simpleType">
<typesafeEnumClass name="TargetGender" />
</bindings>
<bindings node="./xsd:element[#name='WaterResistanceLevel']/xsd:simpleType">
<typesafeEnumClass name="WaterResistanceLevel" />
</bindings>
</bindings>
</bindings>
Update 22.12.2017
I've created a repository on GitHub containing all necessary binding to get the XSD working with Java.

Supporting i18n in GWT

Till now, our web application supports only English. Now we have to provide support for Italian as well. There is GWT module for some functionality. To support the Italian language I have added below line in the file "APP_Module.gwt.xml"
<extend-property name="locale" values="it"/>
I have also placed "XXX_it.properties" file under the source code where the properties file for en is kept.
Setting the locale in the jsp by following line:
<meta name="gwt:property" content="locale=${locale}">
Now, the issue is how to compile the code. I am debugging the application but it is not hitting the client code of GWT presented under WEB-INF/src.
I am very new to GWT. Please suggest how can I compile the code or there is no need of compilation. It will automatically take the changes done in "APP_Module.gwt.xml" and there is some other issue. How can I see logs of GWT?
To add support for locales to GWT application, you need to do the following in your xxx.gwt.xml:
under <module> add this to include the support:
<inherits name="com.google.gwt.i18n.I18N" />
and this to configure it:
<extend-property name="locale" values="en,it"/>
<set-property-fallback name="locale" value="en"/>
Add all your property files under some package like this:
src/main/resources/foo/bar/client/i18n/MyMessages.properties
src/main/resources/foo/bar/client/i18n/MyMessages_it.properties
Then you need to tell GWT to compile them into classes. This is example from a pom.xml file (if you don't use maven, you will have to use a different way, but you still need to configure it).
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>1.3.1.google</version>
<executions>
<execution>
<goals>
<goal>i18n</goal>
<goal>generateAsync</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<i18nMessagesBundles>
<resourceBundle>foo.bar.client.i18n.MyMessages</resourceBundle>
</i18nMessagesBundles>
</configuration>
</plugin>
Then you need to recompile the code. In maven mvn compile. And that's all, you will have your messages in generated sources folder ready to use.
For seeing the logs of gwt you can use gradlew gwt also you can use it to compile the code too.

Categories