General
XML Configuration Mode: Decoupling Your API Catalog from Business Code
0 views

Annotation mode keeps requests close to Java, but large integrations raise a fair question: do I want a wall of curl strings inside my service interfaces? JQuickCurl's XML mode answers with a firm no — you store every API definition in a separate XML file, and the business layer only sees plain Java interfaces with no annotations at all. This is the classic "declarative client" split: contract in configuration, behavior in code.
In this post you'll learn to:
Author an XML API catalog with the official DTD.
Bind it to a plain Java interface automatically.
Use #{...} context variables in XML.
Swap endpoint behavior without recompiling business code.
The Big Idea
apis.xml (curl commands + return types) business code
| |
+-- parsed by JQuickCurlXmlParseFactory ----------> plain interface proxy
The XML file names each request and declares its return type. The factory binds those entries to interface methods by method name. Change the curl in XML → the running app changes behavior. No Java edits, no rebuild.
Step 1: Write the XML Catalog
Save this as src/main/resources/apis.xml. The DOCTYPE references the bundled DTD so your IDE can validate structure as you type.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE curls PUBLIC "-//PAOHAIJIAO//DTD API CURL 1.0//EN"
"classpath:paohaijiao/dtd/Jquick-curl.dtd">
<curls namespace="com.example.weather.WeatherApi">
<curl name="current" returnClass="java.lang.String">
curl -X GET 'https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true'
</curl>
<curl name="currentAt" returnClass="java.lang.String">
curl -X GET 'https://api.open-meteo.com/v1/forecast?latitude=#{lat}&longitude=#{lon}¤t_weather=true'
</curl>
<curl name="sunrise" returnClass="java.lang.String">
curl -X GET 'https://api.sunrise-sunset.org/json?lat=#{lat}&lng=#{lon}&formatted=0'
</curl>
</curls>
Rules to remember while authoring:
<curls namespace="..."> identifies the interface the file maps to.
Each <curl> has name (must equal the Java method name) and returnClass (fully qualified).
The text content is the curl command; #{name} placeholders are resolved at runtime from context/method parameters.
Optional <if>, <foreach>, and <choose> children make content conditional (Post 8 covers <if> in depth).
Step 2: Write a Pure Java Interface
No annotations, no HTTP imports — just signatures matching the name attributes. Parameters are bound with @Param("...") (import from the xml module) so the XML can reference them via #{...}:
import com.github.paohaijiao.xml.param.Param;
public interface WeatherApi {
String current();
String currentAt(@Param("lat") double lat, @Param("lon") double lon);
String sunrise(@Param("lat") double lat, @Param("lon") double lon);
}
Step 3: Build the Proxy from the XML Factory
JQuickCurl ships its own parse handler; the generic XML-proxy factory comes from the companion library:
import com.github.paohaijiao.xml.JQuickCurlXmlParseFactory;
import com.github.paohaijiao.xml.factory.JQuickXmlFactory;
import com.github.paohaijiao.xml.handler.JQuickParseHandler;
public class XmlDemo {
public static void main(String[] args) {
// 1. Parser that understands JQuickCurl XML.
JQuickParseHandler parser = new JQuickCurlXmlParseFactory();
// 2. Factory bound to the classpath resource "apis.xml".
JQuickXmlFactory factory = new JQuickXmlFactory(parser, "apis.xml");
// 3. One proxy for the whole catalog.
WeatherApi api = factory.createApi(WeatherApi.class);
System.out.println(api.current());
System.out.println(api.currentAt(52.52, 13.41));
System.out.println(api.sunrise(52.52, 13.41));
}
}
Expected output: JSON from Open-Meteo and the sunrise/sunset API. The calls above run without authentication and prove the whole round trip.
A Second Catalog Without Touching Java
Want to point current at a different provider, add a header, or insert retry semantics? Edit only the XML:
<curl name="current" returnClass="java.lang.String">
curl -X GET 'https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true' \
-H 'Accept: application/json'
</curl>
The proxy, the interface, and all callers stay unchanged. That is the entire value proposition: API drift is fixed in one configuration file, not across dozens of call sites.
XML Mode vs Annotation Mode — When to Choose Which
Dimension
Annotation mode (@JCurlCommand)
XML mode (apis.xml)
Request location
Next to Java code
Centralized config file
Change without rebuild
No
Yes
IDE help
Java syntax
XML + DTD validation
Variables
${name} from JQuickCurlReq
#{name} from context / @Param args
Best fit
Few endpoints, team owns the code
Large third-party API catalogs, shared config
Summary
XML configuration mode decouples what the HTTP call is from who calls it. You get one searchable, validated, DTD-checked catalog of every integration your service owns, while Java interfaces stay free of annotation noise. This pattern pays off exactly when your API surface is wide and changes often.
Source project: dromara/jquick-curl. Post 8 pushes XML mode further with <if> conditions that render parts of a request only when runtime state says so.
java #springboot #httpclient #opensource #java-library
Read original: https://dev.to/paohaijiao/xml-configuration-mode-decoupling-your-api-catalog-from-business-code-56nm
PreviousXiaomi’s wide foldable promises more power than Samsung’sNextXpost: Lenstore displays my password and email on the address bar
Related posts
Adventurer returns home to Hull after 28-year walk from South America
0Hacker News New
Vending machine has terms and conditions you must accept before using [video]
0Hacker News New
Tomorrow Corporation Tech Demo [video]
0Hacker News New
Does Social Status Run in Families?
0Hacker News New
Show HN: Svoxx – A multilingual freelance marketplace with social features
0Hacker News New
433MHz TUI scanner: using a FT232H connected to a CC1101
0Hacker News New