Skip to content

Commit

Permalink
11_8_async_servlet
Browse files Browse the repository at this point in the history
  • Loading branch information
JavaWebinar committed Dec 26, 2017
1 parent fc4c538 commit 0237062
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public <T> ActorRef startActor(Class<T> actorClass, String name) {
return system.actorOf(Props.create(actorClass), name);
}

public <T> ActorRef startActor(Props props) {
log.info("Start new AKKA actor");
return system.actorOf(props);
}

public <T> T getTypedRef(Class<T> typedClass, String path) {
log.info("Get typed reference with path={}", path);
return TypedActor.get(system).typedActorOf(new TypedProps<T>(typedClass), system.actorFor(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static MailResult sendTo(Addressee to, String subject, String body, List<Attachm
}

static String sendToGroup(Set<Addressee> to, Set<Addressee> cc, String subject, String body, List<Attachment> attachments) throws WebStateException {
log.info("Send mail to \'" + to + "\' cc \'" + cc + "\' subject \'" + subject + (log.isDebugEnabled() ? "\nbody=" + body : ""));
log.info("Send mail to \'" + to + "\' cc \'" + cc + "\' subject \'" + subject + '\'' + (log.isDebugEnabled() ? "\nbody=" + body : ""));
String state = MailResult.OK;
try {
val email = MailConfig.createHtmlEmail();
Expand Down
14 changes: 14 additions & 0 deletions web/webapp/src/main/java/ru/javaops/masterjava/webapp/WebUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
@Slf4j
public class WebUtil {

public static void doAsync(HttpServletResponse resp, Functions.RunnableEx doer) throws IOException {
resp.setCharacterEncoding("UTF-8");
try {
log.info("Start asynchronous processing");
doer.run();
log.info("Asynchronous processing running ...");
} catch (Exception e) {
log.error("Asynchronous processing failed", e);
String message = e.getMessage();
String result = (message != null) ? message : e.getClass().getName();
resp.getWriter().write(result);
}
}

public static void doAndWriteResponse(HttpServletResponse resp, Functions.SupplierEx<String> doer) throws IOException {
log.info("Start sending");
resp.setCharacterEncoding("UTF-8");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import ru.javaops.masterjava.service.mail.GroupResult;
import ru.javaops.masterjava.service.mail.MailRemoteService;
import ru.javaops.masterjava.service.mail.util.MailUtils.MailObject;
import ru.javaops.masterjava.util.Exceptions;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;

import javax.servlet.AsyncContext;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
Expand All @@ -16,8 +18,7 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static ru.javaops.masterjava.webapp.WebUtil.createMailObject;
import static ru.javaops.masterjava.webapp.WebUtil.doAndWriteResponse;
import static ru.javaops.masterjava.webapp.WebUtil.*;
import static ru.javaops.masterjava.webapp.akka.AkkaWebappListener.akkaActivator;

@WebServlet(value = "/sendAkkaTyped", loadOnStartup = 1, asyncSupported = true)
Expand All @@ -36,13 +37,20 @@ public void init(ServletConfig config) throws ServletException {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
req.setCharacterEncoding("UTF-8");
doAndWriteResponse(resp, () -> sendAkka(createMailObject(req)));
}

private String sendAkka(MailObject mailObject) throws Exception {
scala.concurrent.Future<GroupResult> future = mailService.sendBulk(mailObject);
log.info("Receive future, waiting result ...");
GroupResult groupResult = Await.result(future, Duration.create(10, "seconds"));
return groupResult.toString();
// https://dzone.com/articles/limited-usefulness
doAsync(resp, () -> {
MailObject mailObject = createMailObject(req);

final AsyncContext ac = req.startAsync();
ac.start(Exceptions.<IOException>wrap(() -> {
doAndWriteResponse((HttpServletResponse) ac.getResponse(), () -> {
scala.concurrent.Future<GroupResult> future = mailService.sendBulk(mailObject);
log.info("Receive future, await result ...");
GroupResult groupResult = Await.result(future, Duration.create(10, "seconds"));
return groupResult.toString();
});
ac.complete();
}));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import lombok.extern.slf4j.Slf4j;
import ru.javaops.masterjava.service.mail.GroupResult;
import ru.javaops.masterjava.service.mail.util.MailUtils.MailObject;

import javax.servlet.AsyncContext;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
Expand All @@ -14,41 +16,72 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static ru.javaops.masterjava.webapp.WebUtil.createMailObject;
import static ru.javaops.masterjava.webapp.WebUtil.doAndWriteResponse;
import static ru.javaops.masterjava.webapp.WebUtil.doAsync;
import static ru.javaops.masterjava.webapp.akka.AkkaWebappListener.akkaActivator;

@WebServlet(value = "/sendAkkaUntyped", loadOnStartup = 1)
@WebServlet(value = "/sendAkkaUntyped", loadOnStartup = 1, asyncSupported = true)
@Slf4j
@MultipartConfig
public class AkkaUntypedSendServlet extends HttpServlet {
private ActorRef webappActor;
private ActorRef mailActor;
private ExecutorService executorService;

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
webappActor = akkaActivator.startActor(WebappActor.class, "mail-client");
mailActor = akkaActivator.getActorRef("akka.tcp://[email protected]:2553/user/mail-actor");
executorService = Executors.newFixedThreadPool(8);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
doAndWriteResponse(resp, () -> sendAkka(createMailObject(req)));
public void destroy() {
super.destroy();
if (executorService != null) {
log.info("shutdown");
executorService.shutdown();
try {
if (!executorService.awaitTermination(3, TimeUnit.SECONDS)) {
log.info("shutdownNow");
executorService.shutdownNow();
}
} catch (InterruptedException e) { //nothing
}
}
}

private String sendAkka(MailObject mailObject) {
mailActor.tell(mailObject, webappActor);
return "Successfully sent AKKA message";
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
doAsync(resp, () -> {
MailObject mailObject = createMailObject(req);
final AsyncContext ac = req.startAsync();
executorService.submit(() -> {
ActorRef webappActor = akkaActivator.startActor(Props.create(WebappActor.class, ac));
mailActor.tell(mailObject, webappActor);
});
});
}

public static class WebappActor extends AbstractActor {
private final AsyncContext asyncCtx;

public WebappActor(AsyncContext ac) {
this.asyncCtx = ac;
}

@Override
public Receive createReceive() {
return receiveBuilder().match(GroupResult.class,
groupResult -> log.info(groupResult.toString()))
groupResult -> {
log.info("Receive result form mailActor");
asyncCtx.getResponse().getWriter().write(groupResult.toString());
asyncCtx.complete();
})
.build();
}
}
Expand Down

0 comments on commit 0237062

Please sign in to comment.