0

So I'm trying to send an Object from a client to the server and then I do something with this object. I verified that when being sent the object contains data. When I'm in the debugger reading my object all of its properties are null.

Below is where I send the object:

private class registerUser extends Task<Void>
{
        Users user;
        private static final String code = ".register";
        private static final String host = "localhost";
        private static final int portNumber = 4444;
        private clientThread clientThread;


    public registerUser(Users user)
    {
        this.user = user;
    }

    @Override
    protected Void call() throws Exception
    {
        try
        {
            Socket socket = new Socket(host, portNumber);
            Thread.sleep(1000);

            //Setup I/O
            ObjectOutputStream outToServerObject = new ObjectOutputStream(socket.getOutputStream());
            //PrintWriter serverOutString = new PrintWriter(socket.getOutputStream(), false);
            InputStream serverInString = socket.getInputStream();

            //serverOutString.println(code);
           // serverOutString.flush();

            outToServerObject.writeObject(user);
            outToServerObject.flush();
        }
        catch (IOException e)
        {
            System.err.println("Fatal Connection error!");
            e.printStackTrace();
        }
        return null;
    }

The above task is then used when I press a button in my GUI as shown below:

public void btn_registerUser(ActionEvent actionEvent) throws IOException
{

        user.setUserName(txt_Username.getText());
        user.setFirstName(txt_FirstName.getText());
        user.setLastName(txt_LastName.getText());
        user.setCity(txt_City.getText());
        user.setBirthday(date_Birthday.getValue());


        Task<Void> task = new registerUser(user);
        Thread thread = new Thread(task);
        thread.setDaemon(true);
        thread.start();

}

The code in the server where object is received:

//Setup I/O
this.clientOut = new PrintWriter(socket.getOutputStream(), false);
ObjectInputStream inFromClientObject = new ObjectInputStream(socket.getInputStream());


// Scanner in = new Scanner(socket.getInputStream());
Users user = (Users) inFromClientObject.readObject();
doSomething(user);

And the User.java class which is the object at debate

public class Users implements Serializable
{

    /*
    Variables
    TODO Create a friend list
    */
    private transient IntegerProperty userID;
    private transient StringProperty userName;
    private transient StringProperty firstName;
    private transient StringProperty lastName;
    private transient StringProperty city;
    private transient ObjectProperty<LocalDate> birthday;
    private transient ListProperty<String> musicGenre;
    private transient List<String> musicGenres = new ArrayList<>();
    /**
     * Default constructor.
     */
    public Users()
    {
        this(null,null,null,null,null);
    }

    /**
     * Constructor with some initial data.
     * Takes in a {@code String} and sets a reference
     *
     * @param userName
     *
     */
    public Users(String userName,  String firstName, String lastName, String city, LocalDate birthday)
    {
        this.userName = new SimpleStringProperty(userName);
        this.userID = new SimpleIntegerProperty();
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);
        this.city = new SimpleStringProperty(city);
        this.birthday = new SimpleObjectProperty<LocalDate>(birthday);
        ObservableList<String> observableList = FXCollections.observableArrayList(this.musicGenres);
        this.musicGenre = new SimpleListProperty<String>(observableList);

    }
}

I've left out the getters and setters as this questions is getting long already

So in the debugger when running the server all the properties of the user are null when I doSomething(user)

*EDIT The suggestions are working out but I've gotten a problem with

private List<String> musicGenreList = new ArrayList<>();
ObservableList<String> observableList = FXCollections.observableArrayList(musicGenreList);
private ListProperty<String> musicGenre = new SimpleListProperty<String>(observableList);

It's the only way I can add items to the ListProperty but the observableList can't be serialized

Lucky38i
  • 125
  • 1
  • 16
  • 2
    `transient` means "don't serialize this value". So this is doing exactly what you expect. JavaFX properties and collections are not serializable, and you really only want to serialize their values. To do this, you need to implement custom serialization. See https://stackoverflow.com/questions/33452847/using-pojos-as-model-layer-in-javafx-application or https://stackoverflow.com/questions/23187989/using-javafx-beans-properties-in-model-classes – James_D Mar 16 '18 at 19:38
  • You could also use so-called DTO object with properties of usual types like `String`, `Integer` and so on which are serializable. And then you convert your `User` object into `UserDTO`, serialize that DTO, send it, deserialize, construct `Users` object from `UserDTO` and use it on another machine. – Ivan Mar 16 '18 at 19:49
  • Or, say, stream JSON. As long as the `get` and `set` methods are named the same way, you could serialize an object using JavaFX properties and deserialize it into an object representing the same values as regular JavaBean properties, and vice-versa. – James_D Mar 16 '18 at 20:09
  • @James_D This is working out pretty well except for my listProperty, I implemented it by creating an arrayList then attaching that an FXCollection observable arraylist. Then I created a new ListProperty as a `new SimpleListProperty(observableList);`. Of course this can be serialised but its the only way for me to add items to the list. any ideas? – Lucky38i Mar 17 '18 at 11:44

1 Answers1

1

Like James_D said basically I have to create custom WriteExternal and ReadExternal

in the Users.java The changes need to be made

public class Users implements Externalizable
{
    public Users(String userName,  String firstName, String lastName, String city, LocalDate birthday)
    {
        setUserName(userName);
        setFirstName(firstName);
        setBirthday(birthday);
    }

    private IntegerProperty userID = new SimpleIntegerProperty(this, "id");
    private StringProperty userName = new SimpleStringProperty(this, "userName');
    private ObjectProperty<LocalDate> birthday = new SimpleObjectProperty<>(this, "birthday");

    //Create setters and getters...

    @Override
    public void writeExternal(ObjectOutput out) throws IOException
    {
        out.writeInt(getUserID());
        out.writeObject(getUserName());
        out.writeObject(getBirthday());
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
    {
        setUserID((int) in.readInteger());
        setUserName((String) in.readObject());
        setBirthday((LocalDate) in.readObject());
    }
}

However I haven't been able to serialize a ListProperty using the below method

private ObservableList<String> observableList = FXCollections.observableArrayList();
private ListProperty<String> newList = new SimpleListProperty<>(this, "musicGenre", observableList);

For my needs the ListProperty needs to be instantiated this way as I need to add String items to it using user.newListProperty().get().add("String") and without the ObservableList I can't do this

If anyone knows a way around this it'd be appreciated

Lucky38i
  • 125
  • 1
  • 16