Enviar via socket uma classe que extende um JPanel?

Pessoal eu to com o seguinte problema, eu tenho que enviar uma classe que extende um JPanel via socket, só que eu não estou conseguindo esta dando varios erros, alguem poderia me ajudar.

Acontece o seguinte :

Classe JPANEL enviada via socket

public class Emailrec extends JPanel implements Serializable {
	public Emailrec() {
		super();
		initialize();
	}
	private void initialize() {
		this.setSize(300, 200);
		this.setBackground(new Color(200,200,125));
	}
}

Aonde Recebe o JPANEL

.
.
.
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
JPanel painelRecebido = (JPanel) ois.readObject();
.
.
.

Ta dando um java.lang.ClassNotFoundException, só que como a classe Emailrec extende a JPanel, num era para funcionar ???

Agradeco qualquer ajuda

estranho… ja tentou converter pra classe certa? (Emailrec )
so pra tirar a duvida?

[quote=“maxguzenski”]estranho… ja tentou converter pra classe certa? (Emailrec )
so pra tirar a duvida?[/quote]

Ja sim cara, se eu converter ai funciona blz, só que o problema é o seguinte, não mando apenas o Emailrec, eu posso mandar outra classe, entao teria que ser algo generico, por isso eu dei o cast para o JPANEL !!!

Todas as classes que eu mandar iram extender o JPANEL

sim eu sei, so queria tirar a duvida…

posso ver seu codigo na hora que voce da o write ?

[quote=“maxguzenski”]sim eu sei, so queria tirar a duvida…

posso ver seu codigo na hora que voce da o write ?[/quote]

Claro,

this.oos = new ObjectOutputStream(this.socket.getOutputStream());

RPemailrec rpemailrec = new RPemailrec();
this.oos.writeObject(rpemailrec);
this.oos.flush();

Qual eh a classe que ele nao ta encontrando?

é, so agora me liguei q o erro é de classe nao encontrada, e nao de cast propriamente.

Qual eh a classe que ele nao ta encontrando?[/quote]

A classe Emailrec.

Mas como a classe emailrec extends a classe JPanel, não deviria funcionar o cast.

Voce precisa da classe Emailrec no cliente (que esta recebendo o objeto serializado via socket, mesmo fazendo cast pra JPanel.

Fiz umas mudanças no codigo, para ficar mais facil :

Classe TelaParametro :

[code]public abstract class TelaParametro implements Serializable{

public abstract JPanel getJPanel();

}[/code]

Classe que herda a TelaParametro :

public class RPemailrec extends TelaParametro implements Serializable{ public JPanel getJPanel() { JPanel painel = new JPanel(); painel.setSize(200,200); painel.setBackground(new Color(120,160,200)); return painel; } }

Outra classe que herda a TelaParametro

public class Grafemailrec extends TelaParametro implements Serializable { public final JPanel getJPanel() { JPanel painel = new JPanel(); painel.setBackground(new Color(90,68,255)); return painel; } }

Classe que envia o Objeto Rpemailrec e o Objeto Grafemailrec:

this.oos = new ObjectOutputStream(this.socket.getOutputStream()); if(...){ RPemailrec rpemailrec = new RPemailrec(); this.oos.writeObject(rpemailrec); this.oos.flush(); } if(...){ Grafemailrec grafemailrec = new Grafemailrec(); this.oos.writeObject(grafemailrec); this.oos.flush(); } this.oos.close();

Classe que Recebe o Objeto pode ser que seja enviado o Rpemailrec ou o Objeto Grafemailrec
esta classe não sabe qual e ela apenas recebe e executa o metodo getJPanel()

ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); this.tp = (TelaParametro) ois.readObject(); JPanel painel = this.tp.getJPanel();

Mas acontece esse erro ao tentar receber o Objeto :

java.lang.ClassNotFoundException: servidor.telaParametros.receptor.RPemailrec at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClassInternal(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at java.io.ObjectInputStream.resolveClass(Unknown Source) at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source) at java.io.ObjectInputStream.readClassDesc(Unknown Source) at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at cliente.telaParametros.BuscaTela.conectar(BuscaTela.java:86) at cliente.telaParametros.BuscaTela.getJPanel(BuscaTela.java:59) at cliente.telaParametros.DialogParametros.getConteudoJpanel(DialogParametros.java:191) at cliente.painelMenu.PainelMenu$1.actionPerformed(PainelMenu.java:91) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)

Desculpa estar escrevendo esse monte de codigo, mas é que estou com muita duvida nisso, eu tenho que enviar um objeto “generico” (que extende a classe TelaParametro) e executar o metogo getJPanel, que é sobrescrito nas classes filhas (RPemailrec e Grafemailrec), com isso ao receber o objeto no destino (cliente) a aplicacao conseguiria por exemplo exibir o JPANEL.

O Objetivo principal é que no cliente ele não tenha a RPemailrec.class e o Grafemailrec.class.

