So in a nutshell, I'm just trying to get a small working skeleton program that I can use to sort of learn about Http communication and "feel" my way around to figure out what I will eventually need for a bigger program I am working on. This particular code here is actually just a chopped up version of an example from the Apache libraries. I could compile the examples listed on the Apache website, but they didn't run properly, giving a "java.net.ConnectException". I figured it had to do with Windows c-blocking a program like this from making a connection, and that I would need to run it as an administrator. I then tried taking the code and throwing it into an executable jar file, but I get a Cannot-find-or-load-main-class error. Am I an idiot or is the Apache library a little outdated/not fit for Win 8/something else?
Code below:
package NewProject;
import java.net.Socket;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.impl.DefaultBHttpClientConnection;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.HttpProcessorBuilder;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.apache.http.util.EntityUtils;
class NewProject
{
public static void main(String[] args) throws Exception
{
HttpProcessor httpproc = HttpProcessorBuilder.create()
.add(new RequestContent())
.add(new RequestTargetHost())
.add(new RequestConnControl())
.add(new RequestUserAgent("Test/1.1"))
.add(new RequestExpectContinue(true)).build();
HttpRequestExecutor httpexecutor = new HttpRequestExecutor();
HttpCoreContext coreContext = HttpCoreContext.create();
HttpHost host = new HttpHost("localhost", 8080);
coreContext.setTargetHost(host);
Out os = new Out("TestOut.txt");
DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1024);
ConnectionReuseStrategy connStrategy = DefaultConnectionReuseStrategy.INSTANCE;
try
{
String[] targets =
{
"http://www.google.com/"
};
for (int i = 0; i < targets.length; i++)
{
if (!conn.isOpen())
{
Socket socket = new Socket(host.getHostName(), host.getPort());
conn.bind(socket);
}
BasicHttpRequest request = new BasicHttpRequest("GET", targets[i]);
os.println(">> Request URI: " + request.getRequestLine().getUri());
httpexecutor.preProcess(request, httpproc, coreContext);
HttpResponse response = httpexecutor.execute(request, conn, coreContext);
httpexecutor.postProcess(response, httpproc, coreContext);
os.println("<< Response: " + response.getStatusLine());
os.println(EntityUtils.toString(response.getEntity()));
os.println("==============");
if (!connStrategy.keepAlive(response, coreContext))
{
conn.close();
}
else
{
os.println("Connection kept alive...");
}
}
}
catch (IndexOutOfBoundsException iob)
{
os.println("What happened here?");
}
finally
{
conn.close();
}
return;
}
}
... they didn't run properly, giving a "java.net.ConnectException"
That could be caused by lots of things. There are clues in the exception message ... which you chose not to share with us.
... "Cannot find or load Main-Class"
Again multiple possible causes, and there are clues in the exception message ... which you chose not to share with us.
But the fact that you have created a JAR file plus the "Main-Class" hint in the error message fragment you provided suggest that you made a mistake in the creation of the JAR file; i.e. you used the wrong name for the "Main-Class" attribute.
Given that source code, the "Main-Class" attribute should be "NewProject.NewProject". I suspect you set it to something else.
A second possibility is that you haven't handled the dependency on the Apache library correctly. The Apache classes need to be on the classpath specified by the JAR file. (You can't use a -cp argument or $CLASSPATH when you launch with java -jar.)
Am I an idiot or is the Apache library a little outdated/not fit for Win 8/something else?
There is nothing wrong with the Apache library.
The code you posted seems a little low level (e.g. interacting directly with Socket connections). The code posted below should give you what it sounds like you are looking for. The classes used also give you a lot of inroads into setting and getting http parameters (e.g. headers, time-outs, etc).
package org.yaorma.example.http.client;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpClientExample {
public static void main(String[] args) throws Exception {
String response;
response = get("http://www.google.com");
System.out.println("RESPONSE FROM GET -----------------------------------------");
System.out.println(response);
response = post("http://httpbin.org/post", "This is the message I posted to httpbin.org/post");
System.out.println("RESPONSE FROM POST -----------------------------------------");
System.out.println(response);
}
/**
* Method to post a request to a given URL.
*/
public static String post(String urlString, String message) {
try {
// get a connection
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// set the parameters
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// send the message
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(message);
writer.flush();
writer.close();
os.close();
// get the response
conn.connect();
InputStream content = (InputStream) conn.getInputStream();
// read the response
BufferedReader in = new BufferedReader(new InputStreamReader(content));
String rtn = "";
String line;
while ((line = in.readLine()) != null) {
rtn += line + "\n";
}
return rtn;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
/**
* Method to do a get from a given URL.
*/
public static String get(String urlString) {
try {
// get a connection
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// set the parameters
conn.setRequestMethod("GET");
conn.setDoOutput(true);
// get the response
conn.connect();
InputStream content = (InputStream) conn.getInputStream();
// read the response
BufferedReader in = new BufferedReader(new InputStreamReader(content));
String rtn = "";
String line;
while ((line = in.readLine()) != null) {
rtn += line + "\n";
}
return rtn;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
}
Related
I want to make some searches in spotify database only for learning purpose of rest app.
I'm stuck on the first point of
https://developer.spotify.com/documentation/general/guides/authorization-guide/
Authorization Code Flow
to login in spotify with java app:
package spotify;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/*
1) https://developer.spotify.com/dashboard/applications
*/
public class SpotifyMain {
static final String CLIENTID = "blablablablablablablabla";
static final String CLIENTSECRET = "blablablablablablablabla";
static final String REDIRECTURL = "https://github.com/blablablablablablablabla"; //whiltelisted set inside spotify
public static void main(String[] args) {
try {
String url_auth =
"https://accounts.spotify.com/authorize?"
+ "client_id="+CLIENTID+"&"
+ "response_type=code&"
+ "redirect_uri="+REDIRECTURL+"&"
+ "scope=user-read-private%20user-read-email&"
+ "state=34fFs29kd09";
System.out.println(url_auth);
URL url = new URL(url_auth);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I get error 406.
The url I think is correct because if I put that url inside a browser it displays correctly that the app want to access some resources.
If I put that url inside postman the error changes in 400 bad request...
Am I missing something?
thanks
Try removing this line:
conn.setRequestProperty("Accept", "application/json");
HTTP 406 Error is "Not Acceptable" meaning the server has generated a reply that it can't return as the requested Accept content type.
You are trying to open a webpage (HTML) via code and you set
conn.setRequestProperty("Accept", "application/json");
This will not work for auth. You should open the link in the browser, let the user sign in and take the code from the redirect url.
I'm making the HTTP GET request from a basic java program to a URL which happens to be "http://localhost:9992/users/john.doe#example.com":
public class Tester {
public static void main(String[] args) {
HttpRequester.doesUserExist("john.doe#example.com");
}
}
The implementation of the HTTPRequester is this:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpRequester {
private static HttpURLConnection connection = null;
public static boolean doesUserExist(final String email) {
final String targetUrl = Constants.URL_USER_SRVC + email;
System.out.println(targetUrl);
try {
URL url = new URL(targetUrl);
connection = (HttpURLConnection) url.openConnection();
System.out.println(connection.getRequestMethod());
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/json");
connection.setUseCaches(false);
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(
connection.getOutputStream());
outputStream.writeBytes(email);
outputStream.close();
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer response = new StringBuffer();
String line;
while((line = reader.readLine()) != null) {
response.append(line);
response.append('\r');
}
reader.close();
System.out.println(response.toString());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
The webservice embedded in a Grizzly server and here are the APIs:
#Path("/users")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class UserResource {
#GET
public List<User> getUsers() {
return UserService.getUsers();
}
#GET
#Path("/{userEmail}")
public User getUser(#PathParam("userEmail") String userEmail) {
return UserService.getUser(userEmail);
}
}
Please take note that the webservice and java program are two separate projects. When I execute the main method I get this error output in the console:
java.io.IOException: Server returned HTTP response code: 405 for URL: http://localhost:9992/users/john.doe#example.com
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1627)
at com.axa.visualizr.auth.utils.HttpRequester.doesUserExist(HttpRequester.java:30)
at com.axa.visualizr.auth.core.Tester.main(Tester.java:8)
What I think is odd is that the error outputs this at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1627) even though I imported java.net.HttpURLConnection;. I have tried opening the declaration on that line but Eclipse states that it is not an valid line number in that class.
I don't know why it's saying that the method is not allowed when I have setRequestMethod("GET"). Maybe it might be because the java program is not running on any kind of server? The Tester.java is only for testing purposes eventually I will move HTTPRequester to another webservice and make the call from webservice A to webservice B.
Since you are passing something in the requestbody, java is interpreting it as a POST request. Please remove below lines from your code and try:
DataOutputStream outputStream = new DataOutputStream(
connection.getOutputStream());
outputStream.writeBytes(email);
outputStream.close();
Try below code:
final String targetUrl = Constants.URL_USER_SRVC + URLEncoder.encode(email, "UTF-8");
instead of: final String targetUrl = Constants.URL_USER_SRVC + email;
I have something I am trying to achieve.
I have a web application running on my localhost on port 8080.
I have a HTTP Server running on localhost:9005.
I have a JSP form that passes info to a servlet java class, that in turn performs the HTTP post to the URL on the HTTP Server localhost:9010 with the data string.
What I need to do is perform the POST and GET as part of the same connection. I have them working as two separate calls, but not on the same connection. It needs to be the same connection, as I post data, the HTTP Server takes this data, processes it and outputs unique data to this URL. Therefore the GET needs to be part of the same connection as he POST.
Can anyone please help?
This is my Process Request java code:
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.List;
import java.util.Map.Entry;
public class ProcessRequest {
public void sendRequestToGateway() throws Throwable{
String message = URLEncoder.encode("OP1387927", "UTF-8");
try {
URL url = new URL("http://localhost:9005/json");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write("operator=" + message);
writer.close();
System.out.println("connection.getResponseCode() : " + connection.getResponseCode());
System.out.println("connection.getResponseMessage()" + connection.getResponseMessage());
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
receiveMessageFromGateway();
} else {
// Server returned HTTP error code.
}
//receiveMessageFromGateway();
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
}
public void receiveMessageFromGateway() throws Throwable {
HttpURLConnection client = null;
OutputStreamWriter wr = null;
BufferedReader rd = null;
StringBuilder sb = null;
String line = null;
try {
URL url = new URL("http://localhost:9005/json");
client = (HttpURLConnection) url.openConnection();
client.setRequestMethod("GET");
client.setDoOutput(true);
client.setReadTimeout(10000);
client.connect();
System.out.println(" *** headers ***");
for (Entry<String, List<String>> headernew : client.getHeaderFields().entrySet()) {
System.out.println(headernew.getKey() + "=" + headernew.getValue());
}
System.out.println(" \n\n*** Body ***");
rd = new BufferedReader(new InputStreamReader(client.getInputStream()));
sb = new StringBuilder();
while ((line = rd.readLine()) != null) {
sb.append(line + '\n');
}
System.out.println("body=" + sb.toString());
} finally {
client.disconnect();
rd = null;
sb = null;
wr = null;
}
}
}
Why don't you just return the result from the original POST?
In general you can't control connection reuse with HttpUrlConnection. You might be able to cast your connection to the specific implementation class and interfere with it but that's a horribly unstable way of doing it.
Apache HttpClient is probably a better option, given the requirements.
You can use Apache HTTP Client for this. Its very simple.
If you are using maven, just add the following lines into your POM file:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.3</version>
</dependency>
In this example, I'm submitting a POST request and after that a GET request.
Take a look:
public static String get(String p_url) throws IOException
{
CloseableHttpClient httpclient = HttpClients.createDefault();
// First request: POST
HttpPost httpPost = new HttpPost("http://the-api-url.com/Login/Auth&token=12345"));
CloseableHttpResponse response_post = httpclient.execute(httpPost);
System.out.println(response_post.getStatusLine());
HttpEntity entity_post = response_post.getEntity();
System.out.println(EntityUtils.toString(entity_post));
// Second request: GET
HttpGet httpGet = new HttpGet(p_url);
CloseableHttpResponse response_get = httpclient.execute(httpGet);
System.out.println(response_get.getStatusLine());
HttpEntity entity_get = response_get.getEntity();
System.out.println(EntityUtils.toString(entity_get));
response_post.close();
response_get.close();
return EntityUtils.toString(entity_get);
}
I've written a small command line program to read web pages and print the response body out to the terminal.
This works well for most sites, however when reading a chunked response from this url: http://www.pampers.co.uk/home I get the following back trace:
java.io.IOException: Premature EOF
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:538)
at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:582)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:669)
at java.io.FilterInputStream.read(FilterInputStream.java:116)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:2668)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.Reader.read(Reader.java:123)
at HttpPageReader.main(HttpPageReader.java:44)`
I've hardcoded the charset to match the response from this page. What steps should I take to debug this issue? I'm assuming this isn't a Java bug but an issue with what's returned by the web server - however I have viewed the page in my web browser and also downloaded it using curl, both without problem.
The code is as follows, should be easy to copy and paste and run stand alone:
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Logger;
public class HttpPageReader
{
private final static Logger logger = Logger.getLogger(HttpPageReader.class.getName());
private static final int SECOND_IN_MILLI_SECONDS = 1000;
private static final int TIME_OUT_MILLI_SECONDS = 10 * SECOND_IN_MILLI_SECONDS;
public static void main(String[] args)
{
if ( args.length != 1)
{
logger.warning("Please provide a url to download");
System.exit(1);
}
logger.info("Downloading url " + args[0] + "...");
try
{
URL url = new URL(args[0]);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setRequestProperty("User-Agent", "My User Agent");
httpConn.setRequestProperty("Accept", "*/*");
httpConn.setConnectTimeout(TIME_OUT_MILLI_SECONDS);
httpConn.setReadTimeout(TIME_OUT_MILLI_SECONDS);
InputStreamReader inputStreamReader = new InputStreamReader(httpConn.getInputStream(), "utf-8");
char chars[] = new char[1000];
int numRead = inputStreamReader.read(chars);
StringBuffer stringBuffer = new StringBuffer();
while (numRead != -1)
{
stringBuffer.append(new String(chars, 0, numRead));
numRead = inputStreamReader.read(chars);
}
logger.info("done");
logger.info(stringBuffer.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Update: Using IOUtils.toString(httpConn.getInputStream(), "utf-8") as suggested gives pretty much the same backtrace - so the question remains, how do I go about debugging this problem?
Gives:
java.io.IOException: Premature EOF
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:538)
at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:582)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:669)
at java.io.FilterInputStream.read(FilterInputStream.java:116)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:2668)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.Reader.read(Reader.java:123)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1928)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1907)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:1884)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:1834)
at org.apache.commons.io.IOUtils.toString(IOUtils.java:705)
at org.apache.commons.io.IOUtils.toString(IOUtils.java:730)
at HttpPageReader.main(HttpPageReader.java:40)
Try this..... this way its easier... And remember dont overload the program with n nos things until u really need them......
Just Copy paste this code and try out...then try to modify it in your own way.... best of luck !!!
package com.my;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Scanner;
public class TestSrc {
public static void main(String[] args) {
try {
URL url = new URL("http://www.pampers.co.uk/home");
try {
InputStream i = url.openStream();
Scanner scan = new Scanner(i);
while (scan.hasNextLine()) {
System.out.println(scan.nextLine());
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
Have you tried using IOUtils.toString(inputStream) ?
Apache Commons IOUtils
I need to develop an helper class on top of org.apache.httpclient for my android application. Following code works fine for android, but not for JavaSE 1.6 in my PC.
Question is: Can I use org.apache.httpclient both for android and for PC? If I cant: what is your http client library advise?
I want to develop one helper class and use it at all.
Here is the code that works fine in android but some classes cannot be resolved for on Java SE 1.6.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public class HTTPClient {
public static void connect(String url)
{
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet(url);
// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget);
// Examine the response status
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
String result= convertStreamToString(instream);
// now you have the string representation of the HTML request
instream.close();
}
} catch (Exception e) {}
}
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the BufferedReader.readLine()
* method. We iterate until the BufferedReader return null which means
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
Yes you can, you should avoid naming your client helper class as the same thing as an already defined class. Although Java is case sensitive, it is confusing will trip you up when you least expect it. It may even be guilty for causing this problem. Why not call it HttpClientHelper as that is what it truly is.
Here's an example of HttpClient http://hc.apache.org/httpclient-3.x/tutorial.html