Erro ao reconectar a um SessionBean Stateful

:scrambleup: Estou criando um Session Bean Stateful.
Ao tentar reconectar ao bean usando um id obtido do service locator obtenho a exceção:

[code]/*** Método utilizado para reconectar ao EJB **/
public EJBObject getService(String id)
throws ServiceLocatorException {
if (id == null) {
throw new ServiceLocatorException("NULL");
}
try {
System.out.println(id);
byte[] bytes = id.getBytes();
InputStream io = new ByteArrayInputStream(bytes);
ObjectInputStream os = new ObjectInputStream(io);
Object o = os.readObject();
javax.ejb.Handle handle = (javax.ejb.Handle) o;
return handle.getEJBObject();
} catch(Exception ex) {
ex.printStackTrace();
throw new ServiceLocatorException("Location Fail");
}
}

/*** Método utilizado para obter o Id do EJB **/
public String getId(EJBObject session)
throws ServiceLocatorException {
try {
javax.ejb.Handle handle = session.getHandle();
ByteArrayOutputStream fo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(handle);
so.flush();
so.close();
return new String(fo.toByteArray());

} catch(RemoteException ex) {
	  throw new ServiceLocatorException("Falha na Comunicação");
} catch(IOException ex) {
	  throw new ServiceLocatorException("Falha na Leitura");
}

}[/code]

Uso:

J2sdk1.4.2
JBoss 4

Quando vi o seu programa já entendi o problema.

byte[] bytes = id.getBytes();

e

new String(fo.toByteArray());

Aqui há um problema muito comum - achar que podemos guardar arrays de bytes em Strings. Isso dá muitos problemas porque Java tem a mania de trocar um byte pelo caracter ‘?’ se ele não encontrar no charset corrente. Então o que ocorre é que você nunca mais consegue recuperar o byte array original.

Isso dá montes de problemas com criptografia, mas deu problema também com você que só está tentando serializar um objeto.

Só para você ver o estrago, tente fazer o seguinte:

Crie um array de bytes com os bytes de -128 a +127. Converta para uma String com new String(). Agora pegue os bytes da String com .toByteArray(), e compare com o valor original. Você vai ver que cerca de 4 a 6 bytes do array original, dependendo da versão do JDK e do seu “regional settings”, foram trocados por ‘?’. Não importa qual o “charset” que você usar, sempre sempre sempre vai ter algum dos bytes que vai ser trocado por ‘?’.

Dica: Se for guardar um array de bytes em uma String, converta para hexadecimal ou Base-64, ou no seu caso em particular, talvez dê para deixar como byte[] mesmo.

:scrambleup: Valeu pela dica, assim funcionou:

[code] public EJBObject getService(String id)
throws ServiceLocatorException {
if (id == null) {
throw new ServiceLocatorException("NULL");
}
try {
byte[] bytes = Base64.decode(id.getBytes());
ByteArrayInputStream io = new ByteArrayInputStream(bytes);
ObjectInputStream os = new ObjectInputStream(io);
Handle handle = (Handle) os.readObject();
return handle.getEJBObject();
} catch(Exception ex) {
ex.printStackTrace();
throw new ServiceLocatorException("Location Fail");
}
}

public String getId(EJBObject session) 
  throws ServiceLocatorException {
	try {
	  Handle handle = session.getHandle();	  
	  ByteArrayOutputStream fo = new ByteArrayOutputStream();		  
	  ObjectOutputStream so = new ObjectOutputStream(fo);		  
	  so.writeObject(handle);
	  so.flush();		  
	  so.close();
	  return new String(Base64.encode(fo.toByteArray()));
	  
	} catch(RemoteException ex) {
	  throw new ServiceLocatorException("Falha na Comunicação");
	} catch(IOException ex) {
	  throw new ServiceLocatorException("Falha na Leitura");
	}
  }[/code]