RMI é... velho. É um assunto batido, bem documentado, sem maiores mistérios, mas que é um dos pilares mais importantes do JEE, embora ele esteja caminhando para o esquecimento a passos largos com a chegada de tecnologias como o CDI.
Ainda assim, se você estiver estudando não me custa quase nada dar os toques do que fazer, ;-)
Como imaginado, o assunto aqui é prática. Se quiser teoria, tem aqui.
Comece abrindo o eclipse e criando um projeto chamado rmi_sample1:
Uma vez criado o projeto, vamos criar dois pontos de entrada: um para ser usado quando rodarmos o cliente, outro para quando rodarmos o servidor. Bastam duas classes por hora, cada uma com um método main():
Vamos fazer o seguinte agora: na classe do servidor vamos subir o registro, pois sem ele não poderemos disponibilizar os objetos remotos:
public static void main(String[] args) throws Exception {
LocateRegistry.createRegistry(1099);
}
Outra forma de fazer é chamar na linha de comando o rmiregistry, mas vamos fingir que isso jamais existiu, ;-)
Falemos um pouco sobre o tal "objeto remoto":
- Deve implementar uma interface que extenda a interface Remote.
- Deve herdar de UnicastRemoteObject.
- Deve sobrescrever e chamar ativamente o construtor padrão.
No nosso exemplo vamos fazer um pequeno cadastro de alunos. Crie uma interface chamada GestorAlunos:
package sample.api;
import java.rmi.Remote;
public interface GestorAlunos extends Remote {
void adicionarAluno();
String removerAluno();
void consultarAluno();
void listar();
}
Você pessoa esperta que é sabe que esta interface não está completa. Mas quando você estiver criando suas coisas você pode ir por esta abordagem também: defina os nomes, para depois definir os detalhes.
Por exemplo, vamos precisar de uma classe chamada Aluno:
Vamos colocar no aluno estes atributos:
package sample;
public class Aluno {
private int codigo;
private String nome;
private double nota1,nota2,nota3;
private int frequencia;
}
Claro, não esqueça de gerar os getters/setters usando o atalho do eclipse:
Feito isso, volte à interface GestorAlunos e modifique-a:
package sample.api;
import java.rmi.Remote;
import java.util.List;
import sample.Aluno;
public interface GestorAlunos extends Remote {
Aluno adicionarAluno(Aluno aluno) throws RemoteException;
String removerAluno(int codigo) throws RemoteException;
Aluno consultarAluno(int codigo) throws RemoteException;
List listar() throws RemoteException;
}
Parece bom... muito bom... mas até agora apenas definimos o contrato entre o cliente e o servidor, nada mais.
Esta interface, inclusive, será comum aos seus clientes e ao servidor.
vamos para a diversão, vamos fazer agora a implementação do GestorAlunos:
package sample.impl;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.List;
import sample.Aluno;
import sample.api.GestorAlunos;
public class GestorAlunosImpl extends UnicastRemoteObject implements
GestorAlunos {
public GestorAlunosImpl() throws RemoteException {
super();
}
private static final long serialVersionUID = 1179227415408023062L;
@Override
public Aluno adicionarAluno(Aluno aluno) {
return null;
}
@Override
public String removerAluno(int codigo) {
return null;
}
@Override
public Aluno consultarAluno(int codigo) {
return null;
}
@Override
public List listar() {
return null;
}
}
Observe que esta implementação faz nada ainda, apenas implementamos os métodos que a interface obriga bem como herdamos de UnicastRemoteObject.
Vamos deixar assim, uma coisa que chamo de wireframe. Vamos seguir para o MainServer novamente e colocar a nossa implementação no registro:
package sample;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import sample.api.GestorAlunos;
import sample.impl.GestorAlunosImpl;
public class MainServer {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
LocateRegistry.createRegistry(1099);
GestorAlunos gestor = new GestorAlunosImpl();
System.out.println("Servidor rodando");
Naming.rebind("//localhost/GestorAlunos", gestor);
System.out.println("Objeto publicado");
}
}
Feito isso o MainServer passa a ser responsável por subir o registro e em seguida disponibilizar o objeto remoto.
Vamos ao MainClient fazer o código de recuperar a referência pro objeto remoto:
package sample;
import java.rmi.Naming;
import sample.api.GestorAlunos;
public class MainClient {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// conseguindo uma referência remota
GestorAlunos gestor = (GestorAlunos) Naming//
.lookup("//localhost/GestorAlunos");
// fazendo coisas com o gestor
Aluno a = new Aluno();
a.setNome("Fulano de tal");
a.setFrequencia(100);
a.setNota1(10.0);
a.setNota2(9.5);
a.setNota3(7.0);
a = gestor.adicionarAluno(a);
System.out.println(a);
}
}
Simples né? Vamos rodar. Primeiro rode o MainServer (botão direito nele, Run As > Java Application)
Em seguida faça o mesmo com o MainClient. Mas veja, algo de diferente ocorreu:
Esse erro é comum entre estudantes, e a solução é super simples. Torne a classe Aluno serializável:
package sample;
import java.io.Serializable;
public class Aluno implements Serializable{
private static final long serialVersionUID = 1728799560066886492L;
private int codigo;
private String nome;
private double nota1,nota2,nota3;
private int frequencia;
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public double getNota1() {
return nota1;
}
public void setNota1(double nota1) {
this.nota1 = nota1;
}
public double getNota2() {
return nota2;
}
public void setNota2(double nota2) {
this.nota2 = nota2;
}
public double getNota3() {
return nota3;
}
public void setNota3(double nota3) {
this.nota3 = nota3;
}
public int getFrequencia() {
return frequencia;
}
public void setFrequencia(int frequencia) {
this.frequencia = frequencia;
}
}
Salve.
Importante, você vai precisar parar o MainServer novamente, afinal ele ainda está rodando e está com a definição antiga de classe. Agora rode o MainServer novamente. Tudo certo dessa vez, né?
Retornou null, mas não se preocupe ainda: vamos para o GestorAlunosImpl olhar o método adicionarAluno. Vamos modificar essa implementação pra que nos dê algo mais interessante:
package sample.impl;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import sample.Aluno;
import sample.api.GestorAlunos;
public class GestorAlunosImpl extends UnicastRemoteObject implements
GestorAlunos {
private int seq = 0;
private List alunos = new ArrayList();
public GestorAlunosImpl() throws RemoteException {
super();
}
private static final long serialVersionUID = 1179227415408023062L;
@Override
public Aluno adicionarAluno(Aluno aluno) {
aluno.setCodigo(++seq);
alunos.add(aluno);
System.out.println("Aluno adicionado com código " + aluno.getCodigo());
return aluno;
}
@Override
public String removerAluno(int codigo) {
return null;
}
@Override
public Aluno consultarAluno(int codigo) {
return null;
}
@Override
public List listar() {
return null;
}
}
Que beleza, né? agora ele adiciona numa lista e retorna com um código.
Entretanto, se você rodar o MainClient de novo, o retorno ainda será null. Por que isso?
Nosso GestorAlunosImpl não tem os stubs gerados.
Classicamente gerar stubs era um saco, mas estamos usando eclipse e portando a vida é boa.
Crie na raiz do projeto eclipse um arquivo chamado build.xml que tenha isso:
Aperte F5 na pasta do projeto e tenha uma surpresa, :-)
Agora, volte ao MainServer e rode-o outra vez. E faça a mesma coisa com o MainClient:
Bacana?
Agora voe sozinho, passarinho, que o resto é simples, e se você usar o que você viu aqui só o sucesso lhe espera, ;-)
Sem mais para o momento, apenas boa sorte!
Nenhum comentário :
Postar um comentário