top of page

Microservice - Spring: <2> Multi language for Error Message

  • Writer: Anh Nguyen tuan
    Anh Nguyen tuan
  • Jul 9, 2022
  • 2 min read

We will install the dynamic multi language error message for projects on spring boot and spring cloud gateway.


ree

1. Prerequisite

2. Implement


Table Design:

  • I create a new table to store the default message & message_fr. Each 'Error Code' corresponds to a row. 'Error Code' has the standard '{service name}{sequence_number}'.

  • You can define message with parameter. I used the String.format to substitute them.


ree

Sequence Diagram (by Text)

  • A service will call the service 'Configure' to get its message with prefix of code then a cache them in local memory. Example: API Gateway will get all rows with code like 'AGW%'

  • Spring Cloud Bus manage to notify RefreshRemoteApplicationEvent if you wanna update. This service will call to update new values.

  • A request comes, Services will throw Predefined Exception, you manage to response this exception in global error handler.


2.1) Spring Boot


Configure all error messages in a class:

public class ErrorFactory {
    public final static class CustomerError {
        public static final Function<List,ErrorEntity> USERNAME_EXISTS = (args) -> new ErrorEntity(HttpStatus.BAD_REQUEST, "CUS00002", args);
        ...
    }
}

Implement to respond the error message like this:

throw new InvalidRequestException(ErrorFactory.CustomerError.USERNAME_EXISTS.apply(List.of(entity.getUsername())));

2.2) Spring Gateway


It's not easy to get language from Context from Spring Cloud Gateway because of design of Gateway with reactive programming. So, you must pass the language flat into method.


public class ErrorFactory {
    public final static class ApiGatewayError {
        public static final BiFunction<String, List, ErrorEntity> INVALID_SIGNATURE = (lang, args) -> new ErrorEntity(HttpStatus.BAD_REQUEST, "AGW00001", args, lang);
        ...
    }
...
}

Use this code to respond with error message:


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        Locale locale = exchange.getLocaleContext().getLocale();
        String lang = locale == null ? null: locale.getLanguage();
        HttpHeaders headers = request.getHeaders();
        if (headers.getFirst(HeaderConstant.CLIENT_ID)==null){
            return Mono.error(new InvalidRequestException(ApiGatewayError.HEADER_REQUIRED.apply(lang, List.of(HeaderConstant.CLIENT_ID))));
        }

2.3) Result


Try to call this with 'Accept-Language' = 'en' or 'fr'


curl --location --request POST 'http://localhost:8024/api-gateway/customer/customers' \
--header 'Signature: 1231313' \
--header 'Client-ID: ANH' \
--header 'timestamp: 1231434q' \
--header 'Accept-Language: en' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username":"seabird86@gmail.com",
    "name":"jack",
    "mobile":"977958333",
    "date_of_birth":"2017-11-15",
    "verified_datetime":"2017-11-15T08:22:12+07:00",
    "available_time":"01:00:00+07:30"
}'

You will see the different responses.

Comments


bottom of page