Java: Save Object for Later Use - java

Pulling the data from the server (using SOAP methods) is slow and I would like that the program loads with the object already present. I tried the code I found here, but it raises a java.io.NotSerializableException
Now I need the data to remain intact. Is there any way to save it without modifying it?
There were other answers in that post about how to serialize the data, but I am afraid that will skew the results I get with the static object.

java.io.NotSerializableException - This happens if your class isn't implementing Serializable. Object of Serializable class will be written in file as sequence of bytes containing all information of that object.
If you don't want to use it then there are other ways to serialize object like JSON or MessagePack ... Just do research and find one that fits your needs best.

You can use a JSON serializer like Jackson to do this. Ideally the object would have relevant getters for the data you mention that you need to remain intact. Even if the data is private, you can tell Jackson to serialize it anyways using reflection.
ObjectMapper mapper = new ObjectMapper();
// You can use these options if the object doesn't have getters
// for fields that need to be saved, and the fields are private.
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
// Save the string representation somewhere
String yourObjectAsAJsonString = mapper.writeValueAsString(yourObject);
// Load the object back from the string representation
YourObject yourObjectDeserialized = mapper.readValue(yourObjectAsAJsonString, YourObject.class);
Your issue with the java.io.NotSerializableException is probably not under your control because you are receiving the object via SOAP, so you can't make it implement Serializable after the fact. Using a JSON serializer like Jackson can help you get around this problem.

I think your problem is not related to SOAP or data transfer but just Java serialization. Is your class serializable? Can you write a simple main method writing and reading your instance into a file or a ByteArrayOutputStream? See here.
If/when your object is serializable you need to separate the data reading from the deserialization part. Use a ByteArrayOutputStream to collect the data (or a temporary file for very large data) and do the deserialization when the data transfer is completed.
The overall process won't be faster and this will not solve any serialization/deserialization errors, it just allows to separate the two parts allowing you to use different threads or asynchio to better utilize the server resources.

Related

Convert Byte[] to xml

I'm using Axon 2.4.6.
I have a Saga the payload of which was serialized in binary using XStreamSerializer.
The saga looks like this:
public class MySaga extends AbstractAnnotatedSaga {
...
private MyEvent myEvent;
...
}
It contains one event which is the initialize event of the related aggregate object.
Right now I'm having is a deserialization problem because I changed MyEvent by adding one property to it.
I figured out a workaround to this by adding the serialize id that the deserializer is expecting, however this solution might not be the best since I'm on production data right now and would be nice if I was able to somehow upcast the sagas.
So what I intend to do is create a custom serializer that extends JavaSerializer and tweak the SerializedObject<S> that is coming in. The problem is that the SerializedObject is in hex/binary so I need a way to convert it in to an org.dom4j object for instance so I could add the missing property and then be able to deserialize it in to MySaga.
I tried several approaches like
ByteArrayInputStream bos = new ByteArrayInputStream((byte [])serializedObject.getData());
or new XStream();
but they all go from the binary representation straight to the object deserialization, what I need is to get the dom4j or even xml conversion first.
I can't figure out how to do it.
I have to say that Axon 2 is not something I have experience with but let me try to help you nonetheless.
As I can find on the docs, Axon provide an example of how to write an upcaster here using the correct 2.4 documentation link.
What is not clear for me, based on your question, is if you are using the JavaSerializer or an XStreamSerializer (or JacksonSerializer to make it complete).
In the case you are using XML, the docs will provide you an example of an upcaster. What is good to mention (and check) is that you can also look into xStream.ignoreUnknownElements() which will make your Serializer lenient meaning it won't fail when trying to deserialize something which contains an attribute it does not know (very useful I would say).
If you are using JSON, you also have the FAIL_ON_UNKNOWN_PROPERTIES "feature" that can be disabled in this case to make it lenient.
Making your serializers lenient seems to be the correct route if you ask me. If you really need to add a default/derived value to the new field, than the upcaster route is the one you should pick.
KR,
Edit 1: triggered by the comment given by Steven, this led me to add this edit and ask you how long do you expect this Saga to live. Now that I noticed the Event is part of your Saga, I would rather write a new Saga that does not contains the Event as part of it but just fields not coupling it to any specific Event.

Spring MVC - should my domain classes implement Serializable for over-the-wire transfer?

