Wrapper/Adapter Serializable

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

Sobre: Thiago Galbiatti Vespa

Thiago Galbiatti Vespa é mestre em Ciências da Computação e Matemática Computacional pela USP e bacharel em Ciências da Computação pela UNESP. Coordenador de projetos do JavaNoroeste, membro do JCP (Java Community Process), consultor Oracle, arquiteto de software de empresas de médio e grande porte, palestrante de vários eventos e colaborador de projetos open source. Possui as certificações: Oracle Certified Master, Java EE 5 Enterprise Architect – Step 1, 2 and 3; Oracle WebCenter Portal 11g Certified Implementation Specialist; Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert; Oracle Certified Professional, Java EE 5 Web Services Developer; Oracle Certified Expert, NetBeans Integrated Development Environment 6.1 Programmer; Oracle Certified Professional, Java Programmer; Oracle Certified Associate, Java SE 5/SE 6