From ab838a1e6abb85a7a74cb9e85da036118bad6c44 Mon Sep 17 00:00:00 2001 From: Jake Swenson Date: Thu, 17 Nov 2016 00:13:14 -0800 Subject: [PATCH] updating jersey extras to 2.0 to support dropwizard 1.0 --- .deployment | 1 + .gitmodules | 4 + .travis.yml | 15 +- deploy.sh | 7 - perform-release.sh | 1 - pom.xml | 194 +++--------------- prep-release.sh | 1 - rollback-release.sh | 1 - .../web/web/CorrelationRequestContext.java | 14 -- .../web/web/filter/ContextAttributeKeys.java | 9 - .../web/web/filter/ContextProvider.java | 32 --- .../web/web/filter/CorrelationIdFilter.java | 76 ------- .../web/web/filter/LoggingProperties.java | 6 - .../jersey/extras/ContextProperties.java | 9 + .../jersey/extras/ContextProvider.java | 25 +++ .../extras}/NamedRequestHeader.java | 2 +- .../extras}/WellKnownHeaders.java | 2 +- .../extras/filters/CorrelationIdFilter.java | 138 +++++++++++++ .../filters}/IpRequestLoggingFilter.java | 10 +- .../filters/JerseyRequestLoggingFilter.java} | 25 ++- .../common/web/ContextProviderTest.java | 59 ------ .../common/web/CorrelationIdFilterTest.java | 85 -------- .../extras/filters/ContextProviderTest.java | 81 ++++++++ .../filters/CorrelationIdFilterTest.java | 64 ++++++ 24 files changed, 383 insertions(+), 478 deletions(-) create mode 160000 .deployment create mode 100644 .gitmodules delete mode 100755 deploy.sh delete mode 100755 perform-release.sh delete mode 100755 prep-release.sh delete mode 100755 rollback-release.sh delete mode 100644 src/main/java/io/paradoxical/common/web/web/CorrelationRequestContext.java delete mode 100644 src/main/java/io/paradoxical/common/web/web/filter/ContextAttributeKeys.java delete mode 100644 src/main/java/io/paradoxical/common/web/web/filter/ContextProvider.java delete mode 100644 src/main/java/io/paradoxical/common/web/web/filter/CorrelationIdFilter.java delete mode 100644 src/main/java/io/paradoxical/common/web/web/filter/LoggingProperties.java create mode 100644 src/main/java/io/paradoxical/jersey/extras/ContextProperties.java create mode 100644 src/main/java/io/paradoxical/jersey/extras/ContextProvider.java rename src/main/java/io/paradoxical/{common/web/web/filter => jersey/extras}/NamedRequestHeader.java (58%) rename src/main/java/io/paradoxical/{common/web/web/filter => jersey/extras}/WellKnownHeaders.java (87%) create mode 100644 src/main/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilter.java rename src/main/java/io/paradoxical/{common/web/web/filter => jersey/extras/filters}/IpRequestLoggingFilter.java (81%) rename src/main/java/io/paradoxical/{common/web/web/filter/JerseyRequestLogging.java => jersey/extras/filters/JerseyRequestLoggingFilter.java} (68%) delete mode 100644 src/test/java/io/paradoxical/common/web/ContextProviderTest.java delete mode 100644 src/test/java/io/paradoxical/common/web/CorrelationIdFilterTest.java create mode 100644 src/test/java/io/paradoxical/jersey/extras/filters/ContextProviderTest.java create mode 100644 src/test/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilterTest.java diff --git a/.deployment b/.deployment new file mode 160000 index 0000000..0af9864 --- /dev/null +++ b/.deployment @@ -0,0 +1 @@ +Subproject commit 0af9864486fee2a16491f7a9919b47b28e86e338 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..01f0c39 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule ".deployment"] + path = .deployment + url = https://github.com/paradoxical-io/deployment.git + branch = master diff --git a/.travis.yml b/.travis.yml index fe9ca54..b6d17c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,15 @@ language: java jdk: - - oraclejdk8 - +- oraclejdk8 +git: + submodules: false +before_install: +- git submodule update --init --remote --recursive after_success: - - ./deploy.sh \ No newline at end of file +- "./.deployment/deploy.sh" +env: + global: + - secure: EWi7H2SfKN1PkmRb2eoR8FtPVdyqQE6Obwgy2wYWeuDKm22Y9p0es36yneuE4X6TFe4t/T2QSxH09JaA350OEhfD8hB5eJEwr/kmA/pQQdDsn554nWqV/FsFaQuilMFcGRhM6hJ1EUJnZbVkEnKlf+rJNl1vE5amCXztReR7XEZToTajnOSyhkH6YX10qSQAJURTqjaRFJVsyQd4cP80aUvRRZMXdFLF+kCjWsM+1gEYMIl15jOuZU3E2MUNIWZEAkVoi7+Ino1XVUiuHWm9EAsE+pUvzvww8Cy36LC7orryccY4J/c0lFu+NbjStviPnoreas9U21msTB+aZj8JTDSSL/dNu3d/eZg26xHbcsJpBcfVAVb7qxb2vNuT7XpwyrJIVdfbT0fmJ1eDdOyNs44o9mo9C5qH6r+Ywo/eMHAP4uL+HsRl/em/QDFtSiaMrxxMci9y3G9OuDjfQD5xT5ULJJW5+E/CrwOz8FlleQaB0s7SnWiMyupqJa8df2PrlfJP3NkbqVZWCOogSai0Zk+x2EXTVyuTx+6zguRXMPaFzmakb+ZjISeojzC2F5NEtk+P0BAOVHOqcBKAjFSxEXqRBcjQopp7fkA+Xexj9C8CXVzdJNVZv3t6i/HCQy5dUF0/QoghgTMtrtFaU7OsN5gN8460Xt502NQIUvp6Zw4= + - secure: ameSBFDiscY4RBthJQV0jr+uIH+ozXOaaPZa9HHpai724Dzf8INaFv8xDKKIidsgb7ipls/tZa3I9MwOpcJ50iwB2sS4ZJaf4BmXA/nPKnofOLaThJgIy8hxtbyjtyJh0Si5lEVJm5yV2pxoQ3/BDveN1K1xhuMw9cdb73G9xtkd1G5xeY48YkCsVVHmOzrxgdFdB3lcz/NVu7CTXxSDr6smwu6nw7refISXDV1k1X4Zhih9roCYTKPsz2jPea5hUoEbM3/tFowd2JseAVkX6g38aDhzCo6/73CYOaucPYesGcj8f/9cPvy2OHbJR0wbf9bciw8ejHWxJ96NeZkDE9MGuOxxyqoZOG60QYaSIQLNrJkFxAamXmCNmQLkv13UEoE13vYEYDS+6+ilaAHfSbEzQ+WaIPzi8KyDNyGVJtBxB670StVFCLKt5+SqvkUR914YfVft0yT8HAX9mKp/w9OqbiMpLmTm7TvLwTpXITpOXGs49rDYfhvnQgLrjNVbUxmg63oZEPrtsZNnz3AUierMnDPnZViHPS3EI/PZQ8QIPwD4dXucmtpPKnUGtMwonoBgrejkDWtXSE0fJDIQYfaRsAzkrsb1eivoyk7bbd2QznM8sYmdJBb7mB9pIuYdUnrSR2StCInAJPbj5KGhyoIXKQZwM3CpfVfcWXkOWTg= + - secure: myX2BgwTLzGptuTk5AXF6g4sAy+/RxCAxcFcHdZBm7ey/CQLuEFar1ZSRakYxxtVBxKjwFlehjToPWu9HEK8ibkamhzFOO9CJNTcI6fYHF7A5/nVTtdoelrSWSJrOPILocoVO4nnKmhze/BUszNIyK4Of26slTlEiOkrxSD73uul0dM5BqudsLBaAZoYM0iodrAHRVseMWuySwiwJRI0FieOE9hdq3XotJwIU6QCA4bDwRw6TzxI54ZXH1vZWFOIY+iCZ+ebxORZEVZr4ufoKKGKNULjr6eIOvkxQ6bm9BSCGOlMDSPTL4lpcgE/6uY7X0WLmZB8QGfmJawmc2kixjXoTeCPrF4p6Z1Ga1EOTWSc7jlZdY5MTbvgzmuZsU6rNhCKWs2LUN57dvLxBnDaG7pkSn5J7xZdZfzHXYcwrdPsqg1HWUb2t2UECxazAi5RZ9HpnTmlG7FZQBq0paA6rWflNFp5tEru6tFV31qrbjQK1RQPNLdfYkZ7XMemN17YKPqIo6dyrtU6CYJ6CHhB0ePW54NK4oKrbEXZPR7jyMsU4lWolbvp6mPDIRa/SKvrnP5Ob5lBrF14h1ZJcktLEdQh0jC5wvcy/aXYYck0sS3Rmx8oRlqKab1H7OFg5U1sPC7CACKovsfbmuRa5hfwyMeNZh2Px0tfiOkXagl30W8= + - secure: EyLbLkbxjMsFsnl34BmlgvNU7Fjbtdfqymdc3gaia8Uybr77hR+wpXK0u+ns/Fc6x0C5BCX5tkgcLBjPTo+fb+HgNXmzQqesJ5tcpJg/CAiEKROKZuCAKRr1iMyA7tIpy4V9ypB7HafXQNuZ4GqGwHniS06PqQuSw2+RSjD8KbGBvsJFODdGkNfu+DPEJE1Oj4AVWohXQMR8lsqiCzU4XwmVDJxEH+jjhHOD4w8+3NyxKl2ygtPAYago74Js0SqWaapKJHm2VrZVVkNqX1VSlbCVJRG3mS6C7893YE6ueg9NWglheTHkAHnSSr9ZsX/2iBYyu70IeYhw9Gju/s+rlw2EVLW5WXvOoPfmqK2NjW2kWa8ssCFEVsNPrxoYxyBWUDfpQ+nuG93eR3gw1EiKIlUmLxmjm8/GEtBEl8OM9yKHlrBEXH/jBS6n6vJFIZdTNaOVkw+9v+GXpA7YrAMgKGCpatA39Igskw59DUbZBi/wiGawGf9xNLKWx5vh4Ka7baPIeolO4YD8HJb5du4rCWLfhAzW8w+GJ8ERhhe5RTEVG/KZ0ec/CclhviAmxMDxcEycs3xwDXNSoS41VPZPNmUy9YqO+jhGHp/P8QROhtIY4gHusWb68Ro07PiYqkNSMA9mfAF4xXuOIge1EtE4C1pF/XslX+1DaGgA5ZsI0mc= diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 9005911..0000000 --- a/deploy.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -set -x - -if [ "$TRAVIS_BRANCH" == "master" ]; then - mvn clean deploy --settings settings.xml -DskipTests -fi \ No newline at end of file diff --git a/perform-release.sh b/perform-release.sh deleted file mode 100755 index a6574da..0000000 --- a/perform-release.sh +++ /dev/null @@ -1 +0,0 @@ -mvn release:perform -P sign -s settings.xml \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7bbc2b0..e7469fc 100644 --- a/pom.xml +++ b/pom.xml @@ -1,20 +1,26 @@ - - + + 4.0.0 - + 3.0.0 - - io.paradoxical + + + io.paradoxical + deployment-base-pom + 1.0 + + jersey-extras - 1.1-SNAPSHOT + 2.0${revision} jar - Jersey utilities - + jersey-extras http://maven.apache.org + Jersey utilities @@ -28,8 +34,7 @@ ${env.GPG_PASSWORD} 1.7.10 1.16.2 - 1.10.0 - 18.0 + 19.0 1.0.13 1.10.19 4.12 @@ -39,24 +44,20 @@ 2.4 2.14 2.14 - 1.0 - 4.7.2.RELEASE - 2.21 + 1.2.2 + 7.0.1.RELEASE + 2.23.1 1.1 - + - http://github.com:paradoxical-io/common.web - - scm:git:git@github.com:paradoxical-io/common.web.git - - - scm:git:git@github.com:paradoxical-io/common.web.git - - HEAD - + http://github.com:paradoxical-io/jersey-extras + scm:git:git@github.com:paradoxical-io/jersey-extras.git + scm:git:git@github.com:paradoxical-io/jersey-extras.git + HEAD + - + devshorts Anton Kropp @@ -84,11 +85,6 @@ org.glassfish.jersey.test-framework.providers jersey-test-framework-provider-grizzly2 ${jersey.version} - - - org.springframework - spring-test - 4.1.5.RELEASE test @@ -104,7 +100,7 @@ javax.servlet javax.servlet-api - 3.0.1 + 3.1.0 uk.co.jemos.podam @@ -145,11 +141,6 @@ guava ${guava.version} - - com.esotericsoftware - reflectasm - ${reflectasm.version} - ch.qos.logback logback-classic @@ -181,139 +172,6 @@ ${java.version} - - org.apache.maven.plugins - maven-surefire-plugin - ${maven.surefire.plugin.version} - - - -XX:-UseSplitVerifier - - %regex[.*] - - - - - org.apache.maven.plugins - maven-surefire-report-plugin - ${maven.surefire.report.plugin.version} - - true - - - - generate-test-report - test - - report-only - - - - generate-integration-test-report - integration-test - - failsafe-report-only - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.6 - true - - ossrh - https://oss.sonatype.org/ - true - - - - org.codehaus.mojo - buildnumber-maven-plugin - 1.3 - - - validate - - create - - - - - false - false - 5 - - - - org.apache.maven.plugins - maven-release-plugin - 2.5.1 - - - org.apache.maven.scm - maven-scm-provider-gitexe - 1.9.2 - - - - - org.apache.maven.plugins - maven-source-plugin - ${maven.source.plugin.version} - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - - - - - - sign - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - - - true - devshorts - - - - - - diff --git a/prep-release.sh b/prep-release.sh deleted file mode 100755 index 3d839e8..0000000 --- a/prep-release.sh +++ /dev/null @@ -1 +0,0 @@ -mvn release:prepare -P sign -s settings.xml \ No newline at end of file diff --git a/rollback-release.sh b/rollback-release.sh deleted file mode 100755 index 5431311..0000000 --- a/rollback-release.sh +++ /dev/null @@ -1 +0,0 @@ -mvn release:rollback; mvn release:clean \ No newline at end of file diff --git a/src/main/java/io/paradoxical/common/web/web/CorrelationRequestContext.java b/src/main/java/io/paradoxical/common/web/web/CorrelationRequestContext.java deleted file mode 100644 index 71f5829..0000000 --- a/src/main/java/io/paradoxical/common/web/web/CorrelationRequestContext.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.paradoxical.common.web.web; - -import lombok.Getter; -import lombok.Setter; - -import java.util.UUID; - -public class CorrelationRequestContext { - - @Getter - @Setter - private UUID correlationId; - -} diff --git a/src/main/java/io/paradoxical/common/web/web/filter/ContextAttributeKeys.java b/src/main/java/io/paradoxical/common/web/web/filter/ContextAttributeKeys.java deleted file mode 100644 index 6333d84..0000000 --- a/src/main/java/io/paradoxical/common/web/web/filter/ContextAttributeKeys.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.paradoxical.common.web.web.filter; - -public enum ContextAttributeKeys { - CorrelationId; - - public String key() { - return ContextAttributeKeys.class.getPackage() + "-" + name(); - } -} diff --git a/src/main/java/io/paradoxical/common/web/web/filter/ContextProvider.java b/src/main/java/io/paradoxical/common/web/web/filter/ContextProvider.java deleted file mode 100644 index bfa4670..0000000 --- a/src/main/java/io/paradoxical/common/web/web/filter/ContextProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.paradoxical.common.web.web.filter; - -import io.paradoxical.common.web.web.CorrelationRequestContext; - -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import java.util.UUID; - - -public class ContextProvider { - - private HttpServletRequest context; - - @Inject - public ContextProvider(HttpServletRequest context) { - this.context = context; - } - - public UUID getCorrelationId() { - if (context == null) { - return null; - } - - final Object contextAttribute = context.getAttribute(ContextAttributeKeys.CorrelationId.key()); - - if (!(contextAttribute instanceof CorrelationRequestContext)) { - return null; - } - - return ((CorrelationRequestContext) contextAttribute).getCorrelationId(); - } -} diff --git a/src/main/java/io/paradoxical/common/web/web/filter/CorrelationIdFilter.java b/src/main/java/io/paradoxical/common/web/web/filter/CorrelationIdFilter.java deleted file mode 100644 index ab517da..0000000 --- a/src/main/java/io/paradoxical/common/web/web/filter/CorrelationIdFilter.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.paradoxical.common.web.web.filter; - -import io.paradoxical.common.web.web.CorrelationRequestContext; -import org.slf4j.MDC; - -import javax.annotation.Priority; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.core.Context; -import java.io.IOException; -import java.util.UUID; - -@PreMatching -@Priority(Integer.MIN_VALUE) -public class CorrelationIdFilter implements ContainerRequestFilter, ContainerResponseFilter { - - private final NamedRequestHeader correlationIdHeaderName; - @Context private HttpServletRequest request; - - @SuppressWarnings("unused") - public CorrelationIdFilter() { - this(WellKnownHeaders.CorrelationId); - } - - public CorrelationIdFilter(NamedRequestHeader correlationIdHeaderName) { - this.correlationIdHeaderName = correlationIdHeaderName; - } - - - @Override - public void filter(ContainerRequestContext context) { - - if (context == null || request == null) { - return; - } - - final Object requestAttribute = request.getAttribute(ContextAttributeKeys.CorrelationId.key()); - - if (requestAttribute == null) { - setCorrelationId(new CorrelationRequestContext()); - } - else if (requestAttribute instanceof CorrelationRequestContext) { - setCorrelationId((CorrelationRequestContext) requestAttribute); - } - } - - @Override public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws IOException { - /** - * Intentionally don't remove the correlation id since async responses can potentially run on the same thread - * So if you complete an async response from the current thread, you will lose the correlation id that was set - * - * This is safe because every new request gets a correlation id from the header, there's no way to "leave" a correlation id - * in a thread since all new threads will get new correlatoin id - */ - } - - private void setCorrelationId(CorrelationRequestContext domainContext) { - final String requestHeader = request.getHeader(correlationIdHeaderName.headerName()); - - UUID corrId = requestHeader == null ? UUID.randomUUID() : UUID.fromString(requestHeader); - - domainContext.setCorrelationId(corrId); - - request.setAttribute(ContextAttributeKeys.CorrelationId.key(), domainContext); - - MDC.put(LoggingProperties.CORR_ID, domainContext.getCorrelationId().toString()); - } -} - - - - diff --git a/src/main/java/io/paradoxical/common/web/web/filter/LoggingProperties.java b/src/main/java/io/paradoxical/common/web/web/filter/LoggingProperties.java deleted file mode 100644 index b925345..0000000 --- a/src/main/java/io/paradoxical/common/web/web/filter/LoggingProperties.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.paradoxical.common.web.web.filter; - - -public class LoggingProperties { - public static final String CORR_ID = "corrId"; -} diff --git a/src/main/java/io/paradoxical/jersey/extras/ContextProperties.java b/src/main/java/io/paradoxical/jersey/extras/ContextProperties.java new file mode 100644 index 0000000..2a4d11e --- /dev/null +++ b/src/main/java/io/paradoxical/jersey/extras/ContextProperties.java @@ -0,0 +1,9 @@ +package io.paradoxical.jersey.extras; + +public enum ContextProperties { + CorrelationId; + + public String key() { + return ContextProperties.class.getPackage() + "-" + name(); + } +} diff --git a/src/main/java/io/paradoxical/jersey/extras/ContextProvider.java b/src/main/java/io/paradoxical/jersey/extras/ContextProvider.java new file mode 100644 index 0000000..ee7d36a --- /dev/null +++ b/src/main/java/io/paradoxical/jersey/extras/ContextProvider.java @@ -0,0 +1,25 @@ +package io.paradoxical.jersey.extras; + +import io.paradoxical.jersey.extras.filters.CorrelationIdFilter; + +import javax.inject.Inject; +import javax.ws.rs.container.ContainerRequestContext; +import java.util.UUID; + +public class ContextProvider { + + private ContainerRequestContext context; + + @Inject + public ContextProvider(ContainerRequestContext context) { + this.context = context; + } + + public UUID getCorrelationId() { + if (context == null) { + return null; + } + + return CorrelationIdFilter.lookupCorrelationId(context); + } +} diff --git a/src/main/java/io/paradoxical/common/web/web/filter/NamedRequestHeader.java b/src/main/java/io/paradoxical/jersey/extras/NamedRequestHeader.java similarity index 58% rename from src/main/java/io/paradoxical/common/web/web/filter/NamedRequestHeader.java rename to src/main/java/io/paradoxical/jersey/extras/NamedRequestHeader.java index 950c231..e93d522 100644 --- a/src/main/java/io/paradoxical/common/web/web/filter/NamedRequestHeader.java +++ b/src/main/java/io/paradoxical/jersey/extras/NamedRequestHeader.java @@ -1,4 +1,4 @@ -package io.paradoxical.common.web.web.filter; +package io.paradoxical.jersey.extras; public interface NamedRequestHeader { String headerName(); diff --git a/src/main/java/io/paradoxical/common/web/web/filter/WellKnownHeaders.java b/src/main/java/io/paradoxical/jersey/extras/WellKnownHeaders.java similarity index 87% rename from src/main/java/io/paradoxical/common/web/web/filter/WellKnownHeaders.java rename to src/main/java/io/paradoxical/jersey/extras/WellKnownHeaders.java index 1a9d3ba..bf06723 100644 --- a/src/main/java/io/paradoxical/common/web/web/filter/WellKnownHeaders.java +++ b/src/main/java/io/paradoxical/jersey/extras/WellKnownHeaders.java @@ -1,4 +1,4 @@ -package io.paradoxical.common.web.web.filter; +package io.paradoxical.jersey.extras; public enum WellKnownHeaders implements NamedRequestHeader { CorrelationId("X-CorrelationId"); diff --git a/src/main/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilter.java b/src/main/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilter.java new file mode 100644 index 0000000..e27c3c3 --- /dev/null +++ b/src/main/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilter.java @@ -0,0 +1,138 @@ +package io.paradoxical.jersey.extras.filters; + +import com.godaddy.logging.Logger; +import com.google.common.base.Strings; +import io.paradoxical.jersey.extras.ContextProperties; +import io.paradoxical.jersey.extras.NamedRequestHeader; +import io.paradoxical.jersey.extras.WellKnownHeaders; +import lombok.Getter; +import lombok.Setter; +import org.slf4j.MDC; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.PreMatching; +import java.io.IOException; +import java.util.UUID; + +import static com.godaddy.logging.LoggerFactory.getLogger; + +@PreMatching +@Priority(Integer.MIN_VALUE) +public class CorrelationIdFilter implements ContainerRequestFilter, ContainerResponseFilter { + + private static final Logger logger = getLogger(CorrelationIdFilter.class); + + private final NamedRequestHeader correlationIdHeaderName; + + @SuppressWarnings("unused") + public CorrelationIdFilter() { + this(WellKnownHeaders.CorrelationId); + } + + public CorrelationIdFilter(NamedRequestHeader correlationIdHeaderName) { + this.correlationIdHeaderName = correlationIdHeaderName; + } + + public static UUID lookupCorrelationId(ContainerRequestContext context) { + + final Object contextAttribute = context.getProperty(ContextProperties.CorrelationId.key()); + + if (contextAttribute == null || + !(contextAttribute instanceof CorrelationRequestContext)) { + return null; + } + + return ((CorrelationRequestContext) contextAttribute).getCorrelationId(); + } + + @Override + public void filter(ContainerRequestContext context) { + + if (context == null) { + return; + } + + final Object requestAttribute = context.getProperty(ContextProperties.CorrelationId.key()); + + if (requestAttribute == null) { + setCorrelationId(new CorrelationRequestContext(), context); + } + else if (requestAttribute instanceof CorrelationRequestContext) { + setCorrelationId((CorrelationRequestContext) requestAttribute, context); + } + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws IOException { + /** + * Intentionally don't remove the correlation id since async responses can potentially run on the same thread + * So if you complete an async response from the current thread, you will lose the correlation id that was set + * + * This is safe because every new request gets a correlation id from the header, there's no way to "leave" a correlation id + * in a thread since all new threads will get new correlatoin id + */ + + final UUID correlationId = lookupCorrelationId(requestContext); + + if (correlationId == null) { + return; + } + + responseContext.getHeaders() + .add(correlationIdHeaderName.headerName(), + correlationId.toString()); + } + + private void setCorrelationId( + final CorrelationRequestContext correlationContext, + final ContainerRequestContext requestContext) { + + final String requestHeader = requestContext.getHeaderString(correlationIdHeaderName.headerName()); + + UUID corrId = Strings.isNullOrEmpty(requestHeader) ? UUID.randomUUID() : tryParseCorrelationId(requestHeader); + + correlationContext.setCorrelationId(corrId); + + requestContext.setProperty(ContextProperties.CorrelationId.key(), correlationContext); + + MDC.put(LoggingProperties.CORR_ID, correlationContext.getCorrelationId().toString()); + } + + private UUID tryParseCorrelationId(final String requestHeader) { + try { + return UUID.fromString(requestHeader); + } + catch (IllegalArgumentException e) { + final UUID generatedCorrelationId = UUID.randomUUID(); + + logger.with("headerCorrelationId", requestHeader) + .with("generatedCorrelationId", generatedCorrelationId) + .error(e, "Error parsing correlation id from header string"); + + return generatedCorrelationId; + } + } + + static final class CorrelationRequestContext { + + @Getter + @Setter + private UUID correlationId; + + } + + public static final class LoggingProperties { + private LoggingProperties() { + } + + public static final String CORR_ID = "corrId"; + } +} + + + + diff --git a/src/main/java/io/paradoxical/common/web/web/filter/IpRequestLoggingFilter.java b/src/main/java/io/paradoxical/jersey/extras/filters/IpRequestLoggingFilter.java similarity index 81% rename from src/main/java/io/paradoxical/common/web/web/filter/IpRequestLoggingFilter.java rename to src/main/java/io/paradoxical/jersey/extras/filters/IpRequestLoggingFilter.java index 69f38dd..00b2b1a 100644 --- a/src/main/java/io/paradoxical/common/web/web/filter/IpRequestLoggingFilter.java +++ b/src/main/java/io/paradoxical/jersey/extras/filters/IpRequestLoggingFilter.java @@ -1,4 +1,4 @@ -package io.paradoxical.common.web.web.filter; +package io.paradoxical.jersey.extras.filters; import com.godaddy.logging.Logger; @@ -16,7 +16,8 @@ public class IpRequestLoggingFilter implements ContainerRequestFilter { private static final Logger logger = getLogger(IpRequestLoggingFilter.class); private final Consumer requestProcessor; - @Context private HttpServletRequest request; + @Context + private HttpServletRequest request; public IpRequestLoggingFilter() { this(r -> logger.with("remote-addr", r.getRemoteAddr()) @@ -28,12 +29,13 @@ public IpRequestLoggingFilter(Consumer requestProcessor) { this.requestProcessor = requestProcessor; } - @Override public void filter(final ContainerRequestContext requestContext) throws IOException { + @Override + public void filter(final ContainerRequestContext requestContext) throws IOException { if (request == null) { return; } - if(requestProcessor == null){ + if (requestProcessor == null) { return; } diff --git a/src/main/java/io/paradoxical/common/web/web/filter/JerseyRequestLogging.java b/src/main/java/io/paradoxical/jersey/extras/filters/JerseyRequestLoggingFilter.java similarity index 68% rename from src/main/java/io/paradoxical/common/web/web/filter/JerseyRequestLogging.java rename to src/main/java/io/paradoxical/jersey/extras/filters/JerseyRequestLoggingFilter.java index 9efbcda..689ad83 100644 --- a/src/main/java/io/paradoxical/common/web/web/filter/JerseyRequestLogging.java +++ b/src/main/java/io/paradoxical/jersey/extras/filters/JerseyRequestLoggingFilter.java @@ -1,4 +1,4 @@ -package io.paradoxical.common.web.web.filter; +package io.paradoxical.jersey.extras.filters; import org.glassfish.jersey.filter.LoggingFilter; @@ -25,22 +25,23 @@ */ @PreMatching @Priority(Integer.MIN_VALUE + 1) -public class JerseyRequestLogging implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, - ClientResponseFilter, WriterInterceptor { +public class JerseyRequestLoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, + ClientResponseFilter, WriterInterceptor { private final List pathExcludes; private LoggingFilter nativeFilter; - public JerseyRequestLogging(String... pathExcludes) { + public JerseyRequestLoggingFilter(String... pathExcludes) { this(Arrays.asList(pathExcludes)); } - public JerseyRequestLogging(List pathExcludes) { + public JerseyRequestLoggingFilter(List pathExcludes) { nativeFilter = new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true); this.pathExcludes = pathExcludes; } - @Override public void filter(final ClientRequestContext context) throws IOException { + @Override + public void filter(final ClientRequestContext context) throws IOException { if (!isEmpty(pathExcludes) && pathExcludes.stream().anyMatch(i -> i.startsWith(context.getUri().getPath()))) { return; } @@ -48,7 +49,8 @@ public JerseyRequestLogging(List pathExcludes) { nativeFilter.filter(context); } - @Override public void filter(final ContainerRequestContext context) throws IOException { + @Override + public void filter(final ContainerRequestContext context) throws IOException { if (!isEmpty(pathExcludes) && pathExcludes.stream().anyMatch(i -> i.startsWith(context.getUriInfo().getPath()))) { return; } @@ -56,7 +58,8 @@ public JerseyRequestLogging(List pathExcludes) { nativeFilter.filter(context); } - @Override public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws IOException { + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws IOException { if (!isEmpty(pathExcludes) && pathExcludes.stream().anyMatch(i -> i.startsWith(requestContext.getUriInfo().getPath()))) { return; } @@ -64,7 +67,8 @@ public JerseyRequestLogging(List pathExcludes) { nativeFilter.filter(requestContext, responseContext); } - @Override public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) throws IOException { + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) throws IOException { if (!isEmpty(pathExcludes) && pathExcludes.stream().anyMatch(i -> i.startsWith(requestContext.getUri().getPath()))) { return; } @@ -72,7 +76,8 @@ public JerseyRequestLogging(List pathExcludes) { nativeFilter.filter(requestContext, responseContext); } - @Override public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException { + @Override + public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException { nativeFilter.aroundWriteTo(context); } diff --git a/src/test/java/io/paradoxical/common/web/ContextProviderTest.java b/src/test/java/io/paradoxical/common/web/ContextProviderTest.java deleted file mode 100644 index e40b520..0000000 --- a/src/test/java/io/paradoxical/common/web/ContextProviderTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.paradoxical.common.web; - - -import io.paradoxical.common.web.web.CorrelationRequestContext; -import io.paradoxical.common.web.web.filter.ContextAttributeKeys; -import io.paradoxical.common.web.web.filter.ContextProvider; -import org.junit.Test; -import org.springframework.mock.web.MockHttpServletRequest; - -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertNull; - -public class ContextProviderTest { - - private ContextProvider provider; - - @Test - public void when_no_request_is_provided_getting_correlation_should_not_error() { - provider = new ContextProvider(null); - - assertNull(provider.getCorrelationId()); - } - - @Test - public void when_no_correlation_on_request_getting_correlation_should_not_error() { - provider = new ContextProvider(new MockHttpServletRequest()); - - assertNull(provider.getCorrelationId()); - } - - @Test - public void test_get_domain_context() { - MockHttpServletRequest request = new MockHttpServletRequest(); - - CorrelationRequestContext context = new CorrelationRequestContext(); - final UUID correlationId = UUID.randomUUID(); - - context.setCorrelationId(correlationId); - - request.setAttribute(ContextAttributeKeys.CorrelationId.key(), context); - - provider = new ContextProvider(request); - - assertThat(provider.getCorrelationId()).isEqualTo(correlationId); - } - - @Test - public void test_get_domain_context_different_type() { - MockHttpServletRequest request = new MockHttpServletRequest(); - - request.setAttribute(ContextAttributeKeys.CorrelationId.key(), "not domain context"); - - provider = new ContextProvider(request); - - assertNull(provider.getCorrelationId()); - } -} diff --git a/src/test/java/io/paradoxical/common/web/CorrelationIdFilterTest.java b/src/test/java/io/paradoxical/common/web/CorrelationIdFilterTest.java deleted file mode 100644 index 92ea9a8..0000000 --- a/src/test/java/io/paradoxical/common/web/CorrelationIdFilterTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.paradoxical.common.web; - - -import io.paradoxical.common.web.web.CorrelationRequestContext; -import io.paradoxical.common.web.web.filter.ContextAttributeKeys; -import io.paradoxical.common.web.web.filter.CorrelationIdFilter; -import io.paradoxical.common.web.web.filter.LoggingProperties; -import io.paradoxical.common.web.web.filter.WellKnownHeaders; -import org.apache.log4j.MDC; -import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.test.JerseyTest; -import org.junit.Test; -import org.springframework.mock.web.MockHttpServletRequest; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.core.Application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -public class CorrelationIdFilterTest extends JerseyTest { - - private MockHttpServletRequest request = new MockHttpServletRequest(); - private final static ContextAttributeKeys correlationIdContextKey = ContextAttributeKeys.CorrelationId; - - @Override - protected Application configure() { - ResourceConfig config = new ResourceConfig(CorrelationIdFilter.class, Resource.class); - config.register(new AbstractBinder() { - @Override - protected void configure() { - bind(request).to(HttpServletRequest.class); - } - }); - return config; - } - - @Test - public void test_no_domain_context() { - assertNull(request.getAttribute(correlationIdContextKey.key())); - target().path("test").request().get(); - assertNotNull(request.getAttribute(correlationIdContextKey.key())); - } - - @Test - public void test_with_domain_context() { - CorrelationRequestContext context = new CorrelationRequestContext(); - request.setAttribute(correlationIdContextKey.key(), context); - target().path("test").request().get(); - assertNotNull(request.getAttribute(correlationIdContextKey.key())); - //When domain context has more fields we can verify that those fields stayed in tack. - } - - @Test - public void test_mdc() { - String corrId = target().path("test").request().get(String.class); - assertNotNull(corrId); - } - - @Test - public void test_header_contains_corrid() { - final String testCorrelationId = "8ef3a75e-cddb-48b6-83d6-d3377e068831"; - - request.addHeader(WellKnownHeaders.CorrelationId.headerName(), testCorrelationId); - target().path("test").request().get(); - assertThat(request.getAttribute(correlationIdContextKey.key())).isInstanceOf(CorrelationRequestContext.class); - - CorrelationRequestContext context = (CorrelationRequestContext) request.getAttribute(correlationIdContextKey.key()); - - assertThat(context.getCorrelationId().toString()).isEqualTo(testCorrelationId); - } - - @Path("test") - public static class Resource { - @GET - public String getTest() { - return MDC.get(LoggingProperties.CORR_ID).toString(); - } - } - -} diff --git a/src/test/java/io/paradoxical/jersey/extras/filters/ContextProviderTest.java b/src/test/java/io/paradoxical/jersey/extras/filters/ContextProviderTest.java new file mode 100644 index 0000000..63e5759 --- /dev/null +++ b/src/test/java/io/paradoxical/jersey/extras/filters/ContextProviderTest.java @@ -0,0 +1,81 @@ +package io.paradoxical.jersey.extras.filters; + + +import io.paradoxical.jersey.extras.ContextProperties; +import io.paradoxical.jersey.extras.ContextProvider; +import org.glassfish.jersey.internal.MapPropertiesDelegate; +import org.glassfish.jersey.server.ContainerRequest; +import org.junit.Test; + +import java.net.URI; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNull; + +public class ContextProviderTest { + + + @Test + public void when_no_request_is_provided_getting_correlation_should_not_error() { + final ContextProvider provider = new ContextProvider(null); + + assertNull(provider.getCorrelationId()); + } + + @Test + public void when_no_correlation_on_request_getting_correlation_should_not_error() { + + final MapPropertiesDelegate propertiesDelegate = new MapPropertiesDelegate(); + + ContainerRequest containerRequest = new ContainerRequest(URI.create("http://test"), + URI.create("http://test/path"), + "POST", + null, + propertiesDelegate); + + final ContextProvider provider = new ContextProvider(containerRequest); + + assertNull(provider.getCorrelationId()); + } + + @Test + public void test_get_domain_context() { + final MapPropertiesDelegate propertiesDelegate = new MapPropertiesDelegate(); + + ContainerRequest containerRequest = new ContainerRequest(URI.create("http://test"), + URI.create("http://test/path"), + "POST", + null, + propertiesDelegate); + + CorrelationIdFilter.CorrelationRequestContext context = new CorrelationIdFilter.CorrelationRequestContext(); + final UUID correlationId = UUID.randomUUID(); + + context.setCorrelationId(correlationId); + + containerRequest.setProperty(ContextProperties.CorrelationId.key(), context); + + final ContextProvider provider = new ContextProvider(containerRequest); + + assertThat(provider.getCorrelationId()).isEqualTo(correlationId); + } + + @Test + public void test_get_domain_context_different_type() { + + final MapPropertiesDelegate propertiesDelegate = new MapPropertiesDelegate(); + + ContainerRequest containerRequest = new ContainerRequest(URI.create("http://test"), + URI.create("http://test/path"), + "POST", + null, + propertiesDelegate); + + containerRequest.setProperty(ContextProperties.CorrelationId.key(), "not correlation id context"); + + final ContextProvider provider = new ContextProvider(containerRequest); + + assertNull(provider.getCorrelationId()); + } +} diff --git a/src/test/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilterTest.java b/src/test/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilterTest.java new file mode 100644 index 0000000..373acf7 --- /dev/null +++ b/src/test/java/io/paradoxical/jersey/extras/filters/CorrelationIdFilterTest.java @@ -0,0 +1,64 @@ +package io.paradoxical.jersey.extras.filters; + + +import io.paradoxical.jersey.extras.WellKnownHeaders; +import org.apache.log4j.MDC; +import org.glassfish.hk2.utilities.binding.AbstractBinder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; + +public class CorrelationIdFilterTest extends JerseyTest { + + @Override + protected Application configure() { + ResourceConfig config = new ResourceConfig(CorrelationIdFilter.class, Resource.class); + return config; + } + + @Test + public void test_no_context() { + final Response response = target().path("test").request().get(); + + assertNotNull(response.getHeaderString(WellKnownHeaders.CorrelationId.headerName())); + } + + @Test + public void test_mdc() { + String corrId = target().path("test").request().get(String.class); + assertNotNull(corrId); + } + + @Test + public void test_header_contains_corrid() { + final String testCorrelationId = "8ef3a75e-cddb-48b6-83d6-d3377e068831"; + + final Response response = + target().path("test") + .request() + .header(WellKnownHeaders.CorrelationId.headerName(), testCorrelationId) + .get(); + + final String value = response.getHeaderString(WellKnownHeaders.CorrelationId.headerName()); + + assertThat(value).isEqualTo(testCorrelationId); + } + + @Path("test") + public static class Resource { + @GET + public String getTest() { + return MDC.get(CorrelationIdFilter.LoggingProperties.CORR_ID) + .toString(); + } + } + +}