7

I'm using JAXB(xjc version 2.2.4-2) to generate Java classes from a XML Schema. The XML types that map to a Java primitive datatype don't add:

@XmlElement(required = true)

For example when using:

<element name="userId" type="long"/>
<element name="userName" type="string"/> 

will result in:

//no annotation added here
protected long userId;
@XmlElement(required = true)
protected String userName;

Does anyone have an explanation why this happens?

Does any of this have to do with options that you can set with xjc?

Jonathan Ramos
  • 170
  • 2
  • 10

2 Answers2

7

You don't need an annotation to show that a property of Java type long is required as this is implicit from the fact that primitive values can't be null. A non-nillable required element of type xs:long maps to Java long, an optional or nillable one maps to java.lang.Long (which permits null, representing absent or xsi:nil as appropriate).

An element that is both optional and nillable (odd, but allowed by XML Schema) would map to a JAXBElement<Long> to distinguish between absent (a null JAXBElement) and nil (a non-null JAXBElement whose isNil() returns true).

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • I last did a SOAP test and found that the schema, which had an elemtent of type unsignedShort (with implicit minOccurs="1" --> thus required), didn't validate correctly. I could leave that one empty in my request, though it was required. – Jonathan Ramos Dec 10 '12 at 13:06
  • @JonathanRamos An `` should map to a property of type `int` with `@XmlSchemaType(name = "unsignedShort")` and _without_ `@XmlElement(required = true)`, I've just tested that locally and it works fine for me. – Ian Roberts Dec 10 '12 at 13:13
  • Ian, well that's why I deleted it. When I just tested again it worked normally. So I probably did something wrong there. – Jonathan Ramos Dec 10 '12 at 13:34
  • I just found out what I did. I had done: `code` Which leads to: @XmlSchemaType(name = "unsignedShort") protected Integer userNumber; – Jonathan Ramos Dec 10 '12 at 14:50
  • @JonathanRamos yes, that's the same principle - it uses the wrapper type for something that can be `null` and the primitive type for things that can't. – Ian Roberts Dec 10 '12 at 15:01
  • I just tested against the primitive `int`. I created an object which I marshalled to xml. When doing so, without setting a value for the int, it comes with: ` 111 John Doe 0 ` So it defaults *userNumber* to 0 , which is logical, but somewhat unwanted because the request was actually empty, as in `null` like you explained. – Jonathan Ramos Dec 10 '12 at 15:16
2

If you don't mind a BigInteger in your java class you could use type="integer" or type="positiveInteger" (negative userId?). Your validation will work this way at a certain cost.

Another option would be to use jaxb custom bindings. Your element could be:

<element name="userId" type="long"/> 

and your have to create an extra binding file e.g.

<jxb:bindings version="1.0" 
  xmlns:jxb="http://java.sun.com/xml/ns/jaxb" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
  jxb:extensionBindingPrefixes="xjc">
<jxb:bindings schemaLocation="my.xsd" node="//xs:element[@name='UserType']//xs:element[@name='userId']">
 <jxb:property>
  <jxb:baseType name="java.lang.Long" />
 </jxb:property>
</jxb:bindings>
</jxb:bindings>

Now you can call xjc like: xjc my.xsd -b my.xjb

This results in:

@XmlElement(required = true, type = Long.class) protected Integer userId;

IDKFA
  • 436
  • 3
  • 5
  • This does indeed create and object `Long`: `@XmlElement(required = true, type = Long.class) protected Long userId;' Which doesn't let me send a request with that field being empty. Still don't understand, why adding a minOccurs=1 to for example: type="long" doesn't create a `Long` immediately. It feels like a design flaw in JAXB. – Jonathan Ramos Dec 11 '12 at 11:37
  • 1
    Agree, if xjc would create object types instead of primitives this would be more consistent – IDKFA Dec 11 '12 at 11:39