java-xmlrpc-guideline

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Java XML-RPC API Design Guideline

Java XML-RPC API设计指南

Overview

概述

Design XML-RPC APIs with clear exception handling, proper return types, and interoperable serialization.
Core principle: Exceptions signal failure, return values signal success. Use JAXB for cross-language compatibility.
设计具备清晰异常处理、合适返回类型和可互操作序列化机制的XML-RPC API。
核心原则: 异常表示失败,返回值表示成功。使用JAXB实现跨语言兼容性。

Quick Reference

快速参考

ScenarioPattern
API interface method
ReturnType method(Param p) throws XmlRpcException
Void-like operationReturn
int
, always
0
(value is meaningless, workaround for spec limitation)
Success resultReturn value (DTO, primitive, etc.)
Failure resultThrow
XmlRpcException
DTO serializationUse JAXB annotations (
@XmlRootElement
,
@XmlAttribute
)
场景模式
API接口方法
ReturnType method(Param p) throws XmlRpcException
类void操作返回
int
,固定为
0
(无实际意义,是针对规范限制的变通方案)
成功结果返回值(DTO、基本类型等)
失败结果抛出
XmlRpcException
DTO序列化使用JAXB注解(
@XmlRootElement
@XmlAttribute

Exception Handling

异常处理

All API Methods Must Declare XmlRpcException

所有API方法必须声明XmlRpcException

Every interface method must include
throws XmlRpcException
:
java
public interface SomeApi {
    SomeDto someAction(SomeParameterDto request) throws XmlRpcException;
}
Why: XML-RPC library can transmit one exception type to client. Most projects use extension features enabling this. The exception serializes as:
xml
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions">
    <fault>
        <value>
            <struct>
                <member>
                    <name>faultCode</name>
                    <value><i4>1</i4></value>
                </member>
                <member>
                    <name>faultString</name>
                    <value>failed to execute api</value>
                </member>
            </struct>
        </value>
    </fault>
</methodResponse>
Avoid:
enabledForException
feature. It serializes Java exceptions including chained exceptions, but only works with Java clients.
每个接口方法都必须包含
throws XmlRpcException
java
public interface SomeApi {
    SomeDto someAction(SomeParameterDto request) throws XmlRpcException;
}
原因: XML-RPC库只能向客户端传输一种异常类型。大多数项目会使用支持此功能的扩展特性。异常的序列化格式如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions">
    <fault>
        <value>
            <struct>
                <member>
                    <name>faultCode</name>
                    <value><i4>1</i4></value>
                </member>
                <member>
                    <name>faultString</name>
                    <value>failed to execute api</value>
                </member>
            </struct>
        </value>
    </fault>
</methodResponse>
避免: 使用
enabledForException
特性。它会序列化包含链式异常的Java异常,但仅对Java客户端有效。

Return Type Guidelines

返回类型指南

Void Methods Must Return int

Void方法必须返回int

XML-RPC library doesn't support
void
return type. Use
int
instead:
java
public interface ServiceControlApi {
    int start(String name) throws XmlRpcException;
}
Rules:
  • Always return
    0
    (regardless of success or failure)
  • Signal failure by throwing
    XmlRpcException
  • The return value has no meaning - it exists only because XML-RPC spec doesn't support
    void
Why: This is purely a workaround for XML-RPC library limitation. If the spec supported
void
, we would use
void
. The
int
return is meaningless; failure is communicated exclusively through exceptions.
XML-RPC库不支持
void
返回类型,应使用
int
替代:
java
public interface ServiceControlApi {
    int start(String name) throws XmlRpcException;
}
规则:
  • 始终返回
    0
    (无论成功或失败)
  • 通过抛出
    XmlRpcException
    表示失败
  • 返回值无实际意义——仅因XML-RPC规范不支持
    void
    而存在
原因: 这纯粹是针对XML-RPC库限制的变通方案。如果规范支持
void
,我们会直接使用
void
int
返回值无实际意义,失败仅通过异常传递。

Success vs Failure: Clear Separation

成功与失败:明确区分

OutcomeHow to Signal
Operation succeededReturn value
Query found nothingReturn empty/false (this is success)
Operation failedThrow
XmlRpcException
Example - Query API:
java
public interface PublicIpApi {
    boolean isExists(InetAddress address) throws XmlRpcException;
}
  • IP exists → return
    true
  • IP doesn't exist → return
    false
    (success case - query worked)
  • System error during query → throw
    XmlRpcException
Example - Action API:
java
public interface ServiceControlApi {
    int start(String name) throws XmlRpcException;
}
  • Service started → return
    0
  • Service already running → return
    0
    (value is meaningless)
  • Service failed to start → throw
    XmlRpcException
    (this is how failure is signaled)
Why this matters:
  • Returning error codes in response (like
    -1
    or error field in DTO) makes XML-RPC request appear successful
  • Server logs show success, no stack trace
  • Client must inspect response to detect failure
  • Debugging becomes difficult
结果传递方式
操作成功返回值
查询无结果返回空值/false(属于成功情况)
操作失败抛出
XmlRpcException
示例 - 查询API:
java
public interface PublicIpApi {
    boolean isExists(InetAddress address) throws XmlRpcException;
}
  • IP存在 → 返回
    true
  • IP不存在 → 返回
    false
    (成功情况——查询正常执行)
  • 查询过程中出现系统错误 → 抛出
    XmlRpcException
示例 - 操作API:
java
public interface ServiceControlApi {
    int start(String name) throws XmlRpcException;
}
  • 服务启动成功 → 返回
    0
  • 服务已在运行 → 返回
    0
    (值无实际意义)
  • 服务启动失败 → 抛出
    XmlRpcException
    (以此表示失败)
重要性:
  • 在响应中返回错误码(如
    -1
    或DTO中的错误字段)会让XML-RPC请求看起来执行成功
  • 服务器日志会显示成功,无堆栈跟踪
  • 客户端必须检查响应才能发现失败
  • 调试难度加大

DTO Serialization

DTO序列化

Use JAXB, Not Serializable

使用JAXB,而非Serializable

DTOs must use XML structures via JAXB for cross-language compatibility:
java
// GOOD: JAXB DTO
@XmlRootElement
public class ComplexJaxbDto implements Element {
    @XmlAttribute
    private String type;
    
    @XmlAttribute
    private String number;
    
    private List<NestedDto> nestedDtos;
    
    private ComplexJaxbDto() { }
    
    public static final class NestedDto {
        private String value;
        private NestedDto() { }
    }
}
java
// BAD: Serializable DTO (Java-only)
public class SerializableDto implements Serializable {
    private String value;
    public SerializableDto(String value) {
        this.value = value;
    }
}
DTO必须通过JAXB使用XML结构,以实现跨语言兼容性:
java
// 推荐:JAXB DTO
@XmlRootElement
public class ComplexJaxbDto implements Element {
    @XmlAttribute
    private String type;
    
    @XmlAttribute
    private String number;
    
    private List<NestedDto> nestedDtos;
    
    private ComplexJaxbDto() { }
    
    public static final class NestedDto {
        private String value;
        private NestedDto() { }
    }
}
java
// 不推荐:Serializable DTO(仅支持Java)
public class SerializableDto implements Serializable {
    private String value;
    public SerializableDto(String value) {
        this.value = value;
    }
}

Serialization Comparison

序列化对比

Serializable output (unreadable, Java-only):
xml
<ex:serializable>rO0ABXNyACx0aWwueG1scnBj...</ex:serializable>
JAXB output (readable, cross-language):
xml
<ex:jaxb>
    <complexJaxbDto number="number" type="type">
        <nestedDtos>
            <value>test</value>
        </nestedDtos>
        <nestedDtos>
            <value>test2</value>
        </nestedDtos>
    </complexJaxbDto>
</ex:jaxb>
Why JAXB:
  • XML-RPC is designed for interoperability
  • Serializable limits clients to Java
  • JAXB produces human-readable XML
  • Long-term maintainability
Serializable输出(不可读,仅支持Java):
xml
<ex:serializable>rO0ABXNyACx0aWwueG1scnBj...</ex:serializable>
JAXB输出(可读,跨语言):
xml
<ex:jaxb>
    <complexJaxbDto number="number" type="type">
        <nestedDtos>
            <value>test</value>
        </nestedDtos>
        <nestedDtos>
            <value>test2</value>
        </nestedDtos>
    </complexJaxbDto>
</ex:jaxb>
选择JAXB的原因:
  • XML-RPC专为互操作性设计
  • Serializable将客户端限制为Java
  • JAXB生成人类可读的XML
  • 长期可维护性更强

Common Mistakes

常见错误

MistakeProblemFix
Missing
throws XmlRpcException
Client can't receive errorsAdd to all API methods
Using
void
return type
XML-RPC library doesn't support itUse
int
, always return
0
Returning
-1
or other codes
Meaningless, creates confusionAlways return
0
, use exception for failure
Error codes in DTO fieldsRequest appears successfulThrow
XmlRpcException
Using
Serializable
Java-only, unreadableUse JAXB annotations
Using
enabledForException
Java-onlyAvoid, use standard faults
错误问题修复方案
未声明
throws XmlRpcException
客户端无法接收错误信息为所有API方法添加该声明
使用
void
返回类型
XML-RPC库不支持使用
int
,始终返回
0
返回
-1
或其他错误码
无实际意义,造成混淆始终返回
0
,使用异常表示失败
DTO字段中包含错误码请求看起来执行成功抛出
XmlRpcException
使用
Serializable
仅支持Java,输出不可读使用JAXB注解
使用
enabledForException
仅支持Java避免使用,使用标准错误机制

Idempotency Decisions

幂等性决策

For action APIs, decide if operation should be idempotent:
Idempotent approach:
  • start()
    on running service → return
    0
  • Easier for clients, more forgiving
Strict approach:
  • start()
    on running service → throw
    XmlRpcException
  • Explicit about state transitions
Document your choice in the API contract. Either is valid - consistency matters.
对于操作类API,需决定操作是否应具备幂等性:
幂等性方案:
  • 对已运行的服务调用
    start()
    → 返回
    0
  • 对客户端更友好,容错性更强
严格方案:
  • 对已运行的服务调用
    start()
    → 抛出
    XmlRpcException
  • 明确状态转换
请在API契约中记录你的选择。两种方案均有效——保持一致性至关重要。

Checklist

检查清单

Before completing XML-RPC API design:
  • All interface methods declare
    throws XmlRpcException
  • No
    void
    return types (use
    int
    , always return
    0
    )
  • Success cases return values (for non-void methods)
  • Failure cases throw exceptions (never use return codes)
  • For void-like methods: return value is always
    0
    , failure via exception only
  • Idempotency behavior documented
完成XML-RPC API设计前,请检查:
  • 所有接口方法均声明
    throws XmlRpcException
  • void
    返回类型(使用
    int
    ,始终返回
    0
  • 成功情况返回值(非void方法)
  • 失败情况抛出异常(绝不使用返回码)
  • 类void方法:返回值始终为
    0
    ,仅通过异常表示失败
  • 幂等性行为已记录