'JavaFX - Making a post request using org.apache.httpcomponents fails

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);
            }
        }
    }


Solution 1:[1]

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:

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1