Problema RMI: Acesso Remoto no Linux

Pessoal

Tenho uma aplicação em Java Web Start que acessa um servidor tomcat utilizado RMI. Quando coloco esta aplicação na minha máquina(windows) funciona normalmente, consigo acessar todos os métodos de qualquer ponto da rede.

Porém quando coloco a aplicação em produção que é em um servidor linux começa os meus problemas :cry:
Não consigo acessar nenhuma método RMI e a seguinte mensagem de erro é exibida:

java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
	java.io.EOFException
	at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
Caused by: java.io.EOFException
	at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
	at java.io.ObjectInputStream.readObject0(Unknown Source)
	at java.io.ObjectInputStream.readObject(Unknown Source)
	at sun.rmi.server.MarshalInputStream.readLocation(Unknown Source)
	at sun.rmi.server.MarshalInputStream.resolveProxyClass(Unknown Source)
	at java.io.ObjectInputStream.readProxyDesc(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)
	... 13 more

Alguém pode me ajudar! :?:

JMedeiros,

Tive o mesmo problema aqui, o sistema funcionava beleza no Windows e nada de roda em Linux.

Os problema que tive foram as permissões das portas do servidor e problemas com o arquivo policy.

Dê uma olhada em
http://java.sun.com/docs/books/tutorial/rmi/overview.html

Me ajudou bastante, pois neste tipo de programa é uma questão de ajustes para funcionar em ambos sistemas operacionais.
Qualquer dúvida coloque no forum.

Boa sorte

Blacksmithrock você sabe me dizer quais as configurações que vc realizou! já adicionei o AllPermissions no catalina.policy para minha aplicação mas ainda não deu certo.

Ainda não mexi nas portas porque quando dou o comando nmap ele diz que a porta esta aberta… porém não sei se tenho autorização para usa-la!

Qualquer ajuda eu agradeço!

JMedeiros,

Não tenho nenhum exemplo aqui comigo no momento mas amanhã posto a maneira que fiz para rodar o serviço RMI em linux.

JMedeiros,

Considerando que você não está com problema de acesso na porta do serviço RMI e considerando que você tem um arquivo policy no seu classpath do programa cliente que libera tudo e considerando que que o seu programa servidor já tá rodando e está registrando pelo comando rmic, se tudo isso estiver ok basta roda o seu programa cliente com o seguinte comando

java -Djava.security.policy=meu_arquivo_policy.policy meu_programa_cliente

Um ótimo material que detalha todo o procedimento de configuração do RMI em Linux está disponível em

http://www.cs.swan.ac.uk/~csneal/InternetComputing/

Boa sorte

Olá, estou com o mesmo problema, a causa do meu Unmarshal é exatamente java.io.EOFException.
Roda 2 aplicações que se conctam via RMI, servidor e cliente.
Quando rodo o servidor pelo eclipse, o cliente roda, tanto no eclipse quanto por fora.
Quando eu rodo o servidor por fora do eclipse, o cliente não roda, mas ao startar o servidor não ocorre o erro, apenas quando iniciamos o cliente.
Detalhe, minha aplicação usufrui de várias (mais de 30) bibliotecas externas, que NÃO FICAM NO CLASSPATH, isso é feito de propósito, pois tanto nosso cliente quanto nosso servidor rodam via Java Web Start. Todas bibliotecas ficam enumeradas no jnlp.
Algumas vezes, o nosso problema de Unmarsha era porque algumas classes transmitidas pelo reda, não implementavam Remote, mas nesse caso o erro é outro, até onde eu sei, java.io.EOFException é problemas com leitura/escrita de arquivos.
Gostaria de saber se alguém tem alguma idéia, pois nós já esgotamos nossas alternativas.
Utilizamos JSE 1.6.0_01
Qualquer informação será muito útil, obrigado.

jschuler,

Coloque exatamente o erro que retorna.

Até mais !!!

Fiz mais um teste agora, rodando tudo local, até mesmo as url’s do jnlp local, o erro também ocorre, significa que não é problema de Serializable.

Erro ao rodar o cliente:

java.rmi.UnmarshalException: error unmarshalling return; nested exception is: java.io.EOFException at sun.rmi.server.UnicastRef.invoke(Unknown Source) at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source) at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) at $Proxy0.getServico(Unknown Source) at br.com.ampix.directorsystemcontabil.client.ApxClient.main(ApxClient.java:140) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at com.sun.javaws.Launcher.executeApplication(Unknown Source) at com.sun.javaws.Launcher.executeMainClass(Unknown Source) at com.sun.javaws.Launcher.doLaunchApp(Unknown Source) at com.sun.javaws.Launcher.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: java.io.EOFException at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at sun.rmi.server.UnicastRef.unmarshalValue(Unknown Source) ... 14 more
Ps.: ApxClient linha 140 é exatamento onde faco o lookup do servico rmi do meu servidor e invoco um metodo próprio, o lookup ele consegue envocar, retornando um proxy, o que está correto, problema ocorre quando eu invoko um metodo proprio do proxy retornado.
Essa aplicação já rodava antes, exatamente assim, e nada foi alterado desde a ultima versão disponibilizada, além das bibliotecas externas e versões do JRE.
Também já editamos o java.policy, liberando acesso ao rmi.
Alguma idéia?

