Skip to content

Commit 1b54435

Browse files
Fix formatting of detailFormat for resolving cause exceptions (#99)
1 parent b93909e commit 1b54435

45 files changed

Lines changed: 174 additions & 115 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

problem4j-spring-web/src/main/java/io/github/problem4j/spring/web/resolver/HttpMessageNotReadableProblemResolver.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
*/
4949
public class HttpMessageNotReadableProblemResolver extends AbstractProblemResolver {
5050

51-
private final TypeNameMapper typeNameMapper;
51+
private final JacksonErrorHelper jacksonErrorHelper;
5252

5353
/** Creates a new {@link HttpMessageNotReadableProblemResolver} with default problem format. */
5454
public HttpMessageNotReadableProblemResolver() {
@@ -74,7 +74,7 @@ public HttpMessageNotReadableProblemResolver(ProblemFormat problemFormat) {
7474
public HttpMessageNotReadableProblemResolver(
7575
ProblemFormat problemFormat, TypeNameMapper typeNameMapper) {
7676
super(HttpMessageNotReadableException.class, problemFormat);
77-
this.typeNameMapper = typeNameMapper;
77+
this.jacksonErrorHelper = new JacksonErrorHelper(problemFormat, typeNameMapper);
7878
}
7979

8080
/**
@@ -92,7 +92,7 @@ public HttpMessageNotReadableProblemResolver(
9292
public ProblemBuilder resolveBuilder(
9393
ProblemContext context, Exception ex, HttpHeaders headers, HttpStatusCode status) {
9494
if (ex.getCause() instanceof MismatchedInputException e) {
95-
return JacksonErrorHelper.resolveMismatchedInput(e, typeNameMapper);
95+
return jacksonErrorHelper.resolveMismatchedInput(e);
9696
}
9797
return Problem.builder().status(HttpStatus.BAD_REQUEST.value());
9898
}

problem4j-spring-web/src/main/java/io/github/problem4j/spring/web/resolver/JacksonErrorHelper.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,28 @@
2929
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
3030
import io.github.problem4j.core.Problem;
3131
import io.github.problem4j.core.ProblemBuilder;
32+
import io.github.problem4j.spring.web.ProblemFormat;
3233
import io.github.problem4j.spring.web.TypeNameMapper;
3334
import java.util.Optional;
3435
import java.util.stream.Collectors;
3536
import org.springframework.http.HttpStatus;
3637
import org.springframework.util.StringUtils;
3738

39+
/**
40+
* Utility for Jackson exceptions used in situations where these exceptions are the {@code cause} of
41+
* the exception that is being resolved.
42+
*/
3843
final class JacksonErrorHelper {
3944

40-
static ProblemBuilder resolveMismatchedInput(
41-
MismatchedInputException e, TypeNameMapper typeNameMapper) {
45+
private final ProblemFormat problemFormat;
46+
private final TypeNameMapper typeNameMapper;
47+
48+
JacksonErrorHelper(ProblemFormat problemFormat, TypeNameMapper typeNameMapper) {
49+
this.problemFormat = problemFormat;
50+
this.typeNameMapper = typeNameMapper;
51+
}
52+
53+
ProblemBuilder resolveMismatchedInput(MismatchedInputException e) {
4254
Optional<String> optionalProperty = resolvePropertyPath(e);
4355

4456
ProblemBuilder builder = Problem.builder().status(HttpStatus.BAD_REQUEST.value());
@@ -47,15 +59,15 @@ static ProblemBuilder resolveMismatchedInput(
4759
property -> {
4860
String kind = typeNameMapper.map(e.getTargetType()).orElse(null);
4961

50-
builder.detail(TYPE_MISMATCH_DETAIL);
62+
builder.detail(problemFormat.formatDetail(TYPE_MISMATCH_DETAIL));
5163
builder.extension(PROPERTY_EXTENSION, property);
5264
builder.extension(KIND_EXTENSION, kind);
5365
});
5466

5567
return builder;
5668
}
5769

58-
private static Optional<String> resolvePropertyPath(MismatchedInputException e) {
70+
private Optional<String> resolvePropertyPath(MismatchedInputException e) {
5971
String property =
6072
e.getPath().stream()
6173
.map(JsonMappingException.Reference::getFieldName)
@@ -64,6 +76,4 @@ private static Optional<String> resolvePropertyPath(MismatchedInputException e)
6476

6577
return StringUtils.hasLength(property) ? Optional.of(property) : Optional.empty();
6678
}
67-
68-
private JacksonErrorHelper() {}
6979
}

problem4j-spring-web/src/main/java/io/github/problem4j/spring/web/resolver/ServerWebInputProblemResolver.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class ServerWebInputProblemResolver extends AbstractProblemResolver {
5656

5757
private final TypeMismatchProblemResolver typeMismatchProblemResolver;
5858
private final MethodParameterSupport methodParameterSupport;
59-
private final TypeNameMapper typeNameMapper;
59+
private final JacksonErrorHelper jacksonErrorHelper;
6060

6161
/** Creates a new {@link ServerWebInputProblemResolver} with default problem format. */
6262
public ServerWebInputProblemResolver() {
@@ -105,7 +105,7 @@ public ServerWebInputProblemResolver(
105105
super(ServerWebInputException.class, problemFormat);
106106
this.typeMismatchProblemResolver = typeMismatchProblemResolver;
107107
this.methodParameterSupport = methodParameterSupport;
108-
this.typeNameMapper = typeNameMapper;
108+
jacksonErrorHelper = new JacksonErrorHelper(problemFormat, typeNameMapper);
109109
}
110110

111111
/**
@@ -161,7 +161,7 @@ private ProblemBuilder tryAppendingPropertyFromMethodParameter(
161161

162162
private ProblemBuilder resolveDecodingException(DecodingException ex) {
163163
if (ex.getCause() instanceof MismatchedInputException e) {
164-
return JacksonErrorHelper.resolveMismatchedInput(e, typeNameMapper);
164+
return jacksonErrorHelper.resolveMismatchedInput(e);
165165
}
166166
return Problem.builder().status(HttpStatus.BAD_REQUEST.value());
167167
}

problem4j-spring-webflux/src/test/java/io/github/problem4j/spring/webflux/integration/BindingPrimitiveWebFluxTest.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@
4040
@SpringBootTest(
4141
classes = {WebFluxTestApp.class},
4242
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
43-
properties = {"spring.jackson.deserialization.fail-on-null-for-primitives=true"})
43+
properties = {
44+
"problem4j.detail-format=lowercase",
45+
"spring.jackson.deserialization.fail-on-null-for-primitives=true"
46+
})
4447
class BindingPrimitiveWebFluxTest {
4548

4649
@Autowired private WebTestClient webTestClient;
@@ -136,7 +139,7 @@ void givenMalformedPrimitive_whenPost_thenReturnProblem(String path, String json
136139
Problem expected =
137140
Problem.builder()
138141
.status(HttpStatus.BAD_REQUEST.value())
139-
.detail(TYPE_MISMATCH_DETAIL)
142+
.detail(TYPE_MISMATCH_DETAIL.toLowerCase())
140143
.extension(PROPERTY_EXTENSION, "value")
141144
.extension(KIND_EXTENSION, expectedKind)
142145
.build();
@@ -239,7 +242,7 @@ void givenMalformedNested_whenPost_thenReturnProblem(String path, String json) {
239242
.isEqualTo(
240243
Problem.builder()
241244
.status(HttpStatus.BAD_REQUEST.value())
242-
.detail(TYPE_MISMATCH_DETAIL)
245+
.detail(TYPE_MISMATCH_DETAIL.toLowerCase())
243246
.extension(PROPERTY_EXTENSION, "nested.value")
244247
.extension(KIND_EXTENSION, expectedKind)
245248
.build());
@@ -285,7 +288,7 @@ void givenEmptyStringPrimitive_whenPost_thenReturnProblem(String path, String js
285288
.isEqualTo(
286289
Problem.builder()
287290
.status(HttpStatus.BAD_REQUEST.value())
288-
.detail(TYPE_MISMATCH_DETAIL)
291+
.detail(TYPE_MISMATCH_DETAIL.toLowerCase())
289292
.extension(PROPERTY_EXTENSION, "value")
290293
.extension(KIND_EXTENSION, expectedKind)
291294
.build());
@@ -318,7 +321,7 @@ void givenOverflowPrimitive_whenPost_thenReturnProblem(String path, String json)
318321
Problem expected =
319322
Problem.builder()
320323
.status(HttpStatus.BAD_REQUEST.value())
321-
.detail(TYPE_MISMATCH_DETAIL)
324+
.detail(TYPE_MISMATCH_DETAIL.toLowerCase())
322325
.extension(PROPERTY_EXTENSION, "value")
323326
.extension(KIND_EXTENSION, "integer")
324327
.build();
@@ -347,7 +350,7 @@ void givenNullPrimitive_whenPost_thenReturnProblem() {
347350
Problem expected =
348351
Problem.builder()
349352
.status(HttpStatus.BAD_REQUEST.value())
350-
.detail(TYPE_MISMATCH_DETAIL)
353+
.detail(TYPE_MISMATCH_DETAIL.toLowerCase())
351354
.extension(PROPERTY_EXTENSION, "value")
352355
.extension(KIND_EXTENSION, "integer")
353356
.build();
@@ -411,7 +414,7 @@ void givenMalformedComplexObject_whenPost_thenReturnProblemWithFirstInvalidField
411414
.isEqualTo(
412415
Problem.builder()
413416
.status(HttpStatus.BAD_REQUEST.value())
414-
.detail(TYPE_MISMATCH_DETAIL)
417+
.detail(TYPE_MISMATCH_DETAIL.toLowerCase())
415418
.extension(PROPERTY_EXTENSION, expectedProperty)
416419
.extension(KIND_EXTENSION, expectedKind)
417420
.build()));

problem4j-spring-webflux/src/test/java/io/github/problem4j/spring/webflux/integration/ErrorResponseWebFluxTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434

3535
@SpringBootTest(
3636
classes = {WebFluxTestApp.class},
37-
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
37+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
38+
properties = {"problem4j.detail-format=lowercase"})
3839
@AutoConfigureWebTestClient
3940
class ErrorResponseWebFluxTest {
4041

problem4j-spring-webflux/src/test/java/io/github/problem4j/spring/webflux/integration/ErrorWebExceptionHandlerWebFluxTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434

3535
@SpringBootTest(
3636
classes = {WebFluxTestApp.class},
37-
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
37+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
38+
properties = {"problem4j.detail-format=lowercase"})
3839
@AutoConfigureWebTestClient
3940
class ErrorWebExceptionHandlerWebFluxTest {
4041

problem4j-spring-webflux/src/test/java/io/github/problem4j/spring/webflux/integration/MalformedMultipartWebFluxTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535

3636
@SpringBootTest(
3737
classes = {WebFluxTestApp.class},
38-
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
38+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
39+
properties = {"problem4j.detail-format=lowercase"})
3940
@AutoConfigureWebTestClient
4041
class MalformedMultipartWebFluxTest {
4142

problem4j-spring-webflux/src/test/java/io/github/problem4j/spring/webflux/integration/MaxUploadSizeExceededWebFluxTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636

3737
@SpringBootTest(
3838
classes = {WebFluxTestApp.class},
39-
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
39+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
40+
properties = {"problem4j.detail-format=lowercase"})
4041
@AutoConfigureWebTestClient
4142
class MaxUploadSizeExceededWebFluxTest {
4243

@@ -57,7 +58,7 @@ void givenMaxUploadSizeExceeded_shouldReturnProblem() {
5758
.isEqualTo(
5859
Problem.builder()
5960
.status(HttpStatus.PAYLOAD_TOO_LARGE.value())
60-
.detail(MAX_UPLOAD_SIZE_EXCEEDED_DETAIL)
61+
.detail(MAX_UPLOAD_SIZE_EXCEEDED_DETAIL.toLowerCase())
6162
.extension(MAX_EXTENSION, 1)
6263
.build());
6364
}

problem4j-spring-webflux/src/test/java/io/github/problem4j/spring/webflux/integration/MethodNotAllowedWebFluxTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434

3535
@SpringBootTest(
3636
classes = {WebFluxTestApp.class},
37-
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
37+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
38+
properties = {"problem4j.detail-format=lowercase"})
3839
@AutoConfigureWebTestClient
3940
class MethodNotAllowedWebFluxTest {
4041

problem4j-spring-webflux/src/test/java/io/github/problem4j/spring/webflux/integration/MissingParameterWebFluxTest.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252

5353
@SpringBootTest(
5454
classes = {WebFluxTestApp.class},
55-
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
55+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
56+
properties = {"problem4j.detail-format=lowercase"})
5657
@AutoConfigureWebTestClient
5758
class MissingParameterWebFluxTest {
5859

@@ -76,7 +77,7 @@ void givenRequestWithoutPathVariable_shouldReturnProblem() {
7677
.isEqualTo(
7778
Problem.builder()
7879
.status(HttpStatus.BAD_REQUEST.value())
79-
.detail(MISSING_PATH_VARIABLE_DETAIL)
80+
.detail(MISSING_PATH_VARIABLE_DETAIL.toLowerCase())
8081
.extension(NAME_EXTENSION, "var")
8182
.build());
8283
});
@@ -112,7 +113,7 @@ void givenRequestWithoutRequestParam_shouldReturnProblem() {
112113
.isEqualTo(
113114
Problem.builder()
114115
.status(HttpStatus.BAD_REQUEST.value())
115-
.detail(MISSING_REQUEST_PARAM_DETAIL)
116+
.detail(MISSING_REQUEST_PARAM_DETAIL.toLowerCase())
116117
.extension(PARAM_EXTENSION, "param")
117118
.extension(KIND_EXTENSION, "string")
118119
.build());
@@ -154,7 +155,7 @@ void givenRequestWithoutRequestPart_shouldReturnProblem() {
154155
.isEqualTo(
155156
Problem.builder()
156157
.status(HttpStatus.BAD_REQUEST.value())
157-
.detail(MISSING_REQUEST_PART_DETAIL)
158+
.detail(MISSING_REQUEST_PART_DETAIL.toLowerCase())
158159
.extension(PARAM_EXTENSION, "file")
159160
.build());
160161
});
@@ -202,7 +203,7 @@ void givenRequestWithoutRequestHeader_shouldReturnProblem() {
202203
.isEqualTo(
203204
Problem.builder()
204205
.status(HttpStatus.BAD_REQUEST.value())
205-
.detail(MISSING_HEADER_DETAIL)
206+
.detail(MISSING_HEADER_DETAIL.toLowerCase())
206207
.extension(HEADER_EXTENSION, "X-Custom-Header")
207208
.build());
208209
});
@@ -239,7 +240,7 @@ void givenRequestWithoutCookieValue_shouldReturnProblem() {
239240
.isEqualTo(
240241
Problem.builder()
241242
.status(HttpStatus.BAD_REQUEST.value())
242-
.detail(MISSING_COOKIE_DETAIL)
243+
.detail(MISSING_COOKIE_DETAIL.toLowerCase())
243244
.extension(COOKIE_EXTENSION, "x_session")
244245
.build());
245246
});
@@ -276,7 +277,7 @@ void givenRequestWithoutRequestAttribute_shouldReturnProblem() {
276277
.isEqualTo(
277278
Problem.builder()
278279
.status(HttpStatus.BAD_REQUEST.value())
279-
.detail(MISSING_REQUEST_ATTRIBUTE_DETAIL)
280+
.detail(MISSING_REQUEST_ATTRIBUTE_DETAIL.toLowerCase())
280281
.extension(ATTRIBUTE_EXTENSION, "attr")
281282
.build());
282283
});
@@ -297,7 +298,7 @@ void givenRequestWithoutSessionAttribute_shouldReturnProblem() {
297298
.isEqualTo(
298299
Problem.builder()
299300
.status(HttpStatus.BAD_REQUEST.value())
300-
.detail(MISSING_SESSION_ATTRIBUTE_DETAIL)
301+
.detail(MISSING_SESSION_ATTRIBUTE_DETAIL.toLowerCase())
301302
.extension(ATTRIBUTE_EXTENSION, "attr")
302303
.build());
303304
}

0 commit comments

Comments
 (0)