I'm trying to make an online drawing game. For that I'm using the Path class in Android and I need to send it to my Java server. To do that, I had tried to extend the Path class, as follows:
public class SerializedPath extends Path implements Serializable {
private static final long serialVersionUID = -5974912367682897467L;
}
To simplify things and to narrow down the problem, all I did was to send it with outputStream.writeObject(new SerializedPath) and then outputStream.flush() where outputStream is an instance of ObjectOutputStream. Over the server I simply read it using inputStream.readObject() where inputStream is an instance of ObjectInputStream. The exception I'm getting is:
java.io.InvalidClassException: com.droplay.drawingonline.path.SerializedPath; unable to create instance
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.droplay.drawingonline.Session.run(Session.java:71)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedSerializationConstructorAccessor1.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.io.ObjectStreamClass.newInstance(Unknown Source)
... 5 more
Caused by: java.lang.RuntimeException: Stub!
at android.graphics.Path.(Path.java:24)
... 8 more
Now, to isolate the problem, I had tried creating a new class that doesn't have any members and doesn't extend anything and it did work. The server didn't throw any exception and it worked like a charm. I made sure the packages names are the same, the names of the classes are the same, the server uses the same SDK files as my Android project and the files' code in both the Android app and the Java server are EXACTLY the same, but I keep getting this exception. The app doesn't throw any exception. It sends the object just fine. Please, what's wrong with my code? Thank you for helping! :)
Well I managed to solve it by sending the position of each click to the server, instead of a path class. But why didn't it work when I serialized it?
Related
I was experimenting on command pattern and one use of it in wikipedia goes like this:
Networking
It is possible to send whole command objects across the network to be executed on the other machines, for example player actions in computer games.
I assume here sending objects means sending data within the fields of the object, right? And not the code within the execute() method?
I was experimenting through serialization & found a behaviour I couldn't explain. Here's the program:
public class Test {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("Commands"))) {
Command command = () -> {
System.out.println("MUHAHA!");
};
outputStream.writeObject(command);
}
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("Commands"))) {
Command command = (Command) inputStream.readObject();
command.execute();
}
}
}
interface Command extends Serializable {
void execute();
}
Upon execution, I get the string MUHAHA!. So, the implementation of the execute() method is being saved in the file. However, if I comment out the first try{} block & then execute, it fails. The Commands file remains from the previous execution, but it fails to read & parse.
I get the following stack trace:
Exception in thread "main" java.io.IOException: unexpected exception type
at java.io.ObjectStreamClass.throwMiscException(Unknown Source)
at java.io.ObjectStreamClass.invokeReadResolve(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at random.Test.main(Test.java:18)
Caused by: java.lang.NoSuchMethodException: random.Test.$deserializeLambda$(java.lang.invoke.SerializedLambda)
at java.lang.Class.getDeclaredMethod(Unknown Source)
at java.lang.invoke.SerializedLambda$1.run(Unknown Source)
at java.lang.invoke.SerializedLambda$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.lang.invoke.SerializedLambda.readResolve(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)
... 5 more
The NoSuchMethodException makes some sense to me, but why didn't it come the first time? Is it storing the first class created through lambda in some cache (or the Metaspace)?
In the end, is it possible to send an implementation across? I was hoping in the other end the code of the execute method will be written into some dynamically created Command implementation.
It is not storing the implementation in the file. To show that, separate your code into two classes: one that serializes and one that deserializes, and execute them in different environments where neither has the .class files of the other.
This question already has an answer here:
How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?
(1 answer)
Closed 2 years ago.
I am working on a Javafx game and have been attempting to implement some sound using the following code:
URL laserResource = getClass().getResource("LaserBlast.wav");
AudioClip laserPlayer = new AudioClip(laserResource.toString());
This code is instantiated in the main class before any methods. I have a module called JavaFxImages which contains all my resources including my sounds and I have been successfully able to access images for ImageView from the folder through code such as Image asteroid = new Image("Asteroid.png");.
However, when I run my game I get a NullPointerException at the line for my audio clip. I have spent the past many hours researching and trying every different way to access this resource. I've tried many permutations of the URL ("JavaFxImages/LaserBlast.wav", Desktop/JavaFxImages/LaserBlast.wav", etc.), but every time it has the same error. I'm really at a loss for what is wrong with the code. I would greatly appreciate any help that can be given.
Thanks in advance!
The full error message is given below.
Error Message:
Exception in Application constructor
Exception in thread "main" java.lang.RuntimeException: Unable to construct Application instance: class sample.Main
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$156(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:819)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$176(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$174(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$175(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Caused by: java.lang.NullPointerException
at sample.Main.<init>(Main.java:76)
... 10 more
Your error mostly happens on Itellij IDEA - Javafx Project
Instead of:
URL laserResource = getClass().getResource("LaserBlast.wav");
AudioClip laserPlayer = new AudioClip(laserResource.toString());
Use:
//By default your Package_NAME is: sample
File laserResource = new File("src/Package_NAME/LaserBlast.wav");
AudioClip laserPlayer = new AudioClip(laserResource.toURI().toString());
I have been trying to send JSON Raw messages to players using a lot of different methods and none of them seem to work. One thing I have tried is to do this:
String json = "{text:\"Test!\",hoverEvent:{action:show_text,value:\"test\"}}";
PacketPlayOutChat packet = new PacketPlayOutChat(ChatSerializer.a(json), true);
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
Now when eclipse validates the code, no errors appear and it's only when the server runs this code, it gives me this error:
java.lang.NoClassDefFoundError: net/minecraft/server/v1_7_R3/Packet
at bukkit.pangea.terms.Main.registerCommands(Main.java:31) ~[?:?]
at bukkit.pangea.terms.Main.onEnable(Main.java:21) ~[?:?]
at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:321) ~[c
raftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader
.java:335) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManage
r.java:405) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.craftbukkit.v1_8_R1.CraftServer.loadPlugin(CraftServer.jav
a:356) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.craftbukkit.v1_8_R1.CraftServer.enablePlugins(CraftServer.
java:316) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.craftbukkit.v1_8_R1.CraftServer.reload(CraftServer.java:74
6) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.Bukkit.reload(Bukkit.java:534) [craftbukkit.jar:git-Spigot
-952179b-e87122e]
at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:
25) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:14
1) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchCommand(CraftServe
r.java:646) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchServerCommand(Craf
tServer.java:632) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at net.minecraft.server.v1_8_R1.DedicatedServer.aM(DedicatedServer.java:
353) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:3
17) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:6
23) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java
:526) [craftbukkit.jar:git-Spigot-952179b-e87122e]
at java.lang.Thread.run(Unknown Source) [?:1.7.0_71]
Caused by: java.lang.ClassNotFoundException: net.minecraft.server.v1_7_R3.Packet
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.
java:91) ~[craftbukkit.jar:git-Spigot-952179b-e87122e]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.
java:86) ~[craftbukkit.jar:git-Spigot-952179b-e87122e]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_71]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.7.0_71]
... 18 more
A lot of the other things that I have tried also gives me a similar error. If anyone could help me with this problem it would be very helpful, thank you.
Your method works perfectly fine in my version of spigot/craftbukkit, although it seems that I am using a newer version (1.8.3), in which the constructor for the PacketPlayOutChat takes a byte as a second argument instead of a boolean. This byte (values 1 or 2) determines whether the chat message is sent normally or is displayed above the action bar. I would update your craftbukkit/spigot jar to the newest version using BuildTools.
Well it could be, that you use another spigot/bukkit jar on your server, than you work with. Use exactly the same. Otherwise it couldn't find the main class of the server Packet version.
java.lang.NoClassDefFoundError: net/minecraft/server/v1_7_R3/Packet
Here it says, that it can't find the class. Which Spigot/Bukkit version are you using on your server? And which are you using to developing?
You need to have a later version of Spigot in your build path for your project. If you cannot build it as described by the answer above, then you can depend on the jar used by the server instead.
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 tried making a simple project for my skype-bot, and it looks like this:
import com.skype.Skype;
import com.skype.SkypeException;
public class SkypeDemo {
public static void main(String[] args) throws SkypeException {
System.out.println(Skype.getVersion());
}
}
But when i started it i get this error:
Exception in thread "main" com.skype.SkypeException: Loading libskype.jnilib failed.
at com.skype.Utils.convertToSkypeException(Unknown Source)
at com.skype.Utils.getProperty(Unknown Source)
at com.skype.Skype.getVersion(Unknown Source)
at SkypeDemo.main(SkypeDemo.java:6)
Caused by: com.skype.connector.LoadLibraryException: Loading libskype.jnilib failed.
at com.skype.connector.ConnectorUtils.loadLibrary(Unknown Source)
at com.skype.connector.osx.SkypeFramework.init(Unknown Source)
at com.skype.connector.osx.OSXConnector.initializeImpl(Unknown Source)
at com.skype.connector.Connector.initialize(Unknown Source)
at com.skype.connector.Connector.connect(Unknown Source)
at com.skype.connector.Connector.assureAttached(Unknown Source)
at com.skype.connector.Connector.execute(Unknown Source)
at com.skype.connector.Connector.execute(Unknown Source)
at com.skype.connector.Connector.execute(Unknown Source)
at com.skype.connector.Connector.execute(Unknown Source)
... 3 more
So how do I fix this error? Keep in mind I have both Skype jars in the build path.
The error is telling you that it cannot load a native library ("libskype.jnilib"). This is (probably) neither Eclipse or Skype's fault.
It is most likely your fault because either the native library is not where it needs to be (or you haven't told Eclipse where to look), or because you have the wrong flavour of native code (DLL, .so or whatever)
(If there was another chained "cause" in the stack trace, it might tell you more ...)
Reference:
This blog post explains how to add a native library to an Eclipse project - http://www.eclipsezone.com/eclipse/forums/t49342.html (In fact, it describes two ways ...)