Avatar billede nzc Nybegynder
07. maj 2003 - 09:13 Der er 12 kommentarer og
1 løsning

Send object via RMI

Hej!

Jeg skal sende et object fra en klient til en server via RMI. Jeg har kigget lidt på tingene og fundet ud af at man skal serialize sine objecter for at kunne sende dem. Jeg har også fundet ud af at man kan sende objecter vha. en ObjectOutputStream og modtage vha. en ObjectInputStream. Men for at oprette en sådan ObjectOutputStream skal jeg bruge en OutputStream altså noget fra en socket.

Findes der en anden måde at sende objecter via RMI eller kan man fikse det med ObjectOutputStream?

On forhand fanx

NZC
Avatar billede arne_v Ekspert
07. maj 2003 - 11:27 #1
Øh.

RMI laver selv serialiseringem for dig.

Du lookup'er din stub og kalder metoden som om det var en lokal metode,
så sørger stub'en for at serialisere og deserialisere.
Avatar billede arne_v Ekspert
07. maj 2003 - 11:29 #2
Et lille eksempel:

Test.java = interface
---------------------

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

public interface Test extends Remote {
  public String test(String s) throws RemoteException;
}

TestImpl.java = implementation (og server)
------------------------------------------

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class TestImpl extends UnicastRemoteObject implements Test {
  public TestImpl() throws RemoteException {
  }
  public String test(String s) {
      return (s + s);
  }
  public static void main(String[] args) {
      try {
        Naming.rebind("test", new TestImpl());
      } catch (RemoteException e) {
        e.printStackTrace();
      } catch (MalformedURLException e) {
        e.printStackTrace();
      }
  }
}

TestTest.java = test client
---------------------------

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class TestTest {
  public static void main(String[] args) {
      try {
        Test t = (Test) Naming.lookup("test");
        System.out.println(t.test("a"));
        System.out.println(t.test("bb"));
        System.out.println(t.test("ccc"));
      } catch (MalformedURLException e) {
        e.printStackTrace();
      } catch (RemoteException e) {
        e.printStackTrace();
      } catch (NotBoundException e) {
        e.printStackTrace();
      }
  }
}


build.bat = build på windows
-----------------------------

javac *.java
rmic TestImpl
start rmiregistry
start java TestImpl
pause
java TestTest
Avatar billede arne_v Ekspert
07. maj 2003 - 11:30 #3
Argumentet til test metoden er en String og det samme er resulatet.

Men det er ikke nødvendigt med eksplicit serialisation.
Avatar billede nzc Nybegynder
07. maj 2003 - 12:19 #4
jeg tror du har misforstået mig :)

Jeg ved godt at man laver lookup og kan så kalde metoder på objektet som lå det lokalt. Det er ikke det jeg vil :) Jeg vil gerne sendet et objekt til serveren som så skal stoppe objektet ned i en database. Altså

klient skal sende object til server
server stopper objektet ned i database

og mange tak for det udførlige svar :)

NZC
Avatar billede arne_v Ekspert
07. maj 2003 - 12:26 #5
Hvis du vil sende et vilkårligt objekt over RMI så laver du bare en
metode i interfacet der hedder:

void gemDatabase(Object o);

den kan du kalde med hvad som helst og RMI sørger stadig for serialiseringen.

Men jeg tror at jeg begynder at forstå hvor du vil hen. Du vil på
server siden eksplicit serialisere og gemme det serialiserede i
en database ?
Avatar billede arne_v Ekspert
07. maj 2003 - 12:28 #6
Hvis det er rigtigt så vil du nok finde følgende lille eksempel
interessant:

import java.util.*;
import java.io.*;
import java.net.*;

