Connection failed with Java 7 URL

The following code used to run under Java 6 (and earlier) stopped working after upgrading to JRE 7 (Java 7).

FTP File URL:

ftp://ftp-private.ncbi.nlm.nih.gov/pubchem/.fetch/96/4133257873201306969.sdf.gz

Here is the result I get:

applications / octet stream -1 [Ljava.lang.StackTraceElement; @ 5419f97c

And here is my code:

public static void store(URL url, File targetFile){ try { System.out.println(url); URLConnection uc = url.openConnection(); String contentType = uc.getContentType(); System.out.println(contentType); int contentLength = uc.getContentLength(); System.out.println(contentLength); Settings.setDownloadSize(contentLength); if (contentType.startsWith("text/") || contentLength == -1) { throw new IOException("This is not a binary file."); } InputStream raw = uc.getInputStream(); InputStream in = new BufferedInputStream(raw); byte[] data = new byte[contentLength]; int bytesRead = 0; StatusPanel.updateProgrssBar(bytesRead); int offset = 0; while (offset < contentLength) { bytesRead = in.read(data, offset, data.length - offset); if (bytesRead == -1) { break; } offset += bytesRead; StatusPanel.updateProgrssBar(offset); } in.close(); if (offset != contentLength) { throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes"); } FileOutputStream out = new FileOutputStream(targetFile); out.write(data); out.flush(); out.close(); //StatusPanel.setStatus("File has been stored at " + targetFile.toString()); //System.out.println("file has been stored at " + targetFile.toString()); } 

The length of the content returns -1:

 Area: API: Networking Synopsis: Server Connection Shuts Down when Attempting to Read Data When http Response Code is -1 

How do I make this code compatible with Java 7?

Description. As a result of error correction for CR 6886436, the HTTP protocol handler will close the connection to the server, which sends the response without a valid HTTP status bar. When this happens, any attempt to read data on this connection throws an IOException.

For example, the following code is problematic:

 public static void test () throws Exception { ..... HttpURLConnection urlc = (HttpURLConnection)url.openConnection(); .... System.out.println ("Response code: " + urlc.getResponseCode()); /** Following line throws java.io.IOException: Invalid Http response * when Response Code returned was -1 */ InputStream is = urlc.getInputStream(); // PROBLEMATIC CODE 

To work around this problem, check the return value from the getResponseCode method and process the -1 value accordingly; possibly by opening a new connection or calling getErrorStream in a stream. Incompatibility Nature: Behavioral RFE: 7055058

The problem is definitely with the getContentLength() method.

With JRE6, this method returns a value, but with JRE7 I get -1.

+4
source share
1 answer

Based on the Java 7 Javadoc URLConnection, there are two possible reasons why this happens.

The first possible reason is that the content is longer than Integer.MAX_VALUE. To determine if this is a problem, I would use getContentLengthLong () because it returns long instead of int and if the length of the content is longer than Integer.MAX_VALUE getContentLength () will return -1. Furthermore, since Java 7 recommends using getContentLengthLong () over getContentLength () , as stated in the Java 7 URLConnection Javadoc , "it returns long and therefore more portable." If you want to use JRE 6 and 7, I would create shell classes 6 and 7 to create a set of methods that your application uses to interact with URLs. Then in your application, run the script to check if the host has a JRE of 6 or 7 and loads the appropriate wrapper class according to the version of the JRE. This is usually a good design because it does not allow your application to depend on one particular JRE, a third-party library or application, etc.

The second possibility is that the content length header field is not known by the server, so getContentLength () or the getContentLengthLong () method returns -1. That is why I suggest trying getContentLengthLong () before anything else, because it will probably be the fastest solution. If both methods return -1, I would suggest using an application like [Apache JMeter] [11] to determine the header information. A quick way to do this is for JMeter " HTTP Proxy Server " to work with your browser proxy settings set to use localhost as the address and port on which you set the HTTP proxy server for the port. The recorded information will be displayed as separate elements, and if you expand it, there should be an HTTP header manager that contains the name of each header with its own value next to it.

Finally, you can do an analysis on the server itself to see if there are any problems. Make sure the logs look normal, all the correct processes are complete, the configuration is configured correctly, the file still exists and is in the right place, etc. Perhaps the server is no longer responding to content length requests. Also, check if your code works with JRE 7 on another host

I hope that these suggestions will be useful to you and that you can solve this problem that you seem to have. I would also like to point out that you really should consider using the wrapper class and the following notes for each version of the third-party class that you will use in the future, so that you follow the best methods that are easier to maintain, for example, reducing the number of external dependencies that you are using shell classes.

+1
source

Source: https://habr.com/ru/post/1436695/


All Articles