o que colocaste no policy?
como estás compilando?
que parametros da VM estás usando na hora de rodar o Cliente e o Servidor?
A classe interface está correta no cliente?

Policy:

[code]grant codeBase “file:${{java.ext.dirs}}/*” {
permission java.security.AllPermission;
};

grant {
permission java.lang.RuntimePermission “stopThread”;
permission java.net.SocketPermission “*:1024-65535”, “accept,connect,resolve,listen”;
permission java.security.AllPermission;
};

[/code]
Compilo pelo eclipse, utilizando o JDK 1.6.0_01, depois monto nosso jar’s (em torno de 15) utilizando o ant, pois repartimos nosso projeto para melhor administrar. Todos esses jar’s também vão para o jnlp.
Não colocamos nenhum parâmetro na inicialização do aplicativo. (Nem sabia que dava pra fazer isso utilizando jnlp’s).
De que interface você se refere?

Estou me referindo à algo do tipo no lado cliente da sua aplicação

// Count Interface

import java.rmi.*;

public interface Count extends Remote {
  void set(int val) throws RemoteException;
  void reset() throws RemoteException;
  int get() throws RemoteException;
  int increment() throws RemoteException;
}

Nossa interface mais alta na hierarquia é:

[code]package br.com.ampix.basic.interfaces;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface ApxServicoRMIInterface<S extends ApxSession, R extends ApxSession>
extends Remote, ApxServicoInterface {

S openSession() throws RemoteException;

R openSessionReport() throws RemoteException;

}
[/code]

Interface abaixo desta:

[code]package br.com.ampix.basic.directorsystemcontabil.service.interfaces;

import java.rmi.RemoteException;

import br.com.ampix.basic.directorsystemcontabilreport.bolseiro.interfaces.ApxDSCBolseiroInterface;
import br.com.ampix.basic.directorsystemcontabilreport.bolseiro.interfaces.ApxDSCReportBolseiroInterface;
import br.com.ampix.basic.interfaces.ApxBolseiroInterface;
import br.com.ampix.basic.interfaces.ApxServicoRMIInterface;
import br.com.ampix.basic.interfaces.ApxSession;
import br.com.ampix.util.exception.ApxException;

public interface ApxDSCServiceInterface<S extends ApxSession, R extends ApxSession, B extends ApxBolseiroInterface> extends
ApxServicoRMIInterface<S, R> {

Object executeListagem(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException;

Object executeProcessamento(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException;

Object executeInclusao(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException;

Object executeConsulta(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException;

Object executeUpdate(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException;

boolean executeRemove(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException;

ApxDSCReportBolseiroInterface buildReport(ApxDSCReportBolseiroInterface bolseiro) throws RemoteException;

Object executeQuery(B bolseiro) throws RemoteException;

}
[/code]

Classe Abstrata que implementa esta interface:

[code]package br.com.ampix.basic.directorsystemcontabil.service;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;

import br.com.ampix.basic.directorsystemcontabil.factories.interfaces.ApxDSCFactoryDaoInterface;
import br.com.ampix.basic.directorsystemcontabil.factories.interfaces.ApxDSCFactoryRuleInterface;
import br.com.ampix.basic.directorsystemcontabil.service.interfaces.ApxDSCServiceInterface;
import br.com.ampix.basic.directorsystemcontabilreport.factories.interfaces.ApxDSCReportFactoryDaoInterface;
import br.com.ampix.basic.directorsystemcontabilreport.factories.interfaces.ApxDSCReportFactoryRuleInterface;
import br.com.ampix.basic.interfaces.ApxBolseiroInterface;
import br.com.ampix.basic.interfaces.ApxSession;
import br.com.ampix.basic.interfaces.factories.FactoryInterface;
import br.com.ampix.util.exception.ApxException;

public abstract class AbstractApxDSCService<S extends ApxSession, R extends ApxSession, B extends ApxBolseiroInterface> extends
UnicastRemoteObject implements ApxDSCServiceInterface<S, R, B> {

protected static HashMap<String, FactoryInterface> factories = new HashMap();

static {
    try {
        factories.put(ApxDSCFactoryRuleInterface.RULE_NAME, (FactoryInterface) Class.forName(
                "br.com.ampix.directorsystemcontabil.server.factories.DefaultFactoryRule").newInstance());
        factories.put(ApxDSCFactoryDaoInterface.DAO_NAME, (FactoryInterface) Class.forName(
                "br.com.ampix.directorsystemcontabil.server.factories.DefaultFactoryDao").newInstance());
        factories.put(ApxDSCReportFactoryDaoInterface.DAO_NAME, (FactoryInterface) Class.forName(
                "br.com.ampix.directorsystemcontabilreport.server.factories.DefaultFactoryDaoReport").newInstance());
        factories.put(ApxDSCReportFactoryRuleInterface.RULE_NAME, (FactoryInterface) Class.forName(
                "br.com.ampix.directorsystemcontabilreport.server.factories.DefaultFactoryRuleReport").newInstance());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

public static FactoryInterface getFactory(String key) {
    return factories.get(key);
}

public AbstractApxDSCService() throws RemoteException {
    super();
}

}
[/code]

E finalmente, a classe concreta, que realmente chega no cliente como servico de rmi, que foi feito o rebind:


package br.com.ampix.directorsystemcontabil.server.service;

import java.rmi.RemoteException;

import br.com.ampix.basic.directorsystemcontabil.server.DefaultApxReportSession;
import br.com.ampix.basic.directorsystemcontabil.server.DefaultApxSession;
import br.com.ampix.basic.directorsystemcontabil.service.AbstractApxDSCService;
import br.com.ampix.basic.directorsystemcontabilreport.bolseiro.interfaces.ApxDSCBolseiroInterface;
import br.com.ampix.basic.directorsystemcontabilreport.bolseiro.interfaces.ApxDSCReportBolseiroInterface;
import br.com.ampix.basic.interfaces.ApxBolseiroInterface;
import br.com.ampix.interfaces.ctb.RazaoReportInterface;
import br.com.ampix.objetos.ctb.report.RazaoReport;
import br.com.ampix.objetos.ctb.report.cfg.ApxReportCompiler;
import br.com.ampix.pesquisa.interfaces.ApxBolseiroPesquisa;
import br.com.ampix.util.exception.ApxException;

public class DefaultApxDSCService extends AbstractApxDSCService<DefaultApxSession, DefaultApxReportSession, ApxBolseiroPesquisa> {

    private static final long serialVersionUID = 1628317873417746216L;

    private static ApxDSCHibernateController hibernateController;

    public DefaultApxDSCService() throws RemoteException {
        super();
    }

    private Object executeRegra(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException {
        return openSession().execute(bolseiro);
    }

    public Object executeListagem(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException {
        return openSession().executeListagem(bolseiro);
    }

    public Object executeProcessamento(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException {
        return executeRegra(bolseiro);
    }

    public Object executeInclusao(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException {
        return openSession().executeInclusao(bolseiro);
    }

    public Object executeConsulta(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException {
        return openSession().executeConsulta(bolseiro);
    }

    public Object executeUpdate(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException {
        return openSession().executeUpdate(bolseiro);
    }

    public boolean executeRemove(ApxDSCBolseiroInterface bolseiro) throws RemoteException, ApxException {
        return openSession().executeRemove(bolseiro);
    }

    public synchronized static ApxDSCHibernateController getHibernateController() {
        return hibernateController;
    }

    public synchronized static void setHibernateController(ApxDSCHibernateController controller) {
        hibernateController = controller;
    }

    public DefaultApxSession openSession() {
        return new DefaultApxSession(hibernateController.openSession());
    }

    public ApxDSCReportBolseiroInterface buildReport(ApxDSCReportBolseiroInterface bolseiro) throws RemoteException {
        ApxDSCReportBolseiroInterface report = openSessionReport().buildReport(bolseiro);
        System.gc();
        return report;

    }

    public DefaultApxReportSession openSessionReport() throws RemoteException {
        return new DefaultApxReportSession(openSession());
    }

    public Object executeQuery(ApxBolseiroPesquisa bolseiro) throws ApxException {
        return openSession().executeQuery(bolseiro);
    }

}

Parece um pouco complexo, mas não é tanto não, fizemos assim para reutilizarmos em mais aplicações cliente/servidor utilizando o RMI.
Agradeço a cooperação.

Informação útil, retirei o jnlp, estou rodando via linha de comando, meus .jar colocados na pasta EXT do JRE.
Linha de execução do servidor:

jre\bin\java -Djava.security.policy=ampix.policy -jar lib\AmpixLibraries\DirectorSystemContabilServer.jar -Xms128m -Xmx512m

Linha de execução do cliente:

jre\bin\java -Djava.security.policy=ampix.policy -jar lib\AmpixLibraries\DirectorSystemContabilClient.jar -Xms128m -Xmx512m

Descobri, quase sem querer, que EOFException não é utilizada somente na leitura de aruivo, mas também no fechamento inesperado de streams.

FactoryServicoInterface factory = (FactoryServicoInterface) Naming.lookup("//" + host + ":" + port + "/ServiceFactory"); ApxDSCServiceInterface service = (ApxDSCServiceInterface) factory.getServico(InetAddress.getLocalHost()
Ao executar o lookup, retorna a factory, em modo de proxy, mas quando executo a linha abaixo, a sessão está fechada.
Existe algo que posso fazer no servidor para isso não acontecer?