I use Log4j1.x for sending by Socket (SocketAppender in AsyncAppender) some loggingEvent.
I send a personnal object Serializable in the LoggingEvent message.
In the Chainsaw (example of server wide), I would like to recover my personnal object.
I can show the class name (event.getMessage().toString())
I can get the throwable
My personnal object is in a library, the same in the both projects.
My problem : I can't instance the message.
the error :
Exception in thread "Thread-5" java.lang.ClassCastException: java.lang.String cannot be cast to com.my.MyPersonnalObject
at org.apache.log4j.chainsaw.LoggingReceiver$Slurper.run(LoggingReceiver.java:80)
at java.lang.Thread.run(Unknown Source)
How can I rescure my Object ?
Thanks,
I found a simply way.
Override the toString of MyPersonnalObject to return an JSON value :
#Override
public String toString()
{
String str = "";
try
{
str = objectMapper.writeValueAsString(this);
} catch (JsonProcessingException e)
{
StringWriter errors = new StringWriter();
e.printStackTrace(new PrintWriter(errors));
str = "ERROR JSON" + errors.toString();
}
return str;
}
Then, on the other side, use :
public static MyPersonnalObject rescure(String jsonStr)
{
MyPersonnalObject b = null;
try
{
JsonParser jsonParser = jsonFactory.createParser(jsonStr);
b = objectMapper.readValue(jsonParser, MyPersonnalObject.class);
} catch (JsonParseException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return b;
}
Related
How We can store and Retrieve Serializable Java Object as a value in Redis.
I want to perform two operations in Redis
storing the object
Retrieving it.
public boolean addToRedis(Object obj) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(obj);
redis.set("ObjetKey" , out.toByteArray(), Duration.ofSeconds(5000));
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public Object getObjectFromRedis() {
try {
// thows error, also tried with redis.get('ObjetKey').toString().getBytes() (corrupted byte exception)
ByteArrayInputStream in = new ByteArrayInputStream(redis.get('ObjetKey'));
ObjectInputStream is = new ObjectInputStream(in);
return (SomeObject) is.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
You can convert your object to JSON and back using Jackson ObjectMapper. Then just store that json.
example:
private ObjectMapper mapper;
public boolean addToRedis(String key, Object obj) {
try {
redis.set(key, mapper.writeValueAsString(obj), Duration.ofSeconds(5000));
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public <T> T getFromRedis(String key, Class<T> type) {
try {
return mapper.readValue(redis.get(key), type);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
In the getFromRedis method the use of generics and passing the type parameter will let you get the exact type you need.
I'm a student practicing my File IO skills and I am coming up against a problem with reading Objects from a file using ObjectInputStream. The code is consistently throwing an InvalidClassException and I can't find how the code is throwing it online or by trial and error. Here's my code:
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class ReadFromFile {
String filename;
List<Object> os;
public ReadFromFile(String filename) {
this.filename = filename;
os = new ArrayList<>();
}
public Object[] readObject() {
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.print("reading\n");
while (true) {
os.add(ois.readObject());
System.out.print("read one\n");
}
} catch (EOFException e) {
return os.toArray();
} catch (FileNotFoundException e) {
System.out.print("File not found\n");
return os.toArray();
} catch (ClassNotFoundException e) {
System.out.print("Class not found\n");
return os.toArray();
} catch (StreamCorruptedException e) {
System.out.print("SC Exception\n");
e.printStackTrace();
return os.toArray();
} catch (InvalidClassException e) {
e.printStackTrace();
System.out.print("IC Exception\n");
return os.toArray();
} catch (OptionalDataException e) {
System.out.print("OD Exception\n");
return os.toArray();
} catch (IOException e) {
System.out.print("IO Exception\n");
return os.toArray();
}
}
}
I wrote all of the separate catch blocks to figure out what Exception was being thrown and it always throws the InvalidClassException.
Here also is my Tree Class:
import java.io.Serializable;
public class Tree implements Serializable {
private static final long serialVersionUID = -310842754445106856L;
String species;
int age;
double radius;
public Tree() {
this.species = null;
this.age = 0;
this.radius = 0;
}
public Tree(String species, int age, double radius) {
this.species = species;
this.age = age;
this.radius = radius;
}
public String toString() {
return species + ", age: " + age + ", radius: " + radius;
}
}
And here is my write to file function:
public boolean write(Object object) {
try {
File f = new File(filename);
FileOutputStream fos = new FileOutputStream(f,true);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(object + "\n");
oos.close();
} catch (FileNotFoundException e) {
System.out.print("File Not Found\n");
return false;
} catch (IOException e) {
System.out.print("IOException\n");
return false;
}
return true;
}
Your knowledge is appreciated...
Stack trace:
SC Exception
java.io.StreamCorruptedException: invalid stream header: 0AACED00
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:806)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
at ReadFromFile.readObject(ReadFromFile.java:17)
at WriteAndRecord.main(WriteAndRecord.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Process finished with exit code 0
java.io.StreamCorruptedException: invalid stream header: 0AACED00
This is caused by appending to the FileOutputStream. As I mentioned in a comment above, you can't append to a stream written by ObjectOutputStream, at least not without special measures. Keep the file and the ObjectOutputStream open until you've written all the objects you want to write, then close it, then deserialize from it.
NB As I also mentioned,
while ((object = in.readObect()) != null)
is not a valid object-reading loop. readObject() doesn't return null at end of stream: it throws EOFException. null can occur anywhere in the stream, any time you write one. The correct form of the loop is:
try
{
for (;;)
{
Object object = in.readObject();
// ...
}
}
catch (EOFException exc)
{
// end of stream
}
// other catch blocks ...
NB 2 This:
oos.writeObject(object + "\n");
should be just
oos.writeObject(object);
Otherwise you're implicity calling toString() and pointlessly appending a line terminator, so the result of readObject() will be a String, not the original object.
I think this was caused by the lack of a serialVersionUID.
Whenever you serialize an object, the ClassLoader needs something to verify the new loaded object against to verify it and ensure its compatibility. In order to do this, you just need to define a field in your class like this:
private static final long serialVersionUID = 12358903454875L;
Your IDE may have also given you a warning stating the lack of it (Eclipse does this).
This should solve your problem.
You can learn more in this excellent answer by Jon Skeet here: What is a serialVersionUID and why should I use it?.
I send some data to my server and get a response.
In case there was an error the response is a class instance:
{
errorCode (int),
errorMsg (String)
}
In a success case the response is an items array.
I have tried to run the following code and got an error:
code:
private void afterServerOfferResponse(final Gson gson,
String result) {
ServerErrorMessage serverErrorMessage = gson.fromJson(
result, ServerErrorMessage.class);
if (serverErrorMessage.errorCode == 0) {
Type collectionType = new TypeToken<ArrayList<Offer>>() {
}.getType();
mOffersList = gson.fromJson(result, collectionType);
mAdapter = new ImageAdapter(OffersListActivity.this,
mOffersList);
mListView.setAdapter(mAdapter);
error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2
how would you check for an error case without changing the server response too much?
Add a try-catch block to handle the exception. Only when you try to parse the data, it will be validated if its valid JSON response or error.
First try to parse Array Class instance and if JSON exception , then parse with ServerErrorMessage class
Add like this, and handle the exception when Syntax Exception
try{
ServerErrorMessage serverErrorMessage = gson.fromJson(
result, ServerErrorMessage.class);
}catch (JsonSyntaxException e){
// handle the exception
}
catch (JsonIOException e){
// handle the exception
}
catch (JsonParseException e){
// handle the exception
}catch (IOException e){
// handle the exception
}
Another way is to use org.json.JSONObject like this
private boolean isValidJsonResponse(String responseString){
try {
new JSONObject(responseString);
return true;
} catch(JSONException e) {
return false;
}
}
Follow on from an earlier question here. Trying to send this object Employee via HTTP. I'm not getting any errors but am hoping for a printout of the employee details at the other end but something isn't happening. I'm opening my log files to see the printout on my tomcat server but other than the indication that the method has started showing the START printout I'm not getting the END one. So something isn't working right in that section.
Here is the test class Employee:
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int SSN;
public int number;
public void mailCheck() {
System.out.println("Mailing a check to " + name + " " + address);
}
}
Client Side:
public class SerializeAndSend {
public static void main(String args[]){
one.Employee e = new one.Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
sendObject(e);
}
public static Object sendObject(Object obj) {
URLConnection conn = null;
Object reply = null;
try {
// open URL connection
URL url = new URL("///myURL///");
conn = url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
// send object
ObjectOutputStream objOut = new ObjectOutputStream(conn.getOutputStream());
objOut.writeObject(obj);
objOut.flush();
objOut.close();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
// recieve reply
try {
ObjectInputStream objIn = new ObjectInputStream(conn.getInputStream());
reply = objIn.readObject();
objIn.close();
} catch (Exception ex) {
// it is ok if we get an exception here
// that means that there is no object being returned
System.out.println("No Object Returned");
if (!(ex instanceof EOFException))
ex.printStackTrace();
System.err.println("*");
}
return reply;
}
}
I think thats correct. But I'm stuck on the server end, I have the employee class on the server side too:
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("START");
Object obj;
Employee emp = null;
ObjectInputStream objIn = new ObjectInputStream(req.getInputStream());
try {
obj = objIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
emp = (Employee)objIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("END");
System.out.println(emp.name);
}
Any ideas whats going wrong on the receiving end?
try {
obj = objIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
emp = (Employee)objIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
You are sending one object and trying to receive two. You either need this:
obj = objIn.readObject();
if (obj instanceof Employee)
{
Employee emp = (Employee)obj;
}
or this:
Employee emp = (Employee)objIn.readObject();
Not a mixture of both. Two readObject() calls implies reading the stream for two distinct objects, and you aren't sending them.
Secondly, you shouldn't catch Exception and then use instanceof on the exception object. In this case you should have a separate catch (EOFException exc), which is OK if you expect to receive zero objects, but not otherwise, and then catch the other possible exceptions separately: they are not OK.
I use SimpleXML to save a simple POJO into XML file and then read it back. I follow this tutorial. The file is successfully created, but the reading part is just simply not working. It throws the second exception which comes from serializer.read.
Room room = new Room("1");
Serializer serializer = new Persister();
try {
File ff = new File("room.xml");
serializer.write(room, ff);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException\n");
} catch (Exception e) {
System.out.println("Exception from serializer.write\n");
}
try {
File ffi = new File("room.xml");
Room aroom = serializer.read(Room.class, ffi);
System.out.println("RoomName: " + aroom.getRid() + "\n");
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException\n");
} catch (Exception e) {
System.out.println("Exception from serializer.read\n");
}
Any hint?
Make sure you have a default constructor in Room.
public Room(){
}
Alternatively, make sure your constructor looks like this:
public Room(#Attribute(name="rid") String rid){
this.rid = rid;
}