Para gravarmos dados na sessão do usuário é necessário que as classes implementem a interface java.io.Serializable. Caso isso não ocorra, podemos ter erro com a exceção: NotSerializableException ou mal funcionamento da aplicação, principalmente se você estiver em ambiente clusterizado com replicação de sessão.
E isso se torna, um problema quando trabalhamos com a geração automática de clientes de Web Services, pois as classes são geradas sem “implements java.io.Serializable”. Portanto não podemos inserir essas classes no contexto de sessão. Uma solução é editar as classes geradas incluindo o “implements java.io.Serializable”. O problema dessa abordagem é que ao gerar novamente as classes (como por exemplo: alteração de endpoint, atualização de WSDL ou inclusão de política de segurança ou SOAP Handler), as classes com “implements java.io.Serializable” serão sobreescritas e essa solução perderá validade, sendo necessário alterar todas as classes novamente.
Uma boa alternativa para resolver esse problema é a criação de Wrappers serializáveis para classes não serializáveis. Com base nesse problema resolvi criar uma interaface auxiliar para obrigar a implementação da conversão entre o Wrapper e a classe alvo.
public interface Wrappable extends Serializable {
public void wrap(T objectToCopy);
public T unwrap();
}
O método wrap é responsável por receber um objeto e copiar os atributos necessários e o unwrap reconstrói o objeto. Para fins de demonstração utilizaremos a seguinte classe:
public class Boo {
private String doo;
private int foo;
public Boo(String doo, int foo) {
super();
this.doo = doo;
this.foo = foo;
}
public String getDoo() {
return doo;
}
public void setDoo(String doo) {
this.doo = doo;
}
public int getFoo() {
return foo;
}
public void setFoo(int foo) {
this.foo = foo;
}
}
Essa é uma classe não serializável. Para criar o Wrapper serializável correspondente é só implementar devidamente a interface:
public class BooWrapper implements Wrappable {
private static final long serialVersionUID = 201103151148L;
private String doo;
private int foo;
public BooWrapper(Boo object) {
wrap(object);
}
@Override
public void wrap(Boo objectToCopy) {
this.doo = objectToCopy.getDoo();
this.foo = objectToCopy.getFoo();
}
@Override
public Boo unwrap() {
return new Boo(doo, foo);
}
}
Não é recomendado herdar a classe ou mesmo incluí-la como atributo pois como ela não é serializável e também pode conter atributos não serializáveis, o problema não será resolvido (se mesmo assim você quiser, pode marcá-la como transiente). Com base no exemplo acima, podemos utilizar o Wrapper como um Adapter e alterar nome dos atributos/métodos, inserir métodos auxiliares e inserir somente o necessário na sessão. Diminuindo o acoplamento entre a camada Web e a camada de serviços.
Uma outra possibilidade é criar um arquivo de personalização dos bindings do JAXB para ter suporte à Serializable: http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/jaxb/vendorCustomizations.html#serializable