Modify JAXB xs:any attribute processContents using a binding file - java

In a WSDL file, there is an xs:any element that I want to override from:
<xs:element minOccurs="0" maxOccurs="1" name="GetPermissionCollectionResult">
<xs:complexType mixed="true">
<xs:sequence>
<xs:any/>
</xs:sequence>
</xs:complexType>
</xs:element>
To:
<xs:element minOccurs="0" maxOccurs="1" name="GetPermissionCollectionResult">
<xs:complexType mixed="true">
<xs:sequence>
<xs:any processContents="skip"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Ultimately what I'm doing is using JAXB to generate annotated Java code from the WSDL. And for the xs:any element, this is generated:
#XmlAnyElement(lax = true)
Instead I want this:
#XmlAnyElement(lax = false)
The WSDL file is not generated by me so I can't just make the modification to the file. Is there a way of using a JAXB binding file to get the same effect?
I looked at using jaxb:property and jaxb:class elements but neither seems to fit want I want done.

Related

Java class to XSD

Could someone please tell me what XSD matches this Java class?
public class MyClass {
private List<String> list1;
private List<String> list2;
private XMLGregorianCalendar date;
// getters and setters
}
I've tried the following, but I'm receiving an One of :attribute, :attributeGroup, :anyAttribute is expected error:
<xs:element name="myClass">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="list1" type="xs:string"/>
</xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="list2" type="xs:string"/>
</xs:sequence>
<xs:element name="date" nillable="true" type="xs:dateTime"/>
</xs:complexType>
</xs:element>
So it seems I'm not using the <xs:sequence> tag correctly. Could someone please shed some light? (I'm far from being an expert in XML-related stuff)...
I'm using Spring Boot 1.4.4.RELEASE version with Java 7.
The xs:sequence within a xs:complexType defines a specific order in which an elements children must occur. To create a list of elements you simply use the minOccurs and maxOccurs directly on the xs:element tag you want repeated, as follows:
<xs:element name="myClass">
<xs:complexType>
<xs:sequence>
<xs:element name="list1" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="list2" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="date" nillable="true" type="xs:dateTime"/>
</xs:sequence>
</xs:complexType>
</xs:element>
This should create the class you expect and require XML such as the following (order of tags matter):
<myClass>
<list1>a</list1>
<list1>b</list1>
<list2>y</list2>
<list2>z</list2>
<date>2019-06-26T00:00:00.0000000Z</date>
</myClass>
Placing minOccurs and maxOccurs on the xs:sequence tag requires the entire sequence of elements to be repeated.

WSImport bindings for two WSDLs with the same namespace

I am writing a client that leverages two separate WSDLs from a third party. These two WSDLs have the exact same namespaces. So, I created binding files to put the objects generated from the two WSDLs into separate packages to avoid conflicts. However, there are a few common elements between these two WSDLs that share the exact same definition. Having these objects be generated into separate packages is not desirable since I'd like to share them. I have been unable to find any way to do this using binding files. The closest I got was to pull those shared elements out of the WSDLs and put them in a new XSD, change the targetNamespace of this XSD, and then target that namespace in the binding file to put it into a different package. The issue with this approach is that now the namespace of the generated common objects is different, so it doesn't serialize properly when calling the actual service.
The shared elements in question look like this:
<xs:complexType name="OperationResult">
<xs:sequence>
<xs:element name="MessageID" nillable="true" type="xs:string"/>
<xs:element name="Results" nillable="true" type="tns:ArrayOfCommandResult"/>
</xs:sequence>
</xs:complexType>
<xs:element name="OperationResult" nillable="true" type="tns:OperationResult"/>
<xs:complexType name="ArrayOfCommandResult">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="CommandResult" nillable="true" type="tns:CommandResult"/>
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfCommandResult" nillable="true" type="tns:ArrayOfCommandResult"/>
<xs:complexType name="CommandResult">
<xs:sequence>
<xs:element minOccurs="0" name="EntityID" type="xs:int"/>
<xs:element name="EntityType" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="ExchangeID" nillable="true" type="xs:string"/>
<xs:element name="Code" nillable="true" type="xs:string"/>
<xs:element name="Reason" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Description" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="CommandResult" nillable="true" type="tns:CommandResult"/>
and they are just defined inside of the
<xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.mypartnercompany.com/stuff/2013/06"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
Is there anything that I can do to get these common objects to generate to a separate package so I can share them between the two services, without having to change the namespace myself?

Converting Java generic object to XML using JAXB

I want to XML payloads like:
<ResponseDto>
<ResponseHeader>
<success>true</success>
</ResponseHeader>
<ResponseBody>
<ObjectA>
</ObjectA>
</ResponseBody>
</ResponseDto>
and another payload like:
<ResponseDto>
<ResponseHeader>
<success>true</success>
</ResponseHeader>
<ResponseBody>
<ObjectB>
</ObjectB>
</ResponseBody>
</ResponseDto>
so I want to make a class for ResponseDto which contains ResponseHeader Object and a generic Java Object in which I can place different types of objects, so I tried multiple types of Objects in a single class with #XMLElement(name = "ResponseBody") but it did not allow me to have same names of XMLElements
What can I do in this scenario?
Thanks in advance.
Most of enterprise applications use JAXB. You could get many tutorials some are below.
http://www.mkyong.com/java/jaxb-hello-world-example/
https://examples.javacodegeeks.com/core-java/xml/bind/jaxb-marshal-example/
https://www.javacodegeeks.com/2014/12/jaxb-tutorial-xml-binding.html
Step 1: First you would require to make xsd file. There are many online sites where xsd can be generated. Use http://xmlgrid.net/xml2xsd.html for now. XSD should look like this.
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ResponseDto">
<xs:complexType>
<xs:sequence>
<xs:element name="ResponseHeader">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="success"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ResponseBody">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="ObjectA" minOccurs="0"/>
<xs:element type="xs:string" name="ObjectB" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Refer my below post for reference.
read and get xml values in java

Compiling XML schema to Java with key/keyref identity constraints

Lets say I have the following XML schema:
<xs:schema
xmlns="http://www.example.com/data"
xmlns:data="http://www.example.com/data"
targetNamespace="http://www.example.com/data"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="data">
<xs:complexType>
<xs:all>
<xs:element name="countries">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="country" type="country"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="types">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="type" type="type"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="products">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="product" type="product"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
<xs:key name="countryNameKey">
<xs:selector xpath=".//data:country"/>
<xs:field xpath="#name"/>
</xs:key>
<xs:key name="typeNameKey">
<xs:selector xpath=".//data:type"/>
<xs:field xpath="#name"/>
</xs:key>
<xs:keyref name="countryNameRef" refer="data:countryNameKey">
<xs:selector xpath=".//data:product"/>
<xs:field xpath="#country"/>
</xs:keyref>
<xs:keyref name="typeNameRef" refer="data:typeNameKey">
<xs:selector xpath=".//data:product"/>
<xs:field xpath="#type"/>
</xs:keyref>
<xs:unique name="uniqueProducts">
<xs:selector xpath=".//data:product"/>
<xs:field xpath="#country"/>
<xs:field xpath="#type"/>
</xs:unique>
</xs:element>
<xs:complexType name="country">
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="type">
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="product">
<xs:attribute name="country" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
Excuse the contrived example.
As you can see it is tabular data. I define some countries, then I define some types of product. I then define individual products as a type from a country, cheese from France for example.
The important thing to note here is that I use key and keyref to cross-reference all products back to the original country/type.
So, my question is:
Is it possible to compile this schema into java classes that can be unmarshalled using Eclipse Moxy with the cross-references intact?
I know that the JAXB 2.0 spec does not support key/keyref. I also know that Moxy Does.1
Further I know that Moxy doesn't have a Maven plugin and, in any case, uses XJC generated classes and simply adds in a jaxb.properties file to specify the JAXB provider to use.2
So I suspect the answer to my question is "no, you have to craft the classes yourself", but I thought I'd check before I abandoned hope.
To clarify, My product element currently compiles (using maven-jaxb2-plugin) to
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "product")
public class Product implements Cloneable, CopyTo, Equals, HashCode, ToString {
#XmlAttribute(name = "country", required = true)
protected String country;
#XmlAttribute(name = "type", required = true)
protected String type;
//getters and setters
}
It, references the Strings rather than the Country and Type objects.
Currently EclipseLink JAXB (MOXy) only extends the XJC tool to add a jaxb.properties file that indicates that MOXy is the JAXB (JSR-222) provider. I have entered the following enhancement (currently unscheduled) to track this request:
http://bugs.eclipse.org/411619

JAXB does not parse .xsd as intended. C# auto generation from same file does

I am having some trouble with the way JAXB currently generates java objects from .xsd files. Below I have a code snippet from a .xsd file I am using. The intent of this code is that it will have a list of LogicalDevices which are objects that contain various information.
<xs:element name="LogicalDeviceList">
<xs:annotation>
<xs:documentation>List of all LogicalDevices currently added for the application</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="LogicalDevice" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>An added logical device</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="DeviceDefinitionId" use="required">
<xs:annotation>
<xs:documentation>The DeviceDefinitionId of the Logical device</xs:documentation>
.......... Other LogicalDevice Information
Currently the JAXB parser creates an object where the LogicalDeviceList isn't a list of LogicalDevices, and the LogicDevice returns a list of DeviceDefinitionIds.
As the XML I am receiving and unmarshaling cannot change in anyway, is there a way to fix this problem? Is it as simple as changing the .xsd file to read as such
UPDATE: The modification below does not work. 5-24-2013
<xs:element name="LogicalDeviceList" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>List of all LogicalDevices currently added for the application</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="LogicalDevice">
<xs:annotation>
<xs:documentation>An added logical device</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="DeviceDefinitionId" use="required">
<xs:annotation>
<xs:documentation>The DeviceDefinitionId of the Logical device</xs:documentation>
If so, why does the C# .xsd parser generate objects and list from the original xsd as intended and JAXB does not.
For the XML schema fragment:
<xs:element name="LogicalDeviceList">
<xs:annotation>
<xs:documentation>List of all LogicalDevices currently added for the application</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="LogicalDevice" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>An added logical device</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="DeviceDefinitionId" use="required">
<xs:annotation>
<xs:documentation>The DeviceDefinitionId of the Logical device</xs:documentation>
...
You are going to get a class structure like the following where the LogicalDeviceList class has a collection of LogicalDevice instances.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"logicalDevice"
})
public static class LogicalDeviceList {
#XmlElement(name = "LogicalDevice")
protected List<LogicalDeviceList.LogicalDevice> logicalDevice;
JAXB may not exactly match what is generated by C#, but it is a perfectly acceptable representation of the XML schema.

Categories