killbill-memoizeit

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
index 9d67da0..64870ae 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
@@ -360,9 +360,9 @@ public class InvoiceResource extends JaxRsResourceBase {
         final CallContext callContext = context.createCallContextWithAccountId(accountId, createdBy, reason, comment, request);
         final LocalDate inputDate;
         if (dryRunSubscriptionSpec != null) {
-            if (DryRunType.UPCOMING_INVOICE.name().equals(dryRunSubscriptionSpec.getDryRunType())) {
+            if (DryRunType.UPCOMING_INVOICE.equals(dryRunSubscriptionSpec.getDryRunType())) {
                 inputDate = null;
-            } else if (DryRunType.SUBSCRIPTION_ACTION.name().equals(dryRunSubscriptionSpec.getDryRunType()) && dryRunSubscriptionSpec.getEffectiveDate() != null) {
+            } else if (DryRunType.SUBSCRIPTION_ACTION.equals(dryRunSubscriptionSpec.getDryRunType()) && dryRunSubscriptionSpec.getEffectiveDate() != null) {
                 inputDate = dryRunSubscriptionSpec.getEffectiveDate();
             } else {
                 inputDate = toLocalDate(targetDate);
@@ -374,18 +374,18 @@ public class InvoiceResource extends JaxRsResourceBase {
         // Passing a null or empty body means we are trying to generate an invoice with a (future) targetDate
         // On the other hand if body is not null, we are attempting a dryRun subscription operation
         if (dryRunSubscriptionSpec != null && dryRunSubscriptionSpec.getDryRunAction() != null) {
-            if (SubscriptionEventType.START_BILLING.toString().equals(dryRunSubscriptionSpec.getDryRunAction())) {
+            if (SubscriptionEventType.START_BILLING.equals(dryRunSubscriptionSpec.getDryRunAction())) {
                 verifyNonNullOrEmpty(dryRunSubscriptionSpec.getProductName(), "DryRun subscription product category should be specified");
                 verifyNonNullOrEmpty(dryRunSubscriptionSpec.getBillingPeriod(), "DryRun subscription billingPeriod should be specified");
                 verifyNonNullOrEmpty(dryRunSubscriptionSpec.getProductCategory(), "DryRun subscription product category should be specified");
                 if (dryRunSubscriptionSpec.getProductCategory().equals(ProductCategory.ADD_ON)) {
                     verifyNonNullOrEmpty(dryRunSubscriptionSpec.getBundleId(), "DryRun bundle ID should be specified");
                 }
-            } else if (SubscriptionEventType.CHANGE.toString().equals(dryRunSubscriptionSpec.getDryRunAction())) {
+            } else if (SubscriptionEventType.CHANGE.equals(dryRunSubscriptionSpec.getDryRunAction())) {
                 verifyNonNullOrEmpty(dryRunSubscriptionSpec.getProductName(), "DryRun subscription product category should be specified");
                 verifyNonNullOrEmpty(dryRunSubscriptionSpec.getBillingPeriod(), "DryRun subscription billingPeriod should be specified");
                 verifyNonNullOrEmpty(dryRunSubscriptionSpec.getSubscriptionId(), "DryRun subscriptionID should be specified");
-            } else if (SubscriptionEventType.STOP_BILLING.toString().equals(dryRunSubscriptionSpec.getDryRunAction())) {
+            } else if (SubscriptionEventType.STOP_BILLING.equals(dryRunSubscriptionSpec.getDryRunAction())) {
                 verifyNonNullOrEmpty(dryRunSubscriptionSpec.getSubscriptionId(), "DryRun subscriptionID should be specified");
             }
         }
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PluginResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PluginResource.java
index 27bf057..5a14c1e 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PluginResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PluginResource.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 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
@@ -35,6 +35,9 @@ import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.WriteListener;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
@@ -184,17 +187,40 @@ public class PluginResource extends JaxRsResourceBase {
                                           final HttpServletResponse response, final ServletContext servletContext,
                                           final ServletConfig servletConfig, final UriInfo uriInfo) throws ServletException, IOException {
         prepareOSGIRequest(request, servletContext, servletConfig);
-        osgiServlet.service(new OSGIServletRequestWrapper(request, inputStream, formData, uriInfo.getQueryParameters()), new OSGIServletResponseWrapper(response));
 
-        if (response.isCommitted()) {
-            if (response.getStatus() >= 400) {
-                log.warn("{} responded {}", request.getPathInfo(), response.getStatus());
-            }
-            // Jersey will want to return 204, but the servlet should have done the right thing already
-            return null;
-        } else {
-            return Response.status(response.getStatus()).build();
+        final ServletRequest req = new OSGIServletRequestWrapper(request, inputStream, formData, uriInfo.getQueryParameters());
+
+        // The real ServletOutputStream is a HttpOutput, which we don't want to give to plugins.
+        // Jooby for instance would commit the underlying HTTP channel (via ServletServletResponse#send),
+        // meaning that any further headers (e.g. Profiling) that we would add would not be returned.
+        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        final OSGIServletResponseWrapper res = new OSGIServletResponseWrapper(response,
+                                                                              new ServletOutputStream() {
+                                                                                  @Override
+                                                                                  public boolean isReady() {
+                                                                                      return true;
+                                                                                  }
+
+                                                                                  @Override
+                                                                                  public void setWriteListener(final WriteListener writeListener) {
+                                                                                      throw new UnsupportedOperationException();
+                                                                                  }
+
+                                                                                  @Override
+                                                                                  public void write(final int b) throws IOException {
+                                                                                      byteArrayOutputStream.write(b);
+                                                                                  }
+                                                                              });
+
+        osgiServlet.service(req, res);
+
+        if (response.getStatus() >= 400) {
+            log.warn("{} responded {}", request.getPathInfo(), response.getStatus());
         }
+
+        return Response.status(response.getStatus())
+                       .entity(new String(byteArrayOutputStream.toByteArray()))
+                       .build();
     }
 
     private InputStream createInputStream(final HttpServletRequest request, final MultivaluedMap<String, String> form) throws IOException {
@@ -346,8 +372,16 @@ public class PluginResource extends JaxRsResourceBase {
 
     private static final class OSGIServletResponseWrapper extends HttpServletResponseWrapper {
 
-        public OSGIServletResponseWrapper(final HttpServletResponse response) {
+        private final ServletOutputStream servletOutputStream;
+
+        public OSGIServletResponseWrapper(final HttpServletResponse response, final ServletOutputStream servletOutputStream) {
             super(response);
+            this.servletOutputStream = servletOutputStream;
+        }
+
+        @Override
+        public ServletOutputStream getOutputStream() throws IOException {
+            return servletOutputStream;
         }
     }
 }