Skip to content

Commit d19c022

Browse files
i18n issue fixed, security advices message code and title bugs fixed, spring boot problem properties autocomplete issue fixed. Dependencies versions upgraded to latest
1 parent cba1cf2 commit d19c022

File tree

11 files changed

+459
-458
lines changed

11 files changed

+459
-458
lines changed

.mvn/wrapper/maven-wrapper.jar

-61.1 KB
Binary file not shown.

.mvn/wrapper/maven-wrapper.properties

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,19 @@
1-
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip
2-
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
wrapperVersion=3.3.2
18+
distributionType=only-script
19+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip

README.md

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@ Requires Java 17+, Spring boot 3.2.0+ and Jakarta EE 10
2020
7. [Error Key, the central concept behind error attribute's externalization](#error-key)
2121
8. [Error response characteristics](#error-response)
2222
9. [Message resolvers to externalize error response in `properties` files](#message-resolvers)
23-
10. [Creating and throwing exceptions in your applications](#creating-and-throwing-exceptions)
24-
11. [Stack trace embedded in error response](#stack-traces)
25-
12. [Cause chains embedded in error response](#cause-chains)
26-
13. [Customizations of default behaviour](#customizations)
23+
10. [Message Internalization or i18n](#message-internalization)
24+
11. [Creating and throwing exceptions in your applications](#creating-and-throwing-exceptions)
25+
12. [Stack trace embedded in error response](#stack-traces)
26+
13. [Cause chains embedded in error response](#cause-chains)
27+
14. [Customizations of default behaviour](#customizations)
2728
- [Customize error response](#customize-error-response)
2829
- [Customize or Override advices](#customize-or-override-advices)
29-
14. [Define new advices](#define-new-advices)
30-
15. [Testing support](#testing-support)
31-
16. [Example error responses in different scenarios](#example-error-responses)
30+
15. [Define new advices](#define-new-advices)
31+
16. [Testing support](#testing-support)
32+
17. [Example error responses in different scenarios](#example-error-responses)
3233

3334
## Introduction
3435

@@ -49,7 +50,7 @@ all can be done with zero custom code but by specifying error details in `proper
4950

5051
## Installation
5152

52-
> **Current version: 1.9.2** Refer to [Release notes](https://github.com/officiallysingh/spring-boot-problem-handler/releases) while upgrading
53+
> **Current version: 1.9.3** Refer to [Release notes](https://github.com/officiallysingh/spring-boot-problem-handler/releases) while upgrading
5354
5455
Add the `spring-boot-problem-handler` jar to application dependencies. That is all it takes to get a default working
5556
exception handling mechanism in a Spring boot application.
@@ -62,12 +63,12 @@ Maven
6263
<dependency>
6364
<groupId>io.github.officiallysingh</groupId>
6465
<artifactId>spring-boot-problem-handler</artifactId>
65-
<version>1.9.2</version>
66+
<version>1.9.3</version>
6667
</dependency>
6768
```
6869
Gradle
6970
```groovy
70-
implementation 'io.github.officiallysingh:spring-boot-problem-handler:1.9.2'
71+
implementation 'io.github.officiallysingh:spring-boot-problem-handler:1.9.3'
7172
```
7273

7374
It does all hard part, A lot of advices are out of box available that are autoconfigured as `ControllerAdvice`s
@@ -505,9 +506,82 @@ To minimize the number of properties following defaults are taken if `HttpStatus
505506
> `status.`(error key) property is considered only for exceptions where no explicit advice is defined,
506507
otherwise `HttpStatus` is specified in the java code.
507508

509+
## Message internalization
510+
The error messages are read from configured resource bundles,
511+
by [ProblemMessageProvider](src/main/java/com/ksoot/problem/spring/config/ProblemMessageProvider.java)
512+
for current request `Locale` given by `LocaleContextHolder.getLocale()`.
513+
By default, spring boot autoconfigures `AcceptHeaderLocaleContextResolver` to get `Locale` from `Accept-Language` request header.
514+
515+
If the `Accept-Language` header is `fr` then the error messages are read from `_fr.properties` file from configured resource bundles.
516+
Following request in demo project [**`problem-handler-web-demo`**](https://github.com/officiallysingh/problem-handler-web-demo)
517+
518+
```curl
519+
curl --location 'http://localhost:8080/api/states' \
520+
--header 'accept: */*' \
521+
--header 'Content-Type: application/json' \
522+
--header 'Accept-Language: fr' \
523+
--header 'Cookie: JSESSIONID=9EF49EB9744759DF7A1EE71BD2154A53' \
524+
--data '{
525+
"name": "Haryana",
526+
"gstCode": "6"
527+
}'
528+
```
529+
530+
returns following error message in French language as specified in
531+
[**`errors_fr.properties`**]https://github.com/officiallysingh/problem-handler-web-demo/blob/main/src/main/resources/i18n/errors_fr.properties file.
532+
```properties
533+
```json
534+
{
535+
"type": "http://localhost:8080/problems/help.html#401",
536+
"title": "Non autorisé",
537+
"status": 401,
538+
"detail": "Le jeton d'autorisation de l'en-t�te est manquant ou invalide",
539+
"instance": "/api/states",
540+
"method": "POST",
541+
"timestamp": "2025-04-19T14:53:30.285582+05:30",
542+
"code": "401"
543+
}
544+
```
545+
546+
> [!IMPORTANT]
547+
>`LocaleContextHolder.getLocale()` gets the current request `Locale` from `ThreadLocal`, which does not work in case of reactive applications (Webflux)
548+
> as each operator in reactive pipeline can execute in a different thread, and the context is not inherited from calling thread, but explicitly need to be propagated.
549+
> Similar to [**`ReactiveSecurityContextHolder`**](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/context/ReactiveSecurityContextHolder.html) there is no reactive context holder.
550+
551+
For demo purpose, defining the following bean serves the purpose, but not recommended in production.
552+
```java
553+
@Bean
554+
public HttpHandler httpHandler(ApplicationContext applicationContext) {
555+
LocaleContextHolder.getLocaleContext().getLocale();
556+
HttpHandler delegate = WebHttpHandlerBuilder
557+
.applicationContext(applicationContext).build();
558+
return new HttpWebHandlerAdapter(((HttpWebHandlerAdapter) delegate)) {
559+
@Override
560+
protected ServerWebExchange createExchange(ServerHttpRequest request,
561+
ServerHttpResponse response) {
562+
ServerWebExchange serverWebExchange = super
563+
.createExchange(request, response);
564+
LocaleContext localeContext = serverWebExchange.getLocaleContext();
565+
if (localeContext != null) {
566+
LocaleContextHolder.setLocaleContext(localeContext, true);
567+
}
568+
return serverWebExchange;
569+
}
570+
};
571+
}
572+
```
573+
574+
You can define your own [**`ProblemMessageProvider`**](src/main/java/com/ksoot/problem/spring/config/ProblemMessageProvider.java) bean as follows, that should be able to find current request `Locale` somehow.
575+
```java
576+
@Bean
577+
ProblemMessageProvider problemMessageProvider(final MessageSource messageSource) {
578+
return new YourReactiveProblemMessageProvider(messageSource);
579+
}
580+
```
581+
508582
## Creating and throwing exceptions
509583

510-
Apart from exceptions thrown by frameworks or java, every application need to throw custom exceptions.
584+
Apart from exceptions thrown by frameworks or java, every application needs to throw custom exceptions.
511585
[**`ApplicationProblem`**](src/main/java/com/ksoot/problem/core/ApplicationProblem.java) and
512586
[**`ApplicationException`**](src/main/java/com/ksoot/problem/core/ApplicationException.java)
513587
classes are available in the library to throw an unchecked or checked exception respectively.

0 commit comments

Comments
 (0)