killbill-uncached
Changes
payment/src/main/java/org/killbill/billing/payment/dispatcher/CallableWithRequestData.java 44(+44 -0)
pom.xml 2(+1 -1)
Details
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java b/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
index f8c2d67..5a23cab 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
@@ -41,6 +41,7 @@ import org.killbill.billing.payment.api.TransactionStatus;
import org.killbill.billing.payment.dao.PaymentDao;
import org.killbill.billing.payment.dao.PaymentMethodModelDao;
import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
+import org.killbill.billing.payment.dispatcher.CallableWithRequestData;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.dispatcher.PluginDispatcher.PluginDispatcherReturnType;
import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
@@ -56,6 +57,7 @@ import org.killbill.clock.Clock;
import org.killbill.commons.locker.GlobalLock;
import org.killbill.commons.locker.GlobalLocker;
import org.killbill.commons.locker.LockFailedException;
+import org.killbill.commons.request.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/payment/src/main/java/org/killbill/billing/payment/dispatcher/CallableWithRequestData.java b/payment/src/main/java/org/killbill/billing/payment/dispatcher/CallableWithRequestData.java
new file mode 100644
index 0000000..e78d8ad
--- /dev/null
+++ b/payment/src/main/java/org/killbill/billing/payment/dispatcher/CallableWithRequestData.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.payment.dispatcher;
+
+import java.util.concurrent.Callable;
+
+import org.killbill.commons.request.Request;
+import org.killbill.commons.request.RequestData;
+
+public class CallableWithRequestData<T> implements Callable<T> {
+
+ private final RequestData requestData;
+ private final Callable<T> delegate;
+
+ public CallableWithRequestData(final RequestData requestData, final Callable<T> delegate) {
+ this.requestData = requestData;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public T call() throws Exception {
+ try {
+ Request.setPerThreadRequestData(requestData);
+ return delegate.call();
+ } finally {
+ Request.resetPerThreadRequestData();
+ }
+ }
+}
diff --git a/payment/src/main/java/org/killbill/billing/payment/dispatcher/PluginDispatcher.java b/payment/src/main/java/org/killbill/billing/payment/dispatcher/PluginDispatcher.java
index a60eff6..f8b6ca5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dispatcher/PluginDispatcher.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dispatcher/PluginDispatcher.java
@@ -27,6 +27,7 @@ import java.util.concurrent.TimeoutException;
import org.killbill.commons.profiling.Profiling;
import org.killbill.commons.profiling.ProfilingData;
+import org.killbill.commons.request.Request;
public class PluginDispatcher<ReturnType> {
@@ -48,7 +49,10 @@ public class PluginDispatcher<ReturnType> {
public ReturnType dispatchWithTimeout(final Callable<PluginDispatcherReturnType<ReturnType>> task, final long timeout, final TimeUnit unit)
throws TimeoutException, ExecutionException, InterruptedException {
- final Future<PluginDispatcherReturnType<ReturnType>> future = executor.submit(task);
+ // Wrap existing callable to keep the original requestId
+ final Callable<PluginDispatcherReturnType<ReturnType>> callableWithRequestData = new CallableWithRequestData(Request.getPerThreadRequestData(), task);
+
+ final Future<PluginDispatcherReturnType<ReturnType>> future = executor.submit(callableWithRequestData);
final PluginDispatcherReturnType<ReturnType> pluginDispatcherResult = future.get(timeout, unit);
if (pluginDispatcherResult instanceof WithProfilingPluginDispatcherReturnType) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java b/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java
index 0c0b0a7..bd95ba4 100644
--- a/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java
+++ b/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java
@@ -136,8 +136,10 @@ public class PaymentModule extends KillBillModule {
protected void installProcessors(final PaymentConfig paymentConfig) {
- final ExecutorService pluginExecutorService = new WithProfilingThreadPoolExecutor(paymentConfig.getPaymentPluginThreadNb(), paymentConfig.getPaymentPluginThreadNb(),
- 0L, TimeUnit.MILLISECONDS,
+ final ExecutorService pluginExecutorService = new WithProfilingThreadPoolExecutor(paymentConfig.getPaymentPluginThreadNb(),
+ paymentConfig.getPaymentPluginThreadNb(),
+ 0L,
+ TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
new ThreadFactory() {
diff --git a/payment/src/test/java/org/killbill/billing/payment/dispatcher/TestPluginDispatcher.java b/payment/src/test/java/org/killbill/billing/payment/dispatcher/TestPluginDispatcher.java
index d226d73..aef5eec 100644
--- a/payment/src/test/java/org/killbill/billing/payment/dispatcher/TestPluginDispatcher.java
+++ b/payment/src/test/java/org/killbill/billing/payment/dispatcher/TestPluginDispatcher.java
@@ -26,6 +26,8 @@ import org.killbill.billing.ErrorCode;
import org.killbill.billing.payment.PaymentTestSuiteNoDB;
import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.dispatcher.PluginDispatcher.PluginDispatcherReturnType;
+import org.killbill.commons.request.Request;
+import org.killbill.commons.request.RequestData;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -33,6 +35,8 @@ public class TestPluginDispatcher extends PaymentTestSuiteNoDB {
private final PluginDispatcher<Void> voidPluginDispatcher = new PluginDispatcher<Void>(10, Executors.newSingleThreadExecutor());
+ private final PluginDispatcher<String> stringPluginDispatcher = new PluginDispatcher<String>(1, Executors.newSingleThreadExecutor());
+
@Test(groups = "fast")
public void testDispatchWithTimeout() throws TimeoutException, PaymentApiException {
boolean gotIt = false;
@@ -106,4 +110,25 @@ public class TestPluginDispatcher extends PaymentTestSuiteNoDB {
}
Assert.assertTrue(gotIt);
}
+
+
+ @Test(groups = "fast")
+ public void testDispatchWithRequestData() throws TimeoutException, PaymentApiException, ExecutionException, InterruptedException {
+
+ final String requestId = "vive la vie et les coquillettes";
+
+ final Callable<PluginDispatcherReturnType<String>> delegate = new Callable<PluginDispatcherReturnType<String>>() {
+ @Override
+ public PluginDispatcherReturnType<String> call() throws Exception {
+ return PluginDispatcher.<String>createPluginDispatcherReturnType(Request.getPerThreadRequestData().getRequestId());
+ }
+ };
+
+ final CallableWithRequestData<PluginDispatcherReturnType<String>> callable = new CallableWithRequestData<PluginDispatcherReturnType<String>>(new RequestData(requestId),
+ delegate);
+
+ final String actualRequestId = stringPluginDispatcher.dispatchWithTimeout(callable, 100, TimeUnit.MILLISECONDS);
+ Assert.assertEquals(actualRequestId, requestId);
+ }
+
}
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 6b6b458..8deb6da 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
<parent>
<artifactId>killbill-oss-parent</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.37</version>
+ <version>0.38-SNAPSHOT</version>
</parent>
<artifactId>killbill</artifactId>
<version>0.15.3-SNAPSHOT</version>
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/filters/RequestIdFilter.java b/profiles/killbill/src/main/java/org/killbill/billing/server/filters/RequestIdFilter.java
new file mode 100644
index 0000000..3cfe141
--- /dev/null
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/filters/RequestIdFilter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.server.filters;
+
+import java.util.List;
+
+import org.killbill.billing.util.UUIDs;
+import org.killbill.commons.request.Request;
+import org.killbill.commons.request.RequestData;
+
+import com.google.inject.Singleton;
+import com.sun.jersey.spi.container.ContainerRequest;
+import com.sun.jersey.spi.container.ContainerRequestFilter;
+import com.sun.jersey.spi.container.ContainerResponse;
+import com.sun.jersey.spi.container.ContainerResponseFilter;
+
+@Singleton
+public class RequestIdFilter implements ContainerRequestFilter, ContainerResponseFilter {
+
+
+ private static final String REQUEST_ID_HEADER_REQ = "X-Killbill-Request-Id-Req";
+
+ @Override
+ public ContainerRequest filter(final ContainerRequest request) {
+ final List<String> requestIdHeaderRequests = request.getRequestHeader(REQUEST_ID_HEADER_REQ);
+ final String requestId = (requestIdHeaderRequests == null || requestIdHeaderRequests.isEmpty()) ? UUIDs.randomUUID().toString() : requestIdHeaderRequests.get(0);
+ Request.setPerThreadRequestData(new RequestData(requestId));
+ return request;
+ }
+
+ @Override
+ public ContainerResponse filter(final ContainerRequest request, final ContainerResponse response) {
+ Request.resetPerThreadRequestData();
+ return response;
+ }
+}
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/listeners/KillbillGuiceListener.java b/profiles/killbill/src/main/java/org/killbill/billing/server/listeners/KillbillGuiceListener.java
index 6e506da..bca802a 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/listeners/KillbillGuiceListener.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/listeners/KillbillGuiceListener.java
@@ -28,6 +28,7 @@ import org.killbill.billing.jaxrs.util.KillbillEventHandler;
import org.killbill.billing.platform.api.KillbillConfigSource;
import org.killbill.billing.platform.config.DefaultKillbillConfigSource;
import org.killbill.billing.server.filters.ProfilingContainerResponseFilter;
+import org.killbill.billing.server.filters.RequestIdFilter;
import org.killbill.billing.server.filters.ResponseCorsFilter;
import org.killbill.billing.server.modules.KillbillServerModule;
import org.killbill.billing.server.security.TenantFilter;
@@ -73,6 +74,7 @@ public class KillbillGuiceListener extends KillbillPlatformGuiceListener {
// The logging filter is still incompatible with the GZIP filter
//builder.addJerseyFilter(GZIPContentEncodingFilter.class.getName());
builder.addJerseyFilter(ProfilingContainerResponseFilter.class.getName());
+ builder.addJerseyFilter(RequestIdFilter.class.getName());
// Broader, to support the "Try it out!" feature
//builder.addFilter("/" + SWAGGER_PATH + "*", ResponseCorsFilter.class);