Szybkie pytanie o RMI

0

Szybkie pytanie: w RMI aplikacja klienta wywołuje metodę na serwerze i serwer zwraca do klienta obiekt klasy DefaultTableModel (wykorzystywany do zapelnienia danymi tabeli Jtable w oknie JFrame aplikacji klienckiej)...Ten obiekt jest potem po stronie klienta wykorzystywany w taki sposob: Moja_tabela.setModel(nazwa_obiektu_klasy_Default_Table_Model_pobranej_z_serwera)...I po tym wszystkim tabela w aplikacji klienta ma byc wypelniana danymi - i jest...Ale gdy probuje kliknac na komorke, wyskakuje blad:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Connection.Pobranie_tabel$1.isCellEditable(Pobranie_tabel.java:61)
at javax.swing.JTable.isCellEditable(JTable.java:2687)
at javax.swing.JTable.editCellAt(JTable.java:3424)
at javax.swing.plaf.basic.BasicTableUI$Handler.adjustSelection(BasicTableUI.java:1084)
at javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(BasicTableUI.java:1014)
at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:263)
at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:262)
at java.awt.Component.processMouseEvent(Component.java:6038)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
at java.awt.Component.processEvent(Component.java:5806)
at java.awt.Container.processEvent(Container.java:2058)
at java.awt.Component.dispatchEventImpl(Component.java:4413)
at java.awt.Container.dispatchEventImpl(Container.java:2116)
at java.awt.Component.dispatchEvent(Component.java:4243)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3983)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
at java.awt.Container.dispatchEventImpl(Container.java:2102)
at java.awt.Window.dispatchEventImpl(Window.java:2440)
at java.awt.Component.dispatchEvent(Component.java:4243)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

Moje pytanie brzmi: czy przy przesyłaniu obiektów danej klasy przez RMI po stronie klienta również muszą znajdować się klasy, dzięki którym serwer stworzył obiekt i wysyła je do klienta? Bo gdzieś słyszałem, ze tak naprawde nie sa przesylane cale obiekty tylko ich stan i na kliencie tez musza byc te same klasy co na serwerze aby mozna bylo odtworzyc te obiekty po stronie klienta? Dobrze mowie czy nie?

0

Na serwerze i na kliencie musisz mieć te same klasy.

Dlaczego wysyłasz obiekt z pakietu swing? Nie łatwiej jest wysłać kolekcję obiektów biznesowych i po stronie klienta opakować to w tabelę? Przecież klient może nie lubić swinga i używać SWT lub web? Mało elastyczne to twoje rozwiązanie.

0

No ale dobra, przesyłam w taki sposób...Kod klasy, z której wywodzi sie przesyłany obiekt do klienta (obiekt metody Pobierz_model) wygląda tak:

package Connection;

import Classes.SerwerImpl;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

public class Pobranie_tabel implements Serializable
{
private JComboBox combo_sortowanie;
private String selectedItem;

public Pobranie_tabel(JComboBox combo) throws RemoteException
{
    combo_sortowanie=combo;
    //System.out.println("ddddd "+combo_sortowanie.getName().toString());
    combo_sortowanie.removeAllItems();
    System.out.println("Wychodze z konstruktora Pobranie_tabel");
}

public Pobranie_tabel() throws RemoteException
{

}


static String relacja;

public DefaultTableModel Pobierz_model(String zapytanie, String tableName) throws SQLException
{

    String query=zapytanie;
    relacja=new String(tableName);
    ResultSet rs = null;
    DefaultTableModel tModel=null;


    try
    {

// System.out.println("Wszedlem do metody pobierajacej model tabeli");
// Class.forName("org.firebirdsql.jdbc.FBDriver");
// System.out.println("Jestem po Class.forName");

       Connection conn=Polaczenie.ConnectionOpen("Kartoteka", "SYSDBA", "masterkey", "org.firebirdsql.jdbc.FBDriver", "jdbc:firebirdsql:*localhost:3050/");
</li> </ul>

// System.out.println("jestem po Connection");
rs = Polaczenie.conn.createStatement().executeQuery(query);
ResultSet rs1=Polaczenie.conn.createStatement().executeQuery("Select * from Pracownik where nazwisko='Walendziak'");
rs1.next();
System.out.println(rs1.getString(2));
ResultSetMetaData rsmd = rs.getMetaData();
int colCount = rsmd.getColumnCount();

        String[] colHeaders = new String[colCount];
        tModel = new DefaultTableModel()
        {
            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex)
            {
                if(relacja.equals("Stanowisko"))
                {
                    if(columnIndex==0) return false;
                }
                else if(relacja.equals("Dzial"))
                {
                    if(columnIndex==0) return false;
                }
                else if(relacja.equals("Pracownik"))
                {
                    if(columnIndex==0) return false;
                	if(columnIndex==1) return false;
                	if(columnIndex==2) return false;
                	if(columnIndex==3) return false;
                	if(columnIndex==4) return false;
                	if(columnIndex==5) return false;
                	if(columnIndex==6) return false;
                	if(columnIndex==7) return false;
                	if(columnIndex==8) return false;
                	if(columnIndex==9) return false;

                }
                else if(relacja.equals("L_godzin"))
                {
                    if(columnIndex==0) return false;
                    if(columnIndex==1) return false;
                }
                return true;
            }
        };

        for(int i=0;i<colCount;i++)
        {
            colHeaders[i] = rsmd.getColumnName(i+1);
            //combo_sortowanie.addItem(colHeaders[i]);
        }

        tModel.setColumnIdentifiers(colHeaders);

        while(rs.next())
        {
            Object[] obj = new Object[colCount];
            for(int i=0;i<colCount;i++)
            {
                obj[i] = rs.getObject(i+1);
            }

            tModel.addRow(obj);

        }


    }
    catch(Exception ex)
    {
        JOptionPane.showMessageDialog(null,"Nie mozna pobrac danych z bazy: "+ex.getMessage(),"ERROR", JOptionPane.ERROR_MESSAGE);
    }
    return tModel;


}

}

Gdy kliknę na jakąś komórkę to wywala bład, który pokazałem w mojej poprzedniej odpowiedzi (patrz wyżej)...Wygląda tak jakby nie do końca został odtworzony obiekt na kliencie...a implementacje Serializable dodałem, klasy sa zarowno po stronie serwera jak i klienta...Co jest nie tak? Bo rozumiem, że korzystanie z resultSet jest dobre, w sensie że nie muszę ResultSet zamieniać na żadne CachedRowSet?

0

Hmmyy, popatrz przeciez tmodel jest obiektem anonimowej klasy, w której przesłaniasz metody z DefaultTableModel, wydaje mi sie że tutaj właśnie leży błąd, program klienta nic nie wie o tej klasie anonimowej, bo nawet nie może wiedzieć, nie miałbyś tych wszystkich problemów jakbyś nie bawił się Swingiem na serwerze. Na przyszłość kod wstawiaj w znaczniku code...

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