referenciados - El compilador JAXB está vinculando xs: boolean a la clase envoltura booleana de Java, en lugar del tipo primitivo booleano
tipos de variables en java ejemplos (4)
Estoy migrando un proyecto de JAXB 1.0 a JAXB 2.1 y tengo problemas con el mapeo de tipos de datos.
Estoy usando el compilador de enlaces Ant xjc , y he configurado con éxito los enlaces globales de manera que (por ejemplo) xs: date se asigna a java.util.Calendar .
Sin embargo, estoy obteniendo métodos generados que devuelven Boolean
, mientras que quiero Boolean
.
Aquí está el tipo complejo:
<xs:element name="usage-auth-rate-charge">
<xs:complexType>
<xs:sequence>
<xs:element name="service-id" type="xs:string"/>
<xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Y la clase generada se ve así:
public class UsageAuthRateCharge {
........
public Boolean isPricepointCustomFieldsRequired() {
return pricepointCustomFieldsRequired;
}
El problema es que, aunque el boxeo funcionará, si el XML suministrado no contiene un valor para pricepoint_custom_fields_required
, el campo booleano de la clase es nulo, en lugar de falso. Entonces obtengo NullPointerExceptions cuando hago algo como esto:
methodWhichTakesPrimitiveBooleanArg(myUsageAuthRateChargeInstance.isPricepointCustomFieldsRequired());
porque intenta desempaquetar el booleano pasado, excepto que es nulo.
No puedo cambiar el esquema y no puedo ajustar todo el código del cliente para realizar las comprobaciones nulas.
He establecido el atributo optionalProperty en mi binding.xml de la siguiente manera:
<globalBindings optionalProperty="primitive">
En la especificación, dice: "Si el valor del atributo es" primitivo ", se enlaza como lo hizo en JAXB 1.0"
Sin embargo, esto claramente no está sucediendo.
¿Como puedó resolver esté problema?
ACTUALIZAR:
Esto ahora está arreglado en jaxb 2.2.9: https://java.net/jira/browse/JAXB/fixforversion/16850
Problema
La razón por la que obtiene Boolean
lugar de Boolean
es que tiene minOccurs="0"
en su definición de elemento. Se almacenará un valor null
para un elemento ausente.
<xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>
¿Cuál debería ser la solución?
La solución debe ser un archivo de enlace externo que indique que se debe usar un tipo primitivo para valores opcionales (consulte la sección 7.5.1 de la especificación JAXB 2.2).
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings optionalProperty="primitive"/>
</jaxb:bindings>
El archivo de enlace externo se especifica mediante la opción -b
con XJC.
xjc -b binding.xml my-schema.xsd
¿Por qué esa solución no funciona?
Se han abierto los siguientes errores para rastrear el problema con optionalProperty="primitive"
.
Solución
Si no le gusta la forma en que se genera una clase en JAXB, puede crear una clase usted mismo y hacer que JAXB la incluya como parte del esquema para la generación de la clase.
binding.xml
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="my-schema.xsd">
<jxb:bindings node="//xs:element[@name=''usage-auth-rate-charge'']/complexType">
<jxb:class ref="com.example.foo.UsageAuthRateCharge"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
UsageAuthRateCharge
Crea esta clase con los métodos que quieras.
Llamada XJC
Use el indicador -b
en la llamada XJC para especificar el archivo binding.xml
xjc -b binding.xml my-schema.xsd
ACTUALIZAR
Lo que realmente esperaba era que uno de los lectores pudiera ser un miembro del equipo de desarrollo de jaxb que pudiera hacer el cambio fácilmente en jaxb. El usuario archenroot ofreció una posible solución en sus comentarios sobre el problema 927 de jaxb (un duplicado de 926), lo que me lleva a pensar que para la persona correcta, sería un trabajo simple corregirlo.
Soy el líder de EclipseLink JAXB (MOXy) . Me comuniqué con mis colegas que hacen la implementación de referencia de JAXB (también trabajan para Oracle). A continuación se muestra la respuesta que recibí de ellos:
He probado en tronco - y el problema existe. Voy a comprobar el código lo fácil que es arreglarlo.
Esperamos que pueda obtener una solución real para este problema.
Me aburrí de esperar una solución del equipo de desarrollo, así que me subí las mangas y lo hice yo mismo.
Incluyo el siguiente código para ayudar a las personas para quienes esto también es un problema.
Descargo de responsabilidad : mi código probablemente no sea la mejor manera de resolver el problema, pero funciona para mí.
El código generado ahora se ve así:
public boolean isPricepointCustomFieldsRequired() {
if (pricepointCustomFieldsRequired == null) {
return false;
} else {
return pricepointCustomFieldsRequired;
}
}
Y la modificación es la siguiente:
com.sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty: createElementProperty, line ~ 358
Despues de la linea
types.addTo(prop);
inserte el siguiente código:
if (prop.isOptionalPrimitive() && getOptionalPropertyMode() == OptionalPropertyMode.PRIMITIVE &&
!prop.getTypes().isEmpty() && "boolean".equals(prop.getTypes().get(0).getTypeName().getLocalPart()) ) {
prop.defaultValue= CDefaultValue.create(CBuiltinLeafInfo.BOOLEAN, new XmlString("false"));
}
Prueba esto...
<xs:element name="usage-auth-rate-charge">
<xs:complexType>
<xs:sequence>
<xs:element name="service-id" type="xs:string"/>
</xs:sequence>
<xs:attribute name="chosen" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:element>
Encontré tu pregunta mientras miraba cómo hacer exactamente lo opuesto a lo que estabas haciendo. Tenía un atributo booleano que solo generaría código que tenía el atributo como un valor booleano primitivo. Para hacer que jaxb genere este atributo como un objeto booleano en lugar de un primitivo booleano, simplemente eliminé la porción use = "required" de la definición de mi atributo en el xsd.
Solo para completarla
type="xs:boolean" minOccurs="0" maxOccurs="1" == Boolean value (object)
type="xs:boolean" minOccurs="0" maxOccurs="1" nillable="true" == JAXBElement<Boolean> value (object)
type="xs:boolean" minOccurs="1" maxOccurs="1" == boolean value (primitive)
type="xs:boolean" minOccurs="1" maxOccurs="1" nillable="true" == Boolean value (object)