When making a post request to my backend, I get the following error. I can't really find a fix online and am very new to Java.
Here is the error:
Caused by: java.lang.ClassNotFoundException: org.apache.http.concurrent.Cancellable
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 59 more
Code
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.http.HttpHeaders;
import java.util.ArrayList;
import java.util.List;
public class APIBridge {
private final CloseableHttpClient httpClient = HttpClients.createDefault();
public String url = "http://localhost:9004/index.php";
public static void Register(String username, String password) throws UnsupportedEncodingException {
String url = "http://localhost:9004/index.php";
HttpPost post = new HttpPost(url);
// Add request parameter, form parameters
List<NameValuePair> urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("username", username));
urlParameters.add(new BasicNameValuePair("password", password));
urlParameters.add(new BasicNameValuePair("Register", "true"));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(post)) {
System.out.println(EntityUtils.toString(response.getEntity()));
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void close() throws IOException {
httpClient.close();
}
private void sendGet() throws Exception {
HttpGet request = new HttpGet("https://www.google.com/search?q=mkyong");
// Add request headers
request.addHeader("custom-key", "mkyong");
//request.addHeader(, "Googlebot");
try (CloseableHttpResponse response = httpClient.execute(request)) {
// Get HttpResponse Status
System.out.println(response.getStatusLine().toString());
HttpEntity entity = response.getEntity();
Header headers = entity.getContentType();
System.out.println(headers);
if (entity != null) {
// Return it as a String
String result = EntityUtils.toString(entity);
System.out.println(result);
}
}
}
IMO, it is easier to use the HTTP client in the JDK, so I have provided an answer demonstrating this alternate approach.
The Apache HTTP libraries were never targeted at somebody who is "new to Java". If you use them, make sure you use the correct versions of all the libraries and matching documentation as the library has gone through multiple incompatible API changes over years of library upgrades.
From your question, your module-info.java may be wrong or may need to be deleted. But your issue could also be caused by an environment setup or dependency version issue.
Basically, the class isn’t on the class or module path. Or it is on a path, but it is not accessible. The reason for that is not discernable from your question.
Example JavaFXApp using JDK HTTP Client
Makes a post request, gets the result as text and places the text in a TextArea.
module-info.java
module com.example.httpapp {
requires javafx.controls;
requires java.net.http;
exports com.example.httpapp;
}
src/main/java/com/example/httpapp/HttpApp.java
package com.example.httpapp;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpApp extends Application {
#Override
public void start(Stage stage) throws IOException, URISyntaxException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("http://jsonplaceholder.typicode.com/posts"))
.POST(HttpRequest.BodyPublishers.ofString("Sample Post Request"))
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
String responseBody = response.body();
TextArea textArea = new TextArea(responseBody);
textArea.setStyle("-fx-font-family: monospace;");
stage.setScene(new Scene(textArea));
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Authentication
Outside of a local test app, you should not send unencrypted authentication data over a network connection as you have in your question code.
If you also need authentication, it is best to communicate over HTTPS. Then you can securely use basic or digest authentication, or HTTPS mutual authentication, or encode the authentication information in the post body.
Examples for basic authentication using the Java HTTP client are at:
Baeldung: Java HttpClient Basic Authentication
Related
I am trying to import the httpclient, string entity class and all the other classes that are mentioned but none of the classes are getting imported. I have added the jar files to the build path, but nothing seems to resolve the errors. can someone please help me resolve it. im stuck on it for almost a day now.
package httpRequests;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
public class http {
public static void main(String[] args) {
// TODO Auto-generated method stub
String IP = "api.cle.org.pk";
String postURL = "https://" + IP+ "/v1/synth";
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(postURL);
StringEntity postingString = new StringEntity(JSON_MSG,"UTF-8");
post.setEntity(postingString);
post.setHeader("Content-type", "application/json;odata=verbose");
HttpResponse response = httpClient.execute(post);
String JSON_Response=convertStreamToString(response.getEntity().getContent());
}
}
Edit (Answer): KEY is case sensitive. I was using Key instead of key
I am creating a simple HTTP request to google places autocomplete api but I am getting an error
https://developers.google.com/places/web-service/autocomplete
Code: 200
Response: OK
HTTP/1.1 200 OK
"error_message" : "This service requires an API key.",
"predictions" : [],
"status" : "REQUEST_DENIED"
My Key is enabled and live is related to "Google Places API Web Service".
Here is my sample code. What I am doing wrong?
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class GoogleAPI {
public static void main(String[] args) throws URISyntaxException, ClientProtocolException, IOException {
CloseableHttpClient client = HttpClients.createDefault();
URI uri = new URIBuilder().setScheme("https")
.setHost("maps.googleapis.com")
.setPath("maps/api/place/autocomplete/json")
.setParameter("input", "London")
.setParameter("Key", "*********")
.build();
HttpGet getMethod = new HttpGet(uri);
HttpResponse response = client.execute(getMethod);
System.out.println("Code: " + response.getStatusLine().getStatusCode());
System.out.println(("Response: ")+ response.getStatusLine().getReasonPhrase() );
System.out.println(response.getStatusLine().toString());
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");
System.out.println(responseString);
}
}
I have hid my key.
I have been able to successfully authentication to a service that requires ntlm authentication when using the WinHttpClients and a GET request. However when I try to do a POST I always get a 401 return code. Has anyone done this sucessfully before?
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.WinHttpClients;
public class WindowsAuthPOst {
public static void main (String []args) throws Exception, IOException
{
org.apache.log4j.BasicConfigurator.configure();
CloseableHttpClient httpclient = WinHttpClients.createDefault();
HttpHost target = new HttpHost("SomeHost.domain", 443, "https");
HttpClientContext context = HttpClientContext.create();
HttpGet httpget = new HttpGet("/some/Service.svc");
CloseableHttpResponse response1 = httpclient.execute(target, httpget, context);
try {
HttpEntity entity1 = response1.getEntity();
} finally {
response1.close();
}
// Execute an expensive method next reusing the same context (and connection)
HttpPost httppost = new HttpPost("/some/Service.svc");
httppost.setHeader("SOAPAction", "Some Soap Action");
httppost.setEntity(new StringEntity("Soap Payload"));
CloseableHttpResponse response2 = httpclient.execute(target, httppost, context);
try {
HttpEntity entity2 = response2.getEntity();
} finally {
response2.close();
}
}
}
You can check if it is available with.
if (!WinHttpClients.isWinAuthAvailable()) {
System.out.println("Integrated Win auth is not supported!!!");
}
If not, it could be that you do not have jna.jar in your classpath. It depends on jna and will silently return false on the above if it not there, see source code.
Try with get (or options) before post. Some webservers requires that because of CORS.
https://stackoverflow.com/a/38410411/2376661
I have been trying to connect to CRM using the below Java code, but I am getting an authentication issue.
package com.raj;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
public class MSDynaOData {
/**
* #param args
*/
public static void main(String[] args) throws ClientProtocolException, IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
NTCredentials creds = new NTCredentials("XXXXXXXXXX", "XXXXXXX", "", "");
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpHost target = new HttpHost("XXXXXXXXX", 80, "http");
HttpContext localContext = new BasicHttpContext();
// Execute a cheap method first. This will trigger NTLM authentication
String url = "/XRMServices/2011/Organization.svc/Account";
url += "?$select=Name";
HttpGet httpget = new HttpGet(url);
httpget.addHeader("Accept", "application/json");
HttpResponse response = httpclient.execute(target, httpget, localContext);
HttpEntity entity = response.getEntity();
System.out.println(" Status :: " + response.getStatusLine());
for (Header header : response.getAllHeaders()) {
System.out.println(header.getName() + " : " + header.getValue());
}
System.out.println(IOUtils.toString(entity.getContent()));
}
}
Response contains :
Constants.TokenizedStringMsgs.GENERIC_ERROR = "<H1>Sorry, but we're having trouble signing you in</H1><p>Please try again in a few minutes. If this doesn't work, you might want to contact your admin and report the following error: #~#ErrorCode#~#.</p>";
Constants.TokenizedStringMsgs.UPN_DISAMBIGUATE_MESSAGE = "It looks like #~#MemberName_LS#~# is used with more than one account. Which account do you want to use?";
I am able to login to CRM 2011 online through the credentials used in Java code successfully, but when I used same credentials in the code I am getting the above login issue response.
Please let me know if I am missing anything in the above code.
I'm having a problem: I've just copied the following code from NetBeans to Eclipse (an ADT project). I've imported all the same librarys I used in NetBeans, but I have 2 errors, in the following lines:
EntityUtils.consume(entity); - The method consume(HttpEntity) is undefined for the type EntityUtils
httpPut.releaseConnection(); - The method releaseConnection() is undefined for the type HttpPut
Complete code:
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils;
import com.android.lul.classes.User;
public class UserService {
private static final String BASE_URI = "http://localhost:8080/LULServices/webresources";
public static String Login (String login, String password, String ipAdd)
{
String toReturn = null;
final DefaultHttpClient httpclient = new DefaultHttpClient();
try {
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("localhost", 8080),
new UsernamePasswordCredentials("xxxx", "xxxx"));
HttpPut httpPut = new HttpPut(BASE_URI + "/services.users/login");
HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000);
httpPut.addHeader("Content-type", "multipart/form-data");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("login", "login"));
nameValuePairs.add(new BasicNameValuePair("password", "password"));
httpPut.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httpPut);
try {
HttpEntity entity = response.getEntity();
String putResponse = EntityUtils.toString(entity);
toReturn = putResponse;
EntityUtils.consume(entity);
} finally {
httpPut.releaseConnection();
}
} finally {
httpclient.getConnectionManager().shutdown();
return toReturn;
}
Can you help me?
Thanks
Android comes with a prepackaged version of Apache HttpClient that doesn't have those methods. They are no longer supporting development and that code is outdated.
The Android team recommends that you use HttpUrlConnection for new code instead of HttpClient. More information can be found at this blog on the Android Developers site.
I think you should follow a simpler example, as this one seems to be meant to upload files (multipart/form-data), but regarding the specific problems in your code:
Instead of EntityUtils.consume(entity); you can do entity.consumeContent();
http://developer.android.com/reference/org/apache/http/HttpEntity.html
The HTTPRequest classes (HttpPost, HttpPut) don't have any releaseConnection() method. Probably because they don't need to be released (somebody correct me if I'm wrong). That method is usually applicable for persistent connections which is not the case here.
Check your imports; What version of Apache HttpComponents are you using in your new project?