[Resolvido] XStream passando por cima das minhas regras de construtor

4 respostas
rfa1989

Tudo bom pessoal?
Já acompanho como observador o GUJ faz um tempo, mas esse eh o meu primeiro post. E é claro, trata-se de uma duvida =P.

Suponha q eu tenha uma classe Livro:

public class Livro {
	private final String title;

	public Livro(String title) {
		if (title == null || title.equals(""))
			throw new IllegalArgumentException(
					"Titulo nao pode ser nulo ou vazio");
		this.title = title;
	}

	public String getTitle() {
		return title;
	}

}

E uma classe LeitorXMLLivro, que usa o XStream:

public class LeitorXMLLivro {
	public Livro consomeXML(Reader reader) {
		XStream stream = new XStream(new DomDriver());
		stream.alias("livro", Livro.class);
		
		Livro livro = (Livro) stream.fromXML(reader);
		return livro;
	}

Como voces podem ver, qualquer tentativa de criar um objeto livro com String vazia ("") resulta numa exception, como o teste abaixo q roda como esperado

@Test(expected = IllegalArgumentException.class)
public void testStringVazia() {
	String vazia = "";
	Livro livro = new Livro(vazia);
}

MAS… ao rodar o seguinte teste, para o meu espanto ele completou com sucesso:

@Test
public void testConsomeXMLComStringVazia() {
	String xml = "<livro><title></title></livro>";
	
	LeitorXMLLivro leitor = new LeitorXMLLivro();
	Livro livro = leitor.consomeXML(new StringReader(xml));
	
	assertEquals("", livro.getTitle());
}

O que eu imaginava é que XStream usasse o construtor fornecido pela minha classe para popular os objetos.
Mas se ele realmente fizesse assim, não poderia ter criado então um objeto livro com atributo title vazio, como mostrei no ultimo teste acima. O construtor iria reclamar disso.
Colocando um method breakpoint no construtor de Livro, realmente pude verificar que ele nunca tenta acessar esse constructor.

O que acontece então por debaixo dos panos do metodo fromXML do XStream?
A melhor alternativa nesse caso é colocar uma verificacao se o titulo é vazia tambem dentro do metodo consomeXML ?
E finalmente, a duvida mais importante: Como faço para prever da proxima vez q usar uma api de terceiros q esse problema pode ocorrer? É só atraves de testes mesmo ou tem algum “dica” ou “palavra-chave” que devo me atentar ao ler a documentacao da api?

Valeu pessoal.

4 Respostas

fantomas

Oi rfa1989,

Me parece que o XStream não executa o construtor porque ele utiliza reflection no processo de serialização e deserialização semelhante a JVM para construir os objetos.

Neste link [url]http://xstream.codehaus.org/faq.html[/url] nas questões [b]How do I initialize a transient field at deserialization?[/b] e [b]XStream is not calling the default constructor during deserialization.[/b] é dito coisas sobre sua questão.

Lembrando que nas respostas das questões também está a resposta sobre o que fazer em uma situação igual a tua, para isso observe o método [b]readResolve[/b] e pesquise no site sobre o uso dele.

Espero ter ajudado

flws

davidbuzatto

Como sempre, vou sugerir o uso do Simple XML ao invés do XStream.
O Simple é mais fácil de utilizar e tem o mesmo poder do XStream.

http://simple.sourceforge.net/

[]'s

fantomas

Oi davidbuzatto,

Dei uma olhada na sua indicação e gostei bastante.

Vou utilizar no próximo projeto que necessitar de xml.

Valeu!

rfa1989

fantomas, muito obrigado pelo esclarecimento. Ajudou direto ao ponto.

E davidbuzatto, não conhecia o Simple. Vou checar ele também.

Vlw

Criado 12 de janeiro de 2011
Ultima resposta 12 de jan. de 2011
Respostas 4
Participantes 3