java.net.ProtocolException: Cannot write output after reading input - java

I am trying to send the object from applet to struts action class
using object output stream but it gives me a exception java.net.ProtocolException: Cannot write output after reading input.
I created a new instance of URLConnection to giving specific url
and tried to write object in url to send the struts action class from applet
i am calling this method on save button click of applet
public saveDesign()
{
try
{
HttpURLConnection urlConnection = getServletConnection(CallServletConnection.SAVE_DESIGN, null);
// Pragma = no-cache; should be null
if(urlConnection != null && urlConnection.getHeaderFields().get("Pragma") != null)
return false;
OutputStream outstream = urlConnection.getOutputStream();//Exception occur here
ObjectOutputStream objectoutstream = new ObjectOutputStream(outstream);
objectoutstream.writeObject("abc");
objectoutstream.flush();
objectoutstream.close();
System.out.println("vctObjectDetails is write ");
}
catch (MalformedURLException exception) {
exception.printStackTrace();
}
catch(ConnectException exception) {
exception.printStackTrace();
}
catch (IOException exception) {
exception.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
}
but it doesn't work.
Please gives me some tips if anyone knows how to handle this exception.

It all has to do with the lifecycle of an HTTP request (which is what HttpURLConnection abstracts) - once the request has been sent, you cannot modify it any further - in case you have more data to send, you just make another one.
What is happening underneath is that once you call getHeaderFields() (the response header fields), the 'HttpURLConnection' sends the request and makes the response available.
I don't know what is in 'getServletConnection()', but you could try using 'doOutput()' and not reading from the response, until you have finished writing to the request.

Related

Wrapping BodySubscriber<InputStream> in GZIPInputStream leads to hang

I'm using the new java.net.http classes to handle asynchronous HTTP request+response exchanges, and I'm trying to find a way to have the BodySubscriber handle different encoding types such as gzip.
However, mapping a BodySubsriber<InputStream> so that the underlying stream is wrapped by a GZIPInputStream (when "Content-Encoding: gzip" is found in the response header) leads to a hang. No exceptions, just a total cessation of activity.
The code which maps the BodySubscriber looks like this:
private HttpResponse.BodySubscriber<InputStream> gzippedBodySubscriber(
HttpResponse.ResponseInfo responseInfo) {
return HttpResponse.BodySubscribers.mapping(
HttpResponse.BodySubscribers.ofInputStream(),
this::decodeGzipStream);
}
private InputStream decodeGzipStream(InputStream gzippedStream) {
System.out.println("Entered decodeGzipStream method.");
try {
InputStream decodedStream = new GZIPInputStream(gzippedStream);
System.out.println(
"Created GZIPInputStream to handle response body stream.");
return decodedStream;
} catch (IOException ex) {
System.out.println("IOException occurred while trying to create GZIPInputStream.");
throw new UncheckedIOException(ex);
}
}
Receiving an HTTP response which has "gzip" encoding leads to the console showing just this:
Entered EncodedBodyHandler.apply method.
Entered decodeGzipStream method.
Nothing more is seen, so the line after the call to the GZIPInputStream constructor is never executed.
Does anyone know why this attempt to wrap the InputStream from a BodySubscriber<InputStream> in a GZIPInputStream is hanging?
Note: the equivalent method for unencoded (raw text) HTTP response bodies contains simply a call to BodySubscribers.ofInputStream() with no mapping, and this allows the response to be received and displayed without problem.
EDIT: JDK-8217264 is fixed since JDK13
This is indeed a bug. I have logged JDK-8217264. I can suggest two work-arounds:
Workaround one
Do not use BodySubscribers.mapping - but transform the InputStream into a GZIPInputStream after getting the HttpResponse's body:
GZIPInputStream gzin = new GZIPInputStream(resp.getBody());
Workaround two
Have the mapping function return a Supplier<InputStream> instead, taking care not to create the GZIPInputStream until Supplier::get is called
static final class ISS implements Supplier<InputStream> {
final InputStream in;
GZIPInputStream gz;
ISS(InputStream in) {
this.in = in;
}
public synchronized InputStream get() {
if (gz == null) {
try {
gz = new GZIPInputStream(in);
} catch (IOException t) {
throw new UncheckedIOException(t);
}
}
return gz;
}
}
Encountered the exact same problem. I tried the example in the Javadoc of the BodySubscribers.mapping method. Same behavior, the application hangs without any errors.
Could be a bug, because this is an official example from the Javadoc.
public static <W> BodySubscriber<W> asJSON(Class<W> targetType) {
BodySubscriber<InputStream> upstream = BodySubscribers.ofInputStream();
BodySubscriber<W> downstream = BodySubscribers.mapping(
upstream,
(InputStream is) -> {
try (InputStream stream = is) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(stream, targetType);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
return downstream;
} }

Java interrupt inputstream without close() method

So, I have a piece of code which connects to a Server and downloads about 2gb of content in 2mb chunks. All this is done in a Thread. Sometimes I need to stop the Thread because different errors occured in the main Thread or I want to close the application. My problem is that I am not able to close the InputStream of the connection. Everytime I invoke the close() method the InputStream consumes the whole 2gb send by the server.
Is there a way to close an InputStream without consuming the whole content send over by the Server?
fos.getChannel().transferFrom(Channels.newChannel(res.getEntity().getContent()), bytes_read, CHUNK_SIZE);
res.getEntity().getContent().close();
res.getEntity().getContent()returns the InputStream created from the connection.
res is an apache httpResponse.
fos is the FileOutputStream I want to save the response content to.
Edit: Run method of thread
CHUNK_SIZE: int: 2mb in bytes
#Override
public void run() {
int expectedCode;
do{
try {
client = HttpClients.createDefault();
HttpGet req = new HttpGet(url.toString());
HttpResponse res = client.execute(req);
if (res.getStatusLine().getStatusCode() == 200) {
while(running){
fos.getChannel().transferFrom(Channels.newChannel(res.getEntity().getContent()), bytes_read, CHUNK_SIZE);
}
} else {
log.error(Languages.getString("Download.2") + expectedCode); //$NON-NLS-1$
}
} catch (Exception ex) {
log.error(ex);
} finally{
try{
rbc.close();
} catch(Exception ex){
log.error(ex);
}
}
}while(!isFinished() && running);
try{
rbc.close();
fos.close();
client.close();
} catch(Exception ex){
log.error(ex);
}
}
The underlying implementation of Apache HttpClient uses a ContentLengthInputStream for keeping the response. As mentioned in ContentLengthInputStream, the .close() method never actually close the stream, but read all remaining bytes until Content-Length is reached.
Solution: Instead of calling res.getEntity().getContent().close(), try res.close() or req.abort()

How can I use GET-request to get a sentence from http-server

I am working on a project that consists in making connection between two http-agents via http-protocol. So I am writing a java-program for that purpose. the client will send a GET-request to get a sentence from the http-server. That http-Server is a simple java-program, in which we find the following instruction:
final String id="03788444"
My Aim is to get this id from the server using GET-requet. My small Java Server is running on localhost at port 80. Basically my resource is that id, so I write the following:
GET /id HTTP/1.1
But I get nothing from the server.
From the server-side I wrote the following:
"http/1.1 200 OK"
blankline
id
is it correct?
should I put the id in a txt-file and send the file by using http-protocol. I think that id is not a resource. So I should put it in a file???
public class Server {
....
void send_response(){
try {
out= new PrintWriter( socket.getOutputStream());
//status line
out.print("http/1.1 200 OK");
//blank line!!!
out.print("");
out.print(id);
}catch (IOException e) {
e.printStackTrace();
}
}
void close_connection(){
out.close();
}
}
public class Client {
....
void sendGet(){
final String request_line="GET /id http/1.1";
PrintWriter out = null;
.....
try {
out = new PrintWriter(ag_socket.getOutputStream(), true);
// Send request to http-agent
out.println(request_line);
out.println(); // blank line separating header & body
} catch (IOException e) {
e.printStackTrace();
}finally{
//out.close();
}
}

Apparently missing an exception

in my android app I have an AsyncTask which downloads photos from my server. If I get an exception (mainly for connection time out) I show the user a message. My problem is that my code works MOST of the times, (meaning there are times when I interrupt the WiFi connection that I get an exception shown in my logcat but the message won't appear so I ended it up thinking that there might be an exception that I don't handle ) and I can't figure out the exact reason. I'll post the code run in my AsyncTask and the function that does the essential work. Hope you spot out something I'missing
#Override
protected String doInBackground(String... args) {
JSONParser jParser = new JSONParser();
JSONObject jsonObj = jParser.getJSONFromUrl(url);
Log.d("check1",url);
try {
list.addAll(processJsonData(jsonObj));
} catch (JSONException e) {
e.printStackTrace();
onDownloadFailed(this);
return "failed";
} catch (SocketException e) {
Log.e("Exception", e.getLocalizedMessage());
onDownloadFailed(this);
return "failed";
} catch (IOException e) {
Log.e("Exception", e.getLocalizedMessage());
onDownloadFailed(this);
return "failed";
}finally {
jsonObj=null;
}
return "done";
}
process JsonData is actually bigger that's the part for downloading the photos, the other part is about mapping string to an large Json File
private ArrayList<Monument> processJsonData(JSONObject jsonObj) throws IOException, SocketException, JSONException{
if(attachments!=null){
int lengthSize;
if(attachments.length()<3)
lengthSize=attachments.length();
else
lengthSize=3;
for(int j=0;j<lengthSize;++j){
JSONObject atta = attachments.getJSONObject(j);
JSONObject images = atta.optJSONObject(TAG_IMAGES);
if(images!=null){
JSONObject medium = images.getJSONObject(TAG_MEDIUM);
String url_image = medium.getString(TAG_URL_IMAGE);
String id = atta.getString("id");
String filename =title.replace(" ","")+id+".nomedia";
File destination = new File(MyApplication.getPhotoStorage() ,filename);
URL url = new URL (url_image);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destination);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
}
}
}
Maybe you could name the actual exception that is beeing thrown?
It might be a RuntimeException and therefore unchecked.
For further information about checked/unchecked exceptions see: Oracle Docs - Exceptions
The API for InteruptedException says the following;
Thrown when a thread is waiting, sleeping, or otherwise occupied, and
the thread is interrupted, either before or during the activity.
Occasionally a method may wish to test whether the current thread has
been interrupted, and if so, to immediately throw this exception.
As described in the comments of the question, cancelling your AsyncTask only after checking that it has finished should prevent this issue.
Alternatively (but I would recommend against it), you could catch the InteruptedException in the method that cancels your AsyncTask to define your custom catch behavior there. Using catch to work around program logic flaws should only really be a last resort after reconsidering the logical flow of your code.

Code to login not working

could anyone help me with figuring out why this code isn't working? It's supposed to log into HTS, but it doesn't work. It's not giving me any error messages or anything, just no result at all. Any help would be appreciated.
Here's the code:
import java.net.*;
import java.io.*;
public class Login {
private static URL URLObj;
private static URLConnection connect;
public static void main(String[] args) {
try {
URLObj = new URL("http://www.hackthissite.org/user/login");
connect = URLObj.openConnection();
connect.addRequestProperty("REFERER", "http://www.hackthissite.org");
connect.setDoOutput(true);
}
catch (MalformedURLException ex) {
System.out.println("The URL specified was unable to be parsed or uses an invalid protocol. Please try again.");
System.exit(1);
}
catch (Exception ex) {
System.out.println("An exception occurred. " + ex.getMessage());
System.exit(1);
}
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connect.getOutputStream()));
writer.write("username=BrandonHeat&password=**********&btn_submit=Login");
writer.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(connect.getInputStream()));
String lineRead = "";
while ((lineRead = reader.readLine()) != null) {
System.out.println(lineRead);
}
reader.close();
}
catch (Exception ex) {
System.out.println("There was an error reading or writing to the URL: " + ex.getMessage());
}
}
}
i'm just guessing, but the documentation for URLConnection indicates that you must connect after having set the parameters :
1.The connection object is created by invoking the openConnection method on
a URL.
2.The setup parameters and general request properties are manipulated.
3.The actual connection to the remote object is made, using the connect
method.
4.The remote object becomes available. The header fields and the contents of
the remote object can be accessed.
...
The following methods are used to
access the header fields and the
contents after the connection is made
to the remote object:
getContent
getHeaderField
getInputStream
getOutputStream
Edit :
can't you open the URL with you parameters in the URL (ie http://www.hackthissite.org/user/login?username=BrandonHeat&password=xxxxx&btn_submit=Login), or setted as header ?
also, after the connect(), what do you get if you do a getContent() ?
Edit : there is a description of the process here.
Regards
Guillaume

Categories