Entao, bem-vindo ao maravilhoso mundo dos ClassLoaders! Voce vai ter que escrever um ClassLoader que saiba buscar as classes RPemailrec e Grafemailrec (alias, que nomenclatura doida eh essa?). A JVM simplesmente nao consegue executar codigo de uma classe que ela nao conhece, entao vc tem que ensinar a coitada a buscar a classe e carregar ela :wink:

PS: eu jah tive cãibras mais prazerosas do que escrever ClassLoaders, entao, boa sorte :smiley:

Entao, bem-vindo ao maravilhoso mundo dos ClassLoaders! Voce vai ter que escrever um ClassLoader que saiba buscar as classes RPemailrec e Grafemailrec (alias, que nomenclatura doida eh essa?). A JVM simplesmente nao consegue executar codigo de uma classe que ela nao conhece, entao vc tem que ensinar a coitada a buscar a classe e carregar ela :wink:

PS: eu jah tive cãibras mais prazerosas do que escrever ClassLoaders, entao, boa sorte :D[/quote]

Ptz, entao não tem jeito, o cliente tem que de alguma forma acessar o .CLASS, e não adiantar fazer o cast pela classe que ele herda que num vai funcionar :cry: :cry: ???

P.S.: As nomeclaturas são conforme o codigo da operacao que esta sendo executada :slight_smile: :slight_smile: eu tambem acho tosko, mas aqui na empresa eles querem assim !!!

Acho que nao precisa de tanto assim nao. Acho que nao ha a necessidade de se aventurar nos classloader.
Bem, isso vai depender da natureza da aplicacao. Se a ideia eh codificar novas classes no servidor e o cliente tipo de auto updatear essas classes, ai sim eh necessario codificar um classloader.
Mas se todas as classes que forem mandadas pelo socket sejam conhecidas a principio (todas as classes possiveis ja se encontram no jar do cliente), acho que da para fazer de um jeito mais facil, basta usar o Class.forName().
A ideia eh a seguinte, antes de mandar a classe serializada pelo socket, manda primeiro o nome da classe, usando um writeString. No cliente voce da um readString e executa um Class.forName(nomeDaClasse). Depois voce manda a classe serializada e acredito que ira funcionar.

Todas as classes usadas pelo objeto serializado devem estar disponiveis para a deserialização funcionar.

Ptz, entedi, estava lendo uns textos na internet e acabei descobrindo que cada classe tem um “ID” que o readerobject() verifica antes de “gravar” no objeto de destino, entao como são objetos diferentes, mesmo que o objeto enviado tenha herdado esse objeto de destino, vai ter “ID” diferente, por isso o ClassNotFoundException.

De qualquer forma, valeu pela ajuda galera !!!

Vou fazer o cliente ver os .class de alguma forma, mas acho que ClassLoader num vai ser muito bom, pelo trabalho que vou ter, mas quem sabe num é a saida para meu problema.

Valeu pessoal

Cara, não é bem isso, o que acontece é que o que vc envia pelo socket (essa parte, todos concordamos, mas só pra introduzir) é uma estrutura onde tá escrito “a minha classe é xxx.yyy.Emailrec”. O cliente vai tentar carregar essa classe.

O objetivo disso é que alguém no futuro possa fazer:

  em = (Emailrec) painel;

o fato de todas essas classes existirem no seu cliente não necessariamente quebra o data hiding (embora eu seja cético ante a necessidade de passar um JPanel pelo socket). Mas se vc quer independência da implementação, vc não pode usar herança.

eu não sei exatamente o que é diferente entre todas as implementações possíveis, mas antes de sair brincando com class loaders, descubra qual é o mínimo que vc pode enviar e ainda assim ter escolhas. Eu explico…

Vc tem que mandar código?? Vc sobrescreve algum dos métodos do JPanel? Tem polimorfismo aí??

Se não tem, ótimo, refatora seus objetos pra que eles usem um JPanel em vez de serem um, e envie instãncias de JPanel puro.

Se tem código, vc tem que enviar esse código. Daí as possibilidades abrem muito, a mais simples é obviamente mandar os .class pro cliente, e uma boa opção é usar o java.net.URLClassLoader, se vc tem um webserver que pode abrigar seus jars, fica bíltifou.

Outras opções (que dependem do quanto suas subclasses podem sobrescrever do código do JPanel) são criar uma classe específica, que delega o código em questão pra alguém, e com esse delegado vc pode:

  1. deixar o .class disponível na web (pra acessar com URLClassLoader)
  2. abstrair mais ainda e pular pra uma linguagem de scripts (Groovy?) que vc compile na hora e use. Por exemplo:
public void paintComponent(Graphics g) {
  if (delegate == null) return;
  delegate.invokeMethod("paintComponent", new Object[]{this, g});
}

public void setDelegate(GroovyObject delegate) {
  this.delegate = delegate;
}

Boa sorte e []s!