JSR 303 Data Validation
Built-in Validation Annotations
Apply the @Valid annotation to controller methods requiring validation. Use annotations from javax.validation.constraints on fields in value objects to enforce constraints with custom messages.
Group-Based Validation
Group validation handles scenarios like ensuring an ID is null for creation but present for updates. Define group marker interfaces and use @Validated with the appropriate group class from org.springframework.validation.annotation.
Object Type Classifications
- PO (Persistent Object): Represents a database record, excluding any database operations.
- DO (Domain Object): A business entity abstracted from the real world.
- TO (Transfer Object): Facilitates data transfer between applications.
- DTO (Data Transfer Object): Transefrs data between service and presentation layers, optimizing distributed calls.
- VO (Value Object): Used for business layer data transfer, abstracted from business needs, created via
newand garbage-collected. As a view object, it encapsulates data for page rendering or input. - BO (Business Object): Encapsulates business logic, often combining multiple POs or VOs.
- POJO (Plain Ordinary Java Object): A simple Java object with properties and accessors, encompassing DO, DTO, BO, and VO.
- DAO (Data Access Object): Provides database CRUD operations, acting as an interface between business logic and data resources.
Layered Naming Conventions
Domain Model Specifications
- DO (Data Object): Maps directly to database tables, transmitted via DAO layer.
- DTO (Data Transfer Object): Output from Service or Manager layers.
- BO (Business Object): Business logic encapsulation from Service layer.
- AO (Application Object): Reusable model between Web and Service layers, close to presentation.
- VO (View Object): Transfers data to template rendering engines.
- Query: Encapsulates search requests; avoid using Map for parameters exceeding two.
Naming Rules
- Data objects:
xxxDO, wherexxxis the table name. - Data transfer objects:
xxxDTO, withxxxas business domain name. - View objects:
xxxVO, typically matching page names. - POJO is a collecitve term; avoid naming as
xxxPOJO.
Service/DAO Method Naming
- Retrieve single: prefix
get. - Retrieve multiple: prefix
listwith plural suffix (e.g.,listItems). - Count: prefix
count. - Insert: prefix
saveorinsert. - Delete: prefix
removeordelete. - Update: prefix
update.
Global Code Handling
Cross-Origin Configuration
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("*"));
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowCredentials(true);
configSource.registerCorsConfiguration("/**", config);
return new CorsWebFilter(configSource);
}
}
Exception Handling
@RestControllerAdvice(basePackages = "com.example.product.web")
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Response handleValidationError(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
Map<String, String> errors = new HashMap<>();
result.getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return Response.fail(ErrorCode.VALIDATION_FAILED, errors);
}
@ExceptionHandler(Exception.class)
public Response handleGenericError(Exception e) {
return Response.fail(ErrorCode.SYSTEM_ERROR);
}
}
Business Status Codes
public enum ErrorCode {
SYSTEM_ERROR(10000, "System error occurred"),
VALIDATION_FAILED(10001, "Input validation failed");
private final int code;
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() { return code; }
public String getMessage() { return message; }
}
Unified Response Format
public class Response extends HashMap<String, Object> {
public Response() {
put("status", 200);
put("message", "OK");
}
public static Response success() {
return new Response();
}
public static Response success(Object data) {
Response resp = new Response();
resp.put("data", data);
return resp;
}
public static Response fail(int code, String msg) {
Response resp = new Response();
resp.put("status", code);
resp.put("message", msg);
return resp;
}
public static Response fail(ErrorCode error) {
return fail(error.getCode(), error.getMessage());
}
}