diff --git a/src/org/redkale/net/http/Rest.java b/src/org/redkale/net/http/Rest.java index 74936fa8f..fb779843c 100644 --- a/src/org/redkale/net/http/Rest.java +++ b/src/org/redkale/net/http/Rest.java @@ -111,6 +111,8 @@ public final class Rest { if (!java.lang.reflect.Modifier.isPublic(mod)) return null; if (java.lang.reflect.Modifier.isAbstract(mod)) return null; + final java.lang.reflect.Type futureRestOutputType = new TypeToken>() { + }.getType(); final String serviceDesc = Type.getDescriptor(serviceType); final String webServletDesc = Type.getDescriptor(WebServlet.class); final String reqDesc = Type.getDescriptor(HttpRequest.class); @@ -259,6 +261,7 @@ public final class Rest { for (final MappingEntry entry : entrys) { final Method method = entry.mappingMethod; final Class returnType = method.getReturnType(); + final java.lang.reflect.Type returnGenericType = method.getGenericReturnType(); final String methodDesc = Type.getMethodDescriptor(method); final Parameter[] params = method.getParameters(); @@ -925,6 +928,14 @@ public final class Rest { mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false); mv.visitInsn(RETURN); maxLocals++; + } else if (futureRestOutputType == returnGenericType) { + mv.visitVarInsn(ASTORE, maxLocals); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, maxLocals); + mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "finishJson", "(" + respDesc + futureDesc + ")V", false); + mv.visitInsn(RETURN); + maxLocals++; } else if (CompletableFuture.class.isAssignableFrom(returnType)) { mv.visitVarInsn(ASTORE, maxLocals); mv.visitVarInsn(ALOAD, 2);//response diff --git a/src/org/redkale/net/http/RestHttpServlet.java b/src/org/redkale/net/http/RestHttpServlet.java index 2c6d1a0ad..05f657a12 100644 --- a/src/org/redkale/net/http/RestHttpServlet.java +++ b/src/org/redkale/net/http/RestHttpServlet.java @@ -6,7 +6,8 @@ package org.redkale.net.http; import java.io.*; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.*; +import java.util.logging.Level; import jdk.internal.org.objectweb.asm.*; import static jdk.internal.org.objectweb.asm.Opcodes.*; import org.redkale.util.*; @@ -22,6 +23,22 @@ public abstract class RestHttpServlet extends HttpBaseServlet { protected abstract T currentUser(HttpRequest req) throws IOException; + protected void finishJson(final HttpResponse response, CompletableFuture future) throws IOException { + future.whenCompleteAsync((output, e) -> { + if (e != null) { + response.getContext().getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + response.getRequest(), e); + response.finish(500, null); + return; + } + try { + finishJson(response, output); + } catch (IOException ioe) { + response.getContext().getLogger().log(Level.WARNING, "Servlet finish RestOutput occur, forece to close channel. request = " + response.getRequest(), ioe); + response.finish(500, null); + } + }, response.getContext().getExecutor()); + } + protected void finishJson(final HttpResponse response, RestOutput output) throws IOException { if (output == null) { response.finishJson(output);