diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/core/BaseComponents.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/BaseComponents.java index 75fdaf889..7fdac1ff7 100644 --- a/vraptor-core/src/main/java/br/com/caelum/vraptor/core/BaseComponents.java +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/BaseComponents.java @@ -83,6 +83,7 @@ import br.com.caelum.vraptor.http.ParameterNameProvider; import br.com.caelum.vraptor.http.ParametersProvider; import br.com.caelum.vraptor.http.ParanamerNameProvider; +import br.com.caelum.vraptor.http.LateResponseCommitHandler; import br.com.caelum.vraptor.http.UrlToResourceTranslator; import br.com.caelum.vraptor.http.iogi.InstantiatorWithErrors; import br.com.caelum.vraptor.http.iogi.IogiParametersProvider; @@ -278,7 +279,8 @@ ProxyInitializer.class, getProxyInitializerImpl() RestHeadersHandler.class, DefaultRestHeadersHandler.class, FlashScope.class, SessionFlashScope.class, XStreamConverters.class, XStreamConverters.class, - MessageConverter.class, MessageConverter.class + MessageConverter.class, MessageConverter.class, + LateResponseCommitHandler.class, LateResponseCommitHandler.class ); @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/core/EnhancedRequestExecution.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/EnhancedRequestExecution.java index dec09ce3d..ca73ddc9b 100644 --- a/vraptor-core/src/main/java/br/com/caelum/vraptor/core/EnhancedRequestExecution.java +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/core/EnhancedRequestExecution.java @@ -15,7 +15,10 @@ */ package br.com.caelum.vraptor.core; +import java.io.IOException; + import br.com.caelum.vraptor.VRaptorException; +import br.com.caelum.vraptor.http.LateResponseCommitHandler; import br.com.caelum.vraptor.interceptor.Interceptor; import br.com.caelum.vraptor.interceptor.InterceptorRegistry; import br.com.caelum.vraptor.ioc.PrototypeScoped; @@ -31,17 +34,26 @@ public class EnhancedRequestExecution implements RequestExecution { private final InterceptorRegistry registry; private final InterceptorStack stack; + private final LateResponseCommitHandler responseHandler; - public EnhancedRequestExecution(InterceptorStack stack, InterceptorRegistry registry) { - this.stack = stack; + public EnhancedRequestExecution(InterceptorRegistry registry, InterceptorStack stack, + LateResponseCommitHandler responseHandler) { this.registry = registry; + this.stack = stack; + this.responseHandler = responseHandler; } + public void execute() throws VRaptorException { for (Class interceptor : registry.all()) { stack.add(interceptor); } stack.next(null, null); + try { + responseHandler.commit(); + } catch (IOException e) { + throw new VRaptorException("IO error when commiting the response", e); + } } } diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/http/LateResponseCommitHandler.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/http/LateResponseCommitHandler.java new file mode 100644 index 000000000..6fb74a483 --- /dev/null +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/http/LateResponseCommitHandler.java @@ -0,0 +1,46 @@ +package br.com.caelum.vraptor.http; + +import static com.google.common.base.Preconditions.checkState; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletResponse; + +import br.com.caelum.vraptor.ioc.Component; + +@Component +public class LateResponseCommitHandler { + + private final HttpServletResponse response; + + private ByteArrayOutputStream stream; + private PrintWriter writer; + + public LateResponseCommitHandler(HttpServletResponse response) { + this.response = response; + } + + public void commit() throws IOException { + if (stream != null) { + writer.flush(); + if (stream.size() > 0) { + stream.writeTo(response.getOutputStream()); + writer.close(); + } + } + } + + public void writeJson(String data) { + write(data); + response.setContentType("application/json"); + } + + private void write(String data) { + checkState(stream == null, "response data was already wrote"); + stream = new ByteArrayOutputStream(response.getBufferSize()); + writer = new PrintWriter(stream); + writer.write(data); + } +} diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonJSONSerialization.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonJSONSerialization.java index 00cf52776..b9149355f 100644 --- a/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonJSONSerialization.java +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonJSONSerialization.java @@ -15,10 +15,7 @@ */ package br.com.caelum.vraptor.serialization.gson; -import java.io.IOException; - -import javax.servlet.http.HttpServletResponse; - +import br.com.caelum.vraptor.http.LateResponseCommitHandler; import br.com.caelum.vraptor.interceptor.TypeNameExtractor; import br.com.caelum.vraptor.ioc.Component; import br.com.caelum.vraptor.serialization.JSONSerialization; @@ -27,7 +24,6 @@ import br.com.caelum.vraptor.serialization.Serializer; import br.com.caelum.vraptor.serialization.SerializerBuilder; import br.com.caelum.vraptor.serialization.xstream.Serializee; -import br.com.caelum.vraptor.view.ResultException; /** * Gson implementation for JSONSerialization @@ -39,7 +35,7 @@ @Component public class GsonJSONSerialization implements JSONSerialization { - protected final HttpServletResponse response; + protected final LateResponseCommitHandler responseHandler; protected final TypeNameExtractor extractor; @@ -49,9 +45,9 @@ public class GsonJSONSerialization implements JSONSerialization { protected final Serializee serializee; - public GsonJSONSerialization(HttpServletResponse response, TypeNameExtractor extractor, + public GsonJSONSerialization(LateResponseCommitHandler responseHandler, TypeNameExtractor extractor, ProxyInitializer initializer, VRaptorGsonBuilder builder, Serializee serializee) { - this.response = response; + this.responseHandler = responseHandler; this.extractor = extractor; this.initializer = initializer; @@ -68,16 +64,11 @@ public Serializer from(T object) { } public Serializer from(T object, String alias) { - response.setContentType("application/json"); return getSerializer().from(object, alias); } protected SerializerBuilder getSerializer() { - try { - return new GsonSerializer(builder, response.getWriter(), extractor, initializer, serializee); - } catch (IOException e) { - throw new ResultException("Unable to serialize data", e); - } + return new GsonSerializer(builder, responseHandler, extractor, initializer, serializee); } /** diff --git a/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonSerializer.java b/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonSerializer.java index 5da839c25..3e03c3c20 100644 --- a/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonSerializer.java +++ b/vraptor-core/src/main/java/br/com/caelum/vraptor/serialization/gson/GsonSerializer.java @@ -17,8 +17,6 @@ import static com.google.common.base.Preconditions.checkNotNull; -import java.io.IOException; -import java.io.Writer; import java.util.Calendar; import java.util.Collection; import java.util.Date; @@ -28,6 +26,7 @@ import java.util.Map; import java.util.Set; +import br.com.caelum.vraptor.http.LateResponseCommitHandler; import br.com.caelum.vraptor.interceptor.TypeNameExtractor; import br.com.caelum.vraptor.serialization.ProxyInitializer; import br.com.caelum.vraptor.serialization.Serializer; @@ -45,7 +44,7 @@ public class GsonSerializer implements SerializerBuilder { - private final Writer writer; + private final LateResponseCommitHandler responseHandler; private final TypeNameExtractor extractor; @@ -55,9 +54,9 @@ public class GsonSerializer implements SerializerBuilder { protected VRaptorGsonBuilder builder; - public GsonSerializer(VRaptorGsonBuilder builder, Writer writer, TypeNameExtractor extractor, + public GsonSerializer(VRaptorGsonBuilder builder, LateResponseCommitHandler responseHandler, TypeNameExtractor extractor, ProxyInitializer initializer, Serializee serializee) { - this.writer = writer; + this.responseHandler = responseHandler; this.extractor = extractor; this.initializer = initializer; this.builder = builder; @@ -135,7 +134,6 @@ public Serializer include(String... fields) { } public void serialize() { - try { Object root = serializee.getRoot(); builder.setExclusionStrategies(new Exclusions(serializee)); @@ -144,15 +142,12 @@ public void serialize() { String alias = builder.getAlias(); if (builder.isWithoutRoot()) { - writer.write(gson.toJson(root)); + responseHandler.writeJson(gson.toJson(root)); } else { Map tree = new HashMap(); tree.put(alias, root); - writer.write(gson.toJson(tree)); + responseHandler.writeJson(gson.toJson(tree)); } - } catch (IOException e) { - throw new RuntimeException("Não pode serializar", e); - } } public Serializer recursive() {