Why Unified Controller Interfaces Matter: Best Practices and AOP in Java

This article explains common pitfalls in Java controller interface design—such as inconsistent return formats, missing failure handling, and inappropriate parameters—and demonstrates how a unified ResultBean response combined with AOP logging and exception handling can improve code readability, maintainability, and testability.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Why Unified Controller Interfaces Matter: Best Practices and AOP in Java

Common Interface Definition Issues

In daily development we often define various APIs, but many teams make recurring mistakes:

Inconsistent return format : the same endpoint sometimes returns an array, sometimes a single object, or mixes JSON, Map, and plain objects.

Ignoring failure scenarios : only success cases are considered, leading to costly refactoring when errors appear.

Unrelated input parameters : parameters like language or user ID are passed explicitly instead of being obtained from the session.

Complex input parameters : raw JSON strings are used as method arguments, reducing readability.

Missing required return data : create‑operations return only a boolean instead of the newly created object's identifier.

Bad Example 1 – Inconsistent Return Types

@PostMapping("/delete")
public Map<String, Object> delete(long id, String lang) {
    // ...
    try {
        boolean result = configService.delete(id, lang);
        return result; // returns boolean on success, string on failure – a big no‑no
    } catch (Exception e) {
        log.error(e);
        return e.toString();
    }
}

Bad Example 2 – No Failure Handling

@PostMapping("/update")
public void update(long id, Object xxx) {
    // no return, no error handling – forces later refactoring
}

Bad Example 3 – Unrelated Parameters

@PostMapping("/delete")
public Map<String, Object> delete(long id, String lang, String userId) {
    // passing userId directly is a serious design flaw
}

Bad Example 4 – Complex JSON Parameter

@PostMapping("/update")
public Map<String, Object> update(long id, String jsonStr) {
    // raw JSON string makes the method hard to read and test
}

Bad Example 5 – Missing Return Data

@PostMapping("/add")
public boolean add(Object xxx) {
    return configService.add(); // should return the new object's ID instead of a plain boolean
}

Controller Specification Guidelines

All controller methods must return a unified ResultBean (or PageResultBean for pagination). ResultBean / PageResultBean are controller‑only objects and must not be passed to downstream services.

Convert raw request data to proper Java beans in the controller; never pass raw Map, JSON or HttpServletRequest/Response to service layers.

Avoid logging inside controllers; let AOP handle logging and exception handling.

ResultBean Definition (Simplified)

@Data
public class ResultBean<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    public static final int SUCCESS = 0;
    public static final int FAIL = 1;
    public static final int NO_LOGIN = -1;
    public static final int NO_PERMISSION = 2;
    private int code = SUCCESS;
    private String msg = "success";
    private T data;
    public ResultBean() {}
    public ResultBean(T data) { this.data = data; }
    public ResultBean(Throwable e) {
        this.msg = e.toString();
        this.code = FAIL;
    }
}

AOP for Logging and Exception Wrapping

public class ControllerAOP {
    private static final Logger logger = LoggerFactory.getLogger(ControllerAOP.class);

    public Object handlerControllerMethod(ProceedingJoinPoint pjp) {
        long start = System.currentTimeMillis();
        ResultBean<?> result;
        try {
            result = (ResultBean<?>) pjp.proceed();
            logger.info(pjp.getSignature() + " use time:" + (System.currentTimeMillis() - start));
        } catch (Throwable e) {
            result = handlerException(pjp, e);
        }
        return result;
    }

    private ResultBean<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
        ResultBean<?> result = new ResultBean<>();
        if (e instanceof CheckException) {
            result.setMsg(e.getLocalizedMessage());
            result.setCode(ResultBean.FAIL);
        } else if (e instanceof UnloginException) {
            result.setMsg("Unlogin");
            result.setCode(ResultBean.NO_LOGIN);
        } else {
            logger.error(pjp.getSignature() + " error", e);
            result.setMsg(e.toString());
            result.setCode(ResultBean.FAIL);
        }
        return result;
    }
}

AOP Configuration (XML)

<aop:aspectj-autoproxy/>
<bean id="controllerAop" class="xxx.common.aop.ControllerAOP"/>
<aop:config>
    <aop:aspect id="myAop" ref="controllerAop">
        <aop:pointcut id="target" expression="execution(public xxx.common.beans.ResultBean *(..))"/>
        <aop:around method="handlerControllerMethod" pointcut-ref="target"/>
    </aop:aspect>
</aop:config>

Benefits

Using a unified ResultBean format enables consistent API responses, simplifies AOP‑based logging and exception handling, and improves code readability and testability. Adopting these conventions reduces unnecessary refactoring and helps teams focus on business logic rather than repetitive boilerplate.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AOPSpring Bootapi-designcontrollerResultBean
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.