java - una - ¿Cuál es el objetivo de las clases ObjectFactory de JAXB 2?
dos declaraciones producen una colisión en la clase objectfactory (3)
Soy nuevo en el uso de JAXB y utilicé el xjc de JAXB 2.1.3 para generar un conjunto de clases de mi esquema XML. Además de generar una clase para cada elemento en mi esquema, creó una clase ObjectFactory.
No parece haber nada que me impida crear instancias de los elementos directamente, por ejemplo
MyElement element = new MyElement();
mientras que los tutoriales parecen preferir
MyElement element = new ObjectFactory().createMyElement();
Si miro en ObjectFactory.java, veo:
public MyElement createMyElement() {
return new MyElement();
}
Entonces, ¿cuál es el problema? ¿Por qué debería molestarme en mantener la clase ObjectFactory? Supongo que también se sobrescribirá si tuviera que volver a compilar desde un esquema alterado.
Como señaló @Chris, a veces JAXB no puede trabajar con POJO, porque el esquema no se puede asignar exactamente a Java. En estos casos, los objetos del envoltorio JAXBElement
son necesarios para proporcionar la información de tipo adicional.
Hay dos ejemplos concretos que he encontrado donde esto es común.
Si desea ordenar un objeto de una clase que no tiene la anotación
@XmlRootElement
. De manera predeterminada, XJC solo genera@XmlRootElement
para algunos elementos, y no para otros. La lógica exacta para esto es un poco complicada, pero puede forzar a XJC a generar más clases@XmlRootElement
usando el "modo de enlace simple"Cuando su esquema usa grupos de sustitución. Este es un uso bastante avanzado del esquema, pero XJC traduce los grupos de sustitución en Java haciendo un uso
JAXBElement
envoltorios deJAXBElement
.
Por lo tanto, en un modelo de objetos generado por XJC que hace un uso intensivo de JAXBElement
(por el motivo que sea), necesita una forma de construir esas instancias de JAXBElement
. La ObjectFactory
generada es, de lejos, la forma más fácil de hacerlo. Puede construirlos usted mismo, pero es torpe y propenso a errores para hacerlo.
Compatibilidad con versiones anteriores, supongo ...
http://weblogs.java.net/blog/kohsuke/archive/2005/08/a_story_of_migr.html :
... No más ObjectFactory.createXYZ. El problema con esos métodos de fábrica era que arrojaban una JAXBException marcada. Ahora puede simplemente hacer un nuevo XYZ (), no más bloques de prueba / captura. (Lo sé, lo sé, ... este es uno de esos "¿qué estábamos pensando ?!" cosas) ...
La compatibilidad con versiones anteriores no es la única razón. :-PAG
Con esquemas más complicados, como los que tienen limitaciones complicadas en los valores que puede asumir el contenido de un elemento, a veces es necesario crear objetos JAXBElement
reales. Por lo general, no son triviales para crear a mano, por lo que los métodos create*
hacen el trabajo duro por ti. Ejemplo (del esquema XHTML 1.1):
@XmlElementDecl(namespace = "http://www.w3.org/1999/xhtml", name = "style", scope = XhtmlHeadType.class)
public JAXBElement<XhtmlStyleType> createXhtmlHeadTypeStyle(XhtmlStyleType value) {
return new JAXBElement<XhtmlStyleType>(_XhtmlHeadTypeStyle_QNAME, XhtmlStyleType.class, XhtmlHeadType.class, value);
}
Así es como se obtiene una etiqueta <style>
en una etiqueta <head>
:
ObjectFactory factory = new ObjectFactory();
XhtmlHtmlType html = factory.createXhtmlHtmlType();
XhtmlHeadType head = factory.createXhtmlHeadType();
html.setHead(head);
XhtmlStyleType style = factory.createXhtmlStyleType();
head.getContent().add(factory.createXhtmlHeadTypeStyle(style));
Los primeros tres usos de ObjectFactory
podrían considerarse superfluos (aunque útiles para la coherencia), pero el cuarto hace que JAXB sea mucho más fácil de usar. ¡Imagine tener que escribir un new JAXBElement
a mano cada vez!