Is it really necessary to use url.openConnection()? - java

As we all know both these codes will yield the same result
public class MainApp {
public static void main(String[] args) throws IOException {
URL google = new URL("http://www.google.com");
google.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(google.openStream()));
reader.lines().forEach(System.out::println);
}
}
and
public class MainApp {
public static void main(String[] args) throws IOException {
URL google = new URL("http://www.google.com");
BufferedReader reader = new BufferedReader(new InputStreamReader(google.openStream()));
reader.lines().forEach(System.out::println);
}
}
So what's the point in using google.openConnection()?

May be javadoc for this method helps:
public java.net.URLConnection openConnection() throws java.io.IOException
Returns a URLConnection instance that represents a connection to the remote object referred to by the URL. A new instance
of URLConnection is created every time when invoking the
URLStreamHandler.openConnection(URL) method of the protocol handler
for this URL.
It should be noted that a URLConnection instance does not establish
the actual network connection on creation. This will happen only when
calling URLConnection.connect().
If for the URL's protocol (such as HTTP or JAR), there exists a
public, specialized URLConnection subclass belonging to one of the
following packages or one of their subpackages: java.lang, java.io,
java.util, java.net, the connection returned will be of that subclass.
For example, for HTTP an HttpURLConnection will be returned, and for
JAR a JarURLConnection will be returned.
Use this if you want to add some specific connectivity properties to your connection.
For example:
URLConnection urlConnection = google.openConnection();
urlConnection.setReadTimeout(1000);
urlConnection.setConnectTimeout(1000);

Since the code for openStream() is:
public final InputStream openStream() throws java.io.IOException {
return openConnection().getInputStream();
}
It seems quite redundant indeed.
But if I were you, if I openConnection()d, I would then get the InputStream on the returned URLConnection.

openConnection() does not modify the URL object, it returns a URLConnection instance that you could then use. The code in the question ignores the return value of openConnection(), so, in this case, it's indeed pointless. it would only be useful if you actually do something with this connection object, such as, e.g., modifying its timeout:
URL google = new URL("http://www.google.com");
URLConnection conn = google.openConnection();
conn.setTimeout(7); // just an example
BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream()));
reader.lines().forEach(System.out::println);

Related

Read from URL if content is image [duplicate]

I am trying to write a java program that will automatically download and name some of my favorite web comics. Since I will be requesting multiple objects from the same domain, I wanted to have a persistent http connection that I could keep open until all the comics have been downloaded. Below is my work-in-progress. How do I make another request from the same domain but different path without opening a new http connection?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class ComicDownloader
{
public static void main(String[] args)
{
URL url = null;
HttpURLConnection httpc = null;
BufferedReader input = null;
try
{
url = new URL("http://www.cad-comic.com/cad/archive/2002");
httpc = (HttpURLConnection) url.openConnection();
input = new BufferedReader(new InputStreamReader(httpc.getInputStream()));
String inputLine;
while ((inputLine = input.readLine()) != null)
{
System.out.println(inputLine);
}
input.close();
httpc.disconnect();
}
catch (IOException ex)
{
System.out.println(ex);
}
}
}
According to the documentation here, HTTP persistence is being handled transparently in Java, although it gives you the options to control it too via http.keepAlive and http.maxConnections system properties.
However,
The current implementation doesn't
buffer the response body. Which means
that the application has to finish
reading the response body or call
close() to abandon the rest of the
response body, in order for that
connection to be reused. Furthermore,
current implementation will not try
block-reading when cleaning up the
connection, meaning if the whole
response body is not available, the
connection will not be reused.
Take a look at the link and see if it really helps you.
According to this link http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html, HTTP connection reuse is enabled by default, you can use Wireshark to check the interactions between your client and server. The first request contains TCP and SSL handshakes(if your request is https), the subsequent requests fired in the keep-alive time, contains no TCP and SSL handshakes, just application data transfers.
Even though HttpURLConnection enable keep-alive by default, it is not guaranteed that HttpURLConnection uses same TCP connection for multiple HTTP requests. I faced same kind of issue when writing HTTPS client application. Solved this issue by using single instance of SSLContext, SSLSocketFactory and HttpsURLConnection.
public class MyHTTPClient {
private SSLContext mSSLContext = null;
private SSLSocketFactory mSSLSocketFactory = null;
private HttpsURLConnection mConnection = null;
public void init() {
//Setup SSL context and Socket factory here
}
pubblic void sendRequest() {
URL url = new URL("https://example.com/request_receiver");
mConnection = (HttpsURLConnection) url.openConnection();
mConnection.setSSLSocketFactory(mSSLSocketFactory);
// Setup request property and send request
// Open input stream to read response
// Close output, input streams
mConnection.disconnect();
}
}

How do I inject a BufferedReader with InputStreamReader as its parameter using Spring Boot?

My question is along the same lines as this question. However, my BufferedReader takes an InputStreamReader as parameter. My code looks like this:
URL url = new URL("http://localhost:8080/endpoint");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//Line of importance:
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
How do I inject this, so that I can mock it for unit testing? Thanks in advance.
EDIT: Added test code (how I think it should work):
Adding a bean(?):
#Bean
public BufferedReader bufferedReader() throws FileNotFoundException {
return new BufferedReader(new InputStreamReader());
}
Mocking of all dependencies with mock instances:
#Mock
private HttpURLConnection httpURLConnection;
#Mock
private BufferedReader bufferedReader;
#Mock
private InputStream inputStream;
when(URLhandlerClass.getPath(any(String.class))).thenReturn("http://localhost:8080/endpoint);
when(bufferedReader.readLine()).thenReturn("firstLine", "secondLine", "thirdLine");
when(httpURLConnection.getInputStream()).thenReturn(inputStream);
ERROR: FileNotFoundException and Connect: connection refused
What exactly do you want to mock?
Easiest I see here is to fake the whole method, e.g. wrap everything in a service and mock it whole when testing your code.
e.g.
#Service
public class DataReader {
public BufferedReader ReadDataFrom(string url){
URL url = new URL("http://localhost:8080/endpoint");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//Line of importance:
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
}
}
This can easily be faked.
Usually, when you encounter a problem where you ask yourself "wtf I mock this?" the solution is a service ;)

theMovieDB api call throwing IOEXception

I am making an android app that uses theMovieDB API.
Look at the part of my class extending AsyncTask.
private HttpURLConnection urlconnection = null;
private URL url;
protected String doInBackground(String[] task)
{
String DATA=null;
String baseAddress="https://api.themoviedb.org/3/movie/";
String apiKey="225b36fd29826b4c9821dd90bfc4e055";
Uri Url = Uri.parse(baseAddress).buildUpon().appendEncodedPath(task[0]).appendQueryParameter("api_key",apiKey).build();
Log.d("built URL",Url.toString());
try
{
url= new URL(Url.toString());
urlconnection= (HttpURLConnection) url.openConnection();
urlconnection.setRequestMethod("GET");
urlconnection.connect();
InputStream inputStream = urlconnection.getInputStream();
if (inputStream==null)
{
return null;
}
BufferedReader reader= new BufferedReader(new InputStreamReader(inputStream));
StringBuffer buffer=null;
String line;
while ((line=reader.readLine())!=null)
{
buffer.append(line+'\n');
}
DATA=buffer.toString();
}
I am getting IOException (seen in logcat). I checked the built URL on the browser(it was working). The Same set of syntax did work on openweather api. Is there any other thing that themovieDb API need? Help me Solve it. I did check there documentation but there was no info for android.
i got the Solution. I was connected to my mobile hotspot which due to some reason does not work as expected. Switching to my home WIFI fixed the issue.
Thanks for giving your time on my question

using Get request with URLConnection

I am currently writing program to communicate with a device in my network, and the following code is what I have so far, it passed authentication and can get the webpage from the device, however i couldnt get the GET request to work, when I run the code below, i get the error:
Exception in thread "main" java.io.FileNotFoundException: http://192.168.100.222:80
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
when I input data on the webpage, its equivalent of going http://l192.168.xxx.xxx/2?A=3&p=1&X=1234, and from tcpflow, it does GET /2?A=4&p=1&X=1234 HTTP/1.1,
I tried creating a new url connection with http://192.168.xxx.xxx/2?A=3&p=1&X=1234, and it worked, but i have multiple input options and i dont want to create a new connection for each of them, how can I do the equivalent while staying connected? or what I did wrong in the code?
thanks in advance.
public class main {
public static void main(String[] argv) throws Exception {
Authenticator.setDefault(new MyAuthenticator());
URL url = new URL("http://192.168.xxx.xxx");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write("Get /2?A=4&p=1&X=1234 HTTP1.1");
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
System.out.println(decodedString);
}
in.close();
}
I don't want to create a new connection for each of them
Don't worry about that. HttpURLConnection does connection pooling under the hood. Just use your actual URLs, don't try to out-think Java.

HTTP PUT Request to Bitbucket API

I want to develop a java library for bitbucket issues API access.
I've already asked a question about the computation of the HTTP Content-Length header, but this question is specifically about the Bitbucket API and the process of updating an issue (since every other request works well).
The following code doesn't work, giving a 411 Length Required error.
But even more confusing: In the documentation, you are told to use PUT request method. If you "forget" to specify that, status code changes to 200 OK, but leaving the issue unchanged.
public class PutTest {
public static void main(String[] args) throws Exception {
URL u = new URL("https://api.bitbucket.org/1.0/repositories/myname/myproject/issues/1/?title=hello+world");
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.addRequestProperty("Authorization", "Basic "+Base64.encodeToString("user:password".getBytes(), false));
c.addRequestProperty("Content-Length", String.valueOf(u.getQuery().getBytes("UTF-8").length));
c.setRequestMethod("PUT");
c.connect();
System.out.println(c.getResponseCode()+" "+c.getResponseMessage());
}
}
My updated code sample works, with help of another question at stackoverflow: How to send PUT, DELETE HTTP request in HttpURLConnection? Looks like not working.
Utilizing connection's OutputStream works.
public class PutTest {
public static void main(String[] args) throws Exception {
URL u = new URL("https://api.bitbucket.org/1.0/repositories/myname/myproject/issues/1/");
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.addRequestProperty("Authorization", "Basic "+Base64.encodeToString(("user:password").getBytes(), false));
c.setRequestMethod("PUT");
c.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream());
out.write("title=hello+world");
out.close();
c.connect();
System.out.println(c.getResponseCode()+" "+c.getResponseMessage());
}
}

Categories