I have setup a java servlet which accepts parameters from the URL and have it working properly:
public class GetThem extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
try {
double lat=Double.parseDouble(request.getParameter("lat"));
double lon=Double.parseDouble(request.getParameter("lon"));
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(lat + " and " + lon);
} catch (Exception e) {
e.printStackTrace();
}
}
}
So visiting this link:
http://www.example.com:8080/HttpPost/HttpPost?lat=1&lon=2 would output:
"1.0 and 2.0"
I'm currently calling it from another java program using this code:
try{
URL objectGet = new URL("http://www.example.com:8080/HttpPost/HttpPost?lat=" + Double.toString(dg.getLatDouble()) + "&lon=" + Double.toString(dg.getLonDouble()));
URLConnection yc = objectGet.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
...
Now I want to change it so that I'm not using the URL parameters to pass this data to the server. I want to send much larger messages to this server. I am aware that I need to use http post rather than http get to achieve this but am not sure how to do it.
Do I need to change anything on the server side which is receiving data? What do I need to do on the client side which is posting this data?
Any help would be greatly appreciate thanks.
Ideally I'd like to send this data in JSON format.
Below there's sample from the first link found by "java HTTP POST example" in google.
try {
// Construct data
StringBuilder dataBuilder = new StringBuilder();
dataBuilder.append(URLEncoder.encode("key1", "UTF-8")).append('=').append(URLEncoder.encode("value1", "UTF-8")).
append(URLEncoder.encode("key2", "UTF-8")).append('=').append(URLEncoder.encode("value2", "UTF-8"));
// Send data
URL url = new URL("http://hostname:80/cgi");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(dataBuilder.toString());
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
// Process line...
}
wr.close();
rd.close();
} catch (Exception e) {
}
I think you should be using HTTPClient instead of handling connections and streams. Check http://hc.apache.org/httpclient-3.x/tutorial.html
Related
i want to give whole google drive access from my application to users.
and i use following code to authorize from google and oauth2.0.
function OpenGoogleLogin()
{
var url = "https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/drive&redirect_uri=http://localhost:8080/Abc/Oauth2callback&response_type=code&client_id=xxxxxxxxxxxxxxxxxxxxxxxxxx&access_type=offline&approval_prompt=force";
window.location = url;
}
from the above code i got authorization code.
on redirected page i put following servlet code
public class Oauth2callback extends HttpServlet {
private static final long serialVersionUID = 1L;
public Oauth2callback() {
super();
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("entering doGet");
try {
// get code
String code = request.getParameter("code");
// format parameters to post
String urlParameters = "code="
+ code
+ "&client_id=xxxxxxxxxxxxxxxxxxxxx"
+ "&client_secret=xxxxxxxxxxxxxxxxxx"
+ "&redirect_uri=http://localhost:8080/Abc/Oauth2callback"
+ "&grant_type=authorization_code";
//post parameters
URL url = new URL("https://accounts.google.com/o/oauth2/token");
URLConnection urlConn = url.openConnection();
urlConn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(
urlConn.getOutputStream());
writer.write(urlParameters);
writer.flush();
//get output in outputString
String line, outputString = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(
urlConn.getInputStream()));
while ((line = reader.readLine()) != null) {
outputString += line;
}
System.out.println(outputString);
//get Access Token
JsonObject json = (JsonObject)new JsonParser().parse(outputString);
String access_token = json.get("access_token").getAsString();
System.out.println(access_token);
//get User Info
url = new URL(
"https://www.googleapis.com/oauth2/v1/userinfo?access_token="
+ access_token);
urlConn = url.openConnection();
outputString = "";
reader = new BufferedReader(new InputStreamReader(
urlConn.getInputStream()));
while ((line = reader.readLine()) != null) {
outputString += line;
}
System.out.println(outputString);
// Convert JSON response into Pojo class
GooglePojo data = new Gson().fromJson(outputString, GooglePojo.class);
System.out.println(data);
writer.close();
reader.close();
} catch (MalformedURLException e) {
System.out.println( e);
} catch (ProtocolException e) {
System.out.println( e);
} catch (IOException e) {
System.out.println( e);
}
System.out.println("leaving doGet");
}
}
in the above code , google pojo is just a pojo class, but i don't know when i run that servlet, it give me access and refrshtoken..
but with that it gives me error
java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.googleapis.com/oauth2/v1/userinfo?access_token=xxxxxxxxxxxxx.
You are making the initial authorization request with scope https://www.googleapis.com/auth/drive, and using it's code to call https://www.googleapis.com/oauth2/v1/userinfo.
If you want to get user profile information, you will have to use one of these scopes in your initial request,
https://www.googleapis.com/auth/userinfo.email : View email address
https://www.googleapis.com/auth/userinfo.profile : View basic profile info
So, change your first url to
var url = "https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/userinfo.profile&redirect_uri=http://localhost:8080/Abc/Oauth2callback&response_type=code&client_id=xxxxxxxxxxxxxxxxxxxxxxxxxx&access_type=offline&approval_prompt=force";
You need to URLEncode the request parameters. A URL isn't valid as a parameter without encoding.
Im trying to return a JSON string from this api:
https://market.mashape.com/pareshchouhan/trivia
however Java is throwing the error:
java.io.FileNotFoundException: https://pareshchouhan-trivia-v1.p.mashape.com/v1/getAllQuizQuestions?limit=10&page=1
On the line
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
I have used similar code with other Rest APIs so i am a bit unsure why this is happenning.
static String jsonStr;
String data = "";
#Override
protected Void doInBackground(Void... params) {
BufferedReader br = null;
try {
URL url;
String urlStr = "https://pareshchouhan-trivia-v1.p.mashape.com/v1/getAllQuizQuestions?limit=10&page=1";
url = new URL(urlStr);
URLConnection connection = url.openConnection();
connection.setRequestProperty("X-Mashape-Key", "4OFryNEYTWmshe8GheSnmIVEj7gZp1kJf6cjsncjVhXj9WYACn");
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);
OutputStreamWriter outputStreamWr = new OutputStreamWriter(connection.getOutputStream());
outputStreamWr.write(data);
outputStreamWr.flush();
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while((line = br.readLine())!=null) {
sb.append(line);
sb.append(System.getProperty("line.separator"));
}
jsonStr = sb.toString();
} catch (Exception e){
e.printStackTrace();
}
return null;
}
Any help would be greatly appreciated.
Regards.
Turns out I was trying to perform the wrong type of Request. This specific API did not support Get requests. Discovered this using https://www.hurl.it/
regardless, using the tutorial found here:
http://www.mkyong.com/java/how-to-send-http-request-getpost-in-java/
I was able to change the request type and pull the correct data.
Hope this helps.
I'm modifying my code to use Apache HttpComponents after I was advised it's a cleaner approach
HttpURLConnection code (working):
String names = "names[]=EndUser/WebTransaction/WebTransaction/JSP/index.jsp";
try (PrintWriter writer = response.getWriter()) {
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("X-Api-Key", "myId");
conn.setRequestMethod("GET");
conn.setDoOutput(true);
conn.setDoInput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(names);
wr.flush();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
System.out.println(line);
writer.println(HTML_START + "<h2> NewRelic JSON Response:</h2><h3>" + line + "</h3>" + HTML_END);
}
wr.close();
reader.close();
}catch(MalformedURLException e){
e.printStackTrace();
}
This is my code modified to use Apache HttpComponents(404 not found response):
try (PrintWriter writer = response.getWriter()) {
HttpClient client = HttpClientBuilder.create().build();
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("X-Api-Key", "myID"));
nameValuePairs.add(new BasicNameValuePair("names[]", "EndUser/WebTransaction/WebTransaction/JSP/index.jsp"));
HttpGet request1 = new HttpGet(url + URLEncodedUtils.format(nameValuePairs, "utf-8"));
request1.setHeader("Accept", "application/json");
HttpResponse response1 = client.execute(request1);
System.out.println(response1.getStatusLine().getStatusCode());
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(response1.getEntity().getContent()));
while ((line = reader.readLine()) != null) {
System.out.println(line);
writer.println(HTML_START + "<h2> NewRelic JSON Response:</h2><h3>" + line + "</h3>" + HTML_END);
}
reader.close();
}catch(MalformedURLException e){
e.printStackTrace();
}
Could someone point out to me the correct way to accomplish this please.
Much much cleaner approach is to use Retrofit like library, Because these are boilerplate codes.
You can still use this code as a generic method to bring in Json objects so that you can process them and get what ever necessary information you want out of it.But it is not cleaner, It is messy trust me. :)
Since I do not have your actual API url I will try to give an example using this API function.
Retrofit is type safe, which means you specify the model pojo and it will take care of doing necessary casting to the Json object to your model itself which is cool.
model,
public class Application {
private Integer id;
private String name;
private String language;
private String health_status;
//Getters and setters
}
dto,
public class ApplicationListDot {
private List<Application> applications;
}
Interface,
public interface RestController {
#GET("/v2/applications.json")
ApplicationListDot viewApplications();
}
In my java application I used a Httpsurlconnection to post some string data to the server. When I test this code on android, it works perfectly. However, in a java application it does not work. Client java application is as follows:
public static void main(String[] args) {
disableSslVerification();
new HttpsClient().testIt();
}
private void testIt() {
String https_url = "https://XXX.XX.XXX.XXX:XXXX/XXXXX/TestServlet";
URL url;
try {
url = new URL(https_url);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
print_content(con, "test");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void print_content(HttpsURLConnection connection, String data) {
if (connection != null) {
try {
connection.setConnectTimeout(6000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
Charset cSet = Charset.forName("UTF-8");
byte bytes[] = data.getBytes(cSet);
connection.setRequestProperty("Content-Length", ""
+ Integer.toString(bytes.length));
connection.setRequestProperty("Content-Language", "tr");
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(
connection.getOutputStream());
wr.write(bytes);
wr.flush();
wr.close();
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is, cSet));
String line;
StringBuilder response = new StringBuilder();
while ((line = rd.readLine()) != null) {
response.append(line);
response.append(System.getProperty("line.separator"));
}
rd.close();
System.out.println(response.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
And the servlet is as follows:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String s = getHTML(request);
try {
out.print("received data:");
out.print(s);
} finally {
out.close();
}
}
private String getHTML(HttpServletRequest request) throws IOException {
int n = request.getContentLength();
if (n < 1) {
return "";
}
byte bytes[] = new byte[n];
request.getInputStream().read(bytes);
return new String(bytes, "UTF-8");
}
When I run this application, servlet's response is:
received data:tâââ
Always only the first character is correctly send to the servlet. The same code works perfect on android. Can anyone help me please? Thanks...
I can't see an obvious problem with your code that would cause this.
Can anyone help me please?
I suggest that you take a methodical approach to investigating the problem. Use a packet sniffer to check what is actually being sent over the wire. Check that the actual headers in the request and response are correct. Check that the request and response bodies are really properly encoded UTF-8 ...
What you find in your investigation / evidence gathering will help you figure out where the problem (or problems) are occurring ... and that will allow you to home in on the part(s) of your code that is/are responsible.
request.getInputStream().read(bytes);
You might need to do this read in a loop. At the very least, check how many bytes have been read. The array appears to be empty except for the first char.
Reads some number of bytes from the input stream and stores them into
the buffer array b. The number of bytes actually read is returned as
an integer. This method blocks until input data is available, end of
file is detected, or an exception is thrown.
I have successfully implemented this from android to a java httpservlet on google app engine, but I'd like to use python instead for the server side. I'm new to python. Has anyone done this? I have the guestbook example up and running, but I can't seem to send posts from my android app to the server.
I'd also like to issue a string response back to the client like "success".
A guiding hand would be much appreciated.
Thanks
***Client side java:
URL url = new URL(Const.SERVER_NAME);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(
connection.getOutputStream()
);
out.write("content=12345");
out.close();
***Server side Python:
class Upload(webapp.RequestHandler):
def post(self):
greeting.content = self.request.get('content')
greeting.put()
***Server side Java (working)
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
try {
String instring = request.getParameter("content")
// set the response code and write the response data
response.setStatus(HttpServletResponse.SC_OK);
OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream());
writer.write("Success");
writer.flush();
writer.close();
} catch (IOException e) {
try{
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getWriter().print(e.getMessage());
response.getWriter().close();
} catch (IOException ioe) {
}
}
I know it's been a long time. But I did solve this so I'll post the solution.
Android code:
url = new URL(SERVER_URL);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(
connection.getOutputStream());
String post_string;
post_string = "deviceID="+tm.getDeviceId().toString();
// send post string to server
out.write(post_string);
out.close();
//grab a return string from server
BufferedReader in = new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
Toast.makeText(context, in.readLine(), Toast.LENGTH_SHORT).show();
And here's the python server side, using Django with GAE:
def upload(request):
if request.method == 'POST':
deviceID = measurement.deviceID = str(request.POST['deviceID'])
return HttpResponse('Success!')
else:
return HttpResponse('Invalid Data')