2017-04-06 4 views
0

LoginViewController 클래스에서 login 메소드를 호출 할 때 NullPointerException을 수신 할 때 NullPointerException이 발생합니다. 나는 toString을 사용하여 객체를 출력하기 때문에 사용자 객체가 null이 아니라는 것을 알고있다. LoginView.fxml에 클라이언트 및 사용자 클래스를 등록해야합니까? 구현하고자하는 것은 사용자가 로그인을 클릭 할 때 메서드는 서버에 User 객체를 보내는 새 Client를 인스턴스화해야한다는 것입니다.(JavaFX)

예외

User: Username Password 
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException 
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774) 
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49) 
    at javafx.event.Event.fireEvent(Event.java:198) 
    at javafx.scene.Node.fireEvent(Node.java:8411) 
    at javafx.scene.control.Button.fire(Button.java:185) 
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182) 
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96) 
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) 
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) 
    at javafx.event.Event.fireEvent(Event.java:198) 
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757) 
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) 
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) 
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415) 
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555) 
    at com.sun.glass.ui.View.notifyMouse(View.java:937) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at sun.reflect.misc.Trampoline.invoke(Unknown Source) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at sun.reflect.misc.MethodUtil.invoke(Unknown Source) 
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771) 
    ... 48 more 
Caused by: java.lang.NullPointerException 
    at dinnerTime.Client.sendToServer(Client.java:44) 
    at dinnerTime.LoginViewController.login(LoginViewController.java:34) 
    ... 58 more 

Main.java

package dinnerTime; 

import java.io.IOException; 
import javafx.application.Application; 
import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Scene; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class Main extends Application { 
    private Stage primaryStage; 
    private BorderPane mainLayout; 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     this.primaryStage = primaryStage; 
     showLoginView(); 
    } 

    private void showLoginView() throws IOException { 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Main.class.getResource("LoginView.fxml")); 
     mainLayout = loader.load(); 
     Scene scene = new Scene(mainLayout, 540, 400); 
     primaryStage.setScene(scene); 
     primaryStage.setResizable(false); 
     primaryStage.show(); 
    } 
} 

LoginViewController.java

package dinnerTime; 

import java.io.IOException; 
import java.net.URL; 
import java.util.ResourceBundle; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.control.Button; 
import javafx.scene.control.PasswordField; 
import javafx.scene.control.TextField; 

public class LoginViewController { 
    @FXML 
    private Main main; 
    @FXML 
    private TextField username; 
    @FXML 
    private PasswordField password; 
    @FXML 
    private Button login; 
    @FXML 
    private Button register; 

    private Client client; 

    private User user; 

    @FXML 
    public void login() throws IOException { 
     client = new Client("127.0.0.1", 3250); 
     client.start(); 
     user = new User(username.getText(), password.getText()); 
     System.out.println("User: " + user.toString()); 
     client.sendToServer(user); 
    } 
} 

LoginView.fxml

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.Button?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.PasswordField?> 
<?import javafx.scene.control.TextField?> 
<?import javafx.scene.image.Image?> 
<?import javafx.scene.image.ImageView?> 
<?import javafx.scene.layout.AnchorPane?> 
<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.text.Font?> 

<BorderPane prefHeight="400.0" prefWidth="540.0" xmlns="http://javafx.com/javafx/8.0.102" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dinnerTime.LoginViewController"> 
    <center> 
     <AnchorPane prefHeight="400.0" prefWidth="540.0" BorderPane.alignment="CENTER"> 
     <children> 
      <ImageView fitHeight="122.0" fitWidth="124.0" layoutX="238.0" layoutY="14.0" pickOnBounds="true" preserveRatio="true"> 
       <image> 
        <Image url="@../../images/dt-logo-original.png" /> 
       </image> 
      </ImageView> 
      <Label layoutX="14.0" layoutY="14.0" text="Dinner" textFill="#464646"> 
       <font> 
        <Font size="70.0" /> 
       </font> 
      </Label> 
      <Label layoutX="372.0" layoutY="14.0" text="Time" textFill="#464646"> 
       <font> 
        <Font size="70.0" /> 
       </font></Label> 
      <Label layoutX="91.0" layoutY="155.0" text="Username" /> 
      <TextField layoutX="164.0" layoutY="151.0" prefHeight="25.0" prefWidth="216.0" /> 
      <Label layoutX="91.0" layoutY="213.0" text="Password" /> 
      <PasswordField layoutX="164.0" layoutY="209.0" prefHeight="25.0" prefWidth="216.0" /> 
      <Button fx:id="login" layoutX="162.0" layoutY="271.0" mnemonicParsing="false" onAction="#login" prefHeight="59.0" prefWidth="216.0" text="Login" /> 
      <Button layoutX="242.0" layoutY="352.0" mnemonicParsing="false" text="Register" /> 
     </children> 
     </AnchorPane> 
    </center> 
