From 7745f6c3377b61461af736cc2cfd29d2147673a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Willi=20Sch=C3=B6nborn?= Date: Sat, 5 Sep 2020 13:20:08 +0200 Subject: [PATCH] Java 9+ compatibility --- .github/workflows/build.yaml | 3 +- .gitignore | 7 + README.md | 19 ++ jackson-datatype-problem/pom.xml | 4 + .../AbstractThrowableProblemMixIn.java | 8 +- .../{ => jackson}/ExceptionalMixin.java | 4 +- .../ExceptionalWithoutStacktraceMixin.java | 2 +- .../problem/{ => jackson}/ProblemMixIn.java | 6 +- .../problem/{ => jackson}/ProblemModule.java | 12 +- .../{ => jackson}/ProblemTypeConverter.java | 4 +- .../{ => jackson}/StatusTypeDeserializer.java | 6 +- .../{ => jackson}/StatusTypeSerializer.java | 4 +- .../problem/jackson}/UnknownStatus.java | 5 +- .../com.fasterxml.jackson.databind.Module | 2 +- .../{ => jackson}/BusinessException.java | 2 +- .../problem/jackson}/CustomStatus.java | 4 +- .../{ => jackson}/EnforceCoverageTest.java | 7 +- .../problem/{ => jackson}/IOProblem.java | 6 +- .../InsufficientFundsProblem.java | 4 +- .../JacksonStackTraceProcessor.java | 8 +- .../{ => jackson}/OutOfStockException.java | 6 +- .../{ => jackson}/ProblemMixInTest.java | 10 +- .../{ => jackson}/ProblemModuleTest.java | 3 +- .../problem/jackson/UnknownStatusTest.java | 17 ++ ...rg.zalando.problem.spi.StackTraceProcessor | 2 +- pom.xml | 106 +++++++-- problem-gson/pom.xml | 4 + .../{ => gson}/CustomProblemAdapter.java | 4 +- .../{ => gson}/DefaultProblemAdapter.java | 9 +- .../{ => gson}/ProblemAdapterFactory.java | 22 +- .../problem/{ => gson}/StatusTypeAdapter.java | 6 +- .../problem/{ => gson}/URITypeAdapter.java | 6 +- .../zalando/problem/gson/UnknownStatus.java | 23 ++ .../zalando/problem/gson}/CustomStatus.java | 4 +- .../problem/{ => gson}/GsonProblemTest.java | 14 +- .../zalando/problem/{ => gson}/IOProblem.java | 6 +- .../{ => gson}/InsufficientFundsProblem.java | 15 +- .../zalando/problem/{ => gson}/MyProblem.java | 6 +- .../{ => gson}/OutOfStockException.java | 5 +- .../{ => gson}/ProblemAdapterFactoryTest.java | 3 +- .../{ => gson}/StatusTypeAdapterTest.java | 3 +- .../{ => gson}/URITypeAdapterTest.java | 3 +- .../problem/gson}/UnknownStatusTest.java | 2 +- problem/pom.xml | 7 + .../problem/AbstractThrowableProblem.java | 30 +-- .../org/zalando/problem/DefaultProblem.java | 3 +- .../java/org/zalando/problem/Problem.java | 6 +- .../org/zalando/problem/ProblemBuilder.java | 2 +- .../main/java/org/zalando/problem/Status.java | 216 ++++++++++++------ .../org/zalando/problem/ThrowableProblem.java | 8 +- .../org/zalando/problem/package-info.java | 7 +- .../src/test/java/org/example/MyProblem.java | 2 +- .../zalando/problem/EnforceCoverageTest.java | 4 - 53 files changed, 508 insertions(+), 173 deletions(-) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/AbstractThrowableProblemMixIn.java (80%) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/ExceptionalMixin.java (91%) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/ExceptionalWithoutStacktraceMixin.java (89%) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/ProblemMixIn.java (87%) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/ProblemModule.java (87%) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/ProblemTypeConverter.java (79%) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/StatusTypeDeserializer.java (84%) rename jackson-datatype-problem/src/main/java/org/zalando/problem/{ => jackson}/StatusTypeSerializer.java (85%) rename {problem/src/main/java/org/zalando/problem => jackson-datatype-problem/src/main/java/org/zalando/problem/jackson}/UnknownStatus.java (79%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/BusinessException.java (78%) rename {problem-gson/src/test/java/org/zalando/problem => jackson-datatype-problem/src/test/java/org/zalando/problem/jackson}/CustomStatus.java (86%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/EnforceCoverageTest.java (81%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/IOProblem.java (89%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/InsufficientFundsProblem.java (91%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/JacksonStackTraceProcessor.java (80%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/OutOfStockException.java (86%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/ProblemMixInTest.java (96%) rename jackson-datatype-problem/src/test/java/org/zalando/problem/{ => jackson}/ProblemModuleTest.java (85%) create mode 100644 jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/UnknownStatusTest.java rename problem-gson/src/main/java/org/zalando/problem/{ => gson}/CustomProblemAdapter.java (96%) rename problem-gson/src/main/java/org/zalando/problem/{ => gson}/DefaultProblemAdapter.java (93%) rename problem-gson/src/main/java/org/zalando/problem/{ => gson}/ProblemAdapterFactory.java (90%) rename problem-gson/src/main/java/org/zalando/problem/{ => gson}/StatusTypeAdapter.java (89%) rename problem-gson/src/main/java/org/zalando/problem/{ => gson}/URITypeAdapter.java (87%) create mode 100644 problem-gson/src/main/java/org/zalando/problem/gson/UnknownStatus.java rename {jackson-datatype-problem/src/test/java/org/zalando/problem => problem-gson/src/test/java/org/zalando/problem/gson}/CustomStatus.java (87%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/GsonProblemTest.java (97%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/IOProblem.java (87%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/InsufficientFundsProblem.java (59%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/MyProblem.java (92%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/OutOfStockException.java (85%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/ProblemAdapterFactoryTest.java (95%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/StatusTypeAdapterTest.java (91%) rename problem-gson/src/test/java/org/zalando/problem/{ => gson}/URITypeAdapterTest.java (95%) rename {problem/src/test/java/org/zalando/problem => problem-gson/src/test/java/org/zalando/problem/gson}/UnknownStatusTest.java (91%) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3406704..54ba8bf 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -24,7 +24,8 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 1.8 + # See comment on moditect-maven-plugin in pom.xml + java-version: 12 - name: Compile run: ./mvnw clean test-compile -B - name: Test diff --git a/.gitignore b/.gitignore index 7adafbb..8227300 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,13 @@ *.iml .idea/ +### VS Code ### +.vscode +.project +.settings +.classpath +.factorypath + ### Maven ### target/ /.mvn/wrapper/*.jar diff --git a/README.md b/README.md index c2c2418..c53047d 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ It's decoupled from any JSON library, but contains a separate module for Jackson - Java 8 - Any build tool using Maven Central, or direct download - Jackson (optional) +- Gson (optional) ## Installation @@ -44,6 +45,24 @@ Add the following dependency to your project: jackson-datatype-problem ${problem.version} + + org.zalando + problem-gson + ${problem.version} + +``` + +### Java Modules + +Even though the minimum requirement is still Java 8, all modules are Java 9 compatible: + +```java +module org.example { + requires org.zalando.problem; + // pick needed dependencies + requires org.zalando.problem.jackson; + requires org.zalando.problem.gson; +} ``` ## Configuration diff --git a/jackson-datatype-problem/pom.xml b/jackson-datatype-problem/pom.xml index c75b87b..4b5e3c7 100644 --- a/jackson-datatype-problem/pom.xml +++ b/jackson-datatype-problem/pom.xml @@ -11,6 +11,10 @@ jackson-datatype-problem 2.10.1 + org.zalando.problem.jackson + + org.zalando.problem.jackson; + diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/AbstractThrowableProblemMixIn.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/AbstractThrowableProblemMixIn.java similarity index 80% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/AbstractThrowableProblemMixIn.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/AbstractThrowableProblemMixIn.java index 996ac30..bb7bc01 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/AbstractThrowableProblemMixIn.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/AbstractThrowableProblemMixIn.java @@ -1,10 +1,14 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; + import java.net.URI; abstract class AbstractThrowableProblemMixIn { diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/ExceptionalMixin.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ExceptionalMixin.java similarity index 91% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/ExceptionalMixin.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ExceptionalMixin.java index f8fc29d..e6da561 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/ExceptionalMixin.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ExceptionalMixin.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -7,6 +7,8 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import org.zalando.problem.ThrowableProblem; + import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/ExceptionalWithoutStacktraceMixin.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ExceptionalWithoutStacktraceMixin.java similarity index 89% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/ExceptionalWithoutStacktraceMixin.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ExceptionalWithoutStacktraceMixin.java index 45a0dc5..2f47eb3 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/ExceptionalWithoutStacktraceMixin.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ExceptionalWithoutStacktraceMixin.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemMixIn.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemMixIn.java similarity index 87% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemMixIn.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemMixIn.java index 798c082..fccbd52 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemMixIn.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemMixIn.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonInclude; @@ -6,6 +6,10 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.zalando.problem.DefaultProblem; +import org.zalando.problem.Problem; +import org.zalando.problem.StatusType; + import java.net.URI; import java.util.Map; diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemModule.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemModule.java similarity index 87% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemModule.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemModule.java index a647012..31ed534 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemModule.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemModule.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.util.VersionUtil; @@ -6,6 +6,12 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import org.apiguardian.api.API; +import org.zalando.problem.DefaultProblem; +import org.zalando.problem.Exceptional; +import org.zalando.problem.Problem; +import org.zalando.problem.Status; +import org.zalando.problem.StatusType; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -34,7 +40,7 @@ public ProblemModule() { * @throws IllegalArgumentException if there are duplicate status codes across all status types */ @SafeVarargs - public ProblemModule(final Class... types) + public & StatusType> ProblemModule(final Class... types) throws IllegalArgumentException { this(false, buildIndex(types)); @@ -76,7 +82,7 @@ public void setupModule(final SetupContext context) { } @SafeVarargs - private static Map buildIndex( + private static & StatusType> Map buildIndex( final Class... types) { final Map index = new HashMap<>(); diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemTypeConverter.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemTypeConverter.java similarity index 79% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemTypeConverter.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemTypeConverter.java index 38c93f1..28c65d3 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/ProblemTypeConverter.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/ProblemTypeConverter.java @@ -1,7 +1,9 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.databind.util.StdConverter; +import org.zalando.problem.Problem; + import java.net.URI; final class ProblemTypeConverter extends StdConverter { diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/StatusTypeDeserializer.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/StatusTypeDeserializer.java similarity index 84% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/StatusTypeDeserializer.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/StatusTypeDeserializer.java index 213917c..3f89d5f 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/StatusTypeDeserializer.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/StatusTypeDeserializer.java @@ -1,10 +1,12 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.zalando.problem.StatusType; + import java.io.IOException; import java.util.Map; diff --git a/jackson-datatype-problem/src/main/java/org/zalando/problem/StatusTypeSerializer.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/StatusTypeSerializer.java similarity index 85% rename from jackson-datatype-problem/src/main/java/org/zalando/problem/StatusTypeSerializer.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/StatusTypeSerializer.java index 0ba27e5..7ee6a80 100644 --- a/jackson-datatype-problem/src/main/java/org/zalando/problem/StatusTypeSerializer.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/StatusTypeSerializer.java @@ -1,9 +1,11 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import org.zalando.problem.StatusType; + import java.io.IOException; final class StatusTypeSerializer extends JsonSerializer { diff --git a/problem/src/main/java/org/zalando/problem/UnknownStatus.java b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/UnknownStatus.java similarity index 79% rename from problem/src/main/java/org/zalando/problem/UnknownStatus.java rename to jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/UnknownStatus.java index 243cfd5..f6180df 100644 --- a/problem/src/main/java/org/zalando/problem/UnknownStatus.java +++ b/jackson-datatype-problem/src/main/java/org/zalando/problem/jackson/UnknownStatus.java @@ -1,8 +1,7 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; -import javax.annotation.concurrent.Immutable; +import org.zalando.problem.StatusType; -@Immutable final class UnknownStatus implements StatusType { private final int statusCode; diff --git a/jackson-datatype-problem/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module b/jackson-datatype-problem/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module index e5db920..1df0daa 100644 --- a/jackson-datatype-problem/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module +++ b/jackson-datatype-problem/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module @@ -1 +1 @@ -org.zalando.problem.ProblemModule \ No newline at end of file +org.zalando.problem.jackson.ProblemModule \ No newline at end of file diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/BusinessException.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/BusinessException.java similarity index 78% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/BusinessException.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/BusinessException.java index ddbcb14..2f5de2d 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/BusinessException.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/BusinessException.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; abstract class BusinessException extends Exception { diff --git a/problem-gson/src/test/java/org/zalando/problem/CustomStatus.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/CustomStatus.java similarity index 86% rename from problem-gson/src/test/java/org/zalando/problem/CustomStatus.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/CustomStatus.java index cb5f669..102f4da 100644 --- a/problem-gson/src/test/java/org/zalando/problem/CustomStatus.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/CustomStatus.java @@ -1,4 +1,6 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; + +import org.zalando.problem.StatusType; enum CustomStatus implements StatusType { diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/EnforceCoverageTest.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/EnforceCoverageTest.java similarity index 81% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/EnforceCoverageTest.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/EnforceCoverageTest.java index cd3b579..69b8c58 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/EnforceCoverageTest.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/EnforceCoverageTest.java @@ -1,16 +1,13 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; -import com.google.gag.annotation.remark.Hack; -import com.google.gag.annotation.remark.OhNoYouDidnt; import org.junit.jupiter.api.Test; +import org.zalando.problem.AbstractThrowableProblem; import java.net.URI; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.zalando.problem.Status.BAD_REQUEST; -@Hack -@OhNoYouDidnt final class EnforceCoverageTest { @Test diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/IOProblem.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/IOProblem.java similarity index 89% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/IOProblem.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/IOProblem.java index bafaff4..8c7052f 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/IOProblem.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/IOProblem.java @@ -1,9 +1,13 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.zalando.problem.Exceptional; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; + import java.io.IOException; import java.net.URI; diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/InsufficientFundsProblem.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/InsufficientFundsProblem.java similarity index 91% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/InsufficientFundsProblem.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/InsufficientFundsProblem.java index 3c9f9cb..8697d3d 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/InsufficientFundsProblem.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/InsufficientFundsProblem.java @@ -1,9 +1,11 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeName; +import org.zalando.problem.AbstractThrowableProblem; + import java.net.URI; import static org.zalando.problem.Status.BAD_REQUEST; diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/JacksonStackTraceProcessor.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/JacksonStackTraceProcessor.java similarity index 80% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/JacksonStackTraceProcessor.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/JacksonStackTraceProcessor.java index fe0546a..5392b2c 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/JacksonStackTraceProcessor.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/JacksonStackTraceProcessor.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import org.zalando.problem.spi.StackTraceProcessor; @@ -16,7 +16,11 @@ public Collection process(final Collection final ArrayList elements = new ArrayList<>(collection); return elements.stream() - .filter(startsWith("sun.reflect", "java.lang.reflect", "com.fasterxml.jackson").negate()) + .filter(startsWith( + "sun.reflect", + "java.lang.reflect", + "jdk.internal.reflect", + "com.fasterxml.jackson").negate()) .findFirst() .map(elements::indexOf) .map(subList(elements)) diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/OutOfStockException.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/OutOfStockException.java similarity index 86% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/OutOfStockException.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/OutOfStockException.java index e669a32..c493468 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/OutOfStockException.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/OutOfStockException.java @@ -1,9 +1,13 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeName; +import org.zalando.problem.Exceptional; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; + import java.net.URI; import static org.zalando.problem.Status.BAD_REQUEST; diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/ProblemMixInTest.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/ProblemMixInTest.java similarity index 96% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/ProblemMixInTest.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/ProblemMixInTest.java index 532080b..1bbd165 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/ProblemMixInTest.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/ProblemMixInTest.java @@ -1,8 +1,14 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; +import org.zalando.problem.DefaultProblem; +import org.zalando.problem.Exceptional; +import org.zalando.problem.Problem; +import org.zalando.problem.Status; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; import java.io.IOException; import java.io.PrintWriter; @@ -245,7 +251,7 @@ void shouldDeserializeWithProcessedStackTrace() throws IOException { final String stackTrace = getStackTrace(problem); final String[] stackTraceElements = stackTrace.split("\n"); - assertThat(stackTraceElements[1], startsWith("\tat org.zalando.problem.ProblemMixInTest")); + assertThat(stackTraceElements[1], startsWith("\tat " + ProblemMixInTest.class.getName())); } private String getStackTrace(final Throwable throwable) { diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/ProblemModuleTest.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/ProblemModuleTest.java similarity index 85% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/ProblemModuleTest.java rename to jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/ProblemModuleTest.java index 753027b..d6da2cc 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/ProblemModuleTest.java +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/ProblemModuleTest.java @@ -1,6 +1,7 @@ -package org.zalando.problem; +package org.zalando.problem.jackson; import org.junit.jupiter.api.Test; +import org.zalando.problem.Status; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/UnknownStatusTest.java b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/UnknownStatusTest.java new file mode 100644 index 0000000..10cb501 --- /dev/null +++ b/jackson-datatype-problem/src/test/java/org/zalando/problem/jackson/UnknownStatusTest.java @@ -0,0 +1,17 @@ +package org.zalando.problem.jackson; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class UnknownStatusTest { + + @Test + void shouldReturnCodeAndPhrase() { + final int code = 8080; + final UnknownStatus status = new UnknownStatus(code); + assertEquals(8080, status.getStatusCode()); + assertEquals("Unknown", status.getReasonPhrase()); + } + +} \ No newline at end of file diff --git a/jackson-datatype-problem/src/test/resources/META-INF/services/org.zalando.problem.spi.StackTraceProcessor b/jackson-datatype-problem/src/test/resources/META-INF/services/org.zalando.problem.spi.StackTraceProcessor index 65d7271..853b16c 100644 --- a/jackson-datatype-problem/src/test/resources/META-INF/services/org.zalando.problem.spi.StackTraceProcessor +++ b/jackson-datatype-problem/src/test/resources/META-INF/services/org.zalando.problem.spi.StackTraceProcessor @@ -1 +1 @@ -org.zalando.problem.JacksonStackTraceProcessor \ No newline at end of file +org.zalando.problem.jackson.JacksonStackTraceProcessor \ No newline at end of file diff --git a/pom.xml b/pom.xml index 71111c1..8dc81c7 100644 --- a/pom.xml +++ b/pom.xml @@ -61,15 +61,9 @@ provided - com.google.code.findbugs - jsr305 - 3.0.2 - provided - - - com.google.gag - gag - 1.0.1 + org.checkerframework + checker-qual + 3.6.0 provided @@ -78,6 +72,16 @@ 1.18.12 provided + + + org.mapstruct + mapstruct-processor + 1.4.0.CR1 + provided + @@ -154,17 +158,17 @@ apiguardian-api - com.google.code.findbugs - jsr305 - - - com.google.gag - gag + org.checkerframework + checker-qual org.projectlombok lombok + + org.mapstruct + mapstruct-processor + @@ -258,10 +262,69 @@ maven-resources-plugin 3.2.0 + + org.moditect + moditect-maven-plugin + 1.0.0.RC1 + + + + add-module-infos + package + + add-module-info + + + 9 + + + ${module.name} + + ${module.exports} + + + static org.apiguardian.api; + + + + + + --multi-release=9 + + + + + org.apache.maven.plugins maven-compiler-plugin 3.8.1 + -Xlint:unchecked,deprecation @@ -338,6 +401,11 @@ false + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + @@ -353,6 +421,14 @@ org.basepom.maven duplicate-finder-maven-plugin + + org.moditect + moditect-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + org.jacoco jacoco-maven-plugin diff --git a/problem-gson/pom.xml b/problem-gson/pom.xml index c26e663..426d7bf 100644 --- a/problem-gson/pom.xml +++ b/problem-gson/pom.xml @@ -11,6 +11,10 @@ problem-gson 2.8.6 + org.zalando.problem.gson + + org.zalando.problem.gson; + diff --git a/problem-gson/src/main/java/org/zalando/problem/CustomProblemAdapter.java b/problem-gson/src/main/java/org/zalando/problem/gson/CustomProblemAdapter.java similarity index 96% rename from problem-gson/src/main/java/org/zalando/problem/CustomProblemAdapter.java rename to problem-gson/src/main/java/org/zalando/problem/gson/CustomProblemAdapter.java index 81eb74a..8b4b7c7 100644 --- a/problem-gson/src/main/java/org/zalando/problem/CustomProblemAdapter.java +++ b/problem-gson/src/main/java/org/zalando/problem/gson/CustomProblemAdapter.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.Gson; import com.google.gson.JsonElement; @@ -9,6 +9,8 @@ import com.google.gson.stream.JsonWriter; import lombok.AllArgsConstructor; +import org.zalando.problem.AbstractThrowableProblem; + import java.io.IOException; import java.net.URI; import java.util.Optional; diff --git a/problem-gson/src/main/java/org/zalando/problem/DefaultProblemAdapter.java b/problem-gson/src/main/java/org/zalando/problem/gson/DefaultProblemAdapter.java similarity index 93% rename from problem-gson/src/main/java/org/zalando/problem/DefaultProblemAdapter.java rename to problem-gson/src/main/java/org/zalando/problem/gson/DefaultProblemAdapter.java index ac49b6a..59cc510 100644 --- a/problem-gson/src/main/java/org/zalando/problem/DefaultProblemAdapter.java +++ b/problem-gson/src/main/java/org/zalando/problem/gson/DefaultProblemAdapter.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.Gson; import com.google.gson.JsonElement; @@ -9,6 +9,11 @@ import com.google.gson.stream.JsonWriter; import lombok.AllArgsConstructor; +import org.zalando.problem.Problem; +import org.zalando.problem.ProblemBuilder; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; + import java.io.IOException; import java.util.Map; @@ -65,7 +70,7 @@ public void write(final JsonWriter out, final ThrowableProblem problem) throws I @Override public ThrowableProblem read(final JsonReader in) throws IOException { - final ProblemBuilder builder = new ProblemBuilder(); + final ProblemBuilder builder = Problem.builder(); in.beginObject(); while (in.hasNext()) { diff --git a/problem-gson/src/main/java/org/zalando/problem/ProblemAdapterFactory.java b/problem-gson/src/main/java/org/zalando/problem/gson/ProblemAdapterFactory.java similarity index 90% rename from problem-gson/src/main/java/org/zalando/problem/ProblemAdapterFactory.java rename to problem-gson/src/main/java/org/zalando/problem/gson/ProblemAdapterFactory.java index 3762bae..ea371e9 100644 --- a/problem-gson/src/main/java/org/zalando/problem/ProblemAdapterFactory.java +++ b/problem-gson/src/main/java/org/zalando/problem/gson/ProblemAdapterFactory.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.Gson; import com.google.gson.JsonElement; @@ -12,8 +12,14 @@ import lombok.AllArgsConstructor; import org.apiguardian.api.API; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.DefaultProblem; +import org.zalando.problem.Problem; +import org.zalando.problem.Status; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; + import java.io.IOException; import java.net.URI; import java.util.Collections; @@ -24,7 +30,7 @@ import static java.util.Objects.requireNonNull; import static lombok.AccessLevel.PRIVATE; import static org.apiguardian.api.API.Status.EXPERIMENTAL; -import static org.zalando.problem.URITypeAdapter.TYPE; +import static org.zalando.problem.gson.URITypeAdapter.TYPE; /** * Problem {@link TypeAdapterFactory}. @@ -41,7 +47,7 @@ public ProblemAdapterFactory() { } @SafeVarargs - public ProblemAdapterFactory( + public & StatusType> ProblemAdapterFactory( final Class... statusTypes) { this(false, new StatusTypeAdapter(buildIndex(statusTypes)), @@ -58,7 +64,7 @@ private ProblemAdapterFactory( } @SafeVarargs - private static Map buildIndex( + private static & StatusType> Map buildIndex( final Class... types) { final Map index = new HashMap<>(); @@ -84,14 +90,14 @@ public ProblemAdapterFactory withStackTraces(final boolean stackTraces) { return new ProblemAdapterFactory(stackTraces, statusAdapter, subtypes); } - @CheckReturnValue + // TODO @CheckReturnValue public ProblemAdapterFactory registerSubtype( final URI uri, final Class type) { return registerSubType(uri, TypeToken.get(type)); } - @CheckReturnValue + // TODO @CheckReturnValue public ProblemAdapterFactory registerSubType( final URI uri, final TypeToken type) { diff --git a/problem-gson/src/main/java/org/zalando/problem/StatusTypeAdapter.java b/problem-gson/src/main/java/org/zalando/problem/gson/StatusTypeAdapter.java similarity index 89% rename from problem-gson/src/main/java/org/zalando/problem/StatusTypeAdapter.java rename to problem-gson/src/main/java/org/zalando/problem/gson/StatusTypeAdapter.java index 533509e..8c2f651 100644 --- a/problem-gson/src/main/java/org/zalando/problem/StatusTypeAdapter.java +++ b/problem-gson/src/main/java/org/zalando/problem/gson/StatusTypeAdapter.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; @@ -6,7 +6,9 @@ import com.google.gson.stream.JsonWriter; import lombok.AllArgsConstructor; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.zalando.problem.StatusType; + import java.io.IOException; import java.util.Map; import java.util.Objects; diff --git a/problem-gson/src/main/java/org/zalando/problem/URITypeAdapter.java b/problem-gson/src/main/java/org/zalando/problem/gson/URITypeAdapter.java similarity index 87% rename from problem-gson/src/main/java/org/zalando/problem/URITypeAdapter.java rename to problem-gson/src/main/java/org/zalando/problem/gson/URITypeAdapter.java index 3d0ef62..b87a75d 100644 --- a/problem-gson/src/main/java/org/zalando/problem/URITypeAdapter.java +++ b/problem-gson/src/main/java/org/zalando/problem/gson/URITypeAdapter.java @@ -1,11 +1,13 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.zalando.problem.Problem; + import java.io.IOException; import java.net.URI; diff --git a/problem-gson/src/main/java/org/zalando/problem/gson/UnknownStatus.java b/problem-gson/src/main/java/org/zalando/problem/gson/UnknownStatus.java new file mode 100644 index 0000000..427e327 --- /dev/null +++ b/problem-gson/src/main/java/org/zalando/problem/gson/UnknownStatus.java @@ -0,0 +1,23 @@ +package org.zalando.problem.gson; + +import org.zalando.problem.StatusType; + +final class UnknownStatus implements StatusType { + + private final int statusCode; + + UnknownStatus(final int statusCode) { + this.statusCode = statusCode; + } + + @Override + public int getStatusCode() { + return statusCode; + } + + @Override + public String getReasonPhrase() { + return "Unknown"; + } + +} diff --git a/jackson-datatype-problem/src/test/java/org/zalando/problem/CustomStatus.java b/problem-gson/src/test/java/org/zalando/problem/gson/CustomStatus.java similarity index 87% rename from jackson-datatype-problem/src/test/java/org/zalando/problem/CustomStatus.java rename to problem-gson/src/test/java/org/zalando/problem/gson/CustomStatus.java index cb5f669..2c7cd99 100644 --- a/jackson-datatype-problem/src/test/java/org/zalando/problem/CustomStatus.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/CustomStatus.java @@ -1,4 +1,6 @@ -package org.zalando.problem; +package org.zalando.problem.gson; + +import org.zalando.problem.StatusType; enum CustomStatus implements StatusType { diff --git a/problem-gson/src/test/java/org/zalando/problem/GsonProblemTest.java b/problem-gson/src/test/java/org/zalando/problem/gson/GsonProblemTest.java similarity index 97% rename from problem-gson/src/test/java/org/zalando/problem/GsonProblemTest.java rename to problem-gson/src/test/java/org/zalando/problem/gson/GsonProblemTest.java index 922c35f..a902f8b 100644 --- a/problem-gson/src/test/java/org/zalando/problem/GsonProblemTest.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/GsonProblemTest.java @@ -1,9 +1,16 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.stream.JsonReader; import org.junit.jupiter.api.Test; +import org.zalando.problem.DefaultProblem; +import org.zalando.problem.Exceptional; +import org.zalando.problem.Problem; +import org.zalando.problem.ProblemBuilder; +import org.zalando.problem.Status; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; import java.io.File; import java.io.FileNotFoundException; @@ -13,6 +20,7 @@ import java.io.StringWriter; import java.net.URI; import java.net.URL; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -82,8 +90,8 @@ void shouldSerializeCustomProperties() { void shouldSerializeCustomProblem() { final int balance = 10; final int debit = 100; - final InsufficientFundsProblem problem = new InsufficientFundsProblem(balance, debit); - problem.set("foo", "bar"); + final InsufficientFundsProblem problem = new InsufficientFundsProblem( + balance, debit, Collections.singletonMap("foo", "bar")); final String json = gson.toJson(problem); assertThat("json", Objects.nonNull(json)); diff --git a/problem-gson/src/test/java/org/zalando/problem/IOProblem.java b/problem-gson/src/test/java/org/zalando/problem/gson/IOProblem.java similarity index 87% rename from problem-gson/src/test/java/org/zalando/problem/IOProblem.java rename to problem-gson/src/test/java/org/zalando/problem/gson/IOProblem.java index 0f0f179..aad11c1 100644 --- a/problem-gson/src/test/java/org/zalando/problem/IOProblem.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/IOProblem.java @@ -1,8 +1,12 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import java.io.IOException; import java.net.URI; +import org.zalando.problem.Exceptional; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; + final class IOProblem extends IOException implements Exceptional { private final URI type; diff --git a/problem-gson/src/test/java/org/zalando/problem/InsufficientFundsProblem.java b/problem-gson/src/test/java/org/zalando/problem/gson/InsufficientFundsProblem.java similarity index 59% rename from problem-gson/src/test/java/org/zalando/problem/InsufficientFundsProblem.java rename to problem-gson/src/test/java/org/zalando/problem/gson/InsufficientFundsProblem.java index a6bb74b..3cf7d3b 100644 --- a/problem-gson/src/test/java/org/zalando/problem/InsufficientFundsProblem.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/InsufficientFundsProblem.java @@ -1,6 +1,10 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import java.net.URI; +import java.util.Collections; +import java.util.Map; + +import org.zalando.problem.AbstractThrowableProblem; import static org.zalando.problem.Status.BAD_REQUEST; @@ -15,7 +19,14 @@ final class InsufficientFundsProblem extends AbstractThrowableProblem { InsufficientFundsProblem( final int balance, final int debit) { - super(TYPE, "Insufficient Funds", BAD_REQUEST); + this(balance, debit, Collections.emptyMap()); + } + + InsufficientFundsProblem( + final int balance, + final int debit, + final Map parameters) { + super(TYPE, "Insufficient Funds", BAD_REQUEST, null, null, null, parameters); this.balance = balance; this.debit = debit; } diff --git a/problem-gson/src/test/java/org/zalando/problem/MyProblem.java b/problem-gson/src/test/java/org/zalando/problem/gson/MyProblem.java similarity index 92% rename from problem-gson/src/test/java/org/zalando/problem/MyProblem.java rename to problem-gson/src/test/java/org/zalando/problem/gson/MyProblem.java index 4715a31..3f9bac9 100644 --- a/problem-gson/src/test/java/org/zalando/problem/MyProblem.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/MyProblem.java @@ -1,8 +1,10 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.annotations.SerializedName; +import org.zalando.problem.Problem; +import org.zalando.problem.StatusType; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.URI; class MyProblem implements Problem { diff --git a/problem-gson/src/test/java/org/zalando/problem/OutOfStockException.java b/problem-gson/src/test/java/org/zalando/problem/gson/OutOfStockException.java similarity index 85% rename from problem-gson/src/test/java/org/zalando/problem/OutOfStockException.java rename to problem-gson/src/test/java/org/zalando/problem/gson/OutOfStockException.java index d775cd4..951499f 100644 --- a/problem-gson/src/test/java/org/zalando/problem/OutOfStockException.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/OutOfStockException.java @@ -1,7 +1,10 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import java.net.URI; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; + import static org.zalando.problem.Status.BAD_REQUEST; class OutOfStockException extends ThrowableProblem { diff --git a/problem-gson/src/test/java/org/zalando/problem/ProblemAdapterFactoryTest.java b/problem-gson/src/test/java/org/zalando/problem/gson/ProblemAdapterFactoryTest.java similarity index 95% rename from problem-gson/src/test/java/org/zalando/problem/ProblemAdapterFactoryTest.java rename to problem-gson/src/test/java/org/zalando/problem/gson/ProblemAdapterFactoryTest.java index 0755604..7146e88 100644 --- a/problem-gson/src/test/java/org/zalando/problem/ProblemAdapterFactoryTest.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/ProblemAdapterFactoryTest.java @@ -1,7 +1,8 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.ThrowingSupplier; +import org.zalando.problem.Status; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/problem-gson/src/test/java/org/zalando/problem/StatusTypeAdapterTest.java b/problem-gson/src/test/java/org/zalando/problem/gson/StatusTypeAdapterTest.java similarity index 91% rename from problem-gson/src/test/java/org/zalando/problem/StatusTypeAdapterTest.java rename to problem-gson/src/test/java/org/zalando/problem/gson/StatusTypeAdapterTest.java index 0851d8e..cb39b7f 100644 --- a/problem-gson/src/test/java/org/zalando/problem/StatusTypeAdapterTest.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/StatusTypeAdapterTest.java @@ -1,8 +1,9 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.junit.jupiter.api.Test; +import org.zalando.problem.StatusType; import java.util.Collections; diff --git a/problem-gson/src/test/java/org/zalando/problem/URITypeAdapterTest.java b/problem-gson/src/test/java/org/zalando/problem/gson/URITypeAdapterTest.java similarity index 95% rename from problem-gson/src/test/java/org/zalando/problem/URITypeAdapterTest.java rename to problem-gson/src/test/java/org/zalando/problem/gson/URITypeAdapterTest.java index 5ecd172..eabb92a 100644 --- a/problem-gson/src/test/java/org/zalando/problem/URITypeAdapterTest.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/URITypeAdapterTest.java @@ -1,10 +1,11 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonIOException; import com.google.gson.JsonPrimitive; import org.junit.jupiter.api.Test; +import org.zalando.problem.Problem; import java.net.URI; diff --git a/problem/src/test/java/org/zalando/problem/UnknownStatusTest.java b/problem-gson/src/test/java/org/zalando/problem/gson/UnknownStatusTest.java similarity index 91% rename from problem/src/test/java/org/zalando/problem/UnknownStatusTest.java rename to problem-gson/src/test/java/org/zalando/problem/gson/UnknownStatusTest.java index f816fdb..3327227 100644 --- a/problem/src/test/java/org/zalando/problem/UnknownStatusTest.java +++ b/problem-gson/src/test/java/org/zalando/problem/gson/UnknownStatusTest.java @@ -1,4 +1,4 @@ -package org.zalando.problem; +package org.zalando.problem.gson; import org.junit.jupiter.api.Test; diff --git a/problem/pom.xml b/problem/pom.xml index 8427b5c..f7c8ca7 100644 --- a/problem/pom.xml +++ b/problem/pom.xml @@ -10,4 +10,11 @@ problem An implementation of the application/problem+json draft. + + org.zalando.problem + + org.zalando.problem; + org.zalando.problem.spi; + + diff --git a/problem/src/main/java/org/zalando/problem/AbstractThrowableProblem.java b/problem/src/main/java/org/zalando/problem/AbstractThrowableProblem.java index 3ad294e..38aae8b 100644 --- a/problem/src/main/java/org/zalando/problem/AbstractThrowableProblem.java +++ b/problem/src/main/java/org/zalando/problem/AbstractThrowableProblem.java @@ -1,11 +1,8 @@ package org.zalando.problem; -import com.google.gag.annotation.remark.Hack; -import com.google.gag.annotation.remark.OhNoYouDidnt; import org.apiguardian.api.API; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.URI; import java.util.Collections; import java.util.LinkedHashMap; @@ -15,8 +12,6 @@ import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; -@API(status = STABLE) -@Immutable // TODO kind of a lie until we remove set(String, Object) public abstract class AbstractThrowableProblem extends ThrowableProblem { private final URI type; @@ -30,29 +25,34 @@ protected AbstractThrowableProblem() { this(null); } - protected AbstractThrowableProblem(@Nullable final URI type) { + protected AbstractThrowableProblem( + @Nullable final URI type) { this(type, null); } - protected AbstractThrowableProblem(@Nullable final URI type, + protected AbstractThrowableProblem( + @Nullable final URI type, @Nullable final String title) { this(type, title, null); } - protected AbstractThrowableProblem(@Nullable final URI type, + protected AbstractThrowableProblem( + @Nullable final URI type, @Nullable final String title, @Nullable final StatusType status) { this(type, title, status, null); } - protected AbstractThrowableProblem(@Nullable final URI type, + protected AbstractThrowableProblem( + @Nullable final URI type, @Nullable final String title, @Nullable final StatusType status, @Nullable final String detail) { this(type, title, status, detail, null); } - protected AbstractThrowableProblem(@Nullable final URI type, + protected AbstractThrowableProblem( + @Nullable final URI type, @Nullable final String title, @Nullable final StatusType status, @Nullable final String detail, @@ -60,7 +60,8 @@ protected AbstractThrowableProblem(@Nullable final URI type, this(type, title, status, detail, instance, null); } - protected AbstractThrowableProblem(@Nullable final URI type, + protected AbstractThrowableProblem( + @Nullable final URI type, @Nullable final String title, @Nullable final StatusType status, @Nullable final String detail, @@ -69,7 +70,8 @@ protected AbstractThrowableProblem(@Nullable final URI type, this(type, title, status, detail, instance, cause, null); } - protected AbstractThrowableProblem(@Nullable final URI type, + protected AbstractThrowableProblem( + @Nullable final URI type, @Nullable final String title, @Nullable final StatusType status, @Nullable final String detail, @@ -124,8 +126,6 @@ public Map getParameters() { * @see Jackson Issue 562 */ @API(status = INTERNAL) - @Hack - @OhNoYouDidnt void set(final String key, final Object value) { parameters.put(key, value); } diff --git a/problem/src/main/java/org/zalando/problem/DefaultProblem.java b/problem/src/main/java/org/zalando/problem/DefaultProblem.java index c504878..6204998 100644 --- a/problem/src/main/java/org/zalando/problem/DefaultProblem.java +++ b/problem/src/main/java/org/zalando/problem/DefaultProblem.java @@ -1,8 +1,7 @@ package org.zalando.problem; import org.apiguardian.api.API; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.URI; import java.util.Map; diff --git a/problem/src/main/java/org/zalando/problem/Problem.java b/problem/src/main/java/org/zalando/problem/Problem.java index 99e7e8d..fee821c 100644 --- a/problem/src/main/java/org/zalando/problem/Problem.java +++ b/problem/src/main/java/org/zalando/problem/Problem.java @@ -2,8 +2,7 @@ import org.apiguardian.api.API; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.URI; import java.util.Collections; import java.util.Map; @@ -15,9 +14,10 @@ /** * @see RFC 7807: Problem Details for HTTP APIs + * + * {@link Problem} instances are required to be immutable. */ @API(status = STABLE) -@Immutable public interface Problem { URI DEFAULT_TYPE = URI.create("about:blank"); diff --git a/problem/src/main/java/org/zalando/problem/ProblemBuilder.java b/problem/src/main/java/org/zalando/problem/ProblemBuilder.java index c2721c6..576a75e 100644 --- a/problem/src/main/java/org/zalando/problem/ProblemBuilder.java +++ b/problem/src/main/java/org/zalando/problem/ProblemBuilder.java @@ -2,7 +2,7 @@ import org.apiguardian.api.API; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.URI; import java.util.Arrays; import java.util.HashSet; diff --git a/problem/src/main/java/org/zalando/problem/Status.java b/problem/src/main/java/org/zalando/problem/Status.java index 3efbf02..a8b5377 100644 --- a/problem/src/main/java/org/zalando/problem/Status.java +++ b/problem/src/main/java/org/zalando/problem/Status.java @@ -1,9 +1,8 @@ package org.zalando.problem; import org.apiguardian.api.API; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -14,20 +13,22 @@ import static org.apiguardian.api.API.Status.MAINTAINED; /** - * Commonly used status codes defined by HTTP, see - * HTTP/1.1 documentation - * for the complete list. Additional status codes can be added by applications - * by creating an implementation of StatusType. + * Commonly used status codes defined by HTTP, see HTTP/1.1 + * documentation for the complete list. Additional status codes can be added + * by applications by creating an implementation of StatusType. */ @API(status = MAINTAINED) public enum Status implements StatusType { /** - * @see HTTP/1.1: Semantics and Content, section 6.2.1 + * @see HTTP/1.1: + * Semantics and Content, section 6.2.1 */ CONTINUE(100, "Continue"), /** - * @see HTTP/1.1: Semantics and Content, section 6.2.2 + * @see HTTP/1.1: + * Semantics and Content, section 6.2.2 */ SWITCHING_PROTOCOLS(101, "Switching Protocols"), /** @@ -35,36 +36,50 @@ public enum Status implements StatusType { */ PROCESSING(102, "Processing"), /** - * @see A proposal for supporting - * resumable POST/PUT HTTP requests in HTTP/1.0 + * @see A + * proposal for supporting resumable POST/PUT HTTP requests in HTTP/1.0 */ CHECKPOINT(103, "Checkpoint"), /** - * 200 OK, see HTTP/1.1 documentation. + * 200 OK, see HTTP/1.1 + * documentation. */ OK(200, "OK"), /** - * 201 Created, see HTTP/1.1 documentation. + * 201 Created, see HTTP/1.1 + * documentation. */ CREATED(201, "Created"), /** - * 202 Accepted, see HTTP/1.1 documentation. + * 202 Accepted, see HTTP/1.1 + * documentation. */ ACCEPTED(202, "Accepted"), /** - * @see HTTP/1.1: Semantics and Content, section 6.3.4 + * @see HTTP/1.1: + * Semantics and Content, section 6.3.4 */ NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"), /** - * 204 No Content, see HTTP/1.1 documentation. + * 204 No Content, see HTTP/1.1 + * documentation. */ NO_CONTENT(204, "No Content"), /** - * 205 Reset Content, see HTTP/1.1 documentation. + * 205 Reset Content, see HTTP/1.1 + * documentation. */ RESET_CONTENT(205, "Reset Content"), /** - * 206 Reset Content, see HTTP/1.1 documentation. + * 206 Reset Content, see HTTP/1.1 + * documentation. */ PARTIAL_CONTENT(206, "Partial Content"), /** @@ -72,39 +87,54 @@ public enum Status implements StatusType { */ MULTI_STATUS(207, "Multi-Status"), /** - * @see WebDAV Binding Extensions + * @see WebDAV Binding + * Extensions */ ALREADY_REPORTED(208, "Already Reported"), /** - * @see Delta encoding in HTTP + * @see Delta + * encoding in HTTP */ IM_USED(226, "IM Used"), /** - * @see HTTP/1.1: Semantics and Content, section 6.4.1 + * @see HTTP/1.1: + * Semantics and Content, section 6.4.1 */ MULTIPLE_CHOICES(300, "Multiple Choices"), /** - * 301 Moved Permanently, see HTTP/1.1 documentation. + * 301 Moved Permanently, see HTTP/1.1 + * documentation. */ MOVED_PERMANENTLY(301, "Moved Permanently"), /** - * 302 Found, see HTTP/1.1 documentation. + * 302 Found, see HTTP/1.1 + * documentation. */ FOUND(302, "Found"), /** - * 303 See Other, see HTTP/1.1 documentation. + * 303 See Other, see HTTP/1.1 + * documentation. */ SEE_OTHER(303, "See Other"), /** - * 304 Not Modified, see HTTP/1.1 documentation. + * 304 Not Modified, see HTTP/1.1 + * documentation. */ NOT_MODIFIED(304, "Not Modified"), /** - * 305 Use Proxy, see HTTP/1.1 documentation. + * 305 Use Proxy, see HTTP/1.1 + * documentation. */ USE_PROXY(305, "Use Proxy"), /** - * 307 Temporary Redirect, see HTTP/1.1 documentation. + * 307 Temporary Redirect, see HTTP/1.1 + * documentation. */ TEMPORARY_REDIRECT(307, "Temporary Redirect"), /** @@ -112,79 +142,116 @@ public enum Status implements StatusType { */ PERMANENT_REDIRECT(308, "Permanent Redirect"), /** - * 400 Bad Request, see HTTP/1.1 documentation. + * 400 Bad Request, see HTTP/1.1 + * documentation. */ BAD_REQUEST(400, "Bad Request"), /** - * 401 Unauthorized, see HTTP/1.1 documentation. + * 401 Unauthorized, see HTTP/1.1 + * documentation. */ UNAUTHORIZED(401, "Unauthorized"), /** - * 402 Payment Required, see HTTP/1.1 documentation. + * 402 Payment Required, see HTTP/1.1 + * documentation. */ PAYMENT_REQUIRED(402, "Payment Required"), /** - * 403 Forbidden, see HTTP/1.1 documentation. + * 403 Forbidden, see HTTP/1.1 + * documentation. */ FORBIDDEN(403, "Forbidden"), /** - * 404 Not Found, see HTTP/1.1 documentation. + * 404 Not Found, see HTTP/1.1 + * documentation. */ NOT_FOUND(404, "Not Found"), /** - * 405 Method Not Allowed, see HTTP/1.1 documentation. + * 405 Method Not Allowed, see HTTP/1.1 + * documentation. */ METHOD_NOT_ALLOWED(405, "Method Not Allowed"), /** - * 406 Not Acceptable, see HTTP/1.1 documentation. + * 406 Not Acceptable, see HTTP/1.1 + * documentation. */ NOT_ACCEPTABLE(406, "Not Acceptable"), /** - * 407 Proxy Authentication Required, see HTTP/1.1 documentation. + * 407 Proxy Authentication Required, see HTTP/1.1 + * documentation. */ PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"), /** - * 408 Request Timeout, see HTTP/1.1 documentation. + * 408 Request Timeout, see HTTP/1.1 + * documentation. */ REQUEST_TIMEOUT(408, "Request Timeout"), /** - * 409 Conflict, see HTTP/1.1 documentation. + * 409 Conflict, see HTTP/1.1 + * documentation. */ CONFLICT(409, "Conflict"), /** - * 410 Gone, see HTTP/1.1 documentation. + * 410 Gone, see HTTP/1.1 + * documentation. */ GONE(410, "Gone"), /** - * 411 Length Required, see HTTP/1.1 documentation. + * 411 Length Required, see HTTP/1.1 + * documentation. */ LENGTH_REQUIRED(411, "Length Required"), /** - * 412 Precondition Failed, see HTTP/1.1 documentation. + * 412 Precondition Failed, see HTTP/1.1 + * documentation. */ PRECONDITION_FAILED(412, "Precondition Failed"), /** - * 413 Request Entity Too Large, see HTTP/1.1 documentation. + * 413 Request Entity Too Large, see HTTP/1.1 + * documentation. */ REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large"), /** - * 414 Request-URI Too Long, see HTTP/1.1 documentation. + * 414 Request-URI Too Long, see HTTP/1.1 + * documentation. */ REQUEST_URI_TOO_LONG(414, "Request-URI Too Long"), /** - * 415 Unsupported Media Type, see HTTP/1.1 documentation. + * 415 Unsupported Media Type, see HTTP/1.1 + * documentation. */ UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"), /** - * 416 Requested Range Not Satisfiable, see HTTP/1.1 documentation. + * 416 Requested Range Not Satisfiable, see HTTP/1.1 + * documentation. */ REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested Range Not Satisfiable"), /** - * 417 Expectation Failed, see HTTP/1.1 documentation. + * 417 Expectation Failed, see HTTP/1.1 + * documentation. */ EXPECTATION_FAILED(417, "Expectation Failed"), /** - * @see HTCPCP/1.0 + * @see HTCPCP/1.0 */ I_AM_A_TEAPOT(418, "I'm a teapot"), /** @@ -200,51 +267,69 @@ public enum Status implements StatusType { */ FAILED_DEPENDENCY(424, "Failed Dependency"), /** - * @see Upgrading to TLS Within HTTP/1.1 + * @see Upgrading to TLS + * Within HTTP/1.1 */ UPGRADE_REQUIRED(426, "Upgrade Required"), /** - * @see Additional HTTP Status Codes + * @see Additional HTTP + * Status Codes */ PRECONDITION_REQUIRED(428, "Precondition Required"), /** - * @see Additional HTTP Status Codes + * @see Additional HTTP + * Status Codes */ TOO_MANY_REQUESTS(429, "Too Many Requests"), /** - * @see Additional HTTP Status Codes + * @see Additional HTTP + * Status Codes */ REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"), /** - * @see Unavailable For Legal Reasons + * @see Unavailable For + * Legal Reasons */ UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons"), /** - * 500 Internal Server Error, see HTTP/1.1 documentation. + * 500 Internal Server Error, see HTTP/1.1 + * documentation. */ INTERNAL_SERVER_ERROR(500, "Internal Server Error"), /** - * 501 Not Implemented, see HTTP/1.1 documentation. + * 501 Not Implemented, see HTTP/1.1 + * documentation. */ NOT_IMPLEMENTED(501, "Not Implemented"), /** - * 502 Bad Gateway, see HTTP/1.1 documentation. + * 502 Bad Gateway, see HTTP/1.1 + * documentation. */ BAD_GATEWAY(502, "Bad Gateway"), /** - * 503 Service Unavailable, see HTTP/1.1 documentation. + * 503 Service Unavailable, see HTTP/1.1 + * documentation. */ SERVICE_UNAVAILABLE(503, "Service Unavailable"), /** - * 504 Gateway Timeout, see HTTP/1.1 documentation. + * 504 Gateway Timeout, see HTTP/1.1 + * documentation. */ GATEWAY_TIMEOUT(504, "Gateway Timeout"), /** - * 505 HTTP Version Not Supported, see HTTP/1.1 documentation. + * 505 HTTP Version Not Supported, see HTTP/1.1 + * documentation. */ HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version Not Supported"), /** - * @see Transparent Content Negotiation + * @see Transparent + * Content Negotiation */ VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates"), /** @@ -252,7 +337,8 @@ public enum Status implements StatusType { */ INSUFFICIENT_STORAGE(507, "Insufficient Storage"), /** - * @see WebDAV Binding Extensions + * @see WebDAV Binding + * Extensions */ LOOP_DETECTED(508, "Loop Detected"), /** @@ -260,18 +346,18 @@ public enum Status implements StatusType { */ BANDWIDTH_LIMIT_EXCEEDED(509, "Bandwidth Limit Exceeded"), /** - * @see HTTP Extension Framework + * @see HTTP Extension + * Framework */ NOT_EXTENDED(510, "Not Extended"), /** - * @see Additional HTTP Status Codes + * @see Additional HTTP + * Status Codes */ NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required"); private static final Map STATUSES = Arrays.stream(values()) - .collect(collectingAndThen( - toMap(Status::getStatusCode, identity()), - Collections::unmodifiableMap)); + .collect(collectingAndThen(toMap(Status::getStatusCode, identity()), Collections::unmodifiableMap)); private final int code; private final String reason; @@ -297,7 +383,7 @@ public int getStatusCode() { * @return the reason phrase. */ @Override - @Nonnull + @NonNull public String getReasonPhrase() { return reason; } diff --git a/problem/src/main/java/org/zalando/problem/ThrowableProblem.java b/problem/src/main/java/org/zalando/problem/ThrowableProblem.java index 0883b47..8fdc4d1 100644 --- a/problem/src/main/java/org/zalando/problem/ThrowableProblem.java +++ b/problem/src/main/java/org/zalando/problem/ThrowableProblem.java @@ -2,8 +2,7 @@ import org.apiguardian.api.API; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.Objects; import java.util.stream.Stream; @@ -13,8 +12,11 @@ import static org.apiguardian.api.API.Status.STABLE; import static org.zalando.problem.spi.StackTraceProcessor.COMPOUND; +/** + * + * {@link Problem} instances are required to be immutable. + */ @API(status = STABLE) -@Immutable public abstract class ThrowableProblem extends RuntimeException implements Problem, Exceptional { protected ThrowableProblem() { diff --git a/problem/src/main/java/org/zalando/problem/package-info.java b/problem/src/main/java/org/zalando/problem/package-info.java index 7d55a70..5352e50 100644 --- a/problem/src/main/java/org/zalando/problem/package-info.java +++ b/problem/src/main/java/org/zalando/problem/package-info.java @@ -1,3 +1,6 @@ -@ParametersAreNonnullByDefault package org.zalando.problem; +@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.PARAMETER) +package org.zalando.problem; -import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.checkerframework.framework.qual.TypeUseLocation; diff --git a/problem/src/test/java/org/example/MyProblem.java b/problem/src/test/java/org/example/MyProblem.java index 0e56dd1..1f7275d 100644 --- a/problem/src/test/java/org/example/MyProblem.java +++ b/problem/src/test/java/org/example/MyProblem.java @@ -4,7 +4,7 @@ import org.zalando.problem.StatusType; import org.zalando.problem.ThrowableProblem; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.net.URI; import java.util.Map; diff --git a/problem/src/test/java/org/zalando/problem/EnforceCoverageTest.java b/problem/src/test/java/org/zalando/problem/EnforceCoverageTest.java index d119dea..ffb4afb 100644 --- a/problem/src/test/java/org/zalando/problem/EnforceCoverageTest.java +++ b/problem/src/test/java/org/zalando/problem/EnforceCoverageTest.java @@ -1,7 +1,5 @@ package org.zalando.problem; -import com.google.gag.annotation.remark.Hack; -import com.google.gag.annotation.remark.OhNoYouDidnt; import org.junit.jupiter.api.Test; import java.net.URI; @@ -9,8 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.zalando.problem.Status.BAD_REQUEST; -@Hack -@OhNoYouDidnt class EnforceCoverageTest { @Test