JAVA - receiving objects using sockets and threads not working - java

I'm trying to get an object from the server, but it does not work.
Relevant section from the server (By Debug I see that he is really sending the correct object):
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage) {
BorderPane mainPane = new BorderPane();
mainPane.setStyle("-fx-border-color: black;");
mainPane.setPadding(new Insets(5,5,5,5));
GridPane gridPane = new GridPane();
gridPane.setPadding(new Insets(5,5,5,5));
gridPane.add(lblStatus,0,1);
gridPane.add(lblDate,0,2);
mainPane.setTop(gridPane);
createTableView();
mainPane.setCenter(tableView);
Scene scene = new Scene(mainPane, 700, 250);
primaryStage.setTitle("Server"); // Set the window title
primaryStage.setScene(scene); // Place the scene in the window
primaryStage.show(); // Display the window
primaryStage.setAlwaysOnTop(true);
primaryStage.setOnCloseRequest(
new EventHandler<WindowEvent>(){
public void handle(WindowEvent event) {
try {
Platform.exit();
System.exit(0);
serverSocket.close();
socket.close();
}
catch(SocketException ex){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch (IOException e) {
// TODO Auto-generated catch block
Platform.exit();
System.exit(0);
}
}
});
connectToDB();
connectionDate=new Date();
Platform.runLater(() ->lblDate.setText(("Server started at \t"+connectionDate)));
Platform.runLater(() ->lblStatus.setText(connectionStatus));
new Thread( () ->
{
try{
// Create a server socket
serverSocket = new ServerSocket(8000);
while (true){
// Listen for a connection request
socket = serverSocket.accept();
this.clientNo++;
clientRequest clientDetails = new clientRequest(clientNo, new Date(), "New Clinet");
addRowToServerTable(clientDetails);
new Thread(new HandleAClient(socket)).start();
}
}
catch(SocketException ex){
}
catch(IOException ex){
}
}).start();
}
/** Connect to DB */
private void connectToDB(){
// Connection to the database
try{
Class.forName(driver); // Load the JDBC driver
System.out.println("Driver Loaded");
connection = DriverManager.getConnection(url, username, password); // Establish a connection
System.out.println("Connected to " + url);
connectionStatus = "Connected to \t" + url;
}
catch (java.lang.Exception ex){
ex.printStackTrace();
connectionStatus = ex.toString();
}
}
// Define the thread class for handling new connection
class HandleAClient implements Runnable{
private Socket socket; // A connected socket
/** Construct a thread */
public HandleAClient(Socket socket){
this.socket = socket;
}
/** Run a thread */
public void run(){
try{
// Create data input and output streams
ObjectOutputStream outputToClient = new ObjectOutputStream(
socket.getOutputStream());
DataInputStream inputFromClient = new DataInputStream(
socket.getInputStream());
// Continuously serve the client
while (true){
// Receive sql from the client
String sql = inputFromClient.readUTF();
clientRequest clientDetails = new clientRequest(clientNo, new Date(),"New Query");
addRowToServerTable(clientDetails);
// Execute SQL
Object[] rows = executeSQL(sql);
outputToClient.writeObject(rows);
}
}
catch(SocketException ex){
try{
serverSocket.close();
//socket.close();
}
catch (IOException e){
}
}
catch(IOException ex){
}
}
Relevant section from the client (Probably the mistake on the client, when it receives the object he jumps line ".start ();" Of the Thread.):
private void connectToServer(){
try{
// Create a socket to connect to the server
socket = new Socket(host, 8000);
// Create an input stream to receive Object from the server
fromServer = new ObjectInputStream(socket.getInputStream());
// Create an output stream to send data to the server
toServer = new DataOutputStream(socket.getOutputStream());
}
catch (Exception ex){
ex.printStackTrace();
}
}
private void sendAndGetFromServer(String sqlQuery){
new Thread(() ->{
try{
System.out.println("a1");
// Send sql query to server
toServer.writeUTF(sqlQuery);
//toServer.flush();
// Get notification from the server
Student[] rows = (Student[])fromServer.readObject();
setRowsInTable(rows);
}
catch(SocketException ex){
try{
socket.close();
}
catch (IOException e){
}
}
catch (Exception ex){
}
}).start();
I tried to separate into two Thread (One Input and other Output in Server and client) according to the answers I read here --- but it didn't help.
Also tried to change the order of Input and Output --- without success.
No errors!
The client don't get the object.
What's the problem here?
Edit. Student class:
public class Student implements Externalizable
{
private final SimpleIntegerProperty ID;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty address;
private final SimpleObjectProperty<Date> birthDate;
private final SimpleStringProperty department;
private final SimpleIntegerProperty pointsAmount;
private final SimpleObjectProperty<Date> startStudyingDate;
private final SimpleIntegerProperty failedAmount;
private final SimpleDoubleProperty average;
private final SimpleIntegerProperty lavelByGrade;
private final SimpleStringProperty pic;
public Student(int ID, String firstName, String lastName, String address,
Date birthDate, String department,
int pointsAmount, Date startStudyingDate, int failedAmount,
double average, int lavelByGrade, String pic){
this.ID= new SimpleIntegerProperty(ID);
this.firstName= new SimpleStringProperty(firstName);
this.lastName= new SimpleStringProperty(lastName);
this.address= new SimpleStringProperty(address);
this.birthDate= new SimpleObjectProperty<Date>(birthDate);
this.department= new SimpleStringProperty(department);
this.pointsAmount= new SimpleIntegerProperty(pointsAmount);
this.startStudyingDate= new SimpleObjectProperty<Date>(startStudyingDate);
this.failedAmount= new SimpleIntegerProperty(failedAmount);
this.average= new SimpleDoubleProperty(average);
this.lavelByGrade= new SimpleIntegerProperty(lavelByGrade);
this.pic = new SimpleStringProperty(pic);
}
public int getID() {
return ID.get();
}
public void setID(int ID) {
this.ID.set(ID);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public String getAddress() {
return address.get();
}
public void setAddress(String address) {
this.address.set(address);
}
public Date getBirthDate() {
return birthDate.get();
}
public void setBirthDate(Date birthDate) {
this.birthDate.set(birthDate);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String department) {
this.department.set(department);
}
public int getPointsAmount() {
return pointsAmount.get();
}
public void setPointsAmount(int pointsAmount) {
this.pointsAmount.set(pointsAmount);
}
public Date getStartStudyingDate() {
return startStudyingDate.get();
}
public void setStartStudyingDate(Date startStudyingDate) {
this.startStudyingDate.set(startStudyingDate);
}
public int getFailedAmount() {
return failedAmount.get();
}
public void setFailedAmount(int failedAmount) {
this.failedAmount.set(failedAmount);
}
public double getAverage() {
return average.get();
}
public void setAverage(Double average) {
this.average.set(average);
}
public int getLavelByGrade() {
return lavelByGrade.get();
}
public void setLavelByGrade(int lavelByGrade) {
this.lavelByGrade.set(lavelByGrade);
}
public String getPic() {
return pic.get();
}
public void setPic(String pic) {
this.pic.set(pic);
}
#Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
setID(in.readInt());
setFirstName((String)in.readObject());
setLastName((String)in.readObject());
setAddress((String)in.readObject());
setBirthDate((Date)in.readObject());
setDepartment((String)in.readObject());
setPointsAmount(in.readInt());
setStartStudyingDate((Date)in.readObject());
setFailedAmount(in.readInt());
setAverage(in.readDouble());
setLavelByGrade(in.readInt());
setPic((String)in.readObject());
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getID());
out.writeObject(getFirstName());
out.writeObject(getLastName());
out.writeObject(getAddress());
out.writeObject(getBirthDate());
out.writeObject(getDepartment());
out.writeInt(getPointsAmount());
out.writeObject(getStartStudyingDate());
out.writeInt(getFailedAmount());
out.writeDouble(getAverage());
out.writeInt(getLavelByGrade());
out.writeObject(getPic());
}
}

JavaFX properties are not Serializable. So if you try to serialize an object that uses JavaFX properties for its state, you will get an exception.
You have a couple of options here. One is simply to not use Java object serialization, but some other serialization technique, such as representing the object with JSON.
The other option is to implement Externalizable instead of Serializable. Externalizable is a subinterface of Serializable in which you define your own process for serializing and deserializing the data. In particular, instead of serializing the JavaFX properties themselves, just serialize their contents.
A simple example:
import java.io.Externalizable ;
import java.io.IOException ;
import java.io.ObjectInput ;
import java.io.ObjectOutput ;
import javafx.beans.property.IntegerProperty ;
import javafx.beans.property.SimpleIntegerProperty ;
import javafx.beans.property.SimpleStringProperty ;
import javafx.beans.property.StringProperty ;
public class Person implements Externalizable {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty id = new SimpleIntegerProperty();
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
public IntegerProperty idProperty() {
return id ;
}
public final int getId() {
return idProperty().get();
}
public final void setId(int id) {
idProperty().set(id);
}
// important: must have a no-arg constructor:
public Person() { }
public Person(int id, String name) {
setId(id);
setName(name);
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
// write id then name
// note we write the contents of the properties, not the properties
// themselves, as the properties are not serializable:
out.writeInt(getId());
out.writeObject(getName());
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// read data back in same order:
setId(in.readInt());
setName((String)in.readObject());
}
}
Note that this class has a pretty simple structure, so it's easy to implement these two methods. For more complex objects - particularly those which may potentially have circular references - you need to work a bit harder.
Since the class defined above implements Externalizable, it also implements Serializable, and can be serialized in the usual way:
ObjectOutputStream oos = ... ;
oos.writeObject(new Person(007, "James Bond"));
Read my blog post on JavaFX beans and JPA for more.

Try with this post, search part with following text and Externalizable: For quite a long time, I thought the lack of support for Serialization from JavaFX properties really prevented them from being used in any server-side capacity.
http://www.marshall.edu/genomicjava/2014/05/09/one-bean-to-bind-them-all/
https://gist.github.com/james-d/e485ac525c71e20bb453

Related

Cannot deserialize a class only when sent by the server-to-client, works vice versa

The streams used to work, but suddenly just stopped two days ago, and I can't get it fixed.
The client creates and successfully sends a User object and a Message object (serialize by the client and deserialize by the server). When the clients receives any of the two classes (serialized by the server and deserialized by the client), I get exceptions, mainly:
java.io.UTFDataFormatException
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTFSpan(ObjectInputStream.java:3704)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3658)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:3458)
at java.base/java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1239)
at java.base/java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:804)
at java.base/java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:988)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2032)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1907)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2209)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
at Model.MessageClient$1.run(MessageClient.java:69)
at java.base/java.lang.Thread.run(Thread.java:833)
Every so often, I get:
java.io.InvalidClassException: Model.Message; class invalid for deserialization
at java.base/java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:174)
at java.base/java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:921)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2210)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
Client side - streams
public MessageClient(String ip, int port, String usernameStr, ImageIcon icon, Controller controller) {
this.user = new User(usernameStr, icon);
this.controller = controller;
this.port = port;
this.ip = ip;
this.messageBuffer = new Buffer<>();
this.contacts = new ArrayList<>(); //(ArrayList<Model.User>) readObjectFromFile("files/contacts");
setUpStreams();
setUpThreads();
}
public void setUpStreams(){
try {
s = new Socket(ip, port);
try {
ois = new ObjectInputStream(s.getInputStream());
oos = new ObjectOutputStream(s.getOutputStream());
oos.writeObject(user);
oos.flush();
users = new ArrayList<>();
setUpThreads();
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpThreads(){
t1 = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Object o = ois.readObject();
if (o.getClass().isAssignableFrom(Message.class)) {
receiveMessage((Message) o);
}
if (o.getClass().isAssignableFrom(ArrayList.class)) {
updateUsers((ArrayList<Model.User>) o);
}
} catch(EOFException e){
System.out.println("stopped");
t2.stop();
t1.stop();
} catch(IOException | ClassNotFoundException e){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}
}
}
});
t2 = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Message currMessage = messageBuffer.get();
oos.writeObject(currMessage);
oos.flush();
} catch(IOException | InterruptedException e){
e.printStackTrace();
}
}
}
});
t1.start();
t2.start();
}
Server-side streams
#Override
public synchronized void run() {
while (socket.isConnected() && !socket.isClosed()) {
try {
Object o = ois.readObject();
ih.addToBuffer((Model.Message) o);
} catch (EOFException e) {
try {
socket.close();
t2.stop();
t1.stop();
} catch (IOException ex) {
ex.printStackTrace();
}
} catch (IOException | ClassNotFoundException e) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
chm.put(user, null);
clients.remove(this);
sendAll(new Message(user.getUsername() + " has disconnected", null));
}
private class InputHandler implements Runnable{
private Buffer<Model.Message> inputBuffer;
public InputHandler(){
inputBuffer = new Buffer<>();
}
public void addToBuffer(Message msg){
inputBuffer.put(msg);
}
#Override
public synchronized void run() {
Object o = null;
while (!Thread.interrupted()) {
Message temp = null;
Message sendable = null;
try {
temp = inputBuffer.get();
sendable = new Message(temp.getText(), temp.getIcon(), temp.getRecipients(), temp.getSender());
sendable.setCurrID();
sendable.setUploaded(new Timestamp(System.currentTimeMillis()));
sendSelect(sendable ,sendable.getSender());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void sendSelect(Message msg, User selectedUser){
Client currClient;
if(!chm.containsKey(selectedUser)) {
try {
oos.writeObject(new Message(selectedUser.getUsername() + "not found", null));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
} else if ((currClient = chm.get(selectedUser)) != null) {
try {
currClient.oos.writeObject((Model.Message) msg);
currClient.oos.flush();
msg.setDownloaded(new Timestamp(System.currentTimeMillis()));
callback.downloadTimestamp(msg);
} catch (IOException e) {
e.printStackTrace();
}
} else {
addUnsent(selectedUser, msg);
}
}
The classes I serialized copy and pasted.
The classpath is the same, all fields are serializable and the have no-arg constructors. I also made sure both encoding on are set to UTF-8
Message
package Model;
import javax.swing.*;
import java.io.*;
import java.sql.Timestamp;
import java.util.LinkedList;
public class Message implements Serializable{
#Serial
private static final long serialVersionUID = -3930131856060689940L;
private static int nextID = 0;
private int currID;
private final String text;
private final ImageIcon icon;
private Timestamp uploaded;
private Timestamp downloaded;
private final User sender;
private final LinkedList<User> recipients;
public Message(){
currID = nextID;
nextID++;
this.text = null;
this.icon = null;
sender = null;
recipients = null;
}
public Message(String text, User sender){
currID = nextID;
nextID++;
this.text = text;
this.icon = null;
this.sender = sender;
this.recipients = null;
}
public Message(String text, ImageIcon icon, User sender) {
currID = nextID;
nextID++;
this.text = text;
this.icon = icon;
this.sender = sender;
this.recipients = null;
}
public Message(String text, ImageIcon icon, LinkedList<User> recipients, User sender) {
currID = nextID;
nextID++;
this.text = text;
this.icon = icon;
this.sender = sender;
this.recipients = recipients;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Message){
if( ((Message) obj).getCurrID() == this.currID ){
return true;
}
}
return false;
}
public String getText() {
return text;
}
public ImageIcon getIcon() {
return icon;
}
public Timestamp getUploaded() {
return uploaded;
}
public Timestamp getDownloaded() {
return downloaded;
}
public Model.User getSender(){return sender;}
public int getCurrID(){return currID;}
public void setCurrID(){currID = nextID; nextID++;}
public LinkedList<User> getRecipients(){
return recipients;
}
public void setUploaded(Timestamp uploaded) {
this.uploaded = uploaded;
}
public void setDownloaded(Timestamp downloaded) {
this.downloaded = downloaded;
}
}
User
package Model;
import javax.swing.*;
import java.io.Serial;
import java.io.Serializable;
public class User implements Serializable{
#Serial
private static final long serialVersionUID = -5886308724572898536L;
private String username;
private ImageIcon image;
public User(String username, ImageIcon image){
this.username = username;
this.image = image;
}
public int hashCode() {
return username.hashCode();
}
public boolean equals(Object obj) {
if(obj!=null && obj instanceof User)
return username.equals(((User)obj).getUsername());
return false;
}
public String getUsername() {
return username;
}
#Override
public String toString(){
return username;
}
}
The issue was I called setUpThread() twice, messing with the input stream. So if you get this kind of problem, make sure you don't initialize your threads (that are reading input stream from the sockets) more than once.

File operation problem with ObjectOutputStream/ObjectInputStream

I'm trying to write couple of object using ObjectOutputStream to a file. After that, I read the file with ObjectInputStream. The problem is, I can only read first object in the file. When I opened the file with notepad++, I can see the entries for other objects.
Here writer part
public class FileProcess {
private ObjectOutputStream output;
private Accounts account;
public FileProcess() {}
public void WriteObject(Accounts account) {
this.account = account;
openFile();
addRecords();
closeFile();
}
private void openFile() {
try {
output = new ObjectOutputStream(Files.newOutputStream(Paths.get("record_files.txt"),CREATE,APPEND));
}catch (Exception e) {
System.out.println("\nError opening file");
}
}
private void addRecords() {
try {
output.writeObject(account);
}
catch (Exception e) {
System.out.printf("Error writing file %s",e);
}
}
private void closeFile() {
try {
if(output != null)
output.close();
} catch (Exception e) {
System.out.println("\nError closing file");
}
}
}
And Reader part
abstract class User {
private String userID;
private int password;
private String position;
private ObjectInputStream input;
public User(String userID, int password, String position) {
this.userID = userID;
this.password = password;
this.position = position;
}
boolean signIn() {
boolean found_check = false;
openFile();
found_check = checkRecords();
closeFile();
return found_check;
}
private void closeFile() {
try {
if(input != null)
input.close();
} catch (Exception e) {
System.out.println("Error closing file");
}
}
private boolean checkRecords() {
try {
while(true) {
Accounts account = (Accounts) input.readObject();
System.out.printf("%s %d %s",account.getUserID(),account.getPassword(),account.getPosition());
}
}
catch (Exception e) {
System.out.println("\nError reading file");
return false;
}
return false;
}
private void openFile() {
try {
input = new ObjectInputStream(Files.newInputStream(Paths.get("record_files.txt")));
}catch (Exception e) {
System.out.println("Error opening file");
}
}
}
Accounts class implements Serializable
public class Accounts implements Serializable {
private String userID;
private int password;
private String position;
public Accounts(String userID, int password, String position) {
try {
this.userID = userID;
this.password = password;
this.position = position;
}
catch (Exception e) {
System.out.printf(e.toString());
}
}
}
Your code is throwing the following exception: java.io.StreamCorruptedException: invalid type code: AC.
There's a good question and answer here
This was discovered by adding e.printStackTrace(); to the exception handler in User.checkRecords.

Shared ArrayList between socket Java

I have 2 sockets: a client socket (Client class) and a concurrent server socket (ServerC Class) that can handle more clients at same time.
The thread server sends an array to the client when it connects.
If I update the array inside the thread server, then the program works correctly and the next client receives the updated array when it connects.
The trouble starts when the client updates the received array but if a new client connects to the server then the array is not the "new" one. That means that the objects aren't shared.
Is it normal? Is it possible to fix that?
Thank you and sorry for my english.
public class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age){
this.name=name;
this.age=age;
}
public void setNome (String name){
this.name = name;
}
#Override
public String toString(){
return name + " " + age;
}
}
public class Client {
public static void main(String[] args) {
try {
Socket socketClient = new Socket("127.0.0.1",1500);
ObjectOutputStream outToServer = new ObjectOutputStream(socketClient.getOutputStream());
ObjectInputStream inFromServer = new ObjectInputStream(socketClient.getInputStream());
ArrayList<Person> people = (ArrayList<Person>)inFromServer.readObject();
for (Person p : people) {
System.out.println(p); //The second client will print Kevin too
}
people.add(new Person("John",54)); //This person won't be never printed for new clients
socketClient.close();
outToServer.close();
inFromServer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ServerC {
public static void main(String[] args) {
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person("Alex",21));
ServerSocket socketServer = null;
try {
socketServer = new ServerSocket(1500);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
int id=0;
while (true) {
try {
Socket socket = socketServer.accept();
id = id + 1;
ClientServiceThread cst = new ClientServiceThread(socket,id, people);
cst.start();
} catch (IOException e) {
break;
}
}
}
}
class ClientServiceThread extends Thread {
private Socket socket;
private int id=-1;
private ArrayList<Person> people;
public ClientServiceThread (Socket socket, int id, ArrayList<Person> people) {
this.socket = socket;
this.id=id;
this.people = people;
}
public void run() {
System.out.println(people);
try {
ObjectOutputStream outToClient = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream inFromClient = new ObjectInputStream(socket.getInputStream());
outToClient.writeObject(people);
people.add(new Person("Kevin",7));
outToClient.close();
inFromClient.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Send objects and objects arrays through socket

I am creating a java server and a java client.
I need to send from server to client and viceversa an object and then an array of objects.
How can I achieve this? Do I need to serialize the objects classes?
This is the server:
import java.io.*;
import java.net.*;
public class Server extends Thread {
private final ServerSocket Server;
public static void main(String[] args) throws Exception {
new Server();
}
public Server() throws Exception {
Server = new ServerSocket(3000);
System.out.println("Server started on port 3000.");
this.start();
}
#Override
public void run() {
while (true) {
try {
System.out.println("Server is listening to new connections...");
Socket client = Server.accept();
System.out.println("Connection accepted from: " + client.getInetAddress());
Connect c = new Connect(client);
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
}
}
class Connect extends Thread {
private Socket client = null;
BufferedReader in = null;
PrintStream out = null;
public Connect(Socket clientSocket) {
client = clientSocket;
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintStream(client.getOutputStream(), true);
} catch (IOException mainException) {
try {
client.close();
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
}
this.start();
}
#Override
public void run() {
try {
out.close();
in.close();
client.close();
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
}
}
This is my client:
import java.io.*;
import java.net.*;
public class Client {
String remoteAddress = "localhost";
BufferedReader in = null;
PrintStream out = null;
Socket socket = null;
String message = null;
String username = null;
String password = null;
public Client(String username, String password) {
this.username = username;
this.password = password;
}
public String connect() {
try {
// begin a new client connection
socket = new Socket(remoteAddress, 3000);
// open I-O channels
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintStream(socket.getOutputStream(), true);
} catch (Exception exception) {
return false;
System.out.println(exception.getMessage());
}
return "ERROR";
}
public boolean disconnect() throws IOException {
// close flushes I-O with the server
out.close();
in.close();
return true;
}
}
This, instead, is one class:
class Contact {
private String name;
private String surname;
private String telephone;
private String birthday;
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
public String getTelephone() {
return telephone;
}
public String getBirthday() {
return birthday;
}
public void setName(String value) {
name = value;
}
public void setSurname(String value) {
surname = value;
}
public void setTelephone(String value) {
telephone = value;
}
public void setBirthday(String value) {
birthday = value;
}
}
Currently just the server can send data (objects array or only object) to client but I'm thinking about make both able to do.
Also, it'd be nice about to send an object (like the class above), an array of same object and an array of different objects (I can't obtain it with classic arrays, right? May I use ArrayList?)
Thank you.
what about java.io.ObjectOutputStream ? try this http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html
EDIT: here's the example included in the javadoc of the class -slightly modified-, as suggested in the comments:
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeInt(12345);
oos.writeObject("Today");
oos.writeObject(new Date());
oos.close();
and there should be a java.io.ObjectInputStream on the opposite side.
Yes You shoud use serialization for that.
In that case You could use ObjectOutpuStream and writeObject() method. So it is very simple to manage this without thinking about counting bits etc.
http://www.tutorialspoint.com/java/java_serialization.htm

wake up a thread from its state using notify

I am desperate...I'm working all the day on a program but I didn't resolve my issue about thread cuncurrency.Please help me.
I have this class which is a generic Item.My problem is when this object enters in wait() it doesn't wake up anymore even if I call on the same object the method putItemToWork().I would know if there is a mistake on the code about cuncurrency because really I don't understand where I make mistakes...
Item Class
import java.io.*;
public class Item implements Serializable
{
private String id;
private String category;
private String machine;
private boolean isWorked;
private String mchTemp = null;
public Item(String id,String category,String machine,boolean isWorked)
{
this.id = id;
this.category = category;
this.machine = machine;
this.isWorked = isWorked;
}
public synchronized void putItemToWork(String id_machine)
{
try
{
System.out.println("Working the item...");
Thread.sleep((long)(1+Math.random()*10000));
}
catch(InterruptedException ie) {ie.printStackTrace(); }
mchTemp = id_machine;
isWorked = true;
notify();
}
public synchronized String getWorkedItem()
{
if(mchTemp == null)
{
try
{
wait();
}
catch(InterruptedException ie) {ie.printStackTrace(); }
}
return mchTemp;
}
public String getId()
{
return this.id;
}
public String getCategory()
{
return this.category;
}
public String getMachine()
{
return this.machine;
}
public boolean isWorked()
{
return this.isWorked;
}
}
}
ServerMultiThread
import java.io.*;
import java.util.*;
import java.net.*;
import javax.swing.SwingUtilities;
import javax.swing.JTextArea;
public class ServerMultiThread implements Runnable
{
Socket socket;
private ServerSocket serverSocket;
private LinkedList<Item> itemsList;
private LinkedList<Machine> machinesList;
private static final boolean listening = true;
private JTextArea output;
public ServerMultiThread(LinkedList<Item> itemsList,LinkedList<Machine> machinesList,JTextArea output)
{
this.itemsList = itemsList;
this.machinesList = machinesList;
this.output = output;
try
{
this.serverSocket = new ServerSocket(8090);
}
catch(IOException ioe){ioe.printStackTrace(); }
new Thread(this, "Server").start();
}
#Override
public void run()
{
Item itemTemp = null;
SwingUtilities.invokeLater(new Runnable(){#Override public void run(){output.append("Server in run!\n");}});
while(listening)
{
try
{
SwingUtilities.invokeLater(new Runnable(){public void run(){output.append("Waiting for incoming connection...\n");}});
socket = serverSocket.accept();
SwingUtilities.invokeLater(new Runnable(){#Override public void run(){output.append("Connected to: "+socket.getInetAddress()+":"+socket.getPort()+"!\n");}});
ObjectOutputStream ous = new ObjectOutputStream(socket.getOutputStream());
synchronized(itemsList)
{
for(Item item : itemsList)
{
if(!item.isWorked())
{
itemTemp = item;
break;
}
}
new ItemHandler(itemTemp,ous,output);
}
}
catch(IOException ioe) {ioe.printStackTrace(); }
}
}
}
ItemHandler
import java.io.*;
import java.util.LinkedList;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class ItemHandler implements Runnable
{
String id_machine;
private Item item;
private ObjectOutputStream ous;
//private ObjectInputStream ois;
private JTextArea output;
public ItemHandler(Item item,ObjectOutputStream ous,JTextArea output)
{
this.item = item;
this.ous = ous;
//this.ois = ois;
this.output = output;
new Thread(this).start();
}
#Override
public void run()
{
try
{
ous.writeObject(item);
SwingUtilities.invokeLater(new Runnable(){public void run(){output.append("Item Handler "+item.getId()+ " in run!\n");}});
id_machine = item.getWorkedItem();
SwingUtilities.invokeLater(new Runnable(){public void run(){output.append("The item "+item.getId()+" was correctly worked by "+id_machine);}});
//System.out.println("The item "+workedItem.getId()+" was correctly worked by "+workedItem.getMachine());
}
catch(IOException ioe){ioe.printStackTrace();}
}
}
MachineApp
import java.io.*;
import java.net.*;
public class MachineApp
{
private Socket socket;
private String id_machine;
public MachineApp(String id_machine)
{
this.id_machine = id_machine;
try
{
this.socket = new Socket("localhost",8090);
System.out.println("Estabilished connection to main server!");
}
catch(UnknownHostException uhe) {uhe.printStackTrace();}
catch(IOException ioe) {ioe.printStackTrace(); }
execution();
}
private void execution()
{
try
{
//ObjectOutputStream ous = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Item item = (Item) ois.readObject();
item.putItemToWork(id_machine);
System.out.println("Item Worked!");
}
catch(ClassNotFoundException cnfe) {cnfe.printStackTrace(); }
catch(IOException ioe) {ioe.printStackTrace(); }
}
public static void main(String[] args)
{
MachineApp machineApp = new MachineApp(args[0]);
}
}
For me your code works just fine. Are you calling wait/notify from different threads:
public static void main(String[] args) {
final Item item = new Item("id", "cat", "mach", false);
Thread retrievalThread = new Thread(new Runnable() {
#Override
public void run() {
item.getWorkedItem();
}
});
Thread puttingThread = new Thread(new Runnable() {
#Override
public void run() {
item.putItemToWork("id");
}
});
retrievalThread.start();
puttingThread.start();
}
EDIT: after client code was added to question:
I could be wrong but you're sending item object via socket and then trying to call getWorkedItem on it. It doesn't work this way because once you've send item thru network object on the other side (even if it's happening in one JVM) that will be different object. Therefore calling notify on it won't trigger wake up from wait.
How to solve it? Well, you can add some kind of query interface to your server code so you could query which items were worked.
If it's no homework, or learning exercise I think that Hadoop can be good fit for your needs
For starters, you're going to need to make mchTemp volatile, because you're writing to this field in one thread, and reading it from another. Without volatile, changes made in one thread may not be visible in another tread.
private volatile String mchTemp = null;

Categories

Resources