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