From 95fdf5164038e40946789d705e2b64522254fa86 Mon Sep 17 00:00:00 2001
From: Remi Vankeisbelck
Date: Mon, 18 Jan 2016 18:34:49 +0100
Subject: [PATCH] #37 : added AsyncResolution.complete(Resolution) method that
allows for reuse of Resolution classes. As the name says, completes the async
processing. You cannot use several Resolutions when async processing.
---
.../stripes/action/AsyncResolution.java | 12 ++++++++++
.../stripes/action/ForwardResolution.java | 24 ++++++++++++-------
.../stripes/action/JsonResolution.java | 3 +++
.../stripes/action/RedirectResolution.java | 4 ++++
.../stripes/action/StreamingResolution.java | 4 ++++
.../ValidationErrorReportResolution.java | 4 ++++
.../stripes/ajax/JavaScriptResolution.java | 3 +++
.../stripes/mock/MockAsyncContext.java | 15 ++++++++++--
.../stripes/mock/TestMockAsync.java | 21 ++++++++++++++++
9 files changed, 80 insertions(+), 10 deletions(-)
diff --git a/stripes/src/main/java/net/sourceforge/stripes/action/AsyncResolution.java b/stripes/src/main/java/net/sourceforge/stripes/action/AsyncResolution.java
index c050b9aaf..c836e4e39 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/action/AsyncResolution.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/action/AsyncResolution.java
@@ -3,6 +3,8 @@
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
public abstract class AsyncResolution implements Resolution {
@@ -53,4 +55,14 @@ protected void dispatch(String path) {
protected void complete() {
getAsyncContext().complete();
}
+
+ protected void complete(Resolution resolution) {
+ try {
+ resolution.execute(getRequest(), getResponse());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
}
diff --git a/stripes/src/main/java/net/sourceforge/stripes/action/ForwardResolution.java b/stripes/src/main/java/net/sourceforge/stripes/action/ForwardResolution.java
index 28cf1d101..305729c43 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/action/ForwardResolution.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/action/ForwardResolution.java
@@ -144,16 +144,24 @@ public void execute(HttpServletRequest request, HttpServletResponse response)
String oldEvent = (String) request.getAttribute(StripesConstants.REQ_ATTR_EVENT_NAME);
request.setAttribute(StripesConstants.REQ_ATTR_EVENT_NAME, event);
- // Figure out if we're inside an include, and use an include instead of a forward
- if (autoInclude && request.getAttribute(StripesConstants.REQ_ATTR_INCLUDE_PATH) != null) {
- log.trace("Including URL: ", path);
- request.getRequestDispatcher(path).include(request, response);
+ // are we asynchronous ?
+ if (request.isAsyncStarted()) {
+ // async started, dispatch...
+ log.trace("Async mode, dispatching to URL: ", path);
+ request.getAsyncContext().dispatch(path);
} else {
- log.trace("Forwarding to URL: ", path);
- request.getRequestDispatcher(path).forward(request, response);
+ // Figure out if we're inside an include, and use an include instead of a forward
+ if (autoInclude && request.getAttribute(StripesConstants.REQ_ATTR_INCLUDE_PATH) != null) {
+ log.trace("Including URL: ", path);
+ request.getRequestDispatcher(path).include(request, response);
+ } else {
+ log.trace("Forwarding to URL: ", path);
+ request.getRequestDispatcher(path).forward(request, response);
+ }
+
+ // Revert event name to its original value
+ request.setAttribute(StripesConstants.REQ_ATTR_EVENT_NAME, oldEvent);
}
- // Revert event name to its original value
- request.setAttribute(StripesConstants.REQ_ATTR_EVENT_NAME, oldEvent);
}
}
diff --git a/stripes/src/main/java/net/sourceforge/stripes/action/JsonResolution.java b/stripes/src/main/java/net/sourceforge/stripes/action/JsonResolution.java
index 55f37269d..2ff59413a 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/action/JsonResolution.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/action/JsonResolution.java
@@ -46,5 +46,8 @@ public void execute(HttpServletRequest request, HttpServletResponse response) th
response.setContentType("application/json");
builder.build(response.getWriter());
response.flushBuffer();
+ if (request.isAsyncStarted()) {
+ request.getAsyncContext().complete();
+ }
}
}
diff --git a/stripes/src/main/java/net/sourceforge/stripes/action/RedirectResolution.java b/stripes/src/main/java/net/sourceforge/stripes/action/RedirectResolution.java
index c361123f9..b90182282 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/action/RedirectResolution.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/action/RedirectResolution.java
@@ -222,6 +222,10 @@ public void sendRedirect(String location) throws IOException {
log.trace("Redirecting ", this.beans == null ? "" : "(w/flashed bean) ", "to URL: ", url);
response.sendRedirect(url);
+
+ if (request.isAsyncStarted()) {
+ request.getAsyncContext().complete();
+ }
}
/**
diff --git a/stripes/src/main/java/net/sourceforge/stripes/action/StreamingResolution.java b/stripes/src/main/java/net/sourceforge/stripes/action/StreamingResolution.java
index 27a0ffe14..994cc0c23 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/action/StreamingResolution.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/action/StreamingResolution.java
@@ -238,6 +238,10 @@ final public void execute(HttpServletRequest request, HttpServletResponse respon
applyHeaders(response);
stream(response);
+
+ if (request.isAsyncStarted()) {
+ request.getAsyncContext().complete();
+ }
}
/**
diff --git a/stripes/src/main/java/net/sourceforge/stripes/action/ValidationErrorReportResolution.java b/stripes/src/main/java/net/sourceforge/stripes/action/ValidationErrorReportResolution.java
index 37c0144f6..5f5a6f8c9 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/action/ValidationErrorReportResolution.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/action/ValidationErrorReportResolution.java
@@ -65,6 +65,10 @@ public void execute(HttpServletRequest request, HttpServletResponse response) th
writer.println("
Validation errors
");
sendErrors(request, response);
writer.println("
");
+
+ if (request.isAsyncStarted()) {
+ request.getAsyncContext().complete();
+ }
}
/**
diff --git a/stripes/src/main/java/net/sourceforge/stripes/ajax/JavaScriptResolution.java b/stripes/src/main/java/net/sourceforge/stripes/ajax/JavaScriptResolution.java
index aeded5223..422ea151c 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/ajax/JavaScriptResolution.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/ajax/JavaScriptResolution.java
@@ -74,5 +74,8 @@ public void execute(HttpServletRequest request, HttpServletResponse response) th
response.setContentType("text/javascript");
this.builder.build(response.getWriter());
response.flushBuffer();
+ if (request.isAsyncStarted()) {
+ request.getAsyncContext().complete();
+ }
}
}
diff --git a/stripes/src/main/java/net/sourceforge/stripes/mock/MockAsyncContext.java b/stripes/src/main/java/net/sourceforge/stripes/mock/MockAsyncContext.java
index 747d1ae4d..7a4bbdf5b 100644
--- a/stripes/src/main/java/net/sourceforge/stripes/mock/MockAsyncContext.java
+++ b/stripes/src/main/java/net/sourceforge/stripes/mock/MockAsyncContext.java
@@ -6,7 +6,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.ExecutorService;
public class MockAsyncContext implements AsyncContext {
@@ -18,7 +17,7 @@ public class MockAsyncContext implements AsyncContext {
private boolean completed = false;
private boolean timedOut = false;
- private long timeout = 30000;
+ private long timeout = 5000;
private long startedOn;
public MockAsyncContext(ServletRequest request, ServletResponse response) {
@@ -136,4 +135,16 @@ public void waitForCompletion() throws Exception {
Thread.sleep(200);
}
}
+
+ public long getStartedOn() {
+ return startedOn;
+ }
+
+ public boolean isTimedOut() {
+ return timedOut;
+ }
+
+ public boolean isCompleted() {
+ return completed;
+ }
}
diff --git a/stripes/src/test/java/net/sourceforge/stripes/mock/TestMockAsync.java b/stripes/src/test/java/net/sourceforge/stripes/mock/TestMockAsync.java
index 5339b011e..3920b1d9e 100644
--- a/stripes/src/test/java/net/sourceforge/stripes/mock/TestMockAsync.java
+++ b/stripes/src/test/java/net/sourceforge/stripes/mock/TestMockAsync.java
@@ -73,10 +73,19 @@ public void testAsyncException() throws Exception {
assertTrue(caught);
}
+ @Test
+ public void testCompleteWithForwardResolution() throws Exception {
+ MockRoundtrip trip = new MockRoundtrip(getMockServletContext(), AsyncActionBean.class);
+ trip.execute("doAsyncAndCompleteWithForwardResolution");
+ AsyncActionBean bean = trip.getActionBean(AsyncActionBean.class);
+ assertNotNull(bean);
+ }
+
@UrlBinding("/async")
public static class AsyncActionBean implements ActionBean {
private boolean completed = false;
+ private boolean executedForwardResolution;
private ActionBeanContext context;
public ActionBeanContext getContext() {
@@ -142,9 +151,21 @@ protected void executeAsync() throws Exception {
};
}
+ public Resolution doAsyncAndCompleteWithForwardResolution() {
+ return new AsyncResolution() {
+ @Override
+ protected void executeAsync() throws Exception {
+ System.out.println("hiya, I'm forwarding...");
+ complete(new ForwardResolution("/foo/bar.jsp"));
+ }
+ };
+ }
+
+
public boolean isCompleted() {
return completed;
}
+
}