I want to read an object from file using ObjectInputStream.
Here is what the readObject method looks like inside:
public void readObject(ObjectInputStream inbos) throws IOException {
try {
GameModel gm = (GameModel) inbos.readObject();
} catch (IOException ex) {
Logger.getLogger(GameDeserializer.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(GameDeserializer.class.getName()).log(Level.SEVERE, null, ex);
}
}
My GameModel class has a readResolve method. GameModel class is also a singleton.
public Object readResolve() throws ObjectStreamException {
System.out.println("At read resolve method ");
GameModel themodel = getGameModel();
System.out.println("Reading the file : " + themodel.toString() + themodel );
return themodel;
}
The problem is it is not reading the object right.
It is reading it as a pointer.
I need help please.
Your implementation of readResolve() will replace whatever you had written in the stream with the current singleton, so no data from the stream is actually used. (assuming the getGameModel() gets the singleton instance)
Explaining: The ObjectInputStream will instantiate and deserialize a new instance of GameModel, then call readResolve(), which if your current implementation will tell the stream to use the old singleton instead.
If that's what you are trying to do, you should also consider writing an empty writeObject() to avoid writing unnecessary data to the stream.
If that was not what you had in mind and GameModel is really supposed to be a singleton your choices are:
Using readResolve() to copy data from the "just read game model" to the singleton
Using readResolve() to replace the current singleton instance (sounds dangerous)
Any number of tricks with writeReplace/readResolve using a replacement object (like GameModelReplacement) to hold the data you want to save/restore;
About readObject(): It's not clear in your question if that readObject is in GameModel. I'm assuming it's not. However if it is, the statement (GameModel) inbos.readObject(); makes no sense as the GameModel is the current object (this). If that's the case do something like this:
public class GameModel {
private void readObject(ObjectInputStream inbos) throws IOException {
// do nothing
}
private void writeObject(ObjectOuputStream out) throws IOException {
// do nothing
}
private Object readResolve() throws ObjectStreamException {
// discarding serialized gamemodel, and using the singleton.
return getGameModel();
}
}
Related
im currently working in a complete generic scenario in which i map a json as string to a dto class. That works fine with my function mapJsonToDto but im trying to make it more generic so that the developer who uses this function can also specify what exception to be thrown. So they can catch as they like. With this i avoid catching an IOException. Letting the function handle everything.
public class MapperUtils {
public <T extends Throwable> Object mapJsonToDto(Class<?> dtoClass, String jsonDto, T exceptionToThrow) throws IOException {
Object dto = null;
try {
dto = new ObjectMapper().readValue(jsonDto, dtoClass);
} catch (IOException e) {
throw new exceptionToThrow();
}
return dto;
}
}
I cannot understand how to pass an exception class instance to a function and throwing that specific as well.
Instead of passing the exception to throw (which would then have a completely wrong stack trace), I think you'd want a function that converts an exception from one type to another:
public <T extends Throwable, D> D mapJsonToDto(Class<D> dtoClass, String json, Function<IOException, T> exceptionMapper) throws T {
try {
return new ObjectMapper().readValue(json, dtoClass);
// if readValue doesn't do the casting right, try:
return dtoClass.cast(new ObjectMapper().readValue(json, dtoClass);
} catch (IOException e) {
throw exceptionMapper.apply(e);
}
}
And an example:
Person p = mapJsonToDto(Person.class, "{name: \"Joe\"}",
e -> new IllegalArgumentException("malformed JSON", e));
As a general rule, though, this seems like boneheaded design. If you find the IOException overly general, then you can't handwave the problem away by allowing the caller to provide a no doubt similarly overly general mapper. The only way out for a caller is to do a deep dive on the exception and write, I dunno, an if/elseif block with a ton of levels to it to try to ascertain the real problem e.g. via analysing the message, which is all sorts of ugly.
Either you don't care about that level of detail and you should therefore just stick with IOException (what point is there adding code and pointless layers of indirection?), or you do care and this isn't good enough; you'd want to design a better error system. Except, that's not your job, that'd be ObjectMapper.readValue's job. Which is why the IOException it throws should probably just be sent on unmolested.
Your example is nearly done.
I changed only the throws Type to T and throw the given exception.
public <T extends Throwable> Object mapJsonToDto(Class<?> dtoClass, String jsonDto, T exceptionToThrow) throws T {
Object dto = null;
try {
dto = new ObjectMapper().readValue(jsonDto, dtoClass);
} catch (IOException e) {
throw exceptionToThrow;
}
return dto;
}
Call: mapJsonToDto(String.class, "helo", new IllegalStateException());
Question: how to move all logic to strategy (another class) but leave exception-handling logic in class-owner?
I've got: method map which gets data array from input argument, and then perform a lot of logic on that:
class Owner ...
public void map(final LongWritable key, final Text value, final Context context) {
// 1st-fragment of code
String[] data = null;
try { // Not Owner class logic, should be moved to strategy
StringReader reader = new StringReader(line);
CustomParser cParser = new CustomParser(reader,_strategy);
data = cParser.getLine();
} catch (final IOException e) {
outputBadData(line); // Owner class logic
return;
}
// 2nd-fragment of code: logic which is based on `data` array
................
................
}
I want: Actually all logic in 1st fragment (except outputBadData) doesn't belong to this class. I want to move it strategies. It'll look like:
public void map(final LongWritable key, final Text value, final Context context) {
// 1st-fragment of code
String[] data = strategy.getData(value);
// 2nd-fragment of code: logic which is based on `data` array
................
................
}
Problem: outputBadData is a logic of Owner class, not the strategy.
If I've understood right, you must create your Strategy class and define within it a method with required logic.
In this method's signature define 'throws IOException'
for example:
public [return type] readLine(arguments...) throws IOException {
...
}
Also you must have the reference to an object of your new class(Strategy) to invoke the 'readLine' method.
You can store this object as field of Owner class passing it as constructor argument (for using setter method) when you create the instance of this class. And then, in your 'map' method of Owner class, surround the 'readLine' method invocation with 'try-catch' block to handle exception:
try{
strategyReference.readLine(arguments...);
}catch (IOException e) {
outputBadData(line);
return;
I m having a problem of calling a constructor with arguments from default constructor.
Class A {
private static Properties properties;
A(Properties property){
// do some checks
try{
load(property, fileName)
} catch(IOException e) {
throw new RuntimeException();
}
}
A(){
this(load(properties));
}
private static Properties load(Properties properties, String fileName ) throws IOException {
try {
properties.load(A.class.getClassLoader()
.getResourceAsStream(fileName));
} catch (IOException ioException) {
throw new IOException("Unable to process the properties File. " + fileName, ioException);
}
return properties;
}
}
My problem is: In Default constructor I wanted to use try/catch block and do the same operation of throwing a run time exception. Can you help me out as what can be done in this?
WRT this post: chaining constructors in Java without throwing exceptions from the default constructor
I have an option of putting try/catch inside another method. But is there any other way?
P.S: I do not want to use 'throws'
Java does not allow chained constructor calls to be enclosed within a try block, since such constructs could if not restricted allow an object whose base object threw an exception to end up being returned to calling code. This makes it difficult to express certain concepts involving resources like files [e.g. it would be helpful to have a constructor open a file before chaining to the parent and close it afterward, but there's no way to safely have a constructor take responsibility for a file which is opened before chaining to the parent]. The best one can do in Java is avoid public constructors which might throw exceptions and instead use factory methods which can be better equipped to handle them.
Option 1: Pass the other constructor a new empty instance of Properties:
class A
{
public A()
{
this(new Properties());
}
// rest of code...
}
Option 2: Pass the other constructor a null instance of Properties. You'll then have to guard against null in load(...), but you probably should be anyway:
class A
{
public A()
{
this(null);
}
// rest of code...
}
Option 3: Pass the other constructor a default instance of Properties:
class A
{
private static final Properties defaultProperties;
static
{
defaultProperties = new Properties();
// populate here however you wish
}
public A()
{
this(defaultProperties);
}
// rest of code...
}
I'm trying to implement loading and saving for a game I'm working on.
What I want to save is:
A char[][] (bidimensional array/matrix)
An ArrayList<Entity>
Entity is a super class for Dragon, Hero and Item. All three of these types can be contained at once in the ArrayList.
So far I have this:
package logic;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public final class LoadAndSave {
public static final transient boolean available = false;
public static final boolean serialize(Object obj) {
// Write to disk with FileOutputStream
FileOutputStream saveFile;
try {
saveFile = new FileOutputStream("game.sav");
} catch (FileNotFoundException e) {
return false;
}
// Write object with ObjectOutputStream
ObjectOutputStream objOut;
try {
objOut = new ObjectOutputStream(saveFile);
} catch (IOException e) {
//
return false;
}
// Write object out to disk
try {
objOut.writeObject(obj);
} catch (IOException e) {
return false;
}
return true;
}
public static final Object load() {
FileInputStream fileIn;
try {
fileIn = new FileInputStream("game.sav");
} catch (FileNotFoundException e1) {
return null;
}
// Read object using ObjectInputStream
ObjectInputStream objIn;
try {
objIn = new ObjectInputStream(fileIn);
} catch (IOException e) {
return null;
}
// Read an object
Object obj;
try {
obj = objIn.readObject();
} catch (IOException e) {
return null;
} catch (ClassNotFoundException e) {
return null;
}
return obj;
}
}
I think the code is pretty self-explanatory. Now for my questions:
Will this code suffice?
Do I need to implement specific serialization methods for Dragon, Item and Hero?
How will the serialization mechanism deal with the fact that I have an Entity vector full of types that are not Entity, but derived classes?
Thanks for your time!
OK, all seems to be well, except for one the ArrayList. It is either not getting saved or loaded (null pointer exception when calling size()).
What may this be due to?
If you want the entire structure to be serializable, then you'll need to make the parts serialiable as well. What this means in practice is that you need to make your Dragon, Hero, and Item classes implement Serializable. It's just a marker interface, so you only need to add implements Serializable. Some ides (at least eclipse, anyway) may complain that you should add a private long SerialVersionUID which may or may not optimize the serialization a bit - in any case it's not strictly necessary.
This requirement is recursive - any of their subparts that are custom or non-serializable objects have to be taken care of as well, so for example if your Item class looks like this
public class Item implements Serializable {
private String s;
private MyClass c;
..
then you'll also need to make MyClass Serializable, any of it's instance variables, etc etc.
I don't see any reason for specific serialization methods for Dragon, Item and Hero unless you require some very special stuff that the default serialization mechanism cannot handle.
(Of course the classes need to be serializable as mentioned by Steve B)
You already have a lot of code so I suspect that you've already run some tests. Have you faced certain problems? Or how does it come that you are asking this?
Update:
I've noticed some aspects in your code which are not directly related to your question but may anyway be of interest for you:
Do you really mean to use Vector? Does your application make use of multithreading and serialization is required? If not you might prefer to use ArrayList or so instead.
The way you handle exceptions is quite strange. Perhaps you are only doing so as this is an example... You should not suppress exceptions by simply returning true or false. If you expect calling methods to be interested in exceptions you should simply add the exception to the methods signatur (throws...) and let the calling method care about it. If you feel this is not appropriate wrapping such exceptions in custom exceptions, which are more expressive in the context, might be an option. If you don't care about the exception at all wrapping it into a runtime exception is also possible. In case of success your method might simply return nothing...
I have instantized a class that implements Serializable and I am trying to stream that object like this:
try{
Socket socket = new Socket("localhost", 8000);
ObjectOutputStream toServer = new ObjectOutputStream(socket.getOutputStream());
toServer.writeObject(myObject);
} catch (IOException ex) {
System.err.println(ex);
}
All good so far right? Then I am trying to read the fields of that object like this:
//This is an inner class
class HandleClient implements Runnable{
private ObjectInputStream fromClient;
private Socket socket; // This socket was established earlier
try {
fromClient = new ObjectInputStream(socket.getInputStream());
GetField inputObjectFields = fromClient.readFields();
double myFristVariable = inputObjectFields.get("myFirstVariable", 0);
int mySecondVariable = inputObjectFields.get("mySecondVariable", 0);
//do stuff
} catch (IOException ex) {
System.err.println(ex);
} catch (ClassNotFoundException ex) {
System.err.println(ex);
} finally {
try {
fromClient.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
But I always get the error:
java.io.NotActiveException: not in call to readObject
This is my first time streaming objects instead of primitive data types, what am I doing wrong?
BONUS
When I do get this working correctly, is the ENTIRE CLASS passed with the serialized object (i.e. will I have access to the methods of the object's class)? My reading suggests that the entire class is passed with the object, but I have been unable to use the objects methods thus far. How exactly do I call on the object's methods?
In addition to my code above I also experimented with the readObject method, but I was probably using it wrong too because I couldn't get it to work. Please enlighten me.
To answer your first question:
You need to use ObjectInputStream.readObject to deserialize. You cannot read individual fields from the stream*.
fromClient = new ObjectInputStream(socket.getInputStream());
Object myObject = fromClient.readObject();
Don't forget to flush the output stream when writing!
The second question is a little more complex. What the serialization mechanism does is write a class identifier to the stream followed by the serialized object data. When it deserializes it will read the class identifier and attempt to load that class (if it isn't already loaded). It will then instantiate the object using the no-arg constructor and call the private readObject(ObjectInputStream) method. Yes, that's right, it calls a private method from outside the class. Java serialization is special.
If the class cannot be found (i.e. if it's not on the classpath) then an exception will be thrown; otherwise you'll get a fully deserialized object of the correct type assuming no other errors are found.
For example, suppose you have the following classes:
class Server {
public static void main(String[] args) {
// Set up an OutputStream sink, e.g. writing to a socket (not shown)
...
ObjectOutputStream out = new ObjectOutputStream(sink);
out.writeObject(new Data("data goes here"));
out.flush();
out.close();
}
}
class Client {
public static void main(String[] args) {
// Set up an InputStream source (not shown)
...
ObjectInputStream in = new ObjectInputStream(source);
Data d = (Data)in.readObject();
System.out.println(d.getData());
}
}
class Data implements java.io.Serializable {
private String data;
public Data(String d) {
data = d;
}
public String getData() {
return data;
}
}
Now suppose you put those classes into three jars (one class per jar): server.jar, client.jar and data.jar. If you run the following commands then it should all work:
java -cp server.jar:data.jar Server
java -cp client.jar:data.jar Client
But if you do this:
java -cp server.jar:data.jar Server
java -cp client.jar Client
then you'll get a ClassNotFoundException because the client doesn't know how to find the Data class.
Long story short: the class itself is not written to the stream. If deserialization succeeds then you will have access to the object as though it had been created locally, but you will have to downcast the result of readObject to the expected type.
There is some complexity around versioning that I've ignored for now. Take a look at serialVersionUID and how to deal with changes to serializable classes if versioning is likely to be an issue.
*Not strictly true. You can call readFields inside the serializable object's readObject method (or readResolve), but you cannot call it from outside the deserialization mechanism. Does that make sense? It's a little hard to explain.
Looking at the code for ObjectInputStream.readFields(), that exception is called because the curContext field is null. You should call fromClient.readObject() before calling readFields(), as it will set the curContext. Note that readObject() will return the instance that is being serialized, which may be of more use to you.