Java Spring Controller Interface Model Error Exception Enum

For web service development, we generally want to separate API interface, data model and error/exception code from the service code, so client side can use the same interface, model and error message code plus the Java client code. For Hostedcommander new APIs, below are the prototype code. We need to create two packages. Package #1 contains: Spring Interface code, model code, and error/exception code. Package #2 contains the Java client to call the service APIs.

Spring Interface code

package com.xxx.interfaces;
 
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.xxx.models.TaskInput;
/**
 * interfaces
 */
@RequestMapping("api/task")
public interface ITaskController {
    String DO_STH = "do_sth";
    /**
     * do sth
     */
    @RequestMapping(value = "/" + DO_STH, consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {
        MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.POST)
    @ResponseBody
    ResponseEntity dosth(@RequestBody final TaskInput taskInput);
}

Server-side Spring controller code

@RestController
public class TaskController implements ITaskController {
    @Override
    public ResponseEntity dosth(@RequestBody final TaskInput taskInput) {
        System.out.println(taskInput.toString());
        return new ResponseEntity<>("Not implemented", HttpStatus.OK);
    }
}

Model code

package com.xxx.models;
 
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
 
/**
 * TaskInput
 */
@Data //@ToString, @EqualsAndHashCode, @Getter / @Setter and @RequiredArgsConstructor
@Builder(toBuilder = true) //static builder and new instance builder
//this is also for Jackson ObjectMapper to do serialization and deserialization
@NoArgsConstructor(access = AccessLevel.PUBLIC)
//this is also for Jackson ObjectMapper to do serialization and deserialization
@AllArgsConstructor(access = AccessLevel.PUBLIC)
@SuppressWarnings("checkstyle:MemberName") //this is just suppress style check not to use "m_"
public final class TaskInput {
    private String name;
    @Builder.Default //this is ignorable with default value
    private int timeout = 10; //seconds
}

Error code

package com.xxx.interfaces;
 
import java.util.HashMap;
import java.util.Map;
 
import lombok.AllArgsConstructor;
import lombok.Getter;
 
/**
 * test enum
 */
//Lombok can be used only for private constructor and getter, enum has no setters or public constructors
@AllArgsConstructor
@Getter
@SuppressWarnings({"checkstyle:MemberName", "checkstyle:ConstantName"})
public enum ErrorCode {
    INVALID_NAME(1001, "The name is invalid"),
    MALFORMED_JSON(1002, "The json format is invalid");
 
    private final int errorCode;
    private final String errorMessage;
 
    private static final Map<String, ErrorCode> lookup = new HashMap<>();
 
    static {
        for (final ErrorCode e : ErrorCode.values()) {
            lookup.put(e.getErrorMessage(), e);
        }
    }
 
    /**
     * get enum from error message
     *
     * @param message
     * @return
     */
    public static ErrorCode getErrorCode(final String message) {
        return lookup.get(message);
    }
 
    /**
     * get enum from the enum name (case insensitive)
     *
     * @param enumName
     * @return
     */
    public static ErrorCode valueOfIgnoreCase(final String enumName) {
        return valueOf(enumName.toUpperCase());
    }
}

Exception code

public class ApiException extends Exception{
    private int code;
    private boolean isCritical;
    public ApiException (final int code, final boolean isCritical, final String msg) {
        super(msg);
        this.code = code;
        this.isCritical = isCritical;
    }
}
 
public final class EnvironmentApiException extends ApiException {
    public EnvironmentApiException () {
        super(5001, true, "Environment Exception!");
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License