guydeschepper
asked on
Apache HttpClient: send Vector object from servlet to client
Hi,
I'm writing an application where the client sends a request (GET) to a servlet.
For the request I'm using the Jakarta Commons HttpClient from Apache, v2.0.2
The request looks like this:
HttpClient client = new HttpClient();
client.setTimeout(timeout * 1000);
url = new URL(p_protocol, p_hostname, p_WebserverPort, file);
String strUrl = url.toExternalForm();
GetMethod method = new GetMethod(strUrl);
// Provide custom retry handler (seems to be necessary)
DefaultMethodRetryHandler retryhandler = new DefaultMethodRetryHandler( );
retryhandler.setRequestSen tRetryEnab led(false) ;
retryhandler.setRetryCount (1);
method.setMethodRetryHandl er(retryha ndler);
// Prevent CLOSE_WAITs
method.addRequestHeader( "Connection", "close");
// set content type
method.setRequestHeader("C ontent-typ e", "text/plain");
// add token
method.setRequestHeader("t oken", getHostname() + "-" + getID());
The servlet checks the token, and if that is valid it should send a
Vector with strings back to the client.
Currently, the code looks like this:
String receivedToken = request.getHeader("token") ;
if (validToken()) {
ObjectOutputStream oOut = new ObjectOutputStream(respons e.getOutpu tStream()) ;
oOut.write(Base64.encodeBa se64(Seria lizationUt ils.serial ize(servle tVector))) ;
oOut.flush();
oOut.close();
}
and this is the client code for reading the response:
Vector servletVector = (Vector) SerializationUtils.deseria lize(Base6 4.decodeBa se64(metho d.getRespo nseBodyAsS tring().ge tBytes())) ;
But when I run this code, I get following exception:
java.lang.ArrayIndexOutOfB oundsExcep tion: -84
at org.apache.commons.codec.b inary.Base 64.isBase6 4(Base64.j ava:137)
at org.apache.commons.codec.b inary.Base 64.discard NonBase64( Base64.jav a:478)
at org.apache.commons.codec.b inary.Base 64.decodeB ase64(Base 64.java:37 4)
at net.testpackage.Client.pul lData(Clie nt.java:14 65)
at net.testpackage.Client.run (Client.ja va:1971)
When leaving out the Base64 Encoding/Decoding, I get following exception:
org.apache.commons.lang.Se rializatio nException : java.io.UTFDataFormatExcep tion
at org.apache.commons.lang.Se rializatio nUtils.des erialize(S erializati onUtils.ja va:204)
at org.apache.commons.lang.Se rializatio nUtils.des erialize(S erializati onUtils.ja va:229)
at net.testpackage.Client.pul lData(Clie nt.java:14 71)
at net.testpackage.Client.run (Client.ja va:1978)
Caused by: java.io.UTFDataFormatExcep tion
at java.io.ObjectInputStream$ BlockDataI nputStream .readUTFSp an(Unknown Source)
at java.io.ObjectInputStream$ BlockDataI nputStream .readUTFBo dy(Unknown Source)
at java.io.ObjectInputStream$ BlockDataI nputStream .readUTF(U nknown Source)
at java.io.ObjectInputStream. readString (Unknown Source)
at java.io.ObjectInputStream. readObject 0(Unknown Source)
at java.io.ObjectInputStream. readObject (Unknown Source)
at org.apache.commons.lang.Se rializatio nUtils.des erialize(S erializati onUtils.ja va:199)
... 3 more
I tried already several other methods (like converting the Vector to a
ByteArrayOutputStream) but until now I haven't succeeded to get it working.
Any help would be appreciated.
I'm writing an application where the client sends a request (GET) to a servlet.
For the request I'm using the Jakarta Commons HttpClient from Apache, v2.0.2
The request looks like this:
HttpClient client = new HttpClient();
client.setTimeout(timeout * 1000);
url = new URL(p_protocol, p_hostname, p_WebserverPort, file);
String strUrl = url.toExternalForm();
GetMethod method = new GetMethod(strUrl);
// Provide custom retry handler (seems to be necessary)
DefaultMethodRetryHandler retryhandler = new DefaultMethodRetryHandler(
retryhandler.setRequestSen
retryhandler.setRetryCount
method.setMethodRetryHandl
// Prevent CLOSE_WAITs
method.addRequestHeader( "Connection", "close");
// set content type
method.setRequestHeader("C
// add token
method.setRequestHeader("t
The servlet checks the token, and if that is valid it should send a
Vector with strings back to the client.
Currently, the code looks like this:
String receivedToken = request.getHeader("token")
if (validToken()) {
ObjectOutputStream oOut = new ObjectOutputStream(respons
oOut.write(Base64.encodeBa
oOut.flush();
oOut.close();
}
and this is the client code for reading the response:
Vector servletVector = (Vector) SerializationUtils.deseria
But when I run this code, I get following exception:
java.lang.ArrayIndexOutOfB
at org.apache.commons.codec.b
at org.apache.commons.codec.b
at org.apache.commons.codec.b
at net.testpackage.Client.pul
at net.testpackage.Client.run
When leaving out the Base64 Encoding/Decoding, I get following exception:
org.apache.commons.lang.Se
at org.apache.commons.lang.Se
at org.apache.commons.lang.Se
at net.testpackage.Client.pul
at net.testpackage.Client.run
Caused by: java.io.UTFDataFormatExcep
at java.io.ObjectInputStream$
at java.io.ObjectInputStream$
at java.io.ObjectInputStream$
at java.io.ObjectInputStream.
at java.io.ObjectInputStream.
at java.io.ObjectInputStream.
at org.apache.commons.lang.Se
... 3 more
I tried already several other methods (like converting the Vector to a
ByteArrayOutputStream) but until now I haven't succeeded to get it working.
Any help would be appreciated.
If you're base64 encoding it before sending, then you don't need an ObjectOutputStream really. Also you probably shouldn't set it as a header - just send it as part of the response
ASKER
Sorry, I'm not sure what you're suggesting.
First of all, I'm not setting it as a header as you can see in the code, so that can't be the problem
So are you saying I can't use on ObjectOutputStream for sending a String ?
If so, what should I use then ?
To be honnest, I don't see why it would be a problem using an ObjectOutputStream ?
But maybe you can explain a bit more ?
Thanx for your help already...
First of all, I'm not setting it as a header as you can see in the code, so that can't be the problem
So are you saying I can't use on ObjectOutputStream for sending a String ?
If so, what should I use then ?
To be honnest, I don't see why it would be a problem using an ObjectOutputStream ?
But maybe you can explain a bit more ?
Thanx for your help already...
>>First of all, I'm not setting it as a header as you can see in the code
Ignore that sorry - i misread it
>>So are you saying I can't use on ObjectOutputStream for sending a String ?
You could, but an ObjectOutputStream also sends metadata. Are you reading with OInputStream at the other end?
Ignore that sorry - i misread it
>>So are you saying I can't use on ObjectOutputStream for sending a String ?
You could, but an ObjectOutputStream also sends metadata. Are you reading with OInputStream at the other end?
>>You could, but an ObjectOutputStream also sends metadata
(which would be a problem if you're not using ObjectInputStream at the other end). The other problem is you're mixing binary and text content. If you're sending binary output, you must use the output stream directly - you can't use a Writer as you're doing now. So there are really two approaches:
a. use binary output - OOS if you're using OIS at the other end
b. use the Writer to send Base64-encoded data as text
(which would be a problem if you're not using ObjectInputStream at the other end). The other problem is you're mixing binary and text content. If you're sending binary output, you must use the output stream directly - you can't use a Writer as you're doing now. So there are really two approaches:
a. use binary output - OOS if you're using OIS at the other end
b. use the Writer to send Base64-encoded data as text
ASKER
Ok, I see.
I'll try it out (will be later today) and let you know the results.
I'll try it out (will be later today) and let you know the results.
ASKER
I tried both suggestions, but still without success:
a) use OOS & OIS:
servlet-code:
---------------
ObjectOutputStream oOut = new ObjectOutputStream(respons e.getOutpu tStream()) ;
oOut.writeObject(servletVe ctor);
client-code:
--------------
method.setRequestHeader("C ontent-typ e", "text/plain");
ObjectInputStream ois = (ObjectInputStream) method.getResponseBodyAsSt ream();
Vector servletVector = (Vector) ois.readObject();
Exception:
----------
java.lang.ClassCastExcepti on
at net.testpackage.Client.pul lData(Clie nt.java:14 62)
at net.testpackage.Client.run (Client.ja va:1999)
Note:
------
I also tried the same code, but with
method.setRequestHeader("C ontent-typ e", "application/octet-stream" );
But that gave the same exception
b) use Writer to send Base64-encoded data as text:
servlet-code:
---------------
byte[] encodedSerializedData = Base64.encodeBase64(Serial izationUti ls.seriali ze(servlet Vector));
response.getWriter().write (new String(encodedSerializedDa ta));
client-code:
--------------
byte[] servletData = Base64.decodeBase64(method .getRespon seBodyAsSt ring().get Bytes());
Vector servletVector = (Vector) SerializationUtils.deseria lize(servl etData);
Exception:
----------
java.lang.ArrayIndexOutOfB oundsExcep tion: -84
at org.apache.commons.codec.b inary.Base 64.isBase6 4(Base64.j ava:137)
at org.apache.commons.codec.b inary.Base 64.discard NonBase64( Base64.jav a:478)
at org.apache.commons.codec.b inary.Base 64.decodeB ase64(Base 64.java:37 4)
at net.testpackage.Client.pul lData(Clie nt.java:14 65)
at net.testpackage.Client.run (Client.ja va:1971)
a) use OOS & OIS:
servlet-code:
---------------
ObjectOutputStream oOut = new ObjectOutputStream(respons
oOut.writeObject(servletVe
client-code:
--------------
method.setRequestHeader("C
ObjectInputStream ois = (ObjectInputStream) method.getResponseBodyAsSt
Vector servletVector = (Vector) ois.readObject();
Exception:
----------
java.lang.ClassCastExcepti
at net.testpackage.Client.pul
at net.testpackage.Client.run
Note:
------
I also tried the same code, but with
method.setRequestHeader("C
But that gave the same exception
b) use Writer to send Base64-encoded data as text:
servlet-code:
---------------
byte[] encodedSerializedData = Base64.encodeBase64(Serial
response.getWriter().write
client-code:
--------------
byte[] servletData = Base64.decodeBase64(method
Vector servletVector = (Vector) SerializationUtils.deseria
Exception:
----------
java.lang.ArrayIndexOutOfB
at org.apache.commons.codec.b
at org.apache.commons.codec.b
at org.apache.commons.codec.b
at net.testpackage.Client.pul
at net.testpackage.Client.run
Let's take them one at a time:
a. I don't think you need to set the request header, but if you do then your second mime type is the correct one. That should be set at the server Try the following:
ObjectInputStream ois = new ObjectInputStream(method.g etResponse BodyAsStre am());
Object o = ois.readObject();
System.out.println(o.getCl ass());
a. I don't think you need to set the request header, but if you do then your second mime type is the correct one. That should be set at the server Try the following:
ObjectInputStream ois = new ObjectInputStream(method.g
Object o = ois.readObject();
System.out.println(o.getCl
ASKER
ok, I will do that, but to be honest I don't think that will help, because I get the nullpointerexception
at the line
ObjectInputStream ois = new ObjectInputStream(method.g etResponse BodyAsStre am());
at the line
ObjectInputStream ois = new ObjectInputStream(method.g
If that's the case, it suggests that 'method' is null
(or that the method has not been executed and therefore the stream is not available)
ASKER
Sorry, I meant ClassCastException instead of NullPointerException.
In the meantime, I tried the code you suggested, but obviously (and as expected) I still get the exception (ClassCastException that is)
So it seams I cannot cast the stream to an ObjectInputStream for some reason.
In the meantime, I tried the code you suggested, but obviously (and as expected) I still get the exception (ClassCastException that is)
So it seams I cannot cast the stream to an ObjectInputStream for some reason.
>> ObjectInputStream ois = new ObjectInputStream(method.g etResponse BodyAsStre am());
I can't see why this will throw ClassCastException as you are not casting anything (but rather wrapping).
In anycase do you want to try this (and avoid the ObjectStreams):
server:
response.getOutputStream() .write(Bas e64.encode Base64(Ser ialization Utils.seri alize(serv letVector) ));
client:
Vector servletVector = (Vector) SerializationUtils.deseria lize(Base6 4.decodeBa se64(metho d.getRespo nseBodyAsS tring().ge tBytes("IS O-8859-1") ));
I can't see why this will throw ClassCastException as you are not casting anything (but rather wrapping).
In anycase do you want to try this (and avoid the ObjectStreams):
server:
response.getOutputStream()
client:
Vector servletVector = (Vector) SerializationUtils.deseria
ASKER
ok, I tried that code, but still get the ArrayIndexOutOfBoundsExcep tion:
java.lang.ArrayIndexOutOfB oundsExcep tion: -84
at org.apache.commons.codec.b inary.Base 64.isBase6 4(Base64.j ava:137)
at org.apache.commons.codec.b inary.Base 64.discard NonBase64( Base64.jav a:478)
at org.apache.commons.codec.b inary.Base 64.decodeB ase64(Base 64.java:37 4)
at net.testpackage.Client.pul lData(Clie nt.java:15 04)
at net.testpackage.Client.run (Client.ja va:2007)
and line 1504 of Client.java is the code you suggested:
Vector servletVector = (Vector) SerializationUtils.deseria lize(Base6 4.decodeBa se64(metho d.getRespo nseBodyAsS tring().ge tBytes("IS O-8859-1") ));
I really don't understand why this would fail (and especially the ClassCastException when using OOS & OIS seems very strange to me.)
java.lang.ArrayIndexOutOfB
at org.apache.commons.codec.b
at org.apache.commons.codec.b
at org.apache.commons.codec.b
at net.testpackage.Client.pul
at net.testpackage.Client.run
and line 1504 of Client.java is the code you suggested:
Vector servletVector = (Vector) SerializationUtils.deseria
I really don't understand why this would fail (and especially the ClassCastException when using OOS & OIS seems very strange to me.)
Can you check what you get back when you do:
System.out.println(method. getRespons eBodyAsStr ing().getB ytes("ISO- 8859-1"));
That suppose to return you a sting base64 encoded.
You can compare that to what you send in your server:
System.out.println(Base64. encodeBase 64(Seriali zationUtil s.serializ e(servletV ector)));
I wonder if the method inputStream contains more or less and what is the difference...
System.out.println(method.
That suppose to return you a sting base64 encoded.
You can compare that to what you send in your server:
System.out.println(Base64.
I wonder if the method inputStream contains more or less and what is the difference...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Oh boy, am I feeling silly.
I must have misread your previous post, as I still used
ObjectInputStream ois = (ObjectInputStream) method.getResponseBodyAsSt ream();
instead of the suggested
ObjectInputStream ois = new ObjectInputStream(method.g etResponse BodyAsStre am());
I tried again, but this time with the correct code (i.e. wrapping instead of casting) and it seems to be working !
Note that I also added the following code to the server part:
response.setHeader("Conten t-type", "application/octet-stream" );
But I'm not sure this is necessary.
So, the code that seems to be working for me is the following:
Servlet (i.e. server side):
ObjectOutputStream oOut = new ObjectOutputStream(respons e.getOutpu tStream()) ;
response.setHeader("Conten t-type", "application/octet-stream" );
oOut.writeObject(servletVe ctor);
Client:
method.setRequestHeader("C ontent-typ e", "application/octet-stream" );
ObjectInputStream ois = new ObjectInputStream(method.g etResponse BodyAsStre am());
Vector servletVector = (Vector) ois.readObject();
I should have done a copy/paste of the code you posted instead of manually modifying my existing code.
Thanx for all your help !
I must have misread your previous post, as I still used
ObjectInputStream ois = (ObjectInputStream) method.getResponseBodyAsSt
instead of the suggested
ObjectInputStream ois = new ObjectInputStream(method.g
I tried again, but this time with the correct code (i.e. wrapping instead of casting) and it seems to be working !
Note that I also added the following code to the server part:
response.setHeader("Conten
But I'm not sure this is necessary.
So, the code that seems to be working for me is the following:
Servlet (i.e. server side):
ObjectOutputStream oOut = new ObjectOutputStream(respons
response.setHeader("Conten
oOut.writeObject(servletVe
Client:
method.setRequestHeader("C
ObjectInputStream ois = new ObjectInputStream(method.g
Vector servletVector = (Vector) ois.readObject();
I should have done a copy/paste of the code you posted instead of manually modifying my existing code.
Thanx for all your help !
:-) No problem.
>>But I'm not sure this is necessary.
Not necessary, as the entity that's reading it knows the mime type, but
>>method.setRequestHeader( "Content-t ype", "application/octet-stream" );
is redundant
>>But I'm not sure this is necessary.
Not necessary, as the entity that's reading it knows the mime type, but
>>method.setRequestHeader(
is redundant