I'm having difficulty trying to send a simple serialized object to a servlet via POST. On the client side I don't generate any exceptions at run time, but on the server side, the servlet keeps throwing a NullPointerException on the readObject() method of the ObjectInputStream. I don't understand why that is. I've been checking my code with numerous examples from other websites, most notably:
I actually have the book Core Servlets and Java Server Pages where in Chapter 17 Marty Hall describes a way to send a String over a POST request using a ByteArrayOutputStream. In his example he sets the URLConnection method setRequestProperty(...) to set the "Content-Type" with "application/x-www-form-urlencoded". This is fine for his example since he is only sending string data over the wire. Therefore, he is able to set the setRequestProperty(...) method earlier to "Content-Length" and the length of the string. That's an easy thing to do when dealing with strings. This doesn't apply in my case, however.
In my case, I am sending a class named "TableData" which is just acting as a wrapper for a 2D array. In my case, I need to set the method setRequestProperty(...) to "Content-Type" with "application/octet-stream" because I'm sending an object over the wire. If I am still required to set the "Content-Length" property, then how does one do that with an object like TableData? In the case of sending serialized objects to a servlet, I have not seen any examples where they set the "Content-Length" property.
In that book, he also shows: 1.) How to send binary objects from an applet to a servlet. 2.) How to send a serialized java object from the servlet to the applet.
For me, it wasn't too hard to put the pieces together and make an applet that sends serialized java objects to the server.
Again, it's been a while since I've done it but I'm fairly certain, you have to state the size explicitly.
Joined: Sep 24, 2003
I see no evidence of determining the size of an object for purposes of setting the "Content-Length" property. On Page 456 Marty Hall does it using a String object, which is easy, but I'm sending a serialized class that acts as a wrapper for a 2D array. If I have to provide a size for the object, how is it done?
I may still have the project on my home machine. I'll look tonight and see. If I do, I can send it to you. I know I had it working and, because we're using the same book, the code is probably very similar to yours.
Now we're making headway...I went to the ibm site you sited and borrowed some of their code for the servlet for refining purposes. I intoduced a BufferedInputStream into the mix as seen below and made use of an instanceof check on the object being retrieved.
This time when I ran everything, I still get an error on the readObject() method, but this time it is no longer NullPointerException. This time its EOFException. I thought at first that it was perhaps because I wasn't calling flush() on the client side. But I am.
... Attempting to read Object... java.io.EOFException at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at TableDataServlet.doPost(TableDataServlet.java:31) at javax.servlet.http.HttpServlet.service(HttpServlet.java:709) at javax.servlet.http.HttpServlet.service(HttpServlet.java:802) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:825) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:731) at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:526) at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684) at java.lang.Thread.run(Unknown Source)
You seemed to have abandoned me. I still haven't resolved my issue. I've been conversing on another forum where it was suggested I refine my TableData class to include the readObject() and writeObject() methods for serialization. I did that, as you can see below, but it didn't help any. I'm still getting NullPointerException on the readObject() method in the servlet.
Can you collaborate with your buddies and ask around what the problem might be? I really need to get this worked out. Maybe I've inadvertantly discovered a bug what with all the changes having been made with JDK1.5 and Tomcat 5.5?
and encorporated some of their code in with mine earlier. That still leaves my problem unresolved. For the hell of it, I decided to do a simpler test of moving a String object from applet to servlet. Code below.
The test worked! Yeah! So I know the system works to this degree. Now, why won't the system work when I try to pass it my TableData object?
Joined: Sep 24, 2003
Yeah! Woopie! I'm dancing in the streets! Come on everybody, Let's boogie down! Do people still say that?
I found the answer! Here's a lesson for you all to learn so listen up closely. You'll want to keep this in mind when dealing with others trying to perform object serialization from an applet to a servlet.
The reason I kept getting EOFException and NullPointerException messages is because in both the applet and servlet I defined the class TableData as an inner class in each. When I compiled both the applet and servlet, each had its own serialized rendition of the TableData class. After compiling, they must have been incompatible. But I fixed that by making TableData.java in its own file.