public class SerializeToString {
    public static void main(String[] args) throws Exception {
        Vector v = new Vector();
        v.add(0,new Integer(123));
        v.add(1,new String("abc"));
        String s = encode(v);
        Vector v2 = (Vector)decode(s);
        System.out.println((Integer)v2.get(0));
        System.out.println((String)v2.get(1));
    }
    private static String encode(Object o) throws Exception {
        ByteArrayOutputStream ba = new ByteArrayOutputStream(1000);
        ObjectOutputStream oba = new ObjectOutputStream(ba);
        oba.writeObject(o);
        return hexify(ba.toByteArray());
    }
    private static Object decode(String s) throws Exception {
        ByteArrayInputStream ba = new ByteArrayInputStream(dehexify(s));
        ObjectInputStream oba = new ObjectInputStream(ba);
        return oba.readObject();
    }
    private final static String hexValue[] = { "0", "1", "2", "3",
        "4", "5", "6", "7",
        "8", "9", "A", "B",
        "C", "D", "E", "F"};
    private static String hexify(byte[] ba) {
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < ba.length; i++) {
          sb.append(hexValue[(ba[i] >> 4) & 0x0F]);
          sb.append(hexValue[ba[i] & 0x0F]);
        }
        return sb.toString();
    }
    private static byte[] dehexify(String s) {
        int l = s.length() / 2;
        byte[] res = new byte[l];
        for(int i = 0; i < l; i++) {
          res[i] = (byte)Integer.parseInt(s.substring(2*i, 2*i+2), 16);
        }
        return res;
    }
}
Avatar billede nzc Nybegynder
07. maj 2003 - 12:29 #7
hehe nu forstår jeg ikke dig :)

hvad mener du med "Du vil på
server siden eksplicit serialisere og gemme det serialiserede i
en database ?"

Jeg vil sende et objekt fra klienten til serveren og serveren skal så gemme objektet i en db :) Det er sikkert det samme du mener, men vil bare lige være sikker :)

NZC
Avatar billede arne_v Ekspert
07. maj 2003 - 12:31 #8
Det konverterer mellem et vilkårligt objekt og en printable streng.

Hvis du godt kan bruge noget binært så kan du nøjes med:

    private byte[] String encode(Object o) throws Exception {
        ByteArrayOutputStream ba = new ByteArrayOutputStream(1000);
        ObjectOutputStream oba = new ObjectOutputStream(ba);
        oba.writeObject(o);
        return ba.toByteArray();
    }
    private static Object decode(byte[] b) throws Exception {
        ByteArrayInputStream ba = new ByteArrayInputStream(b);
        ObjectInputStream oba = new ObjectInputStream(ba);
        return oba.readObject();
    }
Avatar billede arne_v Ekspert
07. maj 2003 - 12:32 #9
Jeg tror vi er enige.

Servern står med et objekt der skal gemmes i databasen. Det kommer rent
faktisk fra klienten via RMI, men det er "liggyldigt" - serveren skal
bare gemme et objekt og derfor skal du have det serialiseret, så du
kan putte det ned i databasen.

I så fald så se noget af koden ovenfor.
Avatar billede nzc Nybegynder
07. maj 2003 - 12:36 #10
ok godt :)

det vil altså sige at jeg serialiserer objektet og laver en metode der hedder gem(Object o) som så ligger i server interfacet? Eller skal jeg i gang med noget med en ObjectOutputStream og input ?

igen mange tak :)

NZC
Avatar billede arne_v Ekspert
07. maj 2003 - 12:43 #11
Ja - jeg synes at du skal lave en gem(Object o) metode, når nu du er
igang med RMI.

ObjectOutputStream er helt fin men så skifter du fra RMI til
en socket client-server applikation.

[og formentlig bruger RMI ObjectOutputStream alligevel]
Avatar billede nzc Nybegynder
07. maj 2003 - 13:00 #12
Jeg skal liiiiige for at få det helt klart... :)

Jeg laver et server interface der indeholder

public void gem(Object o)

på klienten initialiserer jeg et objekt af typen serverinterface (si) og kalder

si.gem(etellerandetobjekt)

og så går det helt automatisk med at sende objektet. Der er ingen grund til at serializere objektet der skal sendes for det står RMI for.

Håber jeg har forstået det rigtigt :)

Og mange tak for de gode svar :)
Avatar billede arne_v Ekspert
07. maj 2003 - 13:08 #13
Det er korrekt.

RMI compileren generere noget kod etil både client (kaldet stub) og
server (kaldet skeleton).

Den genererede stub kode laver en serialisering og skeleton laver
en deserialisering så din implementations kode på server side
bliver kaldt med det samme objekt som din client kode kaldte med.

Det er hele pointen i RMI at man ikke skal bekymre sig om alle de
trivielle ting såsom serialisering/deserialisering.

Eksplicit serialisering er noget man skal bruge hvis man bruger sockets -
elle rhvis man vil skrive det serialiserede til en fil eller en
database til senere brug.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester