RMI bez konsoli co robię nie tak?

0

Witam,
staram się napisać testową aplikacje rozproszoną wykorzystując RMI i nie bardzo rozumie jak to działa. Napisałem interface, klasę implementującą interface i klienta. Proszę o porady i wskazówki.

Oto one:

Interaface:

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


public interface RMIInterface extends Remote{
	
	public void pokazNapis() throws RemoteException;

}

Klasa implementujaca:

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;


public class RMIImplementacja extends UnicastRemoteObject implements RMIInterface{
	
	String adres;
	int port =1111;
	
	public RMIImplementacja() throws RemoteException, UnknownHostException{
		super();
		String nazwa="RMIInterface";
		adres=(InetAddress.getLocalHost()).toString();
		System.out.println("this address="+adres+",port="+port);
	 
	 Registry rejestr = LocateRegistry.createRegistry(port);
	 rejestr.rebind(nazwa, this);
	
	 }
	 
	public void pokazNapis() throws RemoteException {
		String napis = "Test tego gowna";
		System.out.println(napis);
	}
	
	public static void main(String[] args) throws RemoteException, AlreadyBoundException, UnknownHostException{
		
		RMIImplementacja serv=new RMIImplementacja();
	
}
}
 

Klasa klienta:

import java.net.UnknownHostException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;


public class RMItest {
	
	public static void main(String[] args)throws RemoteException,
	  java.net.MalformedURLException, java.rmi.NotBoundException,       UnknownHostException {
		
		System.setSecurityManager( new RMISecurityManager());
		Registry rejestr;
		int port =1111;
		String adres=("192.168.1.17");
		RMIInterface zmienna;
		
		rejestr=LocateRegistry.getRegistry(adres,port);
		zmienna = (RMIInterface)(rejestr.lookup("RMIInterface"));
		zmienna.pokazNapis();
		
}

}
 
0

Wygląda to mniej więcej ok ale nie robisz w tym swoim RMIImplementacja exportObject(). (rozumiem ze nie łaska napisać co właściwie ci nie działa i jakie lecą wyjątki? nie każdemu sie chce to składać i kompilowac...)
Poza tym proponuje wziąć sobie do serca zasadę jednej odpowiedzialności i stworzyć klasę robiącą za "serwer" która będzie tworzyć obiekt RMIImplementacja i to ona będzie go zapisywać w rejestrze. Tak zeby ta klasa implementująca zdalny interfejs zajmowała sie tylko tym czym się ma zajmowac.

0

Przy próbie odpalenia wyskakują mi takie błędy:

Exception in thread "main" java.security.AccessControlException: access denied (java.net.SocketPermission 192.168.1.17:1111 connect,resolve)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkConnect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)
at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
at sun.rmi.server.UnicastRef.newCall(Unknown Source)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at RMItest.main(RMItest.java:22)

0

Mnie to wygląda na brak uprawnień do portu 1111 na kompie o numerze Ip 192.168.1.17. Złe dane lub przestaw coś w firewallu

0

Czy odpalasz serwer/klient z odpowiednimi uprawnieniami (dodanie przy uruchamianiu odpowiedniego security.policy)?

0

No i widzisz, to trochę rozjaśnia sytuację. Albo wywal te wywołania SecurityManagera bo i tak odpalasz to póki co na localhoście i są niepotrzebne. Albo stwórz sobie pliki client.policy i server.policy:

grant {
	permission java.security.AllPermission;
};

(wiem wiem, samo zło :P)
I przy uruchamianiu serwera/klienta podawaj:

java -Djava.security.policy=client.policy Klient
0

Ok próbowałem, próbowałem i doszedłem do tego, że aby jak odpalam tylko RMIImplementacja to wszystko działa i wyświetla mi się:

this address=Szymon-Komputer/192.168.1.17,port=1099

gdy próbuję puścić RMItest wyrzuca mi coś takiego:

Exception in thread "main" java.lang.AbstractMethodError: RMIImplementacja_Stub.pokazNapis()V at RMItest.main(RMItest.java:23)

I gdy wszystko wyłączam i chce jeszcze raz odpalić RMIImplementacja to wtedy wywala coś takiego:

this address=Szymon-Komputer/192.168.1.17,port=1099
Exception in thread "main" java.rmi.server.ExportException: Port already in use: 1099; nested exception is:
java.net.BindException: Address already in use: JVM_Bind
at sun.rmi.transport.tcp.TCPTransport.listen(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.exportObject(Unknown Source)
at sun.rmi.transport.tcp.TCPEndpoint.exportObject(Unknown Source)
at sun.rmi.transport.LiveRef.exportObject(Unknown Source)
at sun.rmi.server.UnicastServerRef.exportObject(Unknown Source)
at sun.rmi.registry.RegistryImpl.setup(Unknown Source)
at sun.rmi.registry.RegistryImpl.<init>(Unknown Source)
at java.rmi.registry.LocateRegistry.createRegistry(Unknown Source)
at RMIImplementacja.<init>(RMIImplementacja.java:21)
at RMIImplementacja.main(RMIImplementacja.java:33)
Caused by: java.net.BindException: Address already in use: JVM_Bind
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(Unknown Source)
at java.net.ServerSocket.bind(Unknown Source)
at java.net.ServerSocket.<init>(Unknown Source)
at java.net.ServerSocket.<init>(Unknown Source)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createServerSocket(Unknown Source)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createServerSocket(Unknown Source)
at sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(Unknown Source)
... 10 more

0

W takim razie moze rmiregistry masz już uruchomione po prostu? Jeśli tak to zamiast

Registry rejestr = LocateRegistry.createRegistry(port);

Rób locateRegistry() tak jak masz w kliencie. Inaczej rmiregistry próbuje startować na defaultowym porcie 1099 i nie moze bo juz coś tam stoi.

0

(zaznaczam ze pracuje na eclipsie chciałbym to zrobić bez konsoli) przed chwila udało mi się coś zrobić w konsoli odpalając klasę RMItest w oknie konsoli gdzie miałem odpalony RMIImplemetacja wyświetlił się wynik działania funkcji pokażNapis() i teraz czy da rade zrobić to z poziomu eclipse?

Tak działa w Eclipse:
A wiec tak w klasie implementującej zrobiłem tak i dalej działa ale jak chce uruchomić RMItest(czyli klient) to wywala:

Błąd:
Exception in thread "main" java.lang.AbstractMethodError: RMIImplementacja_Stub.pokazNapis()V
at RMItest.main(RMItest.java:23)

Klasa:

public class RMIImplementacja extends UnicastRemoteObject implements RMIInterface{
	
	String adres;
	int port =1099;
	
	public RMIImplementacja() throws RemoteException, UnknownHostException{
		super();
		String nazwa="RMIInterface";
		adres=(InetAddress.getLocalHost()).toString();
		System.out.println("this address="+adres+",port="+port);
	 
	 Registry rejestr = LocateRegistry.getRegistry(port);
	 rejestr.rebind(nazwa, this);
	
	 }
	 
	public void pokazNapis() throws RemoteException {
		String napis = "Test tego gowna";
		System.out.println(napis);
	}
	
	public static void main(String[] args) throws RemoteException, AlreadyBoundException, UnknownHostException{
		
		RMIImplementacja serv=new RMIImplementacja();
	
}
}
0

To co wkleiłeś działa. Uprosciłem sobie to do wersji:

import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMItest {

    public static void main(String[] args) throws RemoteException, java.net.MalformedURLException, java.rmi.NotBoundException,
            UnknownHostException {
        Registry rejestr;
        String adres = ("localhost");
        RMIInterface zmienna;
        rejestr = LocateRegistry.getRegistry(adres);
        zmienna = (RMIInterface) (rejestr.lookup("RMIInterface"));
        zmienna.pokazNapis();
    }

}
import java.net.UnknownHostException;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class RMIImplementacja extends UnicastRemoteObject implements RMIInterface {

    String adres;

    public RMIImplementacja() throws RemoteException, UnknownHostException {
        super();
        String nazwa = "RMIInterface";
        Registry rejestr = LocateRegistry.getRegistry();
        rejestr.rebind(nazwa, this);
    }

    @Override
    public void pokazNapis() throws RemoteException {
        String napis = "Test tego gowna";
        System.out.println(napis);
    }

    public static void main(String[] args) throws RemoteException, AlreadyBoundException, UnknownHostException {

        RMIImplementacja serv = new RMIImplementacja();
    }
}

I działa. Przy czym oczywiście rmiregistry uruchamiam z katalogu bin w którym mam pliki .class (inaczej musiałbym się bawić w ustawianie -Djava.rmi.server.codebase=...)

0

Ehh z poziomu eclipsa dalej mi nie działa :-( i niestety coś tam z konsola działa. Ok próbuje przejść do następnego etapu mojego programu będzie się on składał z kilku okienek OknoKlienta, OknoAdministratora, OknoDodawania, OknoLogowania, OknoDodawaniaKonta. I trafiłem na następny problem OknoLogowania działa dobrze a OknoAdministratora już nie bardzo. Chodzi o to że pokazuje stare dane w tabeli :-( OknoAdministratora działa dobrze dopiero jak utworze nowy obiekt klasy OknoAdministratora w ClientRMI. W SerwerRMI jest dwuwymiarowa tablica i tam gdzie jest "zzzzz" pokazuje mi starą wartość "Gruszka" Proszę o pomoc.

Klasa ClientRMI:

import java.net.UnknownHostException;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;


public class ClientRMI {
	
	public static void main(String[] args)throws RemoteException,
	  java.net.MalformedURLException, java.rmi.NotBoundException, UnknownHostException {
		
		
		Registry rejestr;
		int port =1099;
		String adres=("192.168.1.17");
		RMIInterface zmienna;
		
		rejestr=LocateRegistry.getRegistry(adres,port);
		zmienna = (RMIInterface)(rejestr.lookup("RMIInterface"));
		
		OknoLogowania okno1 = new OknoLogowania();
		//OknoAdmina ad = new OknoAdmina();
		//ad.pokazOknoAdmina();
}

} 

Klasa SerwerRMI:

 
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;


public class SerwerRMI extends UnicastRemoteObject implements RMIInterface{
	
	String adres;
	int port =1099;
	
	public String[] kolumny={"ID","Nazwa","Producent","Ilosc"};
	public Object[][] dane = {
			{"1","Duszki","Hogath",new Integer(4)},
			{"2","ZZZZZ","Dumbli",new Integer(6)},
	};
	
	public SerwerRMI() throws RemoteException, UnknownHostException{
		super();
		String nazwa="RMIInterface";
		adres=(InetAddress.getLocalHost()).toString();
		System.out.println("this address="+adres+",port="+port);
	 
	 Registry rejestr = LocateRegistry.createRegistry(port);
	 rejestr.rebind(nazwa, this);
	
	 }
	public Object[][] zwrocDane()throws RemoteException {
		
		return dane;
	}
	
public String[] zwrocKolumny()throws RemoteException {
		
		return kolumny;
	}

	
	
	public static void main(String[] args) throws RemoteException, AlreadyBoundException, UnknownHostException{
		
		SerwerRMI serv=new SerwerRMI();
	
}

}

Klasa OknoAdmina:

 
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class OknoAdmina extends JFrame implements ActionListener{
	
	
	
	private JButton pokaz=new JButton("Pokaz produkty");
	private JButton dodaj=new JButton("Dodaj");
	private JButton pokazZamowienia=new JButton("Pokaż zamówienia");
	private JButton wyjdz=new JButton("Wyjdz z programu");
	
	private JTable tabela;
	private JScrollPane suwak;
	

	
	public OknoAdmina() throws RemoteException, NotBoundException{
	
	Registry rejestr;
	int port =1099;
	String adres=("192.168.1.17");
	RMIInterface zmienna;
	
	
	rejestr=LocateRegistry.getRegistry(adres,port);
	zmienna = (RMIInterface)(rejestr.lookup("RMIInterface"));
	tabela=new JTable(zmienna.zwrocDane(),zmienna.zwrocKolumny());
	suwak = new JScrollPane(tabela);
	}
	
	@Override
	public void actionPerformed(ActionEvent zdarzenie) {
	    String nazwa = zdarzenie.getActionCommand();
	    if (nazwa=="Dodaj") new OknoDodawania();
	    else if(nazwa=="Wyjdz z programu") System.exit(1);
	}
	
	public void pokazOknoAdmina()
	{
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(600,600);
		setTitle("Okno administratora");
		setLayout(null);
		setVisible(true);
		
		
		pokaz.setSize(150,30);
		pokaz.setLocation(30, 50);
		
		dodaj.setSize(150, 30);
		dodaj.setLocation(30,100);
		dodaj.addActionListener(this);
		
		wyjdz.setSize(150, 30);
		wyjdz.setLocation(30,200);
		wyjdz.addActionListener(this);
		
		pokazZamowienia.setSize(150,30);
		pokazZamowienia.setLocation(30,150);
		
		suwak.setSize(300, 400);
		suwak.setLocation(230, 50);
		tabela.setBackground(new Color(0,252,255));
	
		add(pokaz);
		add(dodaj);
		add(pokazZamowienia);
		add(wyjdz);
		add(suwak);	
	}
	
}

0

Napisałem to już kilka razy w tym temacie. ZASADA JEDNEJ ODPOWIEDZIALNOŚCI. Przeczytaj ją, zrozum i stosuj. NIE możesz mieszać sobie pewnych elementów kodu bo NIGDY nie dojdziesz do tego co nie działa. Skoro masz klasę odpowiedzialną za okienko to ona jest odpowiedzialna TYLKO ZA TO. W szczególności NIE zajmuje się zabawą z RMI.

Ad pytania: mam nadzieję że nie chodzi ci o to że zwracasz sobie to Object[][], zmieniasz w nim coś i się dziwisz ze na serwerze się nie zmieniło, bo jeśli o to pytasz to myśle że czas odstawić javę i rmi i iść polepić sobie jakiś czas z plasteliny. NAJPIERW musisz zrozumieć jak to działa, a POTEM dopiero mozesz się zabierać za pisanie w tym czegoś. W drugą stronę się nie da.

1 użytkowników online, w tym zalogowanych: 0, gości: 1