ObjectOutputStream in Java - java

I have a function
public void loadUserOnline() {
try {
oos.writeObject(req); //Send request to Server to get online users
oos.flush();
LinkedList<UserOnlineInfo> userOnlineInfoList = (LinkedList<UserOnlineInfo>)ois.readObject(); // read object from Server contains online users
Vector<String> listData = new Vector<>(); // a Vector for JList
for (int i = 0; i < userOnlineInfoList.size(); i++) {
listData.add(userOnlineInfoList.get(i).getUser() + " --- " + userOnlineInfoList.get(i).getStatus()); // add elements to Vector
}
theList.setListData(listData); // set data source for JList
}
catch (Exception e){
e.printStackTrace();
}
}
The first time I call this function, it gets data from a server. Then data from the server changes. I call this function a second time, and the data is the same as the first time. Why?

You need to call ObjectOutputStream.reset() every time you want to resend the same object with new values, or else use writeUnshared(). See the Javadoc.

You're using the same ObjectOutputStream instance, oos, which has been exhausted by the first call to this method. If you initialise your ObjectOutputStream again then you'll get a new stream:
public void loadUserOnline() {
// initialise oos here or before the call to this method
ObjectOutputStream oos = new ObjectOutputStream(......
try {
oos.writeObject(req);
....

Related

Deserializing returns null object Java

Currently writing an application like Booking and I am in the stage where i want to store my infomation in files. I have created a Serializable Database class which has a field with a pathname and 2 methods for read/write . I have about 8 other classes which extend the Database and each holds a Hashmap and some querying methods. Naturally I read the Databases from my files before i start the application and i write before exiting, but I ran into a problem where the objects I am reading are all null. I've been at it for 2 hours now and I need a second opinion. This is the database's read/write methods:
public void write() {
try {
File temp = new File(this.filename);
temp.createNewFile(); // create file if not present
FileOutputStream fileOut = new FileOutputStream(this.filename);
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(this);
objectOut.close();
System.out.println("The Object was successfully written to a file");
} catch (Exception ex) {
ex.printStackTrace();
}
}
public Object read() {
Object obj = null;
try {
File temp = new File(this.filename);
temp.createNewFile(); // create file if not present
FileInputStream fileIn = new FileInputStream(this.filename);
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
obj = objectIn.readObject();
System.out.println("The Object was successfully read from the file");
objectIn.close();
} catch (EOFException ex) {
return obj;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
And here is the way I load them (Which is probably the problem) in my Application class
private void loadData() {
accommodationReviewsDatabase = (AccommodationReviews) accommodationReviewsDatabase.read();
brokerAccommodationsDatabase = (BrokerAccommodations) brokerAccommodationsDatabase.read();
credentialsUserDatabase = (CredentialsUser) credentialsUserDatabase.read();
customerReviewsDatabase = (CustomerReviews) customerReviewsDatabase.read();
userConfirmationsDatabase = (UserConfirmations) userConfirmationsDatabase.read();
userMessagesDatabase = (UserMessages) userMessagesDatabase.read();
}
private void writeData() {
accommodationReviewsDatabase.write();
brokerAccommodationsDatabase.write();
credentialsUserDatabase.write();
customerReviewsDatabase.write();
userConfirmationsDatabase.write();
userMessagesDatabase.write();
}
Some extra information that may be asked :
All my classes that I am storing are serializable
The files I am storing the databases are all *.ser (Thats the extension I found)
The files are stored inside the project
If your read() method completes without an EOFException, it ends with return null;. You should return obj;, the object you read.
You should not expect that EOFException will be thrown if your read succeeds. The EOFException would indicate that it ran out of data while it was trying to read your object, and could not complete successfully.
If you do get an EOFException, it is probably a good idea to give some indication instead of silently returning. Silent catch blocks deny you information that could be useful for debugging.

while(true) loop without break

I am quite new to Java programming. For now I am studying source code of an android app called Evercam. However, I have a problem understanding a part of the code which involves while(true) loop.
Here is the snippet of the code:
while (true)
{
while (true)
{
byte[] responseMessageByteArray = new byte[4000];
DatagramPacket datagramPacketRecieve = new DatagramPacket(responseMessageByteArray, responseMessageByteArray.length);
datagramSocket.receive(datagramPacketRecieve);
String responseMessage = new String(datagramPacketRecieve.getData());
EvercamDiscover.printLogMessage("\nResponse Message:\n" + responseMessage);
StringReader stringReader = new StringReader(responseMessage);
InputNode localInputNode = NodeBuilder.read(stringReader);
EnvelopeProbeMatches localEnvelopeProbeMatches = (EnvelopeProbeMatches)(new Persister()).read(EnvelopeProbeMatches.class, localInputNode);
if (localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches.size() > 0)
{
ProbeMatch localProbeMatch = (ProbeMatch) localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches.get(0);
if (uuidArrayList.contains(localProbeMatch.EndpointReference.Address))
{
EvercamDiscover.printLogMessage("ONVIFDiscovery: Address " + localProbeMatch.EndpointReference.Address + " already added");
}
else
{
uuidArrayList.add(localProbeMatch.EndpointReference.Address);
DiscoveredCamera discoveredCamera = getCameraFromProbeMatch(localProbeMatch);
if (discoveredCamera.hasValidIpv4Address())
{
this.onActiveOnvifDevice(discoveredCamera);
cameraList.add(discoveredCamera);
}
}
}
}
}
Doesn't this create an infinite loop? My fundamentals in Java isn't strong, so I would be so grateful if anyone can tell in in what instances will a while(true){//codes} actually exits without any break or does it ever exit??
EDIT
My bad for actually extracting this snippet from decompiling directly from the android project files. I did not know that it would be different, and then again, I know very little. Here is the original code:
public ArrayList<DiscoveredCamera> probe() {
ArrayList<DiscoveredCamera> cameraList = new ArrayList<DiscoveredCamera>();
try {
DatagramSocket datagramSocket = new DatagramSocket();
datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
InetAddress multicastAddress = InetAddress.getByName(PROBE_IP);
if (multicastAddress == null) {
// System.out.println("InetAddress.getByName() for multicast returns null");
return cameraList;
}
// Send the UDP probe message
String soapMessage = getProbeSoapMessage();
// System.out.println(soapMessage);
byte[] soapMessageByteArray = soapMessage.getBytes();
DatagramPacket datagramPacketSend = new DatagramPacket(
soapMessageByteArray, soapMessageByteArray.length,
multicastAddress, PROBE_PORT);
datagramSocket.send(datagramPacketSend);
ArrayList<String> uuidArrayList = new ArrayList<String>();
while (true) {
// System.out.println("Receiving...");
byte[] responseMessageByteArray = new byte[4000];
DatagramPacket datagramPacketRecieve = new DatagramPacket(
responseMessageByteArray,
responseMessageByteArray.length);
datagramSocket.receive(datagramPacketRecieve);
String responseMessage = new String(
datagramPacketRecieve.getData());
EvercamDiscover.printLogMessage("\nResponse Message:\n"
+ responseMessage);
StringReader stringReader = new StringReader(responseMessage);
InputNode localInputNode = NodeBuilder.read(stringReader);
EnvelopeProbeMatches localEnvelopeProbeMatches = new Persister()
.read(EnvelopeProbeMatches.class, localInputNode);
if (localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches
.size() <= 0) {
continue;
}
ProbeMatch localProbeMatch = localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches
.get(0);
// EvercamDiscover.printLogMessage("Probe matches with UUID:\n"
// +
// localProbeMatch.EndpointReference.Address + " URL: " +
// localProbeMatch.XAddrs);
if (uuidArrayList
.contains(localProbeMatch.EndpointReference.Address)) {
EvercamDiscover.printLogMessage("ONVIFDiscovery: Address "
+ localProbeMatch.EndpointReference.Address
+ " already added");
continue;
}
uuidArrayList.add(localProbeMatch.EndpointReference.Address);
DiscoveredCamera discoveredCamera = getCameraFromProbeMatch(localProbeMatch);
if (discoveredCamera.hasValidIpv4Address()) {
onActiveOnvifDevice(discoveredCamera);
cameraList.add(discoveredCamera);
}
}
} catch (Exception e) {
// ONVIF timeout. Don't print anything.
}
Turns out there is continue statement in the actual code. Thank you so much for the response, I will remember that de-compiled classes should not be depended on.
This looks like an infinite loop. To be absolutely sure, you would have to statically read every statement and follow invoked methods to see if any possible invocations like Activity#finish() or Service#stopSelf() exists which would finish the currently running activity, effectively breaking the loop.
Another possibility is that the code is intended to be running in an infinite loop as a background thread service, and some other component would have an option to kill that service when it reaches a certain condition. For example, it could be part of a Runnable class and executed in a thread pool, and when a timeout exists, the pool is shut down.
the only possible way to exit from while loop is if one of the methods being called in loop throws exception. check code of these methods for exception or share it here
Infinite loops without any breaks could be useful for a Service running in background.
You create a new Thread doing the service infinitely thanks to a while(true) and when you stop your application you simply kill the process corresponding to the service.

Java client server application, can't send an ArrayList

I searched the internet and i didn't find something for my question.
I have my client class, my server class and a Loc class. In my client class, i have a Jtext field, that i want to populate with values (free/occupied) depending if the seat is free or not.
In my server class i populate an ArrayList with all the seats free. I want to pass this ArrayList to my client and in the same time to display something like FREE FREE OCCUPIED.
But i can only pass my first value.
Here is the server class:
public static void main(String [] args){
ServerSocket client = null;
Loc l = new Loc();
try {
ArrayList<Loc> lista = new ArrayList<>();
for (int i=0;i<7;i++)
for(int j=0;j<6;j++)
{
l.setLoc(i);
l.setRand(j);
lista.add(l);
}
client = new ServerSocket(9000);
Socket socket = client.accept();
ObjectInputStream dis = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream dos = new ObjectOutputStream(socket.getOutputStream());
l = (Loc) dis.readObject();
System.out.println(l.getRand());
// Loc a = new Loc("ags",2, 42, 125);
dos.writeObject(lista);
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
And here is my client class:
public class Client_Gui extends javax.swing.JFrame {
Socket socket = null;
ObjectOutputStream dos = null;
ObjectInputStream dis= null;
// ObjectOutputStream dos = null;
ArrayList<Loc> lst = new ArrayList<>();
Loc locul = new Loc();
/**
* Creates new form Client_Gui
*/
public Client_Gui() {
initComponents();
Loc loc = new Loc();
try {
ArrayList<Loc> lst = null;
socket = new Socket("localhost",9000);
dos = new ObjectOutputStream(socket.getOutputStream());
dis = new ObjectInputStream(socket.getInputStream());
dos.writeObject(loc);
lst = (ArrayList<Loc>) dis.readObject();
for(Loc a : lst){
if(a.getIdSpectator().equals("") == true)
txt_area.setText("Liber");
else
txt_area.setText("Ocupat");
}
} catch (IOException ex) {
Logger.getLogger(Client_Gui.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Client_Gui.class.getName()).log(Level.SEVERE, null, ex);
}
}
And another question related to this. Can i run my client/server application without sending first some information from the client? I mean, at first i tried to read from client first and then write to server but i got errors. After i changed, and first i write from client and then read, works normally, until it reaches that part with ArrayList.
EDIT: i tried to hard code and in my Client class i put the array list created by code.
Now, when i want to show it in the text field, still only the first value is displayed. Is my syntax wrong?
i used:
for(Loc a : lista){
if(a.getIdSpectator().equals("") == true)
txt_area.setText("Liber");
else
txt_area.setText("Ocupat ");
}
EDIT2: Jasper was right. I used append and now it works. Thanks.
Take a look at how you are constructing the list on the server....
ArrayList<Loc> lista = new ArrayList<>();
for (int i=0;i<7;i++)
for(int j=0;j<6;j++)
{
l.setLoc(i);
l.setRand(j);
lista.add(l);
}
Basically, all this is doing is adding the same instance of l to the array list, but on each loop, you are changing its properties. This means, you'll end up with a list of the same object with the same properties (cause it's just the single instance of the object)
What you should be doing is on each iteration of your loop is creating a new instance of what ever l is, setting its properties according only and that to the list
Updated
Okay, on client, you're setting the text of the JTextArea using
for(Loc a : lst){
if(a.getIdSpectator().equals("") == true)
txt_area.setText("Liber");
else
txt_area.setText("Ocupat");
}
setText replaces the contents of the field with the supplied text. Instead, you want to try using append
for(Loc a : lst){
if(a.getIdSpectator().equals("") == true)
txt_area.append("Liber");
else
txt_area.append("Ocupat");
}
Having said that, I would highly recommend that you consider taking a look at How to Use Tables and How to Use Lists for components that are better suited to display this type of data
You need to put it in a loop so all of your values passed from the socket will be recieve by the server not just the first value you send.
example:
in server
ObjectOutputStream dos = new ObjectOutputStream(socket.getOutputStream());
dos.writeObject(lista);
while(true)
{
l = (Loc) dis.readObject();
System.out.println(l.getRand());
// Loc a = new Loc("ags",2, 42, 125);
}
in client
dis = new ObjectInputStream(socket.getInputStream());
lst = (ArrayList<Loc>) dis.readObject();
for(Loc a : lst){
if(a.getIdSpectator().equals("") == true)
txt_area.setText("Liber");
else
txt_area.setText("Ocupat");
}
your question:
Can i run my client/server application without sending first some information from the client?
just always remember when you are trying to read data packet, someone should write data first.

Java storing BufferedOutputStream in array

In Java i am trying to store each BufferedOutputStream the server makes into an array aside from the threads in order to broadcast some data to all connected clients.
// initialisation
ArrayList<BufferedOutputStream> connections = new ArrayList<BufferedOutputStream>();
// when a client connects
Socket connection = socket.accept();
connections[id] = connection;
// broadcasting to all clients
for (int i = 0; i < connections.size(); i++) {
try {
OutputStreamWriter osw = new OutputStreamWriter(connections.get(i), "US-ASCII");
osw.write(s + "\n");
osw.flush();
} catch (Exception g) {
// catch
}
}
note: only the essential code is given
The problem: The broadcasting loop only broadcasts to the first in the loop, and sometimes the others as well. No error is thrown and the loop iteration as it should.
What is wrong and how do i fix it?
It's probably something obvious but i'm still a beginner..
Thanks!
We can't tell you exactly what is wrong because you've left out important parts of the code. However, if connections[id] = connection is throwing an NPE, that can only mean that connections is null. And, on the face of it, you don't appear to have initialized connections to a non-null value!
The fix is to initialize connections ... somewhere ... to an array of the appropriate size. However, that brings you other problems. What is an appropriate size for the array, and what what you are going t when id is larger than connections.length?
The root problem is an array is (probably) a poor choice for holding the connections ...
Maybe the socket has close, or the i index in the array is null, so the question is, why don't you utilize the List<OutputStream> over Socket[]?
with List<OutputStream> or List<OutputStreamWriter> you will not need to initialize the OutputStreamWriter every time you want to send some data.
somehow You should store client socket object.
whenever you want to broadcast, iterate over collection get socket, get ouput stream from that, and write to socket.
Its working for me properly.
EDIT: Socket[] array = new Socket[#];
You never initialize your array. That could be the problem.
But I suggest using either a List or a Map.
Apparently, I'm guessing you wanna store the socket in a way that you could retrieve it by a property later (name or ID). In this case, I suggest using a HashMap, with Integer as they key, and Socket as the value. This was, you can use map.get(ID);, and it'll return the socket you want.
You could try using a HashMap, maybe have a var for how many people are currently connected.
When someone logs in, do something like
public class Serer {
HashMap<Integer, Socket> list = new HashMap<Integer, Socket>();
static final int maxConnections = 100;
static int currentConnections = 0;
public Server() {
try {
ServerSocket socket = new ServerSocket(/*port#*/, maxConnections);
}catch(IOException e) { }
}
public void acceptConnections() {
while(currentConnections < maxConnections) {
list.put(currentConnections++, serversocket.accept());
}
}
public Socket getSocket(int ID) {
return list.get(ID);
}
public static void main(String[] args) {
new Server().acceptConnections();
}
This isn't tested, and I highly suggest putting the 'acceptConnections' in a thread, so the while loop isn't holding up your code. I didn't catch any exceptions, but hopefully this will give you an idea of using a HashMap to hold your sockets
Now, if you wanna send data to all the sockets, you would need to create an OutputStream for each socket. I suggest making a class (such as User.java), then when someone connects, make a new User, passing it the socket.
while(true) {
new User(ss.accept());
}
Then in your User.java, have something kind of like:
public class User {
ObjectOutputStream out;
ObjectInputStream in;
Socket socket;
public User(Socket socket) {
this.socket = socket;
initStream();
startChat();
}
public void initStream() {
try{
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputSTream(socket.getInputStream());
}catch(IOException e) { }
}
public void startChat() {
new Thread(new Runnable() {
public void run() {
String input;
try {
while((input = (String) in.readObject) != null) {
//this loop only triggers when something is retrieved through the input stream
Server.sendGlobalMessage(input); //can be done in different ways
//The reason why I call this statically from Server.java is because Server.java
//is the class that contains the HashMap, but that's up to you of where to put it.
//You could make the `HashMap` static, and make the sendGlobalMessage() in User.java
}
}catch(IOException | ClassNotFoundException e) { }
};).start();
}
Now finally for the sendGlobalMessage, you will need to either use an Iterator, or you can turn your hashmap into an array. This code is assuming that instead of using a HashMap for sockets, you pass the socket into a User class, then use the HashMap to store the user. (you need access to the output stream)
HashMap<Integer, User> list = new HashMap<Integer, User>();
public static void sendGlobalMessage(String message) {
for(User user : list.values().toArray(new User[list.size]) {
try {
user.out.writeObject(message);
user.out.flush();
}catch(IOException | ClassNotFoundException e) { }
}
}

How to count number of objects stored in a *.ser file

I'm trying to read all the objects stored in a *.ser file and store them in a array of objects. How can I get the number of objects stored in that file(So that I can declare the array to be number_of_objects long)?
I've checked the API and was unable to find a Desirable function.
-edit-
A Part of the code:
Ser[] objTest2 = new Ser[number_of_objects];
for(int i=0; i<=number_of_objects, i++) {
objTest2[i] = (Ser)testOS2.readObject();
objTest2[i].printIt();
}
What you want to look at is the ArrayList class.
It is basically a dynamically growing Array.
You can add items to it like so:
ArrayList list = new ArrayList();
list.add(someObject);
list.add(anotherBoject);
The list will grow as you add new items to it. So you don't have to know the size ahead of time.
If you need to get an array out if the List at the end you can use the toArray() method of List.
Object[] arr = list.toArray(new Object[list.size()]);
Edit:
Here is a general implementation of what you need:
List<Ser> objTest2 = new ArrayList<Ser>();
while (testOS2.available > 0) {
Ser toAdd = ((Ser)testOS2.readObject());
toAdd.printIt();
objTest2.add(toAdd);
}
*I don't think available() is a reliable test for whether or not there are more bytes to read.
Year's later this post is still relevant. I was looking for a way to loop through a .ser file while de-serializing each file, and to some extent, Rohit Singh's post helped. This is my version of the same though:
ArrayList<Profile> availableProfiles = new ArrayList<Profile>();
try {
FileInputStream fileStream = new FileInputStream("profiles.ser");
ObjectInputStream os = new ObjectInputStream(fileStream);
Object profileObject = null;
while((profileObject = os.readObject()) != null) {
Profile castObject = (Profile) profileObject;
availableProfiles.add(castObject);
}
os.close();
} catch(Exception ex) {
if(ex instanceof EOFException) {
out.println("End of file reached!");
out.println("Total profiles found is: " + availableProfiles.size());
} else if(ex instanceof FileNotFoundException) {
out.println("File not found! \n Answer the following to create your profile");
createProfile();
}
}
The most important part is the position of the while-loop. In my version, that loop does not create a new FileInputStream or ObjectInputStream like Singh's does. That will make the ObjectInputStream read the .ser file afresh each time those two are created, and as a result, you only add() one Profile object to the ArrayList- the first one to be serialized- each time the loop restarts.
Instead, we only loop the with the readObject() method until it produces a null signifying no other object was found in the file, and it triggers the EOFException.
while(true)
{
try
{
Employee e=(Employee) ois.readObject();
System.out.println("successfully deserialized.........showing details of object.");
e.display();
}
catch(Exception e)
{
if(e instanceof java.io.EOFException)
{
System.out.println("All objects read and displayed");
break;
}
else
{
System.out.println("Some Exception Occured.");
e.printStackTrace();
}
}
}
Just keep reading objects until you get EOFException. That's what it's for. And use a List instead of an array so you don't need the count in advance.

Categories