No @XmlRootElement generado por JAXB


Estoy tratando de generar clases Java desde el FpML (Finanial Products Markup Language) versión 4.5. Se genera un montón de código, pero no puedo usarlo. Tratando de serializar un documento simple obtengo esto:

javax.xml.bind.MarshalException
  - with linked exception: [com.sun.istack.SAXException2: unable
  to marshal type
  "org.fpml._2008.fpml_4_5.PositionReport"
  as an element because it is missing an
  @XmlRootElement annotation]

De hecho no las clases tienen la anotación @XmlRootElement, así que ¿qué puedo estar haciendo mal?. Estoy apuntando xjc (JAXB 2.1) a fpml-main-4-5.xsd, que luego incluye todos los tipos.

Author: Peter Rosemann, 2009-05-04

14 answers

Para unir lo que otros ya han dicho o insinuado, las reglas por las cuales JAXB XJC decide si poner o no la anotación @XmlRootElement en una clase generada no son triviales ( ver este artículo).

@XmlRootElement existe porque el tiempo de ejecución de JAXB requiere cierta información para ordenar/desmarcar un objeto dado, específicamente el nombre del elemento XML y el espacio de nombres. No puedes pasar cualquier objeto viejo al Marshaller. @XmlRootElement proporciona esta información.

El la anotación es solo una conveniencia, sin embargo-JAXB no lo requiere. La alternativa es usar JAXBElement objetos wrapper, que proporcionan la misma información que @XmlRootElement, pero en la forma de un objeto, en lugar de una anotación.

Sin embargo, JAXBElement los objetos son difíciles de construir, ya que necesita conocer el nombre del elemento XML y el espacio de nombres, algo que la lógica de negocios generalmente no hace.

Afortunadamente, cuando XJC genera un modelo de clase, también genera una clase llamada ObjectFactory. Esto es en parte existe para la compatibilidad hacia atrás con JAXB v1, pero también está ahí como un lugar para que XJC ponga métodos de fábrica generados que crean JAXBElement envoltorios alrededor de sus propios objetos. Maneja el nombre XML y el espacio de nombres por usted, por lo que no necesita preocuparse por ello. Solo tiene que mirar a través de los métodos ObjectFactory (y para esquema grande, puede haber cientos de ellos) para encontrar el que necesita.

 232
Author: skaffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-05 04:16:28

Esto se menciona en la parte inferior de la entrada del blog ya vinculada anteriormente, pero esto funciona como un regalo para mí:

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(new JAXBElement<MyClass>(new QName("uri","local"), MyClass.class, myClassInstance), System.out);
 59
Author: Gurnard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-03 13:18:29

Como se insinúa en una de las respuestas anteriores, no obtendrá un XmlRootElement en su elemento raíz si en el XSD su tipo está definido como un tipo con nombre, ya que ese tipo con nombre podría usarse en otro lugar de su XSD. Trate de mking un tipo anónimo, es decir, en lugar de:

<xsd:element name="myRootElement" type="MyRootElementType" />

<xsd:complexType name="MyRootElementType">
...
</xsd:complexType>

Tendrías:

<xsd:element name="myRootElement">
    <xsd:complexType>
    ...
    <xsd:complexType>
</xsd:element>
 42
Author: Matthew Wise,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-27 16:27:01

@XmlRootElement no es necesario para unmarshalling - si se utiliza la forma de parámetro 2 de Unmarshaller#unmarshall.

Entonces, si en lugar de hacer:

UserType user = (UserType) unmarshaller.unmarshal(new StringReader(responseString));

Uno debe hacer:

JAXBElement<UserType> userElement = unmarshaller.unmarshal(someSource, UserType.class);
UserType user = userElement.getValue();

Este último código no requerirá anotación @XmlRootElement a nivel de clase UserType.

 32
Author: Sayantam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-20 20:55:52

La respuesta de Joe (Joe Jun 26 '09 a las 17:26) lo hace por mí. La respuesta simple es que la ausencia de una anotación @XmlRootElement no es un problema si se selecciona un JAXBElement. Lo que me confundió es que el ObjectFactory generado tiene 2 métodos createMyRootElement: el primero no toma parámetros y da el objeto sin envolver, el segundo toma el objeto sin envolver y lo devuelve envuelto en un JAXBElement, y el marshalling de que JAXBElement funciona bien. Aquí está el código básico que usé (soy nuevo en esto, así que disculpas si el código no está formateado correctamente en esta respuesta), en gran parte extraído de link text :

ObjectFactory objFactory = new ObjectFactory();
MyRootElement root = objFactory.createMyRootElement();
...
// Set root properties
...
if (!writeDocument(objFactory.createMyRootElement(root), output)) {
    System.err.println("Failed to marshal XML document");
}
...

private boolean writeDocument(JAXBElement document, OutputStream output) {

  Class<?> clazz = document.getValue().getClass();
  try {
    JAXBContext context =
        JAXBContext.newInstance(clazz.getPackage().getName());
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    m.marshal(document, output);
    return true;

  } catch (JAXBException e) {
    e.printStackTrace(System.err);
    return false;
  }
}
 20
Author: Yaqoob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-30 15:58:30

Puede solucionar este problema usando el enlace de ¿Cómo generar Clases @XmlRootElement para Tipos Base en XSD?.

Aquí hay un ejemplo con Maven

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.3.1</version>
            <executions>
                <execution>
                    <id>xjc</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <schemaDirectory>src/main/resources/xsd</schemaDirectory>
                <packageName>com.mycompany.schemas</packageName>
                <bindingFiles>bindings.xjb</bindingFiles>
                <extension>true</extension>
            </configuration>
        </plugin>

Aquí está el contenido del archivo binding.xjb

<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
              xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
              jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <jxb:bindings schemaLocation="path/to/myschema.xsd" node="/xs:schema">
        <jxb:globalBindings>
            <xjc:simple/>
        </jxb:globalBindings>
    </jxb:bindings>
</jxb:bindings>
 16
Author: Olivier.Roger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:34

Como sabes la respuesta es usar ObjectFactory(). Aquí hay una muestra del código que funcionó para mí:)

ObjectFactory myRootFactory = new ObjectFactory();

MyRootType myRootType = myRootFactory.createMyRootType();

try {

        File file = new File("./file.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(MyRoot.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        //output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        JABXElement<MyRootType> myRootElement = myRootFactory.createMyRoot(myRootType);

        jaxbMarshaller.marshal(myRootElement, file);
        jaxbMarshaller.marshal(myRootElement, System.out);

    } catch (JAXBException e) {
        e.printStackTrace();
    }
 7
Author: Shehaaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-02 14:26:07

Tampoco funciona para nosotros. Pero encontramos un artículo ampliamente citado que agrega algunos antecedentes... Voy a enlazar aquí por el bien de la siguiente persona: http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html

 6
Author: mcherm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-18 15:38:42

Con una compilación Maven, puede agregar la anotación @XmlRootElement

Con el plug-in "jaxb2-basics-annotate".

Ver más información : ver

Configurar Maven para generar clases a partir de esquemas XML usando JAXB

Y Generación de código JAXB XJC

 4
Author: metatechbe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 12:40:36

En caso de que mi experiencia de este problema le dé a alguien una Eureka! momento.. Añadiré lo siguiente:

También estaba teniendo este problema, al usar un archivo xsd que había generado usando la opción de menú "Generar xsd desde el documento de instancia" de IntelliJ.

Cuando acepté todos los valores predeterminados de esta herramienta, generó un archivo xsd que cuando se usa con jaxb, generó archivos java sin @XmlRootElement. En tiempo de ejecución cuando traté de marshal obtuve la misma excepción que se discutió en este pregunta.

Volví a la herramienta IntellJ y vi la opción predeterminada en el menú desplegable "Desgin Type" (que, por supuesto, no entendía.. y todavía no si soy honesto) fue:

Tipo de diseño:

"elementos locales / tipos complejos globales"

Cambié esto a

"elementos/tipos locales"

, ahora generó un xsd (sustancialmente) diferente, que produjo el @XmlRootElement cuando se usa con jaxb. No puedo decirlo Entiendo lo que entra y lo que sale, pero funcionó para mí.

 4
Author: johnm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-26 15:44:10

¿Intentaste cambiar tu xsd así?

<!-- create-logical-system -->
<xs:element name="methodCall">
  <xs:complexType>
    ...
  </xs:complexType>
</xs:element>
 3
Author: Tony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-02 22:45:58

JAXBElement wrappers funciona para casos en los que JAXB no genera @XmlRootElement. Estas envolturas están disponibles en la clase ObjectFactory generada por maven-jaxb2-plugin. Por ejemplo:

     public class HelloWorldEndpoint {
        @PayloadRoot(namespace = NAMESPACE_URI, localPart = "person")
        @ResponsePayload
        public JAXBElement<Greeting> sayHello(@RequestPayload JAXBElement<Person> request) {

        Person person = request.getValue();

        String greeting = "Hello " + person.getFirstName() + " " + person.getLastName() + "!";

        Greeting greet = new Greeting();
        greet.setGreeting(greeting);

        ObjectFactory factory = new ObjectFactory();
        JAXBElement<Greeting> response = factory.createGreeting(greet);
        return response;
      }
 }
 2
Author: zer0Id0l,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-09 15:31:08

Para solucionarlo debe configurar un enlace xml antes de compilar con wsimport, estableciendo generateElementProperty como false.

     <jaxws:bindings wsdlLocation="LOCATION_OF_WSDL"
      xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
         <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
    <jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='NAMESPACE_OF_WSDL']">
      <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xjc:generateElementProperty>false</xjc:generateElementProperty> 
      </jxb:globalBindings>
  </jaxws:bindings>
</jaxws:bindings>
 1
Author: leandruol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-15 15:14:45

Después de interrumpir durante dos días encontré la solución para el problema.Puede usar la clase ObjectFactory para solucionar las clases que no tienen el@XmlRootElement . ObjectFactory tiene métodos sobrecargados para envolverlo alrededor del JAXBElement. Método:1 hace la creación simple del objeto y Método:2 envolverá el objeto con @JAXBElement. Usar siempre el método : 2 para evitar javax.XML.unir.MarshalException - con linked falta una anotación @XmlRootElement

Método:1

public GetCountry createGetCountry() {
        return new GetCountry();
    }

Método:2

 @XmlElementDecl(namespace = "my/name/space", name = "getCountry")
 public JAXBElement<GetCountry> createGetCountry(GetCountry value) {
        return new JAXBElement<GetCountry>(_GetCountry_QNAME, GetCountry.class, null, value);
    }

Ejemplo de código de trabajo:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
WebServiceTemplate springWSTemplate = context.getBean(WebServiceTemplate.class);

GetCountry request = new GetCountry();
request.setGuid("1f3e1771-3049-49f5-95e6-dc3732c3227b");

JAXBElement<GetCountryResponse> jaxbResponse = (JAXBElement<GetCountryResponse>)springWSTemplate .marshalSendAndReceive(new ObjectFactory().createGetCountry(request));

GetCountryResponse response = jaxbResponse.getValue();
 1
Author: prasadg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-03 12:46:54