domingo, 6 de janeiro de 2019

Loop infinito no XML

A forma mais simples de evitar o loop é usando o próprio construtor no setter.

O exemplo foi tirado de: https://www.devmedia.com.br/introducao-a-jaxb-2/11547

Eu apenas criei mais um atributo: contatoAnterior.
E alterei o teste para provocar o ciclo:
             contato.setContatoAnterior( contato );

Com o setter original ( this.contatoAnterior = contatoAnterior; ) deverão tomar o erro:
Exception in thread "main" javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: Foi detectado um ciclo no gráfico do objeto. Isso causará XML profundo infinitamente: contato.Contato@2d98a335 -> contato.Contato@2d98a335]

Com  o setter modificado para usar o contrutor. O retorno fica bom.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<contato>
    <contatoAnterior>
        <endereco>
            <bairro>Centro LADRÃO</bairro>
            <cep>20000-000 SEM-VERGONHA</cep>
            <cidade>Rio de Janeiro SAFADO</cidade>
            <logradouro>Rua Moraes PILANTRA</logradouro>
            <numero>40 VIGARISTA</numero>
        </endereco>
        <idade>34</idade>
        <nome>Marco Maciel</nome>
        <sexo>M</sexo>
    </contatoAnterior>
    <endereco>
        <bairro>Centro</bairro>
        <cep>20000-000</cep>
        <cidade>Rio de Janeiro</cidade>
        <logradouro>Rua Moraes</logradouro>
        <numero>40</numero>
    </endereco>
    <idade>34</idade>
    <nome>Marco Maciel</nome>
    <sexo>M</sexo>
</contato>


------------------------------------------------------------------
package contato;

import javax.xml.bind.annotation.*;
@XmlRootElementpublic class Contato {

    private String nome;    private String sexo; 
    private int idade;    private Endereco endereco;
    private Contato contatoAnterior;
    public Contato() {}

    public Contato(String nome, String sexo
                    , int idade, Endereco endereco) {
        this.nome = nome;     
        this.sexo = sexo;     
        this.idade = idade;     
        this.endereco = endereco; 
    }

    // outros G e S
    public Contato getContatoAnterior() {
        return contatoAnterior;    }

    public void setContatoAnterior(Contato contatoAnterior) {
        //this.contatoAnterior = contatoAnterior;  // original

       this.contatoAnterior = new Contato( contatoAnterior.getNome(),

            contatoAnterior.getSexo(), contatoAnterior.getIdade(),

         contatoAnterior.getEndereco());

     }

}

------------------------------------------------------------------
package contato;
/* Os imports foram omitidos para não ocupar espaço */

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashMap;
public class JaxbTeste {

    public static void main(String args[]) throws JAXBException,
                                       FileNotFoundException {
        Endereco endereco = new Endereco("Rua Moraes", 40, "Centro"
                         ,"Rio de Janeiro", "20000-000");     
         Contato contato = new Contato("Marco Maciel", "M",34, endereco);     

        contato.setContatoAnterior( contato );
        JAXBContext context = JAXBContext.newInstance(Contato.class);     
         //saída 1 – console     
        Marshaller m = context.createMarshaller();     
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);     
        m.marshal(contato, System.out); 
    }
}