I'm trying to learn Spring Boot by implementing a simple REST API.
My understanding was that if I need to transfer an object over the wire, that object should implement Serializable.
In many examples on the net though, including official ones, domain classes that need to be transferred from server to client (or vice-versa) do not to implement Serializable.
For instance: https://spring.io/guides/gs/rest-service/
But in some cases, they do:
For instance: https://github.com/szerhusenBC/jwt-spring-security-demo/blob/master/src/main/java/org/zerhusen/security/JwtAuthenticationRequest.java
Is there a general rule of thumb on when to implement Serializable?
To update this, advice about Serializable has changed, the recommendation currently seems to be Don’t use Serializable for anything.
Using the Java serialization API means you need something in Java on the other side of the wire to deserialize the objects, so you have to control the code that deserializes as well as the code that serializes.
This typically isn't relevant for REST applications, consuming the application response is the business of someone else's code, usually outside your organization. When building a REST application it's normal to try to avoid imposing limitations on what is consuming it, picking a format that is more technology-agnostic and broadly available.
Some reasons for having an object implement java.io.Serializable would be:
so you can put it in an HttpSession
so you can pass it across a network between parts of a distributed application
so you can save it to the file system and restore it later (for instance, you could make the contents of a queue serializable and have the queue contents saved when the application shuts down, reading from the save location when the application starts to restore the queue to its state on shutdown).
In all these cases, you serialize so you can save something to a filesystem or send it across a network.
There are many ways to serialize an object. Java's object serialization is just one of them. From the official documentation:
To serialize an object means to convert its state to a byte stream
REST APIs usually send and receive JSON or XML. In that case serializing an object means converting its state to a String.
There is no direct connection between "sending an object over the wire" and implementing Serializable. The technologies you use dictate whether or not Serializable has to be implemented.
The specific examples you have mentioned do not transfer objects over the wire. From the example links I see that the controller methods return a domain object with ResponseBody annotation. Just because the return type of the method is the domain object it is not necessary that the whole object is being sent to the client. One of the handler method in Spring mvc framework internally intercepts the invocation and determines that the method return type does not translate to direct ModelAndView object. RequestResponseBoodyMethodProcessor which handles the return value of such annotated methods and uses one of the message converters to write the return object to the http response body. In the case the message converter used would be MappingJackson2HttpMessageConverter. So if are to follow the same coding style you are not required to implement Serializable for your domain objects.
Have a look at this link for the Http message converters provided by default from spring. The list is quiet extensive however not exhaustive and if requirements arise you can implement your own custom message converter to user as-well.
that's a good question when to implement Serializable interface.
these links can provides some useful contents:
Serializing java.io.Serializable instance into JSON with Spring and Jackson JSON
When and why JPA entities should implement the Serializable interface?
I sometimes wonder about this, and I think
Because Java is a open source language, and more libraries providered by third party. for tells who will serialize and deserialize the object, the java offical declare a constract interface, makes transfer easy and safety throught different library.
It's just a constract, most third-party libraries can serialize/deserialize when checking implement this constract. and jackson's jar library is not use it.
So you can deem if you use serialize/deserialize object data in your own system, and simple process, likes just serialize and response it(jackson in spring MVC), you needn't to implements it.
but if you used in other jar library, likes saving in HttpSession, or other third-party componens/library, you should(or have to) implement Serializable, otherwise the libraries will throw a exception to tell you the constract interfaced which it knows is not provide.
But they said it's a good habit and best properties that to implement the Serializable when serialize a custom class. :)
you should serialize if you are using caching for database operations.Usually the third party cache providers like (hazle cast, Jboss cache etc..) internally serialize/ de serialise objects.In that case model classes should implement Serializable to facilitate caching.

Persisting a Parcelable object in Android

I have a class in my Android app that I've made Parcelable so that it can be passed between Activities.
I would like to be able to save this object to the filesystem. It seems that since I've already implemented Parcelable, it would make sense to pipe the output of this to the filesystem and read it back later.
Is there a correct way to do this? Or must I implement both Parcelable and Serialiazble if I want to both pass the object between Activities and also save it to the filesystem?
From http://developer.android.com/reference/android/os/Parcel.html
Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.
For this problem, I did the following:
Implemented Serializable in my object
Added a toJSON() method to convert the object to a JSON object
Used a custom JSONSerializer to write the JSON objects to a file
Added a constructor that takes a JSON object as a parameter, used by the custom JSONSerializer
It ended up being pretty simple...I can paste some sample code if needed.

Java: Serialization: How to store only a reference, not the content

