I have a Trade object with the code below and it implements the Serializable interface but since it contains javafx properties , I get this java.io.NotSerializableException and hence failed to properly do writeObject() and readObject(). My ultimate goal is to be able to write and read this object using ObjectOutputStream and ObjectInputStream
I read the 3 links:
NotSerializableException on SimpleListProperty
Oracle doc
Java Custom Serialization
Since my Trade class is running a ScheduledService to pick up the closing price from Google Finance, I know that I need to call startService() within the readObject() to ensure that when the readObject() method is called and the object is deserialized, the thread will restart again.
Furthermore, I understand that I need to I need to define these 2 private methods within my Trade Class.
private void writeObject(ObjectOutputStream out) throws IOException
{
out.defaultWriteObject();
// What else should I write in here?
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
// our "pseudo-constructor"
in.defaultReadObject();
// Not sure what else I need to write in here
// now we are a "live" object again, so let's run rebuild and start
startService();
}
Question: I have read the 3rd link above and I am still confused about what else should go into these two private methods above ?
Because my trade object has quite a lot of properties, but all it really needs
are just buySell,transactionDate,symbol, double volume, double price to construct an object. Should I set the rest of the properties to transient then?
public class Trade implements Serializable{
// properties
private Long creationTime;
private int counter;
private ObjectProperty<LocalDate> transactionDate;
private StringProperty symbol;
private StringProperty details;
private StringProperty buySell;
private DoubleProperty volume;
private DoubleProperty price;
private ReadOnlyDoubleWrapper transactionFee;
private final ReadOnlyDoubleWrapper closingPrice;
private final PauseTransition delay;
private ReadOnlyBooleanWrapper caution;
private final ScheduledService<webScraping> stockService = new ScheduledService<webScraping>() {
// web scrape google finance data
...
}
// constructor
public Trade(BuySell buySell, LocalDate transactionDate, String symbol, double volume, double price){
...
startService();
creationTime = Calendar.getInstance().getTimeInMillis();
}
// getters and setters and instance methods that return the properties themselves
public Long getCreationTime(){
return this.creationTime;
}
private Object writeReplace() {
return new TradeProxy(this);
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
...
private static class TradeProxy implements Serializable{
private String buySell;
private LocalDate transactionDate;
private String stockTicker;
private double price;
private double volume;
private Long creationTime;
private TradeProxy(Trade trade){
this.buySell = trade.getBuySell();
this.transactionDate = trade.getTransactionDate();
this.stockTicker = trade.getStockTicker();
this.price = trade.getPrice();
this.volume = trade.getVolume();
this.creationTime = trade.getCreationTime();
}
private void writeObject(ObjectOutputStream s ) throws IOException{
s.defaultWriteObject();
}
private Object readResolve() throws ObjectStreamException{
return new Trade(this.buySell,this.transactionDate, this.symbol, this.volume, this.price);
}
}
}
UPDATE: I have updated my code. But since creationTime is not an argument of the Trade's constructor, I do not know how to serialize/deserialize it in my case. To be more precise, if I create a Trade object at time say creationTime = 1443444301488, I want this object be serialized and when I read in the object and deserialize it, I want to the creationTime to be exactly the same as what it was (i.e. 1443444301488) and I don't know how to achieve this. This is the problem that I am facing now.
I would avoid serializing javafx objects. Instead create a javabean object that contains the state that should be serialized. Then you can have your Trade object build itself from the serialized proxy javabean.
class TradeSerialProxy {
private String simpleBeanFields;
private int moreSimpleStateFields;
//getters and setters
}
then
public Trade (TradeSerialProxy proxy) {
//build the Trade object using the proxy.
}
You see something similar to this in the Effective Java book. Though in that book he uses proxies for security purposes. The rule I follow is to only serialize simple javabean objects and that's that. Avoid serializing complicated objects.
Also, if you use regular Java serialization, then you might run into version problems whenever your class implementation changes. There are ways around this, like using JSON and GSON for serialization. Because I was using pure standard Java, and no external libs/jars, I had to accomplish this with HashMap... where I would only serialize the HashMap and have the real objects build themselves using a HashMap passed to it. I had to do this to avoid getting the constant serial version mismatch exception and sticking to pure standard vanilla Java.
EDIT: This is an object that uses serialization proxy pattern. This apporach is from Effective Java 2nd Edition item 78.
public class UserProfile implements Serializable {
///////////////////////////////////////////////////////////////////////////
//private variables
private String profileName = null;
private int version = 0;
private LeaderboardPermissions leaderboardState = LeaderboardPermissions.ASK;
private boolean upgradeWalkThrough = true;
private final Map<GameType, GameTypeStats> gameTypeStats;
private final String id;
private boolean offNet = true;
///////////////////////////////////////////////////////////////////////////
//serialization stuff
private static final long serialVersionUID = 7625672295622776890L;
private UserProfile(UserProfileProxy t) {
this.profileName = t.profileName;
this.version = t.version;
this.leaderboardState = t.leaderboardState;
this.upgradeWalkThrough = t.upgradeWalkThrough;
this.gameTypeStats = t.gameTypeStats;
this.id = t.id;
this.offNet = t.offNet;
}
private Object writeReplace() {
return new UserProfileProxy(this);
}
private void readObject(ObjectInputStream stream)
throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
///////////////////////////////
//serialization proxy
private static class UserProfileProxy implements Serializable {
private String profileName = null;
private int version = 0;
private final LeaderboardPermissions leaderboardState;
private boolean upgradeWalkThrough = true;
private final Map<GameType, GameTypeStats> gameTypeStats;
private String id;
private static final long serialVersionUID = 6985672045622776890L;
private boolean offNet;
private UserProfileProxy(UserProfile t) {
this.profileName = t.profileName;
this.version = t.version;
this.leaderboardState = t.leaderboardState;
this.upgradeWalkThrough = t.upgradeWalkThrough;
this.gameTypeStats = t.gameTypeStats;
this.id = t.id;
this.offNet = t.offNet;
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
}
private Object readResolve() throws ObjectStreamException {
return new UserProfile(this);
}
}
This approach is baked into Java object serialization protocol. Another method I am using now utilizes a HashMap<String, Object> as the proxy.
Here is the interface. I had to have the methods in this interface return their hash because my extensive use of encrypting the serialized object's hashes to prevent tampering with the saved files. I'm not necessarily recommending this but showing possibilities of serialization proxies.
public interface MapSerializable {
public static String CLASS_KEY = "MapSerializable.CLASS_KEY";
/**
* Object will populate a HashMap of objects that it can use at some later
* point to reinitialize itself. Return the hash of the objects used to
* build itself.
*
* #param serial
* #return
* #throws IOException
*/
public int populateSerialMap(HashMap<String, Object> serial) throws IOException;
/**
* Object will initialize itself using the input HashMap. Returns the hash
* of the objects that were used to initialize itself from the Map.
*
* #param serial
* #return hash of the objects that were used to load yourself.
* #throws IOException
*/
public int initializeFromMap(HashMap<String, Object> serial) throws IOException;
}
And here is an example of an object using it.
public class GameType implements MapSerializable {
////////////////////////////////////////////////////////////////////////////
//private variables
private String displayName = null;
////////////////////////////////////////////////////////////////////////////
//constrcutor
public GameType(String name) {
this.displayName = name;
}
GameType() {
}
////////////////////////////////////////////////////////////////////////////
//public methods
#Override
public int populateSerialMap(HashMap<String, Object> serial) throws IOException {
serial.put("displayName", displayName);
return 17 * Objects.hashCode(displayName);
}
#Override
public final int initializeFromMap(HashMap<String, Object> serial) throws IOException {
int hash = 0;
ObjectHashPair<String> ohp = model.utils.SerialUtils.getObjectFromMap(serial, "displayName", "");
displayName = ohp.obj;
hash += 17 * ohp.hash;
return hash;
}
}
EDIT2: Deeper explanation into the first method.
You need to first understand some of the basics of Java serialization. Java does most of the heavy lifting for you, it actually has a writeObject and readObject that work just fine for most cases. This is good news for you since all you need to do is deciding what fields need to go into the proxy just the things you want to serialize (the state) and not have to worry about actually doing the serialization (adding/removing objects to the stream). Next, you need to be able to initialize your main class using the proxy and vice versa. So create a constructor in your main class that takes a proxy object as input, in that constructor initialize your main class. Do the same for the proxy object. Lastly, Java even gives you the ability to use a proxy for writing and reading via the writeReplace and readResource methods. The writeReplace for the main class will return an instance of the proxy, essentially telling Java to serialize that object instead. On the flip side in the proxy you'll need a readResolve to return an instance of the main object during deserialization.
SO lets go through the steps in a bullet list:
1) Decide what fields need saving and create your proxy class (I used an inner nested class) to have those fields.
2) Create the constructors in main and proxy class. Main(Proxy obj) and Proxy(Main obj).
3) Implement the writeReplace and readResolve on the main and proxy classes, respectively.
I hope that helps.
Related
I have created a simple class:
public class Example
{
private String name;
private int age;
// With getters and setters.
}
that I would like "put" into a chronicle map:
ChronicleMap<String,Example> map = ChronicleMapBuilder
.of(String.class, Example.class)
.name("example-map")
.entries(5_000)
.averageValue(new Example())
.valueMarshaller(ExampleSerializer.getInstance())
.averageKey("Horatio")
.createPersistedTo(new File("../logs/example.txt"));
However, I do not fully understand how to implement the ExampleSerializer class because I am not sure how the string member variables should be handled. How do I size strings? In the read and write methods, how do I read the string member variable, and how do I write the string member variable respectively. Pls note that on average, the name member string length will be between 7-10 characters. I have created the serializer below:
public class ExampleSerializer implements SizedReader<Example>,SizedWriter<Example>
{
private static ExampleSerializer INSTANCE = new ExampleSerializer();
public static ExampleSerializer getInstance() { return INSTANCE; }
private ExampleSerializer() {}
#NotNull
#Override
public Example read(Bytes in, long size, #Nullable Example using)
{
if (using == null)
using = new Example();
using.setAge(in.readInt());
using.setName(in.readUtf8()); // NOT SURE IF THIS IS CORRECT FOR A STRING
return using;
}
#Override
public long size(#NotNull Example toWrite)
{
return Integer.BYTES + ???; // NOT SURE WHAT THE SIZE SHOULD BE FOR STRING MEMBER?
}
#Override
public void write(Bytes out, long size, #NotNull Example toWrite)
{
out.writeInt(toWrite.getAge());
out.writeUtf8(toWrite.getName()); // NOT SURE IF THIS IS CORRECT FOR A STRING
}
}
When reading Effective Java I found that the most useful approach to implement singletons is just using enums with single INSTANCE. But in case we need to make it a class, according to some of his susggestions the perfect serializable thread-safe singleton class would look like this:
public class SerializableSingletonClass implements Serializable{
private static final long serialVersionUID = 1L;
private int value;
private String name;
private SerializableSingletonClass(int value, String name) {
if( value < 0 ) throw new IllegalArgumentException("Value may not be less than 0");
this.value = value;
this.name = Validate.notNull(name, "Name may not be null");
}
private static class SerializableSingletonHolder{
public static final SerializableSingletonClass INSTANCE;
static {
INSTANCE = new SerializableSingletonClass(0, "default");
}
}
private void readObject(ObjectInputStream stream) throws InvalidObjectException{
throw new InvalidObjectException("proxy required");
}
private Object writeReplace(){
return new SerializationProxy(this);
}
private static class SerializationProxy implements Serializable{
private static final long serialVersionUID = 1L;
public SerializationProxy(SerializableSingletonClass ignored) { } //Here is the question
private Object readResolve(){
return SerializableSingletonHolder.INSTANCE;
}
}
}
As far as I got he proposed to just replace serialized instances with one that's used currently.
So, why do we ever need to make singletons serializable in the owing that their serial form would not be ever used. We just throw it out and replace deserialized instance with the current one.
To me the problem of implementing serializable singletons looks like only a theoretical one. Accoring to what I said, deserializing singleton doesn't make much sense (in the case of enums either).
So what did I miss? Couldn't you explain it in a bit more detail?
enums are also serializable, just not their fields.
I think it's important to keep it simple and easy to maintain e.g. use a text file if you are going to save it.
I would add a method like save and load to it (possibly with a filename)
enum SaveableSingleton {
INSTANCE;
String name;
int value;
public void load(String filename) throws IOException {
try (Scanner scanner = new Scanner(new File(filename))) {
name = scanner.nexLine();
value = scanner.nextInt();
}
}
public void save(String filename) throws IOException {
try (PrintWriter pw = new PrintWriter(new File(filename))) {
pw.println(name);
pw.println(value);
}
}
}
creates a file like
my-name-is
12345
If you have some field in some other serializable class where you store this singleton instance and want to serialize / deserialize that class, you would always have to mark that field transient and make sure to fill it manually on deserialization. If you handle it in the Singleton, you don't have to do this. I guess that is the reason for a serializable singleton.
While creating my app. architecture I faced the need for one structure, that will be described below.
I'm pretty sure, that there is a well known design pattern with the same functionality, because I think that problem, for which I develop it is really common.
I write my own implementation of this, but I always try to use "build in language" implementations of patterns, so - please help me to name this construction.
The idea is close to reader-writer pattern. We have a "container" in which we can add Objects by the key (). And also we can get this objects by keys, removing it from container.
So, the implemented class should have two methods:
void putObject(Key key, Object object);
Object getObject(Key key); // remove <Key,Object> from container.
The next is most interesting.
This container should work in multi-threading environment as follows:
If there is no object associated with key, while calling get(Key
key) method the caller thread should WAIT for the object in this
container.
When another thread will call putObject(Key key, Object object)
method it should check if there is some thread that wait exactly for
this object, and if it is - then signal and wake up the thread that
waits.
I think that it is common structure, does it have "official" name?
My Java implementation of this pattern:
private static interface BlackBox {
public void addObject(IdObject object);
public IdObject getObject(ObjectId id);
}
private static class BlackBoxImpl implements BlackBox {
private final Lock conditionLock = new ReentrantLock();
private final Map<ObjectId, IdObject> savedObjects;
private final Map<ObjectId, Condition> waitingConditions;
public BlackBoxImpl() {
this.savedObjects = new ConcurrentHashMap<ObjectId, IdObject>(20);
this.waitingConditions = new ConcurrentHashMap<ObjectId, Condition>(20);
}
#Override
public void addObject(IdObject object) {
savedObjects.put(object.getId(), object);
if (waitingConditions.containsKey(object.getId())) {
Condition waitCondition = waitingConditions.get(object.getId());
conditionLock.lock();
waitCondition.signal();
conditionLock.unlock();
}
}
#Override
public IdObject getObject(ObjectId id) {
if (savedObjects.containsKey(id)) {
return savedObjects.get(id);
} else {
conditionLock.lock();
Condition waitCondition = conditionLock.newCondition();
waitingConditions.put(id, waitCondition);
waitCondition.awaitUninterruptibly();
conditionLock.unlock();
return savedObjects.get(id);
}
}
}
private static interface IdObject {
public ObjectId getId();
}
private static class IdObjectImpl implements IdObject {
protected final ObjectId id;
public IdObjectImpl(ObjectId id) {
this.id = id;
}
#Override
public ObjectId getId() {
return id;
}
}
private static interface ObjectId {
}
private static class ObjectIdImpl implements ObjectId {
}
I would probably use something like a
ConcurrentMap<K,BlockingQue<V>>.
Use the concurrent methods of the Map to add the pair. Take from your queue for the value. Use an ArrayBlockingQue(1).
Something like this perhaps:
static class MultiQueue<K, V> {
// The base structure.
final ConcurrentMap<K, BlockingQueue<V>> queues = new ConcurrentHashMap<>();
/**
* Put an item in the structure.
*
* The entry in the map will be created if no entry is currently there.
*
* The value will then be posted to the queue.
*/
public void put(K k, V v) throws InterruptedException {
// Make it if not present.
ensurePresence(k).put(v);
}
/**
* Get an item from the structure.
*
* The entry in the map will be created if no entry is currently there.
*
* The value will then be taken from the queue.
*/
public void get(K k) throws InterruptedException {
// Make it if not present - and wait for it.
ensurePresence(k).take();
}
private BlockingQueue<V> ensurePresence(K k) {
// Make it if not present.
return queues.computeIfAbsent(k, v -> new ArrayBlockingQueue(1));
}
}
Looking at your design, to me what you are describing
We have a "container" in which we can add Objects by the key (). And also we can get this objects by keys, removing it from container.
This container should work in multi-threading environment
is close to concurrent Object pool. It uses a set of initialized objects kept ready to use. A client of the pool will request an object from the pool and perform operations on the returned object.
The only real difference I see is that you are getting the objects based on your own criteria.
I have encountered a weird problem in my app (java).
I have an enum. Something like that
public enum myEnum implement myIntrface{
valueA(1),valueb(2),valuec(3),valued(4)
private int i;
// and then - a constructor
public MyEnum(int number){
i = number;
}
private MyObj obj = new MyObj;
// getter and setter for obj
}
and in another class I have this
MyEnum.valueA.setObj(new Obj(...))
in briefe - I have an enum with a private instance member that has a set and a get.
So far so good -
The only thing that amazes me is that later on I look at the value of the MyEnum.valueA().obj is null.
there is nothing that updates the value to null, I have even gave it a default value in the constructor and I still see it null later.
any suggestions?
Enums should be un-modifiable classes so you shouldn't really be doing this. If your looking to modify the state of a type based object like an enum you should use an final class approach with embedded constants. Below is an example of a class based approach with a modifiable name an a un-modifiable name...
public final class Connection {
public static final Connection EMAIL = new Connection("email");
public static final Connection PHONE = new Connection("phone");
public static final Connection FAX = new Connection("fax");
/**/
private final String unmodifiableName; //<-- it's final
private String modifiableName;
/*
* The constructor is private so no new connections can be created outside.
*/
private Connection(String name) {
this.unmodifiableName = name;
}
public String getUnmodifiableName() {
return unmodifiableName;
}
public String getModifiableName() {
return modifiableName;
}
public void setModifiableName(String modifiableName) {
this.modifiableName = modifiableName;
}
}
The purpose of enums is to represent constant values. It does not make any sense to set the fields of a constant value.
You should declare your fields as final, and use the constructor to initialize all of them.
For reference, the following code works as expected:
public class Test {
public static enum MyEnum {
valueA(1),valueb(2),valuec(3),valued(4);
private int i;
private Object o;
private MyEnum(int number) {
i = number;
}
public void set(Object o) {
this.o = o;
}
public Object get() {
return o;
}
}
public static void main(String[] args) {
System.out.println(MyEnum.valueA.get()); // prints "null"
MyEnum.valueA.set(new Integer(42));
System.out.println(MyEnum.valueA.get()); // prints "42"
}
}
the cause of this problem is the db40 framework . It loads an enum from the db using reflection. This is well documented .
http://developer.db4o.com/Forums/tabid/98/aft/5439/Default.aspx
Right now I have about 60 Message types which are passed to a getStuff(Message) method of a class which implements ContainerOfThings. There are multiple variations of an ContainerOfThings such as BoxOfStuff and BagOfTricks both of which realize the getStuff(Message) method which generates a string based on member variables. The result may also have pre-pended or post-pended data such as labels or concatenated data. See code below.
public class BoxOfStuff implements ContainerOfThings
{
private String var1;
private String var2;
private String varN;
public String getStuff(Message message)
{
if (message.equals(Message.GET_STUFF1))
return var1;
else if (message.equals(Message.GET_STUFF2))
return "Var2 is: " + var2;
else if (message.equals(Message.GET_STUFFN))
return varN + "\n";
// Etc. for each Message.GET_*
}
// getters and setters for each var*
}
public class Message
{
private String id = null;
private Message(String id)
{ this.id = id; }
public final String toString()
{ return this.id; }
public static final Message GET_STUFF1 = new Message("V1");
public static final Message GET_STUFF2 = new Message("V2");
public static final Message GET_STUFFN = new Message("VN");
}
I am trying to find a design that meets the following objectives. (1) The string returned from getStuf() needs to reflect the current state of the implementing class's member fields. (2) Also I would prefer to get away from an incredibly long series of if / else if blocks. One concern is ease of potentially changing to a persistent data-driven configurable object approach which a Map lends well towards. (3) Design should allow for simple maintenance and/or edits.
One design that could work but is a little messy is to create a Map with all key/values initialized in the constructor and also reset any key/value pair inside each setter method. In this way, the response to getStuff(Message) is updated to the new content after changes (ie: in a setVar*() method). Any other thoughts?
I think you'll need two maps. One will be a Map<Message, String> where the value will be a format string (i.e. something that will get passed into String.format()). The second map will be a Map<Message, Field> which should be fairly self explanatory once you take a look at the reflection libs. These will need to be setup at init time but after that the getStuff() method should be fairly clean and your setters won't be affected at all.
BTW, Java doesn't generally prefix interfaces with I.
I'm not 100% sure I understand your problem, but it sounds like you want to memoize the result of your getStuff() call.
One easy way to do this is to use the makeComputingMap() method from the MapMaker class in the Google Guava library.
For example, you could do:
Map<Message, String> map = new MapMaker()
.expireAfterWrite(10, TimeUnit.MINUTES)
.makeComputingMap(
new Function<Message, String>() {
public String apply(Message message) {
// Your getStuff() implementation here
}
});
Does that make sense?
How about this:
public abstract class BaseOfBox implements IContainerOfThings {
protected final Map<Message, String> stuffs =
new HashMap<Message, String>();
public final String getStuff(Message message) {
return stuffs.get(message);
}
}
public class BoxOfStuff extends BaseOfBox {
private String var1;
private String var2;
public BoxOfStuff() {
super();
}
public setVar1(String var1) {
this.var1 = var1;
stuffs.put(Message.GET_STUFF1, var1);
}
public setVar2(String var2) {
this.var2 = var2;
stuffs.put(Message.GET_STUFF2, "Var2 is: " + var2);
}
...
}
Frankly, I think this is a pretty ugly solution, but so are the requirements, IMO. I suspect a more elegant solution can only be found if we review the (real) requirements