2016-02-17 5 views
1

Je commence juste à apprendre RMI et JFrame et j'ai été bloqué sur une exception pour un peu. J'écris une interaction client/serveur qui va accéder aux informations de stock de la base de données de Yahoo.Java RMI Exception Error

Voici mon code:

package stockquote; 

public class StockQuote{ 

    public double currentPrice, priceChange, dailyLow, dailyHigh; 

    public StockQuote(double price, double change, double low, double high){ 
     currentPrice = price; 
     priceChange = change; 
     dailyLow = low; 
     dailyHigh = high; 
    } 

    public StockQuote(){ 
     currentPrice = 0; 
     priceChange = 0; 
     dailyLow = 0; 
     dailyHigh = 0; 
    } 
} 



package stockquote; 

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

public interface StockQuoteInterface extends Remote{ 
    public StockQuote getQuote(String symbol) throws RemoteException; 
} 



package stockquote; 

import java.rmi.*; 
import java.rmi.registry.*; 
import java.rmi.server.UnicastRemoteObject; 

import java.io.*; 
import java.util.Properties; 
import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.net.URLConnection; 
import java.rmi.RemoteException; 
import java.util.*; 

public class StockQuoteServer implements StockQuoteInterface{ 

    public StockQuote getQuote(String symbol) throws RemoteException{ 

     StockQuote information = new StockQuote(); 

     try{ 
      URL url = new URL("http://download.finance.yahoo.com/d/quotes.csv?s=" + symbol + "&f=l1c1hg"); 
      URLConnection conn = url.openConnection(); 
      BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
      String quoteString = in.readLine(); 
      in.close(); 

      String[] data = quoteString.split(","); 

      information.currentPrice = Double.parseDouble(data[0]); 
      information.priceChange = Double.parseDouble(data[1]); 
      information.dailyHigh = Double.parseDouble(data[2]); 
      information.dailyLow = Double.parseDouble(data[3]); 

     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

     return information; 
    } 

    public static void main(String[] args) throws Exception { 
     try { 
      StockQuoteServer obj = new StockQuoteServer(); 
      StockQuoteInterface stub = (StockQuoteInterface) UnicastRemoteObject.exportObject(obj, 0); 

      Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT); 

      registry.rebind("StockQuoteServer", stub); 
      System.err.println("StockQuote Server is running."); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 



package stockquote; 

import javax.swing.*; 

import java.awt.*; 
import java.awt.event.*; 
import java.rmi.*; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.registry.Registry; 
import java.util.*; 

public class StockQuoteClient extends JFrame implements ActionListener{ 
    private static final long serialVersionUID = 1L; 

    private static StockQuoteInterface stockQuote; 

    private JTextField symbolField = new JTextField(10); 
    private JTextField currentPriceField = new JTextField(10); 
    private JTextField priceChangeField = new JTextField(10); 
    private JTextField dailyHighField = new JTextField(10); 
    private JTextField dailyLowField = new JTextField(10); 
    private JButton lookup = new JButton("Lookup"); 

    public StockQuoteClient() throws RemoteException{ 

     try { 
      Registry registry = LocateRegistry.getRegistry("localhost"); 
      stockQuote = (StockQuoteInterface) registry.lookup("StockQuoteServer"); 

     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(0); 
     } 

     this.setLayout(new GridLayout(0,1)); 
     JPanel symbolPanel = new JPanel(); 
     symbolPanel.add(new JLabel("Stock Symbol: ")); 
     symbolPanel.add(symbolField); 
     this.add(symbolPanel); 

     this.setLayout(new GridLayout(0,1)); 
     JPanel fieldsPanel = new JPanel(); 
     fieldsPanel.add(new JLabel("Current Price: ")); 
     fieldsPanel.add(currentPriceField); 
     fieldsPanel.add(new JLabel("Price Change: ")); 
     fieldsPanel.add(priceChangeField); 
     fieldsPanel.add(new JLabel("Daily High: ")); 
     fieldsPanel.add(dailyHighField); 
     fieldsPanel.add(new JLabel("Daily Low: ")); 
     fieldsPanel.add(dailyLowField); 
     this.add(fieldsPanel); 

     JPanel lookupButtonPanel = new JPanel(); 
     lookupButtonPanel.add(lookup); 
     this.add(lookupButtonPanel); 

     lookup.addActionListener(this); 

     this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     this.setSize(240, 350); 
     this.setVisible(true); 

    } 

    public void actionPerformed(ActionEvent e){ 
     StockQuote quoteInfo = new StockQuote(); 

     Object source = e.getSource(); 

     try{ 
      if(source == lookup){ 
       String symbol = symbolField.getText().trim(); 
       quoteInfo = stockQuote.getQuote(symbol); 
       if(quoteInfo.currentPrice == 0.0){ 
        currentPriceField.setText("Error"); 
        priceChangeField.setText("Error"); 
        dailyHighField.setText("Error"); 
        dailyLowField.setText("Error"); 
       }else{ 
        currentPriceField.setText(Double.toString(quoteInfo.currentPrice)); 
        priceChangeField.setText(Double.toString(quoteInfo.priceChange)); 
        dailyHighField.setText(Double.toString(quoteInfo.dailyHigh)); 
        dailyLowField.setText(Double.toString(quoteInfo.dailyLow)); 
       } 
      } 
     }catch(RemoteException ex){ 
      ex.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) throws RemoteException{ 
     /*StockQuote ggg = new StockQuote(); 

     Scanner keyboard = new Scanner(System.in); 
     System.out.println("Enter a symbol: "); 
     String symbol = keyboard.nextLine(); 

     ggg = stockQuote.getQuote(symbol); 

     System.out.println(ggg.currentPrice);*/ 
     new StockQuoteClient(); 
    } 

} 

Et voici l'exception que je reçois.

Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: stockquote.StockQuote 
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 com.sun.proxy.$Proxy0.getQuote(Unknown Source) 
at stockquote.StockQuoteClient.main(StockQuoteClient.java:101) 
Caused by: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: stockquote.StockQuote 
at java.io.ObjectInputStream.readObject0(Unknown Source) 
at java.io.ObjectInputStream.readObject(Unknown Source) 
at sun.rmi.server.UnicastRef.unmarshalValue(Unknown Source) 
... 5 more 
Caused by: java.io.NotSerializableException: stockquote.StockQuote 
at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
at java.io.ObjectOutputStream.writeObject(Unknown Source) 
at sun.rmi.server.UnicastRef.marshalValue(Unknown Source) 
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) 
at sun.rmi.transport.Transport$1.run(Unknown Source) 
at sun.rmi.transport.Transport$1.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at sun.rmi.transport.Transport.serviceCall(Unknown Source) 
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) 
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) 
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$256(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
at java.lang.Thread.run(Unknown Source) 

Répondre

1

La cause racine rapportée dans la trace de la pile est

java.io.NotSerializableException: stockquote.StockQuote

De toute évidence, vous avez une instance d'une classe nommée stockquote.StockQuote dans l'objet graphique d'un objet que vous essayez de sérialiser, mais cette classe n'est pas sérialisable. D'autres parties de la trace de la pile, il semble que la tentative de sérialisation est liée à une tentative d'invocation d'une méthode distante - RMI s'appuie sur la sérialisation Java pour fournir des arguments aux méthodes distantes et recevoir des valeurs de retour.

Il est certain que stockquote.StockQuote doit implémenter java.io.Serializable si vous souhaitez pouvoir transmettre ou renvoyer des instances sur RMI. Cela peut être suffisant ou non pour sérialiser les instances, en fonction des membres de la classe.

+0

Merci beaucoup pour votre aide, cela fonctionne correctement maintenant. Je ne sais pas pourquoi je n'ai pas vu ça. –

1

La pile de données vous indique exactement quelle est l'erreur. Vous devez créer StockQuote impement Serializable, car RMI utilise le mécanisme de sérialisation de Java pour transmettre des données (telles que les arguments de méthode et la valeur de retour) sur le réseau.

+0

Merci beaucoup pour votre aide, cela fonctionne correctement maintenant. Je ne sais pas pourquoi je n'ai pas vu ça. –