Para unir o que outros já declararam ou sugeriram, as regras pelas quais o JAXB XJC decide se deve ou não colocar a @XmlRootElement
anotação em uma classe gerada não são triviais ( consulte este artigo ).
@XmlRootElement
existe porque o tempo de execução JAXB requer determinadas informações para organizar / remover o compartilhamento de um determinado objeto, especificamente o nome do elemento XML e o espaço de nomes. Você não pode simplesmente passar nenhum objeto antigo para o Marshaller. @XmlRootElement
fornece essas informações.
A anotação é apenas uma conveniência, no entanto - o JAXB não exige isso. A alternativa é usar JAXBElement
objetos wrapper, que fornecem as mesmas informações @XmlRootElement
, mas na forma de um objeto, em vez de uma anotação.
No entanto, os JAXBElement
objetos são difíceis de construir, pois você precisa saber o nome do elemento XML e o espaço para nome, o que a lógica comercial geralmente não tem.
Felizmente, quando o XJC gera um modelo de classe, ele também gera uma classe chamada ObjectFactory
. Isso está parcialmente disponível para compatibilidade com o JAXB v1, mas também como um local para o XJC colocar métodos de fábrica gerados que criam JAXBElement
wrappers em torno de seus próprios objetos. Ele lida com o nome XML e o namespace para você, para que você não precise se preocupar com isso. Você só precisa examinar os ObjectFactory
métodos (e para esquemas grandes, pode haver centenas deles) para encontrar o que você precisa.
new ObjectFactory().createPositionReport(positionReport)
retornaJAXBElement<PositionReport>
JXBElement
? No meu caso, o método de fábrica é 0-arity e apenas retorna umnew
objeto. (Por que algumas classes recebem ajudantes do wrapper JAXBElement e outras não?) Acho que nesse caso devemos criar o wrapper por conta própria?Isso é mencionado na parte inferior da postagem do blog já vinculada acima, mas funciona como um deleite para mim:
fonte
jc
no snippet acima?Conforme sugerido em uma das respostas acima, você não receberá um XMLRootElement em seu elemento raiz se no XSD seu tipo for definido como um tipo nomeado, pois esse tipo nomeado poderá ser usado em outro lugar no seu XSD. Tente definir um tipo anônimo, ou seja, em vez de:
você teria:
fonte
@XmlRootElement não é necessário para desserializar - se alguém usar o formulário de 2 parâmetros de Unmarshaller # unmarshall.
Então, se em vez de fazer:
deve-se fazer:
O último código não exigirá a anotação @XmlRootElement no nível da classe UserType.
fonte
String pathname = "file.xml"; InputStream stream = new FileInputStream(pathname); JAXBContext jaxbContext = JAXBContext.newInstance(UserType.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader someSource = factory.createXMLEventReader(stream); JAXBElement<UserType> userElement = jaxbUnmarshaller.unmarshal(someSource, UserType.class); UserType user = userElement.getValue();
A resposta de Joe (Joe 26/06/2009 às 17:26) faz isso por mim. A resposta simples é que a ausência de uma anotação @XmlRootElement não é problema se você empacotar um JAXBElement. O que me confundiu é que o ObjectFactory gerado possui 2 métodos createMyRootElement - o primeiro não aceita parâmetros e fornece o objeto desembrulhado, o segundo pega o objeto desembrulhado e o devolve em um JAXBElement e indica que o JAXBElement funciona bem. Aqui está o código básico que eu usei (sou novo nisso, desculpe-me se o código não estiver formatado corretamente nesta resposta), amplamente extraído do texto do link :
fonte
Você pode corrigir esse problema usando a ligação de Como gerar classes @XmlRootElement para tipos de base no XSD? .
Aqui está um exemplo com o Maven
Aqui está o
binding.xjb
conteúdo do arquivofonte
Como você sabe a resposta é usar o ObjectFactory (). Aqui está uma amostra do código que funcionou para mim :)
fonte
Também não está funcionando para nós. Mas encontramos um artigo amplamente citado que adiciona ALGUNS antecedentes ... Vou colocar um link aqui para o bem da próxima pessoa: http://weblogs.java.net/blog/kohsuke/archive/2006/03 /why_does_jaxb_p.html
fonte
Depois de fazer o manuseio por dois dias, encontrei a solução para o problema. Você pode usar a classe ObjectFactory para solucionar as classes que não possuem o @XmlRootElement . O ObjectFactory sobrecarregou métodos para envolvê-lo em torno do JAXBElement.
Método 1 faz a criação simples do objeto.
Método: 2 envolverá o objeto com @JAXBElement .
Sempre use o método: 2 para evitar javax.xml.bind.MarshalException - com a exceção vinculada ausente na anotação @XmlRootElement.
Encontre o código de exemplo abaixo
Método: 1 faz a criação simples do objeto
Método: 2 envolverá o objeto com @JAXBElement .
Exemplo de código de trabalho:
fonte
Caso minha experiência com esse problema dê a alguém um Eureka! momento .. vou adicionar o seguinte:
Eu também estava tendo esse problema ao usar um arquivo xsd que eu havia gerado usando a opção de menu "Gerar xsd a partir do documento da instância" do IntelliJ.
Quando aceitei todos os padrões desta ferramenta, ela gerou um arquivo xsd que, quando usado com jaxb, gerava arquivos java sem
@XmlRootElement
. No tempo de execução, quando tentei empacotar, recebi a mesma exceção discutida nesta pergunta.Voltei à ferramenta IntellJ e vi a opção padrão no menu suspenso "Desgin Type" (que é claro que eu não entendi ... e ainda não sei se sou honesto):
Tipo Desgin:
Eu mudei isso para
, agora gerou um xsd (substancialmente) diferente, que produziu o
@XmlRootElement
quando usado com o jaxb. Não posso dizer que entendo as vantagens e desvantagens, mas funcionou para mim.fonte
Com uma compilação do Maven, você pode adicionar o
@XmlRootElement
anotaçãocom o
jaxb2-basics-annotate
plug-in " ".Veja mais informações: consulte
Configure o Maven para gerar classes do esquema XML usando JAXB
e geração de código JAXB XJC
fonte
Os wrappers JAXBElement funcionam para casos em que nenhum
@XmlRootElement
é gerado pelo JAXB. Esses wrappers estão disponíveis naObjectFactory
classe gerada pormaven-jaxb2-plugin
. Por exemplo:fonte
Você tentou mudar seu xsd assim?
fonte
Para resolvê-lo, você deve configurar uma ligação xml antes para compilar com wsimport, configurando generateElementProperty como false.
fonte
<jaxb:bindings> ... <jaxws:bindings> ... </jaxws:bindings> ... </jaxb:bindings>
O tópico é bastante antigo, mas ainda é relevante nos contextos de negócios corporativos. Tentei evitar tocar nos xsds para atualizá-los facilmente no futuro. Aqui estão minhas soluções ..
1. Principalmente
xjc:simple
é suficienteEle criará principalmente XmlRootElements para importar definições xsd.
2. Divida suas
jaxb2-maven-plugin
execuçõesDescobri que isso faz uma enorme diferença se você tentar gerar classes a partir de várias definições xsd em vez de uma definição de execução por xsd.
Portanto, se você tem uma definição com múltiplos
<source>
, tente apenas dividi-los:O gerador não perceberá o fato de que uma classe pode ser suficiente e, portanto, criará classes personalizadas por execução. E é exatamente isso que eu preciso;).
fonte