package net.sourceforge.stripes.examples.async;
import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.controller.AsyncResponse;
import net.sourceforge.stripes.examples.bugzooky.ext.Public;
import net.sourceforge.stripes.validation.Validate;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
@Public
@UrlBinding("/async")
public class AsyncActionBean implements ActionBean {
private static final String JSP_PATH = "/WEB-INF/async/async.jsp";
private ActionBeanContext context;
public ActionBeanContext getContext() {
return context;
}
public void setContext(ActionBeanContext context) {
this.context = context;
}
// property to test binding/validation
@Validate(required = true)
private String someProp;
// those are set by the http client response, and
// used in the JSP...
private Exception clientException;
private boolean cancelled;
private int status;
private String ghResponse;
// display the test page
@DefaultHandler
@DontValidate
public Resolution display() {
return new ForwardResolution("/WEB-INF/async/async.jsp");
}
/**
* asynchronously fetch data from a remote web service (github)
* and set instance fields for use in the view.
*/
public void asyncEvent(final AsyncResponse async) {
// we use an Async Http Client in order to call the github web service as a demo.
// the async http client calls back one of the lambdas when it's done, and
// then we complete the async request.
final Resolution forwardResolution = new ForwardResolution(JSP_PATH);
HttpHost host = new HttpHost("api.github.com", 443, "https");
new AsyncHttpClient(host)
.buildRequest("/repos/StripesFramework/stripes/commits")
.completed(new AsyncHttpClient.Consumer<HttpResponse>() {
@Override
public void accept(HttpResponse result) {
// response is returned, deserialize result
status = result.getStatusLine().getStatusCode();
if (status == 200) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
result.getEntity().writeTo(bos);
bos.close();
ghResponse = bos.toString("UTF-8");
} catch (Exception e) {
clientException = e;
}
async.complete(forwardResolution);
} else {
ghResponse = result.getStatusLine().getReasonPhrase();
async.complete(forwardResolution);
}
}
})
.failed(new AsyncHttpClient.Consumer<Exception>() {
@Override
public void accept(Exception e) {
// http client failure
clientException = e;
async.complete(forwardResolution);
}
})
.cancelled(new Runnable() {
@Override
public void run() {
// just for demo, we never call it...
cancelled = true;
async.complete(forwardResolution);
}
}).get(); // trigger async request
}
@DontValidate
public void asyncEventThatTimeouts(AsyncResponse r) throws Exception {
r.setTimeout(1000);
r.getResponse().getWriter().write("OK");
// never call complete/dispatch...
}
@DontValidate
public void asyncEventThatThrows(AsyncResponse r) {
throw new RuntimeException("BOOM");
}
@DontValidate
public void asyncWrites(final AsyncResponse r) {
final String[] parts = new String[]{
"This", "is", "asynchronously", "written", "!",
"We", "use", "readystatechange", "in",
"order", "to", "be", "notified", "when", "the",
"server", "pushes", "some", "data"
};
new Thread(new Runnable() {
@Override
public void run() {
boolean error = false;
try {
PrintWriter w = r.getResponse().getWriter();
for (int i = 0; i < parts.length; i++) {
w.println("<div class=\"asyncWrite\">" + parts[i] + "</div>");
w.flush();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// don't care
}
}
} catch (IOException e) {
error = true;
r.complete(new ErrorResolution(500, e.getMessage()));
}
if (!error) {
r.complete(new StreamingResolution("text/plain", "<em>Bye</em>"));
}
}
}).start();
}
// getters for instance fields that have been set by event method
public boolean isCancelled() {
return cancelled;
}
public int getStatus() {
return status;
}
public String getGhResponse() {
return ghResponse;
}
public Exception getClientException() {
return clientException;
}
// get/set for test binding prop
public String getSomeProp() {
return someProp;
}
public void setSomeProp(String someProp) {
this.someProp = someProp;
}
}