Problema com o Unmarshal do JAXB

20 respostas
V

Oi pessoal.

Tenho um problema em relação aos métodos unmarshal que retornam JAXBElement<T> da interface javax.xml.bind.Unmarshaller.

O problema é que o JAXBElement retornado traz apenas os atributos da minha tag XML, mas não trás os elementos. Debugando isso, eu vi que o QName dele (atributo name) está errado e o scope está em GlobalScope, porém tais campos são protected final e a instância do JAXBElement é criada pela implementação do Unmarshaller em algum lugar das profundezas do JAXB. Não achei nenhum método no Unmarshaller para definir o name e/ou o scope.

Alguém aí já pegou um problema parecido?

20 Respostas

V

Ok, consegui resolver.

DocumentBuilderFactory dd = DocumentBuilderFactory.newInstance();
        dd.setNamespaceAware(true); // &lt;-- TAVA FALTANDO ESTA BOSTA!
G

Estou com o mesmo erro, mas mesmo setando setNamespaceAware continua. Teria como passar seu código para unmarshal.

F

Infelizmente,

Tenho que ressuscitar esse tópico…não consigo fazer com que o Unmarshall funcione corretamente.
O erro: não há elementos na classe de resultado.

método

public void parseExplainConsultaPF(String explain) throws CrivoInterfaceException {
		JustificativaType justificativaType = null;
		try {
			JAXBContext jaxbContext = JAXBContext.newInstance("com.example.ws"); 
			
			Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
			
			JAXBElement&lt;JustificativaType&gt; element = unmarshaller.unmarshal(new StreamSource(new StringReader(explain)), JustificativaType.class);
			
			justificativaType = element.getValue();
		       
                       //more code
	}

JAXB (generated by approach WSDL2Java)

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "JustificativaType", propOrder = {
    "justificativas"
})
public class JustificativaType {

    @XmlElement(required = true)
    protected List&lt;JustificativaTextualType&gt; justificativas;

   
    public List&lt;JustificativaTextualType&gt; getJustificativas() {
        if (justificativas == null) {
            justificativas = new ArrayList&lt;JustificativaTextualType&gt;();
        }
        return this.justificativas;
    }

no teste:

justificativaType.getJustificativas() //null

nunca retorna os elementos filhos!

Obs: XML que está sendo consumido (exatamente dessa maneira).

&lt;justificativas&gt;
&lt;justificativaTextual criterio="POLITICA_PJ" /&gt;
&lt;justificativaTextual criterio="CLIENTES - PJ"&gt;
&lt;regra&gt;
&lt;valor&gt;
&lt;texto&gt;
Cliente OK&lt;/texto&gt;
&lt;/valor&gt;
&lt;/regra&gt;
&lt;/justificativaTextual&gt;
&lt;justificativaTextual criterio="POLITICA ADIÇÃO AUTOMÁTICA - PJ"&gt;
&lt;regra&gt;
&lt;valor&gt;
&lt;texto&gt;
Aprovada no Drive de Qualidade do Crédito&lt;/texto&gt;
&lt;/valor&gt;
&lt;/regra&gt;
&lt;regra&gt;
&lt;valor&gt;
&lt;texto&gt;
Cadastro  Divergente no Sintegra&lt;/texto&gt;
&lt;/valor&gt;
&lt;/regra&gt;
&lt;/justificativaTextual&gt;
&lt;justificativaTextual criterio="ALERTA - BLACK LIST PJ"&gt;
&lt;regra&gt;
&lt;valor&gt;
&lt;texto&gt;
Aprovado no Drive de Qualidade do Crédito &lt;/texto&gt;
&lt;/valor&gt;
&lt;/regra&gt;
&lt;/justificativaTextual&gt;
&lt;justificativaTextual criterio="CADASTRO SRF"&gt;
&lt;regra&gt;
&lt;valor&gt;
&lt;texto&gt;
Municipio "Diferente" Sintegra&lt;/texto&gt;
&lt;/valor&gt;
&lt;/regra&gt;
&lt;regra&gt;
&lt;valor&gt;
&lt;texto&gt;
Estado igual a Sintegra&lt;/texto&gt;
&lt;/valor&gt;
&lt;/regra&gt;
&lt;/justificativaTextual&gt;
&lt;justificativaTextual criterio="ADIÇÃO_INADIMPLÊNCIA_PJ_ICS" /&gt;
&lt;/justificativas&gt;

Alguém pode me ajudar?

F

alguém? o criador do tópico?

A

Você poderia postar o código do JustificativaTextualType, também?

[]´s

F

Você poderia postar o código do JustificativaTextualType, também?

[]´s

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "JustificativaTextualType", propOrder = {
    "regra"
})
public class JustificativaTextualType {

    protected List&lt;RegraType&gt; regra;
    @XmlAttribute(required = true)
    protected String criterio;

    
    public List&lt;RegraType&gt; getRegra() {
        if (regra == null) {
            regra = new ArrayList&lt;RegraType&gt;();
        }
        return this.regra;
    }

 
    public String getCriterio() {
        return criterio;
    }


    public void setCriterio(String value) {
        this.criterio = value;
    }

}

Valeu!

A

Troque:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "JustificativaType", propOrder = {
    "justificativas"
})
public class JustificativaType {

    @XmlElement(required = true)
    protected List&lt;JustificativaTextualType&gt; justificativas;

   
    public List&lt;JustificativaTextualType&gt; getJustificativas() {
        if (justificativas == null) {
            justificativas = new ArrayList&lt;JustificativaTextualType&gt;();
        }
        return this.justificativas;
    }

Por

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "JustificativaType", propOrder = {
    "justificativaTextual"
})
public class JustificativaType {

    @XmlElement(required = true)
    protected List&lt;JustificativaTextualType&gt; justificativaTextual;

   
    public List&lt;JustificativaTextualType&gt; getJustificativas() {
        if (justificativaTextual == null) {
            justificativaTextual= new ArrayList&lt;JustificativaTextualType&gt;();
        }
        return this.justificativaTextual;
    }

Aqui funcionou.

Mas, que mal lhe pergunte, como você arranjou esse XML ? Ele tem um schema?

[]´s!

F

Fiz a modificação que mencionou e ainda não funcionou…

Sobre o XML, existe um WS que devolve esse XML, porém, não há um XSD.
Eu fiz um XSD para ele pois os campos são sempre os mesmos…

Um abraço.

A

felipeguerra:
Fiz a modificação que mencionou e ainda não funcionou…

Sobre o XML, existe um WS que devolve esse XML, porém, não há um XSD.
Eu fiz um XSD para ele pois os campos são sempre os mesmos…

Um abraço.

Não funcionou, mas continuou com o mesmo problema? Ou mudou algo?

Eu também mudei a linha

JAXBContext jaxbContext = JAXBContext.newInstance("com.example.ws");

para

JAXBContext jaxbContext = JAXBContext.newInstance(JustificativaType.class, JustificativaTextualType.class);

mas isso não deveria fazer diferença. De qualquer maneira, teste para ver se é isso.

[]´s

F

Eu quis dizer que continua vindo NULL nos elementos filhos :

justificativaType.getJustificativaTextual() //null

asaudate:

Eu também mudei a linha

JAXBContext jaxbContext = JAXBContext.newInstance("com.example.ws");

para

JAXBContext jaxbContext = JAXBContext.newInstance(JustificativaType.class, JustificativaTextualType.class);

mas isso não deveria fazer diferença. De qualquer maneira, teste para ver se é isso.

[]´s


Infelizmente, não fez diferença mesmo. :frowning:

A

Observe que a idéia era mudar o nome da propriedade, mesmo, não do getter. Foi isso que você fez?

[]´s

F

asaudate:
Observe que a idéia era mudar o nome da propriedade, mesmo, não do getter. Foi isso que você fez?

[]´s


Desculpe, quem mudou foi o FMK ao gerar a classe novamente…mas eu não entendi, qual é a relação do nome da propriedade e o respectivo ‘get’ como problema?

Abraço!

A

felipeguerra:
asaudate:
Observe que a idéia era mudar o nome da propriedade, mesmo, não do getter. Foi isso que você fez?

[]´s


Desculpe, quem mudou foi o FMK ao gerar a classe novamente…mas eu não entendi, qual é a relação do nome da propriedade e o respectivo ‘get’ como problema?

Abraço!

A classe está configurada para ter acesso direto para a propriedade. Ou seja, é o nome da propriedade que deve ser alterado. O nome do getter não faz diferença.

[]´s

A

victorwss:
Oi pessoal.

Tenho um problema em relação aos métodos unmarshal que retornam JAXBElement<T> da interface javax.xml.bind.Unmarshaller.

O problema é que o JAXBElement retornado traz apenas os atributos da minha tag XML, mas não trás os elementos. Debugando isso, eu vi que o QName dele (atributo name) está errado e o scope está em GlobalScope, porém tais campos são protected final e a instância do JAXBElement é criada pela implementação do Unmarshaller em algum lugar das profundezas do JAXB. Não achei nenhum método no Unmarshaller para definir o name e/ou o scope.

Alguém aí já pegou um problema parecido?

Vitor,

No JAXB para que ele não crie os objetos todos como inner classes quando é feito o unmarshall do xml é necessário usar escopo global, usando escopos globais é necessário usar JAXBElement

Uma outra alternativa para resolver este seu problema (trabalhar com JAXBElement definindo o QNAME) é você usar algo parecido com o código abaixo

JAXBElement&lt;MeuObjeto&gt; element = new JAXBElement(new QName( "http://example.org", "MeuObjeto", "n1"), MeuObjeto.class, results);

onde http://example.org é o seu namespace e n1 é o prefixo

F

André Fonseca:

Vitor,

No JAXB para que ele não crie os objetos todos como inner classes quando é feito o unmarshall do xml é necessário usar escopo global, usando escopos globais é necessário usar JAXBElement

Uma outra alternativa para resolver este seu problema (trabalhar com JAXBElement definindo o QNAME) é você usar algo parecido com o código abaixo

JAXBElement&lt;MeuObjeto&gt; element = new JAXBElement(new QName( &quot;http://example.org&quot;, &quot;MeuObjeto&quot;, &quot;n1&quot;), MeuObjeto.class, results);

onde http://example.org é o seu namespace e n1 é o prefixo


Não entendi a aplicação no meu caso, onde o WSDL que originou as classes, é algo mais ou menos assim:

&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;
&lt;wsdl:definitions xmlns:tns="http://www.example.com/Consulta/" 
				xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
				xmlns:s="http://www.w3.org/2001/XMLSchema" name="ConsultaCrivo" targetNamespace="http://www.example.com/Consulta/" 
				xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"&gt;
&lt;wsdl:types&gt;
	&lt;s:schema targetNamespace="http://www.example.com/Consulta/" elementFormDefault="qualified"&gt;

            &lt;s:complexType name="JustificativaType"&gt;
	    	&lt;s:sequence&gt;
				&lt;s:element name="justificativaTextual" minOccurs="1" maxOccurs="unbounded" type="tns:JustificativaTextualType"&gt;&lt;/s:element&gt;
	    	&lt;/s:sequence&gt;
	    &lt;/s:complexType&gt;
	    
	    &lt;s:complexType name="JustificativaTextualType"&gt;
	    	&lt;s:sequence&gt;
	    		&lt;s:element name="regra" minOccurs="0" maxOccurs="unbounded" type="tns:RegraType"&gt;&lt;/s:element&gt;
	    	&lt;/s:sequence&gt;
	    	&lt;s:attribute name="criterio" use="required" type="s:string"&gt;&lt;/s:attribute&gt;
	    &lt;/s:complexType&gt;
		
		&lt;s:complexType name="RegraType"&gt;
	    	&lt;s:sequence&gt;
	    		&lt;s:element name="valor" type="tns:ValorType" minOccurs="0" maxOccurs="unbounded"&gt;&lt;/s:element&gt;
	    	&lt;/s:sequence&gt;
	    &lt;/s:complexType&gt;
	    
	    &lt;s:complexType name="ValorType"&gt;
	    	&lt;s:sequence&gt;
	    		&lt;s:element name="texto" minOccurs="0" maxOccurs="1" type="s:string"&gt;&lt;/s:element&gt;
	    	&lt;/s:sequence&gt;
	    &lt;/s:complexType&gt;
       &lt;/s:schema&gt;

       &lt;!--  restante suprimido --&gt;

&lt;/wsdl:types&gt;
&lt;/wsdl:definitions&gt;
A

Felipe,

Dê uma olhada no código que estou colocando em anexo… é o teste que eu rodei aqui.

[]´s

A

[quote=felipeguerra]

André Fonseca:

Não entendi a aplicação no meu caso, onde o WSDL que originou as classes, é algo mais ou menos assim:

Não seria para o seu caso, esse código que postei serve para trabalhar com o Escopo Global de objetos anotados que não possuem o XMLRootElement (foi o que o Victor falou no primeiro post)

[]´s

F

André Fonseca:
felipeguerra:

Não entendi a aplicação no meu caso, onde o WSDL que originou as classes, é algo mais ou menos assim:

Não seria para o seu caso, esse código que postei serve para trabalhar com o Escopo Global de objetos anotados que não possuem o XMLRootElement (foi o que o Victor falou no primeiro post)

[]´s


Entendido!

valeu

F

asaudate:
Felipe,

Dê uma olhada no código que estou colocando em anexo… é o teste que eu rodei aqui.

[]´s


O meu código está igual no que tange a forma, ou seja, usei de classes diferentes para fazer a mesma coisa que o seu código…porém, ainda não funciona.

Se eu conseguisse depurar o FMK…

F

Pessoal, resolvi o problema, agreguei o cabeçalho e o namespace ao XML de entrada e pronto!

Criado 23 de janeiro de 2008
Ultima resposta 3 de dez. de 2010
Respostas 20
Participantes 5