JAXB (new) annotation - annotations

If you have some Java class:
#XmlType(namespace="")
#XmlRootElement(name="", namespace="")
public class Car
{
// This is some comment
#XmlElement()
private long id;
...
And you want to create schema like this (with comment inside schema):
<xs:complexType name="Car ">
<xs:sequence>
<xs:documentation> This is some comment</xs:documentation>
<xs:element name="id" type="xs:long"/>
</xs:sequence>
</xs:complexType>
Is there way how to configure JAXB?
I have think, is there way how to create "new annotation", so my Java class would look like:
#XmlType(namespace="")
#XmlRootElement(name="", namespace="")
public class Car
{
#XmlDoc("This is some comment")
#XmlElement()
private long id;
...
In other words: can I tell jaxb, that new annotation is important to him and how it should be "parsed" in context.generateSchema (schemaOutputResolver)
(As example: #XmlDoc is new annotation and jaxb should take its value and put in xs: document element)

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
This functionality does not currently exist today, but it has been requested before:
https://java.net/jira/browse/JAXB-273
There is also an open enhancement request where we are gather the requirements to add this type of feature to MOXy. I would be interested in getting your thoughts on it:
http://bugs.eclipse.org/409419

Related

non-overrideing jaxb generation

I am trying to generate a bunch of xml annotated pojos. To do this I have all my xsd files in the resource folder of my project (they are from the polycom rmx sdk, RmxSdkApiV7_8-EMA_EMA-V7_8_0_303). I then right click on each one (over 150 of them) go to generate and click JAXB classes. I pick the project and give it a namespace than finish the wizard. After doing this there is a warning that any newly generated classes will override existing ones. This is my problem, because some commonly used objects will have different definitions in different xsd files. So when the override happens whatever was defined is lost.
So for example, response_trans_conf.xsd defines GET as
<xsd:element name="GET">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="CONFERENCE" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
Where as another schema file like trans_conf_2.xsd defines GET as
<xsd:element name="GET">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="ID"/>
<xsd:element ref="OBJ_TOKEN"/>
<xsd:any processContents="skip" minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
So I'll end up with a Get object that looks like
public class GET {
#XmlElement(name = "CONFERENCE")
protected ConferenceContent conference;
OR (respectively)
public class GET {
#XmlElement(name = "ID", required = true)
protected BigInteger id;
#XmlElement(name = "OBJ_TOKEN", required = true)
protected String objtoken;
#XmlAnyElement
protected List<Element> any;
What I need is an object that a combination of both. Like I said there are over 150 xsd files in this sdk. So this problem is multiplied by few other common objects.
FYI at the same time of wanting a combined class rather then an overridden one Im hoping the solution would also prevent duplicates some how.
due to lack of answers I have implemented a workaround which is to manually add the missing/needed members.
Im sure the comment above by ulab would work as well but I really do not want to edit the xsd's
The other option I see but did not implement is a wrapper. extending these common classes to have all the members in another layer above the sdk's generated file. that would ensure the sdk doesnt need to be touch even when there is a new version and a new generation of files.

Creating Soap messages with objectTypes using SUDS library in Robot Framework

i am struggling to create this part of the soap message using robot framework with SUDS library.
<ns1:Request>
<ns0:ID objectType="SomeType">Value</ns0:ID>
</ns1:Request>
If i do like this, then i get all i need but not the objectType.
${object}= Create Wsdl Object ns19:RequestTypeSingle
Set Wsdl Object Attribute ${object} ID 1234
Output
<ns1:Request>
<ns0:ID>1234</ns0:ID>
</ns1:Request>
If i check what my ns19:RequestTypeSingle wants i get this:
${object} = (RequestTypeSingle){
ID =
(ID){
_objectType = ""
}
}
"RequestTypeSingle" definition
<xs:complexType name="RequestTypeSingle">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="ID" nillable="true">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="objectType" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
So how can i declare this "(ID){_objectType = ""} with SUDS or some other?
Thanks to ombre42 this can be done like this (first question answered):
${req}= Create WSDL Object ns19:RequestTypeSingle # may need namespace prefix here
Set Wsdl Object Attribute ${req.ID} _objectType SomeType
(Continuing question).
How ever this will not set the value as i mentioned in my request example. It would seem that this kind of syntax would work but it did not. Any great ideas on this one?
This will give an error: "ValueError: Object must be a WSDL object (suds.sudsobject.Object)."
${req}= Create WSDL Object ns19:RequestTypeSingle # may need namespace prefix here
Set Wsdl Object Attribute ${req} ID 1234
Set Wsdl Object Attribute ${req.ID} _objectType SomeType
And this will overwrite the first _objectType definition.
${req}= Create WSDL Object ns19:RequestTypeSingle # may need namespace prefix here
Set Wsdl Object Attribute ${req.ID} _objectType SomeType
Set Wsdl Object Attribute ${req} ID 1234
What i mean by overwrite is that i get this:
<ns1:Request>
<ns0:ID>1234</ns0:ID>
</ns1:Request>
When assigning a value to property that is expressed as an XML attribute instead of an element, prefix the name with an underscore (why _objectType instead of objectType).
${req}= Create WSDL Object RequestTypeSingle # may need namespace prefix here
Set Wsdl Object Attribute ${req.ID} _objectType SomeType

Sparx Enterprise Architect - XSD Generation : Importing a XSDschema reference in the generated one

I'm using Sparx Enterprise Architect v10 to generate XSD schema from XML Schema graphic model.
Basically, I created 2 different XSDschema : 1 main XSDshema with my entities that are complexType :
<xs:complexType name="EntitytXT">
<xs:annotation>
<xs:documentation>This is the definition of an EntitytXT</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="element1" type="shared:StringXT" minOccurs="1" maxOccurs="1"/>
<xs:element name="element2" type="shared:StringXT" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
The other created XSDschema is the "shared one" and is simple with just the type StringXT; composed of things like that :
<xs:simpleType name="StringXT">
<xs:restriction base="xs:string">
<xs:maxLength value="5" />
</xs:restriction>
</xs:simpleType>`
What I want to do is :
Whenever I generate the first main XSD with EA, that the imported xsd "shared" path
xmlns:v1shared="http://xxxx/common/v1/shared" AND that the tag
<xs:import namespace="http://xxxx/shared" schemaLocation="http:/xx/xx/common/shared.xsd" />
are present in my generated resulting XSD.
Many thanks.
So, after almost a day, it ended up to be fairly obvious.
I didn't find any specific answer to this practical import procedure for different XSDschema in EA.
The thing is : you have 2 XSDschema as 2 different packages. To ensure the "shared" one to be imported into the main one (with the tag <xs:import explicitly in the xsd header, you must :
Enter 2 different target Namespace, one concerning each XSDschema package
Add the "shared" (+its namespace) in the XMLNS tab within the main XSDschema properties
Double check the SchemaLocation Tagged value for each XSDschema package
And last, but not least, in the xs sequence for your main complexTypes <xs:element name="element1" type="shared:StringXT" the "type" tag must be just :StringXT (without the 'shared') in order to 'link' the main XSDschema and the shared one. You can go to the XSDschema attributes and check their tagged values. You should see something like +Attributes +from StringXT
hope it helps!

Soap does not cast response fields to into typed objects

I am a SOAP newb assigned to resurrecting an old soap interface. I've ported the soap service onto a new tomcat at a new path (and left the client unchanged). I send the request:
http://myserver:8181/soap/SoapTest?wsdl
and I get back:
<wsdl:definitions xmlns:ns1="http://webservices.mycompany.com"
xmlns:ns3="http://schemas.xmlsoap.org/wsdl/soap/http"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.mycompany.com/SoapTest"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="SoapTestService"
targetNamespace="http://www.mycompany.com/SoapTest">
<wsdl:import location="http://myserver:8181/soap/SoapTest?wsdl=SoapTest.wsdl"
namespace="http://webservices.mycompany.com"></wsdl:import>
<wsdl:binding name="SoapTestServiceSoapBinding" type="ns1:SoapTest">...</wsdl:binding>
<wsdl:service name="SoapTestService">...</wsdl:service>
</wsdl:definitions>
Seems promising. A request to the import location SoapTest?wsdl=SoapTest.wsdl returns:
<wsdl:definitions xmlns:ns1="http://webservices.mycompany.com"
xmlns:ns2="http://jaxb.dev.java.net/array" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="SoapTest"
targetNamespace="http://webservices.mycompany.com">
<wsdl:types>
<xs:schema xmlns:tns="http://webservices.mycompany.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://webservices.mycompany.com" version="1.0">
<xs:complexType name="sessionObj">
<xs:sequence>
<xs:element name="code" type="xs:int"/>
<xs:element name="id" type="xs:long"/>
<xs:element minOccurs="0" name="role" type="xs:string"/>
<xs:element minOccurs="0" name="username" type="xs:string"/>
</xs:sequence>
</xs:complexType>
... (and so on)
So the client can receive member xs name:type associations but seems not to be - or not to be applying them. That is ...
HUH.. upon review, I see xs being used as a namespace but xmlns:xsd defined?? How might this happen?
ZSI client queries (from Windows, if that makes any difference) to this interface (Linux) receive responses containing the expected data payload but then map each data item into an individual "property" - resulting in a list of generic properties.
I was expecting a list of typed members, with each property cast to its xs type (e.g. int, long, string, string for the above), right?
Thanks in advance for any clues.
Given that you've not provided enough information for the real issue at hand, I will base this on the basis of you been a newb, and therefore wrap my answer around portions I find relevant to your question.
Your main web service is described in the WSDL http://myserver:8181/soap/SoapTest?wsdl, which holds an import to a parent WSDL. This parent WSDL holds service definitions which can be bind by your main service.
Seems promising. A request to the import location
SoapTest?wsdl=SoapTest.wsdl returns:
..
From the document definition provided above, the import:
<wsdl:import location="http://myserver:8181/soap/SoapTest?wsdl=SoapTest.wsdl"
namespace="http://webservices.mycompany.com">
</wsdl:import>
injects the parent WSDL file which holds the schema defintion for all elements and attributes relevant for your service. Meaning a standalone call to it, will reveal the xs namespace definition. See here for more on schema and datatypes.
HUH.. upon review, I see xs being used as a namespace but xmlns:xsd
defined?? How might this happen?
Yes, the schema is defined not as a separate file, but as part of the WSDL. It is defined between <wsdl:types> tags:
<wsdl:types>
<xs:schema xmlns:tns="http://webservices.mycompany.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://webservices.mycompany.com" version="1.0">
[..]
</wsdl:types>
See here also for more on ZSI binding and stub generation.
From ZSI documentation:
If the operation invoked returns a ComplexType, typecode information must be provided in order to tell ZSI how to deserialize the response.
In order for ZSI to transparently deserialize the returned complex type into a Person instance, a module defining the class and its typecode must be appended to the ZSI.Path list. It is also possible to explicitly tell ZSI what class and typecode to use by passing the class as a parameter to the Binding.Receive() method. The first method is often preferred, particularly for publically-distributed libraries.
Code Generation from WSDL and XML Schema is the second way ZSI provides to access WSDL services. Given the path to a WSDL service, two files are generated, a 'service' file and a 'types' file, that one can then use to access the service.

Why is an XSD element of type s:date becoming a string when generating a Service Reference?

I'm trying to create a new Service Reference from a WSDL and all of the properties I expect to be DateTime instead of string.
For example, this xsd definition for Contact:
<s:complexType name="Contact">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Address" type="tns:Address" />
<s:element minOccurs="0" maxOccurs="1" name="Email" type="s:string" />
...
<s:element minOccurs="1" maxOccurs="1" name="BirthDate" type="s:date" />
</s:sequence>
The type of BirthDate is s:date, but the generated type (in Reference.cs) is a string.
internal partial class Contact : object, IExtensibleDataObject, INotifyPropertyChanged
{
[OptionalField]
private MembershipMgmtMediator.Address AddressField;
[OptionalField]
private string EmailField;
private string BirthDateField;
}
If i create a web project and add it as a Web Reference instead of a Service Reference, it correctly becomes a DateTime. I assume that has something to do with the way wsdl.exe and svcutil.exe work behind the scenes, but regardless, I'm stuck on trying to figure out how to correctly get Visual Studio to recognize that this property should be a DateTime.
There is some good info in these questions: How to generate xs:Date in WCF OperationContract parameter and Best practices for DateTime serialization in .NET 3.5.
As Alex states in his comment to the question, WCF does not support xs:date types. However, it is perhaps more accurate to say that the default DataContractSerializer does not support that type, while the above questions indicate that the XmlSerializer can handle it.
See this link for a DataContractSerializer against XmlSerializer comparison.
If I run:
svcutil http://my_web_site?wsdl /ser:XmlSerializer /d:C:\temp
Then a WSDL fragment like this:
<s:complexType name="Contact">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="BirthDate" type="s:date" />
</s:sequence>
</s:complexType>
Has this class generated:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
public partial class Contact
{
private System.DateTime birthDateField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="date", Order=0)]
public System.DateTime BirthDate
{
get
{
return this.birthDateField;
}
set
{
this.birthDateField = value;
}
}
}
That svcutil invocation produces two files: Service1.cs and output.config. If I include the code file in the project and add the system.serviceModel bits into the configuration file (i.e., web.config or app.config) I can then call the service as normal. For example:
Service1SoapClient client = new Service1SoapClient("Service1Soap");
var contact = client.GetContact();
This approach is not without disadvantages. The Service1.cs file is markedly different if generated without the /ser:XmlSerializer parameter, where you will get additional classes such as WebMethodNameRequest, WebMethodNameRequestBody, WebMethodNameReponse, WebMethodNameReponseBody and so on. If these classes are important in your interactions with the service, my approach may not work for you.
Edit:
In terms of nullable properties, there is some good information in this question: svcutil.exe - Proxy generated not allowing for nullable fields
To get a property nullable in the generated proxy class, the nillable field needs to be set in the WSDL. So something like this:
<s:element minOccurs="0" maxOccurs="1" name="SomeProperty" type="s:date" nillable="true" />
Would generate a property called public System.Nullable<System.DateTime> SomeProperty in the proxy class.
However in your case you can use the SomePropertySpecified property to indicate the presence or absence of the property. These kinds of properties are generated when you have minOccurs="0".
In terms of date formatting I'm not sure. xs:date values are intended to be yyyy-mm-dd with optional timezone information (w3.org). If Oracle is expecting dates in a different format then I wonder how they can be xs:date values at all.
Is there any documentation or other information you can provide regarding the service you are trying to consume?
Edit 2:
I am a little unclear on exactly what "Dates must be in the database format." means in the Oracle docs. If the type is an xs:date then serializing them to the database format would surely mean that it was no longer an xs:date?
Still, there are some things you try in that regard:
Force XmlSerializer to serialize DateTime as 'YYYY-MM-DD hh:mm:ss'
http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly
You may need to simply experiment sending a few queries to the web service to see just how this date business affects things.
Are you sure those *IsSpecified parameters aren't there? To use my Contact class above as the example, minOccurs=0 on the BirthDate property would give the Contact class an extra property called BirthDateIsSpecified.
Although I believe nick_w's answer covers the question quite well (and I'm awarding him the bounty), I'm providing the solution I'm going to use in my specific case, where just using XmlSerializer isn't enough. In the end, I think I'm going to go with an extension that converts DateTime objects to string, using a custom format specifier.
public static class SoapUtils
{
public static string ToOraDate( this DateTime? dt )
{
return dt != null ? dt.Value.ToString("dd-MMM-yyyy",
CultureInfo.InvariantCulture) :
}
}
// Calling a service
someDate = DateTime.Now;
service.SomeMethod( someDate.ToOraDate() );
While this is not a real solution, I think that it may work as a workaround. It is dirty and ugly, and I know that, but it may be better than having String in your code.
Since your own classes (like Address) are properly processed, you could build a simple wrapper around Date class that you would include in your project and schema. The class would have only a Date property or a field and a getter to it.