DEV Community

paohaijiao
paohaijiao

Posted on

Say Goodbye to Hand-Written HTTP Code

Say Goodbye to Hand-Written HTTP Code: Run Your curl Command Directly in Java with JQuickCurl

Every backend engineer knows the drill: you spend ten minutes in Postman or the browser DevTools crafting the perfect request, click "Copy as cURL", and then… stare at the screen. You have to manually translate headers, query strings, JSON bodies, and timeouts into OkHttp builders, RestTemplate exchanges, or HttpClient request objects. Translation bugs sneak in, the code balloons, and nobody wants to maintain it.

JQuickCurl (a Dromara open-source project) takes the opposite approach: the curl command itself becomes your request definition. You paste curl syntax into a Java annotation, declare an interface, and call it like a local method. The library parses your curl command with ANTLR4, executes it over the battle-tested OkHttp transport layer, and converts the response into whatever Java type you ask for.

In this first post of the series you will:

  • Learn what JQuickCurl is and when it shines.
  • Add the dependency with Maven.
  • Write a complete Hello-World example.
  • Understand what happens behind the scenes (spoiler: no system curl binary is ever spawned).

What Exactly Is JQuickCurl?

JQuickCurl is a curl-command-driven HTTP client framework for Java, licensed under Apache-2.0. Its core idea: reuse the same curl snippets your frontend, QA, and API docs already share.

Layer Technology
curl syntax parsing ANTLR4 (in-process, no ProcessBuilder)
HTTP transport OkHttp 4.x (connection pool, HTTP/2, interceptors)
Request definition @JCurlCommand annotation and XML files
Dynamic behavior ${...} variable substitution, XML <if> conditions
Extra features file upload/download, batch execution, retry, timeouts, interceptors, dynamic proxy

Because parsing happens inside the JVM, JQuickCurl never calls the system curl binary. That means the same Java code works on Windows, Linux, and macOS, needs no external installation, and keeps full programmatic control over the request lifecycle.

Step 1: Add the Maven Dependency

Add this to your pom.xml (check Maven Central for the newest release; the examples here use 2.5.0):

<dependency>
    <groupId>io.github.paohaijiao</groupId>
    <artifactId>jquick-curl</artifactId>
    <version>2.5.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Step 2: Declare Your First curl-Powered API

Create an interface and put a raw curl command inside @JCurlCommand. The only "parameter convention" you need today is a JQuickCurlReq — a simple HashMap<String, Object> that carries variables for the command (more on that in a later post).

import com.github.paohaijiao.anno.JCurlCommand;
import com.github.paohaijiao.domain.req.JQuickCurlReq;

public interface EchoApi {

    // Any curl command starting with "curl" works as the annotation value.
    @JCurlCommand("curl -X GET https://httpbin.org/get")
    String get(JQuickCurlReq request);
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Run It from a main Method

JCurlInvoker.createProxy(Class) builds a JDK dynamic proxy for your interface. Every call on that proxy parses the annotation's curl command, executes it, and converts the HTTP response body into the method's return type.

import com.github.paohaijiao.domain.req.JQuickCurlReq;
import com.github.paohaijiao.executor.JCurlInvoker;

public class HelloCurl {

    public static void main(String[] args) {
        // 1. Create the proxy once — it is cheap and reusable.
        EchoApi api = JCurlInvoker.createProxy(EchoApi.class);

        // 2. An empty request map for a command without variables.
        JQuickCurlReq request = new JQuickCurlReq();

        // 3. Call your interface method like a local Java method.
        String body = api.get(request);

        System.out.println("HTTP response body:");
        System.out.println(body);
    }
}
Enter fullscreen mode Exit fullscreen mode

Compile and run:

mvn compile exec:java -Dexec.mainClass=HelloCurl
Enter fullscreen mode Exit fullscreen mode

You will see httpbin's JSON echo — the args, headers, and url that your request actually sent:

{
  "args": {},
  "headers": {
    "Accept-Encoding": "gzip",
    "Host": "httpbin.org",
    "User-Agent": "okhttp/4.10.0"
  },
  "url": "https://httpbin.org/get"
}
Enter fullscreen mode Exit fullscreen mode

That's the whole point: the request was described by curl syntax, yet executed by OkHttp in-process.

What Just Happened Under the Hood?

Three stages, all inside your JVM:

  1. Parse — ANTLR4 lexes and parses the annotation string curl -X GET https://httpbin.org/get into an abstract syntax tree of HTTP method, URL, headers, data, and options.
  2. Build & execute — a visitor walks the tree and produces a real OkHttp Request; the executor sends it through OkHttp's client (connection pool, timeouts, retries, and interceptors included).
  3. Convert — the raw response body is converted to the declared return type. Here it's String, but byte[], InputStream, custom POJOs, collections, JResult, and raw JQuickCurlResponseBody are all supported.

No curl process, no shell, no command injection risk.

Why Backend Teams Care

  • Zero translation bugs: the command in your code is byte-for-byte the one you tested in Postman.
  • One format for everyone: product docs, curl examples, and Java code stay in sync.
  • Configurable where it counts: timeouts, proxies, and retries can be layered on top without rewriting the request.
  • Lightweight: Apache-2.0, pure Java, no external runtime.

Summary

JQuickCurl lets you declare HTTP calls the way you already think about them — as curl commands. In roughly ten lines of Java you have a typed, proxy-based HTTP client with no request-building boilerplate. The Hello-World example above is the smallest building block of a much larger toolkit: dynamic variables, XML API catalogs, conditional rendering, file transfer, batch runs, interceptors, and authentication are all covered in the upcoming posts of this series.

Bookmark the repository — dromara/jquick-curl — and stay tuned for Post 2, where we wire this into a real Spring Boot application.

java #springboot #httpclient #opensource #java-library

Top comments (0)