</BorderPane> 
,745,

Client.java는

package dinnerTime; 

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

public class Client extends Thread { 
    private String ip; 
    private int port; 
    private Socket socket; 
    private ObjectOutputStream oos; 
    private ObjectInputStream ois; 

    public Client(String ip, int port) { 
     this.ip = ip; 
     this.port = port; 
    } 

    public void run() { 
     try { 
      socket = new Socket(ip, port); 
      oos = new ObjectOutputStream(socket.getOutputStream()); 
      oos.flush(); 
      ois = new ObjectInputStream(socket.getInputStream()); 

      while (true) { 
       try { 
        Object obj = ois.readObject(); 

        if (obj instanceof Recipe) { 

        } 


       } catch (IOException | ClassNotFoundException e) { 
       } 
      } 
     } catch (IOException e) { 
     } 
    } 

    public void sendToServer(Object obj) { 
     try { 
      oos.writeObject(obj); 
      oos.flush(); 
     } catch (IOException e) { 
     } 
    } 
} 

User.java

package dinnerTime; 

import java.io.Serializable; 

public class User implements Serializable { 
    private String name, password; 

    public User(String name, String password){ 
     this.name = name; 
     this.password = password; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String toString() { 
     return name + " " + password; 
    } 
} 
+1

가 왜'@의 FXML'와'Client'와'User' 주석 않습니다 : 한 가지 방법은 연결이 설정 될 때 실행하는 몇 가지 종류의 콜백을 제공하는 것입니다? 이러한 클래스는 노드가 아니며 FXML 파일이나 장면 그래프에 포함되지 않습니다. –

+0

나쁜데, 그들은 지금 제거됩니다. 여전히 같은 예외입니다. 어떤 아이디어? – Slamdunk

답변

0

당신은 클라이언트의 oos 필드에서 race condition 있습니다. 백그라운드 스레드에서 실행되는 run() 메서드에서 초기화하지만 컨트롤러의 login()에서 호출되고 FX 응용 프로그램 스레드에서 실행되는 sendToServer()에서 액세스하려고합니다. 이러한 서로 다른 스레드에 있기 때문에

먼저 실행됩니다하는지에 보장이 없다 : 어떤 일이 일어나고하면 백그라운드 스레드가 oos 초기화하고, 따라서 oos.writeObject(...)가 널 포인터 예외를 던지기 전에 sendToServer() 실행지고 있다는 점이다.

이 문제를 해결하려면 클라이언트가 완전히 연결될 때까지 sendToServer()으로 전화하지 않아야합니다.

public class Client extends Thread { 
    private String ip; 
    private int port; 
    private Socket socket; 
    private ObjectOutputStream oos; 
    private ObjectInputStream ois; 

    private Runnable onConnected ; 

    public void setOnConnected(Runnable onConnected) { 
     this.onConnected = onConnected ; 
    } 

    public Client(String ip, int port) { 
     this.ip = ip; 
     this.port = port; 
    } 

    public void run() { 
     try { 
      socket = new Socket(ip, port); 
      oos = new ObjectOutputStream(socket.getOutputStream()); 
      oos.flush(); 

      if (onConnected != null) { 
       onConnected.run(); 
      } 

      ois = new ObjectInputStream(socket.getInputStream()); 

      while (true) { 
       try { 
        Object obj = ois.readObject(); 

        if (obj instanceof Recipe) { 

        } 


       } catch (IOException | ClassNotFoundException e) { 
       } 
      } 
     } catch (IOException e) { 
     } 
    } 

    public void sendToServer(Object obj) { 
     try { 
      oos.writeObject(obj); 
      oos.flush(); 
     } catch (IOException e) { 
     } 
    } 
} 

다음

@FXML 
public void login() throws IOException { 
    client = new Client("127.0.0.1", 3250); 
    user = new User(username.getText(), password.getText()); 
    client.setOnConnected(() -> client.sendToServer(user)); 
    client.start(); 
}