I am sending an object encased in a Message object encase in a SignedObject over a TCP connection using an ObjectInputStream. Here's the basic code:
Send
Object data = someObject;
ObjectOutputStream = new ObjectOutputStream(socket.getOutputStream());
Message newMsg = new Message(data);
out.writeObject(security.signObject(newMsg,privKey));
Receive
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Object line = in.readObject();
SignedObject messageIn = (SignedObject) line;
Message msg = (Message) messageIn.getObject();
The Message class is a basic class with only fields and no methods. One of the fields is Object Message.data, which in this case contains either siena.Filter or siena.Notification. When I call SignedObject.getObject(), I get an InvalidObjectException. The stack trace is below.
java.io.InvalidObjectException: siena.SENPInvalidFormat
at siena.Filter.readObject(Filter.java:127)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at java.security.SignedObject.getObject(Unknown Source)
The code for the message transfer is correct. It works for numerous other cases with other classes, and even with other versions of the same class. It is not working for a specific version of siena.Filter and siena.Notification.
I can see that the readObject() method of the class being sent (siena.Filter or siena.Notification) is being called, but I don't know if this is supposed to be happening or not. I know that an exception is being thrown within the siena method, which I'm guessing is causing the InvalidObjectException.
So the question is, is the problem that siena.class.readObject() is throwing an exception and is not written properly, or is the problem that siena.class.readObject() is being called at all? If the latter, how would I go about fixing that?
Thanks,
David
Why do you just type cast what you are getting from your InputObjectStream to the type of object that you are passing ? Once you get readObject, just typecast it to your SingledObject, should work ? Sorry again I am unable to completely understand. Its better you put in some code here.
Related
I have an object in Jython that extends a Java Swing JFrame. My goal is to serialize it in order to save it on MySql, query the database, deserialize it and review the JFrame exactly as it was before it was deserialized (with all fields filled in).
I honestly don't know where to start. I can't imagine serialization - saving to database.
I guess the serialized JFrame could be blob, longblob or bit type on MySql.
For now I have done a local experiment using my old and little academic knowledge on the serialization of objects in java, with poor results:
def saveArt(self, e):
v = Vector()
v.add(self) # self = JFrame in question
out = ObjectOutputStream(BufferedOutputStream(FileOutputStream("prova.dat")))
out.writeObject(v)
out.close()
What I did was just put the frame in a Java vector and save it to the file, however I got the following error:
Exception in thread "AWT-EventQueue-0" at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at javax.swing.event.EventListenerList.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteObject(Unknown Source)
at javax.swing.JComponent.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.saveInternal(Unknown Source)
at java.awt.AWTEventMulticaster.save(Unknown Source)
at java.awt.Component.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeArray(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.access$300(Unknown Source)
at java.io.ObjectOutputStream$PutFieldImpl.writeFields(Unknown Source)
at java.io.ObjectOutputStream.writeFields(Unknown Source)
at java.util.Vector.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
java.io.NotSerializableException: java.io.NotSerializableException: org.python.core.packagecache.SysPackageManager
This experiment is of little importance, because it is certainly not the final goal. It was just to figure out if I could serialize it locally.
The final goal is to save it on the MySql database and extract it exactly as it was saved.
So I need to understand 3 things:
how to serialize JFrame with Jython (assuming serialization is the best way to "package" a filled JFrame for a database, if there's a better way don't hesitate to say so)
what kind of data to set on Mysql (assuming MySql is the perfect dbms to do this, if there are better technologies, don't hesitate to say it!) and if you need to make a particular query
how to deserialize it to see it exactly as I left it (assuming deserialization is the best way to retrieve the JFrame)
Thank you so much in advance my saviors (if there are any)
Firstly, Java Serialization is a bad idea at the best of times. The Secure Coding Guidelines for Java SE says "Note: Deserialization of untrusted data is inherently dangerous and should be avoided." Unfortunately that text is no longer in red.
It is even more problematic in this case as that data will just be in a blob in the database, and Swing doesn't guarantee serialisation compatibility between versions (perhaps even updates?).
That out of the way: From the stracktrace, the problem object is a SysPackageManager somewhere within ConcurrentHashMap itself within ConcurrentHashMap itself, which you probably don't want to keep.
Setting the system property sun.io.serialization.extendedDebugInfo (may change) to true will give some more information as to how the object is referenced.
Clearly JFrame is too much. There are better ways to store data.
Tom has covered reasons of error and possible ways to debug further
I will try to address the 3 things you asked in detail with java code:
How to serialize ? - Answered below
Which datatype to use to create mysql column to store this data ? - I would say mediumblob in case of mysql, blob might to too small and longblob might be too big. I used longtext as well and it works as expected without any issues, but its really long answer to explain why blob and not text fields. May be this stackoverflow answer will throw more light - What column type should be used to store serialized data in a mysql db?
How to de-serialize and use ? - Answered below
Moving to answer:
You can achieve this in few steps
create JFrame
serializing java object to mysql database - this is as simple as
preparedStatement.setObject(jframe_object_to_save_to_database);
pstmt.executeUpdate();
de-serializing java object from mysql database and converting it into JFrame object - this is not that straight forward, but not that complicate too, my approch will be of 4 steps like below
3.a. Just read your column value as bytes array
3.b. create a ByteArrayInputStream object of the bytes array we got from database
3.c. create ObjectInputStream from ByteArrayInputStream
3.d. use ObjectInputStream.readObject() method to get de-serialized object
These steps are covered in the below code snippet
byte[] buf = rs.getBytes(1);
ObjectInputStream objectIn = null;
if (buf != null)
objectIn = new ObjectInputStream(new ByteArrayInputStream(buf));
Object deSerializedObject = objectIn.readObject();
Now as we have the de-serialized object ready for our use (from 3.d), you can parse it into a JFrame object easily and use it as you need
Jframe deSerializedObject = (JFrame) objectIn.readObject();
Below is the complete java implementation that I have, it is a simple JFrame working code with mysql database, please follow Step 1 thru Step 5 which I wrote as comments in the code and also read the Note that I mentioned in deSerializeJavaObjectFromDB method
import java.awt.FlowLayout;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SerializeToDatabase {
private static final String SQL_CREATE_TABLE = "create table if not exists serialized_java_objects (object_name varchar(1000), serialized_object blob)";
private static final String SQL_SERIALIZE_OBJECT = "INSERT INTO serialized_java_objects(object_name, serialized_object) VALUES (?, ?)";
private static final String SQL_DESERIALIZE_OBJECT = "SELECT serialized_object FROM serialized_java_objects limit 1";
public static void createTable(Connection connection) throws SQLException {
connection.createStatement().executeUpdate(SQL_CREATE_TABLE);
}
public static void serializeJavaObjectToDB(Connection connection,
Object objectToSerialize) throws SQLException {
PreparedStatement pstmt = connection
.prepareStatement(SQL_SERIALIZE_OBJECT);
// just setting the class name
pstmt.setString(1, objectToSerialize.getClass().getName());
pstmt.setObject(2, objectToSerialize);
pstmt.executeUpdate();
pstmt.close();
System.out.println("Java object serialized to database. Object: " + objectToSerialize);
}
/**
* To de-serialize a java object from database
*
* #throws SQLException
* #throws IOException
* #throws ClassNotFoundException
*/
public static Object deSerializeJavaObjectFromDB(Connection connection) throws SQLException, IOException,
ClassNotFoundException {
PreparedStatement pstmt = connection.prepareStatement(SQL_DESERIALIZE_OBJECT);
ResultSet rs = pstmt.executeQuery();
rs.next();
//NOTE - below is the most basic way of retrieving data from result set, works perfect for general data
//Object object = rs.getObject(1);
//NOTE - below is the way how we need to implement to retrieve serialized objects from resultset
byte[] buf = rs.getBytes(1);
ObjectInputStream objectIn = null;
if (buf != null)
objectIn = new ObjectInputStream(new ByteArrayInputStream(buf));
Object deSerializedObject = objectIn.readObject();
rs.close();
pstmt.close();
System.out.println("Java object de-serialized from database. Object: "
+ deSerializedObject + " Classname: "
+ deSerializedObject.getClass().getName());
return deSerializedObject;
}
public static Connection getMySqlConnection(String ipAddr, String portNumber, String db, String userName, String password) throws SQLException {
Connection mysqlConn = null;
Properties properties = new Properties();
properties.put("user", userName);
properties.put("password", password);
mysqlConn = DriverManager.getConnection("jdbc:mysql://"+ipAddr+":"+portNumber+"/"+db, properties);
return mysqlConn;
}
/**
* Serialization and de-serialization of java object from mysql
*
* #throws ClassNotFoundException
* #throws SQLException
* #throws IOException
*/
public static void main(String args[]) throws ClassNotFoundException,
SQLException, IOException {
//step 1 - create mysql connection
Connection connection = getMySqlConnection("192.168.1.119", "3306", "xxx", "xxx", "xxx");
//step 2 - create JFrame
JFrame frame = new JFrame("JFrame Example");
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JLabel label = new JLabel("JFrame By Example");
JButton button = new JButton();
button.setText("Button");
panel.add(label);
panel.add(button);
frame.add(panel);
frame.setSize(200, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//uncomment below line if you want to see the JFrame before persisting data
//frame.setVisible(true);
//step 3 - create table
createTable(connection);
//step 4 - serializing java object to mysql database
serializeJavaObjectToDB(connection, frame);
//step 5 - de-serializing java object from mysql database and converting it into JFrame object
JFrame objFromDatabase = (JFrame) deSerializeJavaObjectFromDB(connection);
//setVisible(true) will show the JFrame as is, what ever we have persisted
objFromDatabase.setVisible(true);
//finally close the connection
connection.close();
}
}
Note1: I have no jython setup, so I am unable to provide python/jython code snippet here. But I am trying to answer this in pure java, I think you can relate it easily to your need in jython (as the classes that I've used do not vary)
Note2: I did not want to debate if persistence of serialization is right or wrong, that depends on type of application, type of users, type of project and many other scenarios. You are better judge for your case
Note3: This post helped me to answer this question better - https://javapapers.com/core-java/serialize-de-serialize-java-object-from-database/
I'm writing a simple program that consists of a window with 8 buttons with different colors added to a VBox that then is added to the program stage's scene.
For changing a button's color, I have to call the setRippleColor() method, whose definition is the following:
public void setRippleColor(Color color) {
((Shape) ((SkinBase) getSkin()).getChildren().get(0)).setFill(color);
}
The problem is that when I call this method using a Color object as its parameter, I get a NullPointerException.
For example, if I use this code:
buttonGreen.setRippleColor((Color.web("0x259B24")));
buttonOrange.setRippleColor(Color.web("0xe67e22"));
buttonBlue.setRippleColor(Color.web("0x3498db"));
buttonPurple.setRippleColor(Color.web("0x9b59b6"));
buttonYellow.setRippleColor(Color.web("0xf1c40f"));
buttonRed.setRippleColor(Color.web("0xe74c3c"));
buttonBrown.setRippleColor(Color.web("0x663300"));
buttonGrey.setRippleColor(Color.web("0x222222"));
VBox verticalLayout = new VBox(8);
verticalLayout.getChildren().addAll(buttonGreen,
buttonOrange,
buttonBlue,
buttonPurple,
buttonYellow,
buttonRed,
buttonBrown,
buttonGrey);
the console is going to say this:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at CustomButton.setRippleColor(CustomButton.java:166)
at StartingPoint.start(StartingPoint.java:25)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
Being the 166th and 25th lines of code the definition of the method and the first call thereof, respectively.
Nevertheless, if instead of using an hexadecimal value as a color I use one of the default colors of the Color class (Color.GREEN, for example), everything runs perfectly.
It's important to mention that I'm not using the java.awt.Color class instead of javafx.scene.paint.Color; the library is no the problem.
UPDATE: I did some rudamentary logging in order to know what's null.
Instead of using Color.web("...") as a parameter for setRippleColor(), I created a few Color objects whose definition is what at the beggining was the setRippleColor()'s parameter, and I surrounded the calls to the setRippleMethod() with the following try{} catch{}:
Color green = Color.web("0x259B24");
try {
buttonGreen.setRippleColor(green);
} catch (NullPointerException exception) {
SkinBase skin = (SkinBase) buttonGreen.getSkin();
ObservableList<Node> children = skin.getChildren();
Shape shape = (Shape) skin.getChildren().get(0);
System.out.println("Color " + green);
System.out.println("Skin: " + skin);
System.out.println("Children: " + children);
System.out.println("Shape: " + shape);
}
And this is what the console prints out:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at StartingPoint.start(StartingPoint.java:31)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
For as far as I understand, this means that the button's skin's children return null, but I don't understand why does this not happen when I use Color.GREEN instead of the Color object found in the above code.
UPDATE 2: It turns out that when I use Color.GREEN as a parameter for setRippleColor() the result is the same that if I use Color.web("#colorstring"), thing that is obvious and there wouldn't be an explanation if that wasn't the case. I don't know why, but I have the memory of using Color.GREEN and having the program running without any errors.
The good thing is that now I will remember that every time that something doesn't make sense, I have to run the code again and make sure that it doesn't make sense to me because I don't have enough knowledge about the topic, and not because it never happened.
So, the problem was due to that the button's skin hasn't been initialized before the setRippleColor() method is called.
This is how I solved it:
try{
((Shape) ((SkinBase) getSkin()).getChildren().get(0)).setFill(color);
} catch (NullPointerException exception){
createDefaultSkin();
setRippleColor(color);
}
If the skin hasn't been initialized when the method is called, it's initialized and then the setRippleColor() calls himself again.
The most likely cause is that you are trying to call these methods before the skin has been initialized. In this scenario, getSkin() will return null and thus ((SkinBase)getSkin()).getChildren() will throw a null pointer exception.
A simple way to avoid this is to do a null check:
public void setRippleColor(Color color) {
if (getSkin() == null) {
createDefaultSkin();
}
SkinBase skin = (SkinBase) getSkin();
Shape shape = (Shape) skin.getChildren().get(0);
shape.setFill(color);
}
You can probably vastly improve on this code: it seems you should really know somewhere in the code what the first child of the skin is, and should be able to reference it directly. This will at least provide a fix, though.
So, I don't know why the Client part of my project give me this type of error
Exception in thread "main" java.lang.ClassNotFoundException: Mining.FrequentPatternMiner
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at java.io.ObjectInputStream.resolveClass(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at JabberClient.main(JabberClient.java:81)
In the Server part, I cast the FrequentPatternMiner variable and then i give it to the ObjectOutputStream
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
FrequentPatternMiner fpMiner=new FrequentPatternMiner(dataTarget, minsup);
fpMiner.salva("FP_"+nameFile+"_minSup"+minsup+".dat");
System.out.println("Frequent Patterns \n"+fpMiner);
out.flush();
out.writeObject((Object)fpMiner);
In the Client part, i do this
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Object fpMiner=in.readObject();
(((ObjectInput)in).readObject());
System.out.println(fpMiner);
How would I fix my code? Can you help me?
The code is correct, but your premise isn't. You've said, that the class "FrequentPatternMiner must be unknown for the client". With that premise you can't serialize the class as you did, because serialization only transfers the data of the object and not it's implementation.
You might want to look into DataTransferObjects (which has to be known on both client and server) or use a simple array to transfer the object.
Example using a simple array as "DTO"
Server:
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
// The following line assumes that dataTarget and minsup are types
// that are serializable and known to the client
Object[] objArray = new Object[] { dataTarget, minsup };
out.flush();
out.writeObject(objArray);
Client:
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Object[] objArray = (Object[])in.readObject();
System.out.println(objArray);
// FrequentPatternMiner must still known to the client, if you need more than
// the constructor arguments (like methods of the FrequentPatternMiner) Object.
FrequentPatternMiner fpMiner=new FrequentPatternMiner(objArray[0], objArray[1]);
Further Idea
If you don't want that FrequentPatternMiner implementation/class is known to the client, you can try "Remoting" or "Remote Procedure Calls" (RPC). This is an advanced subject and there are a lot of libraries out there (and platforms) that provide this functionallity. They do basically this:
You need an Interface for the Class on the client (like interface IPatternMiner { void doMine() }
You connect server and client (depends on the library on how to do this) and obtain an instance of IPatternMiner
You call a method on the interface and the implementation gets executed on the server (with the parameters pased in from the client). Note that file operations write on the file system on the server
The problem you have is that FrequentPatternMiner is not on your classpath.
What you can do is ctrl+t on Eclipse and look for FrequentPatternMiner to know what is the jar containing this class. Then ensure that your project is referencing this class.
If you are using maven you can use mvm dependency:tree goal to know if your project contain this jar.
Casting to Object doesn't have any magical properties. Everything can be cast to Object. It doesn't change the fact that what is written to the object stream is a FrequentPatternMiner, and if that class isn't available at the receiver, this exception will result.
Solution: deploy the class.
Similarly, casting an ObjectInputStream to ObjectInput accomplishes precisely nothing.
You need to tyecast.
System.out.println((FrequentPatternMiner )fpMiner);
Else how would the client know class of the Object that is being deserialized. Note it is not necessary to typecast just for using it in sysout. It will print using Objects toString() method.
Though your Exception says
Exception in thread "main" java.lang.ClassNotFoundException
You need to add this class on the client side too. Lastly check that serialVersionUID is same for the class in server and client.
I've written a JApplet that that connects to a server. On connecting it receives an ImageIcon. On receipt it send a String "I" to the server to confirm. This signals the server to send the next imageIcon.
while(noExceptions){
try{
Object something = in.readObject();
if(something instanceof ImageIcon){
camDisplay.setIcon( (ImageIcon)something );
validate();
sendMessage("I");
}else{
System.out.println("What the hell was that?!");
}
Runtime rt = Runtime.getRuntime();
rt.gc();
}catch(Exception e){
noExceptions=false;
...
}
}
I added the call to the garbage collector when I first got the exception but it didn't help. I put in some printlns and it always crashes on the 128th image. Exception is thrown at Object something = in.readObject();
camDisplay is a JLabel that is shown in the applet.
Exception in thread "Thread-12" java.lang.OutOfMemoryError: Java heap space
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Unknown Source)
at java.io.ObjectInputStream.readArray(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at javax.swing.ImageIcon.readObject(Unknown Source)
at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at RoboClient.run(RoboClient.java:226)
at java.lang.Thread.run(Unknown Source)
FIX:
System.out.println((sendImageCount++)+" send image");
out.writeUnshared( new ImageIcon(_image) );
out.flush();
if(sendImageCount>100){
out.reset();
sendImageCount=0;
}
See ObjectOutputStream.reset() and ObjectOutputStream.writeUnshared().
One crude way to address this problem is to flush the inputstream after retrieving every x(say 50 in this case) ImageIcons and close the inputStream and reOpen to get the remaining ImageIcons. Now the GC will be able to garbage the earlier retrived imageicons.
Looks like the Inputstream holds the references of the ImageIcons which is preventing from Gced.
I've tried using the standard serializing type things, stuff like:
FileOutputStream f_out;
try {
f_out = new FileOutputStream("MAOS.data");
ObjectOutputStream obj_out = new ObjectOutputStream (f_out);
obj_out.writeObject(s);
obj_out.flush();
obj_out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} ;
But the problem seems to be that if my object s contains any recursion at ALL I get a stack overflow. If s is a graph that contains nodes and edges (with nodes knowing about edges for purposes of spreading activation, and edges knowing about nodes for the same reason) then it stack overflows. If I take edges out entirely, and just have nodes that know about which nodes they're supposed to spread activation too, the same thing happens! I can even just try to save the ArrayList of nodes that the graph knows about, and the stack overflows again!
I'm so frustrated!
Graphs aren't exactly strange and mysterious, surely SOMEONE has wanted to save one before me. I'm seeing something about saving them as XML files here...but if my problem is the recursiveness, wouldn't I still be having the same problems even if I saved it differently? I just can't think of how you could make a graph without there being connections!
Am I just doing things wrong, or is this object serialization less powerful than I thought? Or do I need to just abandon the idea of saving a graph?
-Jenny
Edit, part of the HUGE stack trace:
Exception in thread "main" java.lang.StackOverflowError
at java.io.ObjectStreamClass.getPrimFieldValues(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.util.ArrayList.writeObject(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.util.ArrayList.writeObject(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.util.ArrayList.writeObject(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.util.ArrayList.writeObject(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
These sort of structures are best saved like this:
collection of nodes, each node has a unique ID
collection of edges, each edge has two node IDs (or however many nodes an edge connects to)
without using any recursion. On reading the nodes, create a dictionary of nodes indexed by their ID. Then use the dictionary to fix up the edges when they're read. The IDs do not need to be part of the objects' run time structure, they only need to be unique within the data stream when the stream is written/read.
You could use the JGraphT library which supports serializing graphs into a text file with the ML format. GraphMLExporter Javadoc.
Java serialisation can cope with arbitrary graphs (although not necessarily very efficiently). Probably the problem lies with a custom implementation of writeObject. Perhaps a section of stack trace might help.
A useful serialization format you should consider is JSON, where dictionaries (as suggested by #Skizz) are easily represented:
A JSONObject is an unordered collection of name/value pairs. Its external form is a string wrapped in curly braces with colons between the names and values, and commas between the values and names. The internal form is an object having get() and opt() methods for accessing the values by name, and put() methods for adding or replacing values by name. The values can be any of these types: Boolean, JSONArray, JSONObject, Number, and String, or the JSONObject.NULL object.
Java serialization is capable of handling cyclic references (I assume this is what you mean by recursion), but there is a known problem with large graphs that is described here.
Don't let the date of the article throw you off, just follow chain of comments after it.
It seems you will have to use another serialization technique to accomplish this. Several have been mentioned, and some performance metrics give JSON high marks.
Hmmm. One solution would be to make it into a java bean and use XMLEncoder/XMLDecoder. This is a solution I've used in the past to save and load classes.