I'm creating an undo-redo mechanism. To achieve this, I'm using Serialization. Recording the current state by writing it to a ByteArrayOutputStream, using ObjectOutputStream and putting the byte[] into an ArrayList.
But the problem is that, some of the classes are holding a reference/pointer to a BufferedImage. Which I don't want to serialize because of its size (and it doesn't implement Serializable). The reason why I don't want to write it is that it will never change. But it is a different image for each instance of the class, so the static keyword isn't a solution.
My attempt to solve:
public transient BufferedImage img;
This causes the ObjectOutputStream will not serialize the BufferedImage, but it won't store the reference as well. After deserializing, it will be null.
So, in short, I want to keep the reference to the object, but not the object itself. Which means that, after deserialazing I will be able to use the BufferedImage (because of it isn't removed by the Garbage Collector).
Many thanks.
OK, simple enough, keep a Map<String, BufferedImage> of all images somewhere in your application, let each of your classes serialize the key to its image. And in the readResolve() method, look up the image from the map.
What you are asking for is impossible. Think about it...if you serialized your object and sent it over the internet to a different computer, how on earth would that BufferedImage reference end up pointing to the right object without you sending over the BufferedImage itself as well?
It seems like you're serializing and deserializing within the same Java instance. That's certainly not what Java serialization is meant for; the general case is that the instance that serializes an object will not be the same as the one that deserializes it.
What you can do is write custom (de)serialization logic for your class via readObject() and writeObject(). You could for instance serialize the resource URL or a unique identifier for the image instead of the image itself.
You could add writeObject(java.io.ObjectOutputStream stream) and readObject(java.io.ObjectInputStream stream) methods to your object to customize the serialization process.
Mark the reference transient and then perform logic in writeObject to write a token in the stream to let you identify it later in readObject and re-create it.
See this page for an example of this:
http://www.javapractices.com/topic/TopicAction.do?Id=70
In short you can't with only serialization. So I'd suggest getting clever with it. Still continue to mark it transient, but you can hook the serialization process to write out the image when you save it. By adding a methods:
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException;
private void writeObject(java.io.ObjectOutputStream stream)
throws IOException
Those will get called when you deserialize and serialize (respectively). You could then save the file's contents out to a temp folder. Using some sort of unique ID for each instance you could keep separate files on the filesystem so when you undo/redo you would read and write to the same file no matter how many levels of undo/redo you have.
Remember to call defaultWriteObject() and defaultReadObject() inside those methods you're adding so the default serialization is performed.

Better way to store data in java?

I am currently working on a videogame, and i want to have the user be able to save their character to a new file. I know how to use the file io (for the most part), but i have been using the 'serialize' to serialize a whole object (that contains all the variables for the character) and save it to a file. The problem is that i am constantly updating the object and making changes to it, so when i try to load the old character with the new object, it errors and crashes. Same with levels as-well (an object holding a few 2d-array of variables).
There must be a better way to do this so it is compatible with future versions. If there is a way, would anybody please offer some source code and/or a link to a nice tutorial? All help is appreciated, thanks!!!
Use XML or an embedded database (fast and lightweight) such as Derby or H2. You could even use a plain old properties file.
In fact, see if the properties file will work for you. And only if that won't work, try XML or the embedded database approach.
if you are looking for java serializers here is the benchmark for you https://github.com/eishay/jvm-serializers/wiki/
Apache Avro seems to perform well.
Another way is to store the values in the persistent store like HSQLDB or H2 db and load it to memory at startup and persist when needed.You can also use SQLite (for driver check this)
You can implement Externalizable instead of Serializable, and in the readExternal() and writeExternal() methods you can put the logic to read/write the object. This way you have full control of serialization/deserialization and can make changes fairly easily. Alternatively you can use JSON serialization by using Gson. I would not recommend XML, but if you want to you can check out xstream for the same thing.
If you are extending your objects in backwards compatible ways, i.e. add fields, and not removing fields. Make sure that you have declared a serialVersionUID as per the serializable javadoc.
http://download.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html
One additional option to consider since you're already using serialization, you could implement Externalizable instead of Serializable. The code you use to serialize objects would remain the same. However in your class you would specify exactly how you want it serialized by overriding readExternal() and writeExternal(). E.g.:
public class MyClass implements Externalizable {
private int foo;
private String bar;
public readExternal(ObjectInput in) {
foo = in.readInt();
bar = in.readUTF();
}
public writeExternal(ObjectOutput out) {
out.writeInt(foo);
out.writeUTF(bar);
}
}
Just be sure to keep the order the same when reading and writing. Try to only add fields, however if you need to remove a field leave a gap to account for old versions.
Ultimately though if you're making a lot of changes it might best to switch to a properties or XML file as LES2 suggested. It'll be more portable and readable that way.
This game uses java.util.prefs.Preferences for cross-platform convenience. Because keys are stored individually, new additions rarely interfere with existing entries.

Categories

Resources