Java: Cannot write to a URLConnection if doOutput=false - call setDoOutput(true) - java

I'm a QA with desire to learn more about Java programming and problem I'm experiencing is this:
I'm trying to POST Employee data to the database of some fake Rest API, but I'm getting
Cannot write to a URLConnection if doOutput=false - call
setDoOutput(true)"
So far, I tried some ideas from StackOverflow, but inexperienced as I am, I could easily fall deeper into a problem.
So URL is: http://dummy.restapiexample.com/api/v1/create and firstly I created an Employee class of json object:
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
Employees em = new Employees();
em.setEmployeeName("Alex");
em.setEmployeeSalary("1234");
em.setEmployeeAge("28");
try{
URL url = new URL("http://dummy.restapiexample.com/api/v1/create");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Unsuccessful call: HTTP error : "
+ conn.getResponseCode());
}
// URLConnection urlc = url.openConnection();
// urlc.setDoOutput(true);
PrintWriter pw = new PrintWriter(conn.getOutputStream());
pw.print(new Gson().toJson(em));
pw.close();
pw.flush();
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream())
);
String json = "";
String output;
while ((output = br.readLine()) != null) {
json += output;
}
conn.disconnect();
System.out.println("Employee name: " + em.getEmployeeName());
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Well, using one of your ideas and added next lines of code (it's commented in above code):
URLConnection urlc = url.openConnection();
urlc.setDoOutput(true);
So the code looks like:
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
Employees em = new Employees();
em.setEmployeeName("Alex");
em.setEmployeeSalary("1234");
em.setEmployeeAge("28");
try{
URL url = new URL("http://dummy.restapiexample.com/api/v1/create");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Unsuccessful call: HTTP error : "
+ conn.getResponseCode());
}
URLConnection urlc = url.openConnection();
urlc.setDoOutput(true);
PrintWriter pw = new PrintWriter(urlc.getOutputStream());
pw.print(new Gson().toJson(em));
pw.close();
pw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(
(urlc.getInputStream())));
String json = "";
String output;
while ((output = br.readLine()) != null) {
json += output;
}
conn.disconnect();
System.out.println("Employee name: " + em.getEmployeeName());
}
catch (MalformedURLException e) {
e.printStackTrace(); }
catch (IOException e) {
e.printStackTrace();
}
}}
With this second code I'm not getting that error, but there is no inserting to the database(checking that using postman, with GET method)...
Well, what am I missing? I guess, I'm missing something basic...

Using url.openConnection twice means you get two different connections. You send the request to the second connection, and try to read the response from the first connection. You should call doOutput on the connection you open originally.
The second problem is you're calling getResponseCode before the request is sent. In http, the request must be sent entirely before the server sends a response. You should move the code that calls doOutput and writes the request body before the code that tries to check the response code.

Related

Trying to get an Access Token from Dwolla restful api

