Skip to content

Commit 6ea1f6e

Browse files
Add "Unknown Error" fallback for title resolution
In order to ensure non-null constraint on title field, some default value must be decided for it, as the builder tries to resolve missing title based on status code, matching codes that originate from ProblemStatus enum. Current draft implementation consists of adding "Unknown Error" string, stored in constant of Problem interface. This still might change in the future.
1 parent 57de741 commit 6ea1f6e

8 files changed

Lines changed: 28 additions & 25 deletions

File tree

src/main/java/io/github/problem4j/core/AbstractProblem.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public abstract class AbstractProblem implements Problem, Serializable {
5353
private static final long serialVersionUID = 1L;
5454

5555
private final URI type;
56-
private final @Nullable String title;
56+
private final String title;
5757
private final int status;
5858
private final @Nullable String detail;
5959
private final @Nullable URI instance;
@@ -73,7 +73,7 @@ public abstract class AbstractProblem implements Problem, Serializable {
7373
*/
7474
public AbstractProblem(
7575
@Nullable URI type,
76-
@Nullable String title,
76+
String title,
7777
int status,
7878
@Nullable String detail,
7979
@Nullable URI instance,
@@ -98,7 +98,7 @@ public URI getType() {
9898
* @return a short, human-readable title describing the problem
9999
*/
100100
@Override
101-
public @Nullable String getTitle() {
101+
public String getTitle() {
102102
return this.title;
103103
}
104104

@@ -233,9 +233,7 @@ public int hashCode() {
233233
public String toString() {
234234
List<String> entries = new ArrayList<>();
235235
entries.add("type=" + getType());
236-
if (getTitle() != null) {
237-
entries.add("title=" + getTitle());
238-
}
236+
entries.add("title=" + getTitle());
239237
entries.add("status=" + getStatus());
240238
if (getDetail() != null) {
241239
entries.add("detail=" + getDetail());

src/main/java/io/github/problem4j/core/AbstractProblemBuilder.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,7 @@ public Problem build() {
266266
String title = this.title;
267267
if (title == null) {
268268
Optional<ProblemStatus> status = ProblemStatus.findValue(this.status);
269-
if (status.isPresent()) {
270-
title = status.get().getTitle();
271-
}
269+
title = status.map(ProblemStatus::getTitle).orElse(Problem.UNKNOWN_TITLE);
272270
}
273271
return new ProblemImpl(type, title, status, detail, instance, extensions);
274272
}

src/main/java/io/github/problem4j/core/Problem.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ public interface Problem {
4747
/** Default type URI for generic problems. */
4848
URI BLANK_TYPE = URI.create("about:blank");
4949

50+
/**
51+
* Fallback to resolution of {@code title} field while calling {@link ProblemBuilder#build()}
52+
* method.
53+
*/
54+
String UNKNOWN_TITLE = "Unknown Error";
55+
5056
/** MIME content type for this problem. */
5157
String CONTENT_TYPE = "application/problem+json";
5258

@@ -82,7 +88,7 @@ static Extension extension(@Nullable String key, @Nullable Object value) {
8288
/**
8389
* @return a short, human-readable title describing the problem
8490
*/
85-
@Nullable String getTitle();
91+
String getTitle();
8692

8793
/**
8894
* @return the HTTP status code generated for this problem

src/main/java/io/github/problem4j/core/ProblemException.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,7 @@ protected ProblemException(
136136
*/
137137
private static @Nullable String produceExceptionMessage(Problem problem) {
138138
StringBuilder builder = new StringBuilder();
139-
140-
if (problem.getTitle() != null) {
141-
builder.append(problem.getTitle());
142-
}
139+
builder.append(problem.getTitle());
143140

144141
if (problem.getDetail() != null) {
145142
if (builder.length() > 0) {

src/main/java/io/github/problem4j/core/ProblemImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class ProblemImpl extends AbstractProblem {
3030

3131
ProblemImpl(
3232
@Nullable URI type,
33-
@Nullable String title,
33+
String title,
3434
int status,
3535
@Nullable String detail,
3636
@Nullable URI instance,

src/test/java/io/github/problem4j/core/ProblemBuilderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void givenNullProblemStatus_shouldNotSetTitleOrStatus() {
7777
Problem problem = Problem.builder().status(null).build();
7878

7979
assertThat(problem.getStatus()).isZero();
80-
assertThat(problem.getTitle()).isNull();
80+
assertThat(problem.getTitle()).isEqualTo(Problem.UNKNOWN_TITLE);
8181
}
8282

8383
@Test
@@ -266,7 +266,7 @@ void givenUnknownNumericStatus_shouldNotDeriveTitle() {
266266
Problem problem = Problem.builder().status(999).build();
267267

268268
assertThat(problem.getStatus()).isEqualTo(999);
269-
assertThat(problem.getTitle()).isNull();
269+
assertThat(problem.getTitle()).isEqualTo(Problem.UNKNOWN_TITLE);
270270
}
271271

272272
@Test

src/test/java/io/github/problem4j/core/ProblemExceptionTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void givenProblemWithDetail_whenCreatingException_thenMessageWithDetail() {
9898

9999
ProblemException exception = new ProblemException(problem);
100100

101-
assertEquals("Something went wrong", exception.getMessage());
101+
assertEquals("Unknown Error: Something went wrong", exception.getMessage());
102102
}
103103

104104
@Test
@@ -144,7 +144,7 @@ void givenProblemWithLargeStatus_whenCreatingException_thenStatusIncludedInMessa
144144

145145
ProblemException exception = new ProblemException(problem);
146146

147-
assertEquals("Custom protocol error (code: 999)", exception.getMessage());
147+
assertEquals("Unknown Error: Custom protocol error (code: 999)", exception.getMessage());
148148
}
149149

150150
@Test

src/test/java/io/github/problem4j/core/ProblemImplTest.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ void givenAllFieldsPopulated_whenToString_thenContainsAllFields() {
6767
@Test
6868
void givenNullExtensionsAndNullableFields_whenToString_thenOmitsNulls() {
6969
Map<String, Object> extensions = new HashMap<>();
70-
Problem problem = new ProblemImpl(null, null, 200, null, null, extensions);
70+
Problem problem = new ProblemImpl(null, ProblemStatus.OK_TITLE, 200, null, null, extensions);
7171

7272
String result = problem.toString();
7373

74-
assertThat(result).isEqualTo("Problem{type=about:blank, status=200}");
74+
assertThat(result).isEqualTo("Problem{type=about:blank, title=OK, status=200}");
7575
}
7676

7777
@Test
@@ -80,7 +80,8 @@ void givenOnlyNumberExtensions_whenToString_thenContainsNumbers() {
8080
extensions.put("ext1", 123);
8181
extensions.put("ext2", 456.78);
8282

83-
Problem problem = new ProblemImpl(null, null, 0, null, null, extensions);
83+
Problem problem =
84+
new ProblemImpl(null, ProblemStatus.INTERNAL_SERVER_ERROR_TITLE, 0, null, null, extensions);
8485

8586
String result = problem.toString();
8687

@@ -94,7 +95,8 @@ void givenOnlyBooleanExtensions_whenToString_thenContainsBooleans() {
9495
extensions.put("flag1", true);
9596
extensions.put("flag2", false);
9697

97-
Problem problem = new ProblemImpl(null, null, 0, null, null, extensions);
98+
Problem problem =
99+
new ProblemImpl(null, ProblemStatus.INTERNAL_SERVER_ERROR_TITLE, 0, null, null, extensions);
98100

99101
String result = problem.toString();
100102

@@ -107,7 +109,8 @@ void givenNonPrimitiveExtension_whenToString_thenUsesItsToString() {
107109
Map<String, Object> extensions = new HashMap<>();
108110
extensions.put("obj", new DummyObject("biz\tbar"));
109111

110-
Problem problem = new ProblemImpl(null, null, 0, null, null, extensions);
112+
Problem problem =
113+
new ProblemImpl(null, ProblemStatus.INTERNAL_SERVER_ERROR_TITLE, 0, null, null, extensions);
111114

112115
String result = problem.toString();
113116

@@ -119,7 +122,8 @@ void givenStringWithSpecialCharacters_whenToString_thenProperlyHandlesIt() {
119122
Map<String, Object> extensions = new HashMap<>();
120123
extensions.put("ext", "a\"b\\c\nd");
121124

122-
Problem problem = new ProblemImpl(null, null, 0, null, null, extensions);
125+
Problem problem =
126+
new ProblemImpl(null, ProblemStatus.INTERNAL_SERVER_ERROR_TITLE, 0, null, null, extensions);
123127

124128
String result = problem.toString();
125129

0 commit comments

Comments
 (0)