generate client wsimport miss link between two object - java

I would like to generate client stubs from a wsdl with wsimport maven plugin , this is works well but with one issue : i have two object that should be linked togerther but afetr the generation is donne , it's not perfect
<types>
<xsd:schema elementFormDefault="qualified" targetNamespace="http://www.hello.com/ns/xsd/boba/restitution-restituerCarriereAvecValo.xsd">
<xsd:import namespace="http://www.hello.com/holla/infosRetour.xsd" schemaLocation="xsd/infosRetour.xsd"/>
<xsd:import namespace="http://www.hello.com/ns/wsdl/boba/messageRetourModuleValorisation.xsd" schemaLocation="xsd/messageRetourModuleValorisation.xsd"/>
<xsd:element name="messageIn" type="xsd:anyType"/>
<xsd:element name="messageOut">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="ir:infosRetour">
<xsd:choice>
<xsd:element name="messageRetour" type="xsd:anyType"/>
<xsd:element name="rejetControleSyntaxiqueSemantique" type="xsd:anyType"/>
<xsd:element name="rejetControleIdentification" type="xsd:anyType"/>
</xsd:choice>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
here my object messageOut sould have a field messageRetour of type messageRetour class, but when i see my class messageOut this field is set as Object and not the montioned class.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"messageRetour",
"rejetControleSyntaxiqueSemantique",
"rejetControleIdentification"
})
#XmlRootElement(name = "messageOut")
public class MessageOut
extends InfosRetour
{
protected Object messageRetour;
protected Object rejetControleSyntaxiqueSemantique;
protected Object rejetControleIdentification;
as you can see here here is the sub class generated , you can see that there is a class named messageRetour
HOW CAN I CHANGE THIS TYPE TO BE SET AS A CLASS AND NOT AS OBJECT ?
even when i chnage this line <xsd:element name="messageRetour" type="xsd:anyType"/> to <xsd:element name="messageRetour"/> i got the same issue always Object and not a class

You get Object because of xsd:anyType as type.
You should change the type of <xsd:element name="messageRetour" type="xsd:anyType"/> to the messageRetour type.
This type is probably provided by one of the schemas you import. I'm not sure about the specific name, will be probably MessageRetour or messageRetour or message-retour, something like that. So it will probably be something like:
<xsd:element name="messageRetour" type="ir:messageRetour"/>
If the type is provided by the other imported schema, you may need to declare a namespace prefix first (like xmlns:mrmv="http://www.hello.com/ns/wsdl/boba/messageRetourModuleValorisation.xsd") and then use mrmv:messageRetour as type.

Related

SOAP via jax-ws: entity classes missing in schema

So, I have a soap server-side project. Annotations - #WebService over interface and implementation, #WebMethod over interface' methods, #XmlRootElement over entity-classes that are in return and arguments in web-methods, and #XmlElement over their fields(over getters actually). Tried also partially and fully swap #XmlRootElement with #XmlType, and #XmlElement with #XmlAttribute.
Project is launched via publisher class or via Tomcat(WSServletContextListener), everything's working after weeks of trial and error. In WSDL schema, for instance:
<xsd:element name="Sell_i">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="session" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="terminal" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="info" nillable="true" type="tns:TransactionSellInfo"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
Represents the Sell_i method. TransactionSellInfo is an input argument here, and tns points to this namespace aka this wsdl. So, it should be described here. It of course has all the annonations. But, it's just missing, as well as every other class. What's the solution?
Worth noting: schema type is RPC(tho changing to Document doesn't cause classes to appear in wsdl). Also, on the same machine wsimport from wsdl creates classes for those missing entities, which is very wierd(didn't test wsimport on other machines tho). But soapUI won't work with that wsdl and rightfully says that it's malformed.
Maybe it's something quite basic that I'm missing, but google gives nothing useful on all my tries. Any help is appreciated!

How does JAXB decide which type to create when it marshals XML that can match both types?

I have an XML schema whose topmost element is Document
<xsd:element name="Document" type="Document"/>
It contains one element of type ZZ_Customer which is restriction of Customer.
Both of these elements contain children of the same name but with slightly different types.
<xsd:complexType name="Document">
<xsd:sequence>
<xsd:element name="CstmrCdtTrfInitn" type="ZZ_Customer"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ZZ_Customer">
<xsd:complexContent>
<xsd:restriction base="Customer">
<xsd:sequence>
<xsd:element name="GrpHdr" type="ZZ_Group"/>
<xsd:element name="PmtInf" type="ZZ_Payment" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="Customer">
<xsd:sequence>
<xsd:element name="GrpHdr" type="Group"/>
<xsd:element name="PmtInf" type="Payment" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
When JAXB unmarshalls an XML file will it create an instance of ZZ_Customer or will it create an instance of Customer? Likewise when will it create an instance of Group or ZZ_Group?
I've noticed is that JAXB will instances of ZZ_* for certain parts of the XML but uses their base counter parts for other parts of the XML.
On what basis does it makes its decisions? It does not appear obvious which criteria that JAXB is using.
Unfortunately I have no control over the schema and its design.
Since Document has a property that corresponds to the sub-type.
The sub-type will be created when unmarshalling. This makes sense since in Java when a property is typed to the subclass you can't set an instance of the super class on it.
If the property had corresponded to the super type, by default JAXB would have unmarshalled it to an instance of the super type. The XML can contain the xsi:type attribute to specify that the subtype is being used.

some noob wsdl questions

<xsd:element name="loginResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="loginReturn" type="tns:test"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="test">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="tx" type="xsd:int"/>
<xsd:element minOccurs="0" maxOccurs="1" name="result" type="xsd:int"/>
<xsd:element minOccurs="0" maxOccurs="1" name="name_space" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
I just want to ask why is the type tns:test used? How can I get the tx, result, namespace values in complextype name="test", because that's the response should I get based on the api they given to me.
tns is the target namespace prefix, which should be defined at the top of your WSDL or XSD file (which includes test).
You didn't wrote how you do access the values, but I assume that your code is working in a different namespace, so that test cannot be indentified. Most likely there is a method which allows you to get values by element name and namespace. Note that in that case, the namespace isn't tns but rather the URL which is defined at top of source file.
If you're not familiar with namespaces: Each XML element is associated with a namespace, like a class in Java is part of a package. In XML there is no import statement, so you have to name an element by name and namespace. To keep the files readable you can define namespace prefixes (probably as an abbreviation).

JAXB Generation nillable=true

Using JAXB 2.2.4 I am generating Java code with the following binding file:
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings generateElementProperty="false">
</globalBindings>
Unfortunately, the generated code has a nillable = true annotation. See the following example:
#XmlElement(name = "ArtID", nillable = true)
protected STEBeitrag artID;
This is the definition of STEBeitrag:
<xsd:complexType name="CT_Beitrag">
<xsd:complexContent>
<xsd:extension base="allgemein:CT_Objekt">
<xsd:sequence>
<xsd:element name="ArtID" type="daten:STE_Beitrag" minOccurs="0" maxOccurs="1" nillable="true"/></xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="STE_Beitrag" abstract="true">
<xsd:simpleContent>
<xsd:extension base="xsd:string"/>
</xsd:simpleContent>
</xsd:complexType>
If I do not set the ArtID in the generated CT_Beitrag object then the unmarshaller produces an output like
<ns:ArtID xsi:nil="true"/>
The element ArtID has an abstract type and therefore this XML output is invalid.
How can I generate code with JAXB that omits the nillable=true in the XmlElement annotation?
By the way, the schema canĀ“t be changed.
I have no solution, but this problem is addressed in bug
http://java.net/jira/browse/JAXB-890
I hope this problem wil be solved.
I don't how to do what you're asking and I'd be surprised if what you're asking is worth the effort.
There are 2 options that jump to my mind:
Change the schema (I know you said you can't but perhaps you can take a local copy of the schema if you can't change it due to it being hosted on a server outside of your control)
Change the generated code... simply change nillable=true to nillable=false

JAXB minOccurs=0. Element exists or not?

I have an XML schema:
<xsd:element name="Person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
<xsd:element name="lat" type="xsd:double" minOccurs="0"/>
<xsd:element name="lon" type="xsd:double" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
And I have an XML message:
<Person>
<name>Fred</name>
</Person>
I use JAXB to auto-generate my classes (i.e. Person.java, etc).
So at run time I use JAXB to unmarshal the above XML message and get a Person object instance. When I do a p.getLat() or p.getLon() the return values are 0.0 even though the original XML didn't contain <lat> or <lon> elements.
What makes this worse is that 0.0, 0.0 is a valid latitude and longitude. It's rare for a person to be located there but that's beside the point!
An article on the IBM site suggested using an additional XML element as metadata to explicitly state whether the optional element exists or not. i.e.
<xsd:element name="hasLat" type="xsd:boolean"/>
<xsd:element name="hasLon" type="xsd:boolean"/>
So the XML message above would become:
<Person>
<name>Fred</name>
<hasLat>false</hasLat>
<hasLon>false</hasLon>
</Person>
This seems like an ugly hack. There must be a proper way with JAXB to check if the element existed so that I can trust the return value from my getLat(), getLon()?
I don't see that problem at all. For me xjc generates a Person class with the properties lat and lon with type Double.
If I unmarshall an XML file with no <lat> or <lon> elements, then the resulting Person objects has null values for those properties, as I'd expect.
I don't know how you get 0.0 anywhere.
My XML Schema:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/person">
<xsd:element name="Person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
<xsd:element name="lat" type="xsd:double" minOccurs="0"/>
<xsd:element name="lon" type="xsd:double" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
My Test.java:
import com.example.person.Person;
import javax.xml.bind.JAXB;
import java.io.File;
public class Test {
public static void main(String[] args) {
Person p = JAXB.unmarshal(new File("foo.xml"), Person.class);
System.out.println(p.getName());
System.out.println(p.getLat());
System.out.println(p.getLon());
}
}
My foo.xml:
<Person>
<name>Fred</name>
<lat>1.0</lat>
</Person>
Output:
Fred
1.0
null
The most likely reason for getting 0.0 returned vs null is the use of the Double primitive type or Double object type. The Double primitive will default to 0.0 if the value is null, since null is not a valid value for primitive types. The Double object will allow you to assign a null value to these fields. A peak at your Person class will probably reveal this.

Categories