Im having trouble getting an access token for the sandbox environment.
Im following this guide for authenticating: OAuth
So when i create my request, following this guide, i get the following response from the api:
{"error":"access_denied","error_description":"Invalid application credentials."}
Im using key for mf client ID and secret as my client secret as per the instructions.
Here is the code Im using:
public static void main(String[] args) {
try {
URL url = new URL("https://www.dwolla.com/oauth/v2/token");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("client_id", "<Key>");
conn.setRequestProperty("client_secret", "<Secret>");
conn.setRequestProperty("grant_type", "client_credentials");
conn.setDoInput(true);
conn.setDoOutput(true);
System.out.println("Message:" + conn.getResponseMessage());
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 ex) {
Logger.getLogger(PaymentTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(PaymentTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
I was able to get an access token finally. My problem is first of all the above code uses client_id and client_secret as header params. These need to go in the body of the request.
My second problem is that I used the wrong content type for the message I was sending.
Here is the code that worked for me:
URL url = new URL("https://sandbox.dwolla.com/oauth/v2/token");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoInput(true);
conn.setDoOutput(true);
String data = "";
JSONObject jsonObj = new JSONObject();
jsonObj.put("client_id", "<Your Client ID>");
jsonObj.put("client_secret", "<Your Client Secret>");
jsonObj.put("grant_type", "client_credentials");
data = jsonObj.toString();
System.out.println("data = " + data);
byte[] outputInBytes = data.getBytes("UTF-8");
OutputStream os = conn.getOutputStream();
os.write( outputInBytes );
os.close();
System.out.println("Message:" + conn.getResponseMessage());
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();

HttpURLConnection always failing with 401

I'm trying to use HttpURLConnection for connecting to server from Android app which I'm developing. For now, I'm testing the connection code not in an app but as a plain java program with main class. I guess this doesn't make any difference as far as HttpUrlConnection.
Please examine the code snippet. Another issue is even errorStream is throwing null. This I feel is because of malformed URL.
private static String urlConnectionTry() {
URL url; HttpURLConnection connection = null;
try {
String urlParameters = "email=" + URLEncoder.encode("email", "UTF-8") +
"&pwd=" + URLEncoder.encode("password", "UTF-8");
//Create connection
url = new URL("http://example.com/login");
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("uuid", getUuid());
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
//Get Response
InputStream is = connection.getErrorStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(connection != null) {
connection.disconnect();
}
}
}
private static String getUuid() {
try {
Document doc=Jsoup.connect("http://example.com/getUuid").get();
Elements metaElems = doc.select("meta");
for (Element metaElem : metaElems) {
if(metaElem.attr("name").equals("uuid")) {
return metaElem.attr("content");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
You're probably receiving 401 because the credentials that was sent to the server is not authorized- it's probably not registered or the password is incorrect.
As for the null error stream, take a look at this SO answer.
If the connection was not connected, or if the server did not have an error while connecting or if the server had an error but no error data was sent, this method will return null.
It is probably better if you check first the response code using HttpUrlConnection#getResponseCode(). Decide on whether you'll be checking the contents of the error stream based on the response code you get.

Java program to call REST service that needs authentication

public class RestClient {
public static void main(String[] args) {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("fromSku","NONE" );
jsonObject.put("toSku","ASA5500-ENCR-K8" );
jsonObject.put("modelNo", "ASAV10");
jsonObject.put("serialNo", "ASATSTSN");
System.out.println(jsonObject);
URL url = new URL("http://licruleswb- dev.cloudapps.cisco.com/LicenseRules/rest/invokeASARule");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
String encodedCredentials = new String(
org.apache.commons.codec.binary.Base64.encodeBase64
(org.apache.commons.codec.binary.StringUtils.getBytesUtf8("username:password"))
);
System.out.println(encodedCredentials);
connection.setRequestProperty ("Authorization", encodedCredentials);
connection.setRequestProperty("Content-Type", "application/json");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(jsonObject.toString());
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
System.out.println(in.toString());
while (in.readLine() != null) {
System.out.println(in.readLine());
}
System.out.println("\nREST Service Invoked Successfully..");
in.close();
} catch (Exception e) {
System.out.println("\nError while calling REST Service");
System.out.println(e);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Output:
<html><head>
</head><body>
<p>The document has moved here.</p>
null
REST Service Invoked Successfully..
Can anyone help me out to resolve this issue. This link is working perfectly fine if used in REST Client ad on But with this java program it's throwing a 302 error.
I came across your thread when trying something similar. For me the problem was solved by concatenating "Basic " with encodedCredentials variable, making it "Basic EncodedValue".

Java http post: values arent added

I try to send post request, but webserver returns that I added no post-values. I spent a lot of time trying to solve this issue, but no result. Here is the code:
public static String post(String url, String postParams)
{
URLConnection connection = null;
try
{
connection = initializeConnection(url);
connection.setDoOutput(true);
((HttpURLConnection) connection).setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/xml");
connection.setRequestProperty("Accept", "text/xml");
connection.setUseCaches(false);
connection.setDoInput(true);
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.write(postParams.getBytes());
wr.flush();
wr.close();
// Get Response
InputStream is = connection.getInputStream();
return inputStreamToString(is);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
protected static HttpURLConnection initializeConnection(String stringUrl)
{
HttpURLConnection connection;
URL url = null;
try
{
url = new URL(stringUrl);
}
catch (MalformedURLException e1)
{
e1.printStackTrace();
}
try
{
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
return connection;
}
public static String inputStreamToString(InputStream is)
{
BufferedReader r = new BufferedReader(new InputStreamReader(is));
StringBuilder total = new StringBuilder();
String line;
try
{
while ((line = r.readLine()) != null)
{
total.append(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
return total.toString();
}
I receive a message from webserver where it is told that no post-values are added. As far as I understand from the code, the values are added. I'm stuck.
It turned out that all I had to do was to replace
connection.setRequestProperty("Content-Type", "text/xml");
with
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
So simple and so much time spent to clear it out...
By the way, how could I know that server requires this header? I thought that all the work that is essential to the request would be automatically done by java..
P.S. Installing fiddler helped to solve the issue, thanks for that.
debug the 'postParams' parameter and check what been sent.

Java - URL Connection in Threads

I currently have a project where different parameters are requested from an online CGI file, and each request is supposed to be processed in different threads. When I run my code by itself it works great, however it doesn't seem to connect when I put it in a thread.
My code is below:
public void run() {
connect();
}
public synchronized void connect(){
StringBuffer response = new StringBuffer("");
try {
String data = "year=" + year + "&top=" + numNames + "number=";
// Send data
URL url = new URL("http://www.ssa.gov/cgi-bin/popularnames.cgi");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
response.append(line);
}
wr.close();
rd.close();
} catch (Exception e) {
System.out.println(e);
}
System.out.println(response);
}
}
Remove the synchronized call on connect. That should solve your problem
public synchronized void connect(){

Categories

Resources