Created
March 15, 2016 11:33
-
-
Save serac/211c65de13eec4914cf0 to your computer and use it in GitHub Desktop.
Recipe for Logging Rendered Velocity Template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* See LICENSE for licensing and NOTICE for copyright. */ | |
| package edu.vt.middleware.ed.ws.soap.mvc; | |
| import java.io.Writer; | |
| import java.lang.reflect.Constructor; | |
| import javax.servlet.http.HttpServletResponse; | |
| import org.apache.velocity.Template; | |
| import org.apache.velocity.context.Context; | |
| import org.apache.velocity.exception.MethodInvocationException; | |
| import org.springframework.web.servlet.view.velocity.VelocityView; | |
| import org.springframework.web.util.NestedServletException; | |
| /** | |
| * Velocity view that allows setting the {@link java.io.Writer} class used to render the template. | |
| * | |
| * @author Middleware Services | |
| */ | |
| public class ConfigurableVelocityView extends VelocityView | |
| { | |
| /** Writer class. */ | |
| private Class<? extends Writer> writerClass; | |
| /** | |
| * Sets the {@link java.io.Writer} class used to render the Velocity template. | |
| * | |
| * @param clazz Writer class whose constructor takes exactly one argument, the {@link | |
| * javax.servlet.http.HttpServletResponse#getWriter()} to wrap. | |
| */ | |
| public void setWriterClass(final Class<? extends Writer> clazz) | |
| { | |
| writerClass = clazz; | |
| } | |
| @Override | |
| protected void mergeTemplate(final Template template, final Context context, final HttpServletResponse response) | |
| throws Exception | |
| { | |
| final Writer writer = newWriter(response.getWriter()); | |
| try { | |
| template.merge(context, writer); | |
| } catch (MethodInvocationException ex) { | |
| final Throwable cause = ex.getWrappedThrowable(); | |
| throw new NestedServletException( | |
| "Method invocation failed during rendering of Velocity view named '" + getBeanName() + "': " + ex.getMessage() + | |
| "; reference [" + ex.getReferenceName() + "], method '" + ex.getMethodName() + "'", | |
| cause == null ? ex : cause); | |
| } finally { | |
| writer.flush(); | |
| } | |
| } | |
| /** | |
| * Creates a new instance of the configured writer class. | |
| * | |
| * @param wrapped Writer to wrap. | |
| * | |
| * @return New wrapped writer instance. | |
| * | |
| * @throws Exception On errors creating the writer. | |
| */ | |
| private Writer newWriter(final Writer wrapped) | |
| throws Exception | |
| { | |
| if (writerClass == null) { | |
| return wrapped; | |
| } | |
| final Constructor<? extends Writer> constructor = writerClass.getConstructor(Writer.class); | |
| return constructor.newInstance(wrapped); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* See LICENSE for licensing and NOTICE for copyright. */ | |
| package edu.vt.middleware.ed.ws.soap.mvc; | |
| import java.io.Writer; | |
| import org.springframework.web.servlet.view.AbstractTemplateViewResolver; | |
| /** | |
| * View resolver for use with {@link ConfigurableVelocityView}. | |
| * | |
| * @author Middleware Services | |
| */ | |
| public class ConfigurableVelocityViewResolver extends AbstractTemplateViewResolver | |
| { | |
| /** Writer class. */ | |
| private final Class<? extends Writer> writerClass; | |
| /** Creates a new instance. */ | |
| public ConfigurableVelocityViewResolver() | |
| { | |
| this(null); | |
| } | |
| /** | |
| * Creates a new instance that uses the given writer class for rendering the Velocity template. | |
| * | |
| * @param clazz Writer class whose constructor takes exactly one argument, the {@link | |
| * javax.servlet.http.HttpServletResponse#getWriter()} to wrap. | |
| */ | |
| public ConfigurableVelocityViewResolver(final Class<? extends Writer> clazz) | |
| { | |
| writerClass = clazz; | |
| setViewClass(requiredViewClass()); | |
| } | |
| /** @return <code>XmlStripVelocityView.class.</code> */ | |
| @Override | |
| protected Class requiredViewClass() | |
| { | |
| return ConfigurableVelocityView.class; | |
| } | |
| @Override | |
| protected ConfigurableVelocityView buildView(final String viewName) | |
| throws Exception | |
| { | |
| final ConfigurableVelocityView view = (ConfigurableVelocityView) super.buildView(viewName); | |
| view.setWriterClass(writerClass); | |
| return view; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* See LICENSE for licensing and NOTICE for copyright. */ | |
| package edu.vt.middleware.ed.ws.soap.mvc; | |
| import java.io.FilterWriter; | |
| import java.io.IOException; | |
| import java.io.Writer; | |
| import java.nio.CharBuffer; | |
| import edu.vt.middleware.ed.util.logging.Logger; | |
| import edu.vt.middleware.ed.util.logging.LoggerFactory; | |
| /** | |
| * Buffers data passed to <code>write</code> methods and writes the data to DEBUG logger on {@link #flush()}. | |
| * | |
| * @author Middleware Services | |
| */ | |
| public class LoggingWriter extends FilterWriter | |
| { | |
| /** Logger instance. */ | |
| private final Logger logger = LoggerFactory.getLogger(LoggingWriter.class); | |
| /** Output buffer. */ | |
| private CharBuffer buffer; | |
| /** | |
| * Create a new instance around the given writer. | |
| * | |
| * @param out a Writer object to provide the underlying stream. | |
| */ | |
| public LoggingWriter(final Writer out) | |
| { | |
| super(out); | |
| if (logger.isDebugEnabled()) { | |
| buffer = CharBuffer.allocate(2048); | |
| } | |
| } | |
| @Override | |
| public void write(final int c) | |
| throws IOException | |
| { | |
| if (buffer != null) { | |
| if (!buffer.hasRemaining()) { | |
| growBuffer(); | |
| } | |
| buffer.put((char) c); | |
| } | |
| super.write(c); | |
| } | |
| @Override | |
| public void write(final char[] cbuf, final int off, final int len) | |
| throws IOException | |
| { | |
| if (buffer != null) { | |
| if (buffer.limit() - buffer.position() < len) { | |
| growBuffer(); | |
| } | |
| buffer.put(cbuf, off, len); | |
| } | |
| super.write(cbuf, off, len); | |
| } | |
| @Override | |
| public void write(final String str, final int off, final int len) | |
| throws IOException | |
| { | |
| if (buffer != null) { | |
| if (buffer.limit() - buffer.position() < len) { | |
| growBuffer(); | |
| } | |
| buffer.put(str, off, len); | |
| } | |
| super.write(str, off, len); | |
| } | |
| @Override | |
| public void flush() | |
| throws IOException | |
| { | |
| super.flush(); | |
| if (buffer != null) { | |
| buffer.flip(); | |
| logger.debug("Written data:\n{}", buffer); | |
| buffer.clear(); | |
| } | |
| } | |
| /** Allocates a new buffer of 2x capacity of current and copies content over. */ | |
| private void growBuffer() | |
| { | |
| final CharBuffer tmp = CharBuffer.allocate(buffer.capacity() * 2); | |
| buffer.flip(); | |
| tmp.put(buffer); | |
| buffer = tmp; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <beans xmlns="http://www.springframework.org/schema/beans" | |
| xmlns:context="http://www.springframework.org/schema/context" | |
| xmlns:c="http://www.springframework.org/schema/c" | |
| xmlns:p="http://www.springframework.org/schema/p" | |
| xmlns:mvc="http://www.springframework.org/schema/mvc" | |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| xsi:schemaLocation="http://www.springframework.org/schema/beans | |
| http://www.springframework.org/schema/beans/spring-beans.xsd | |
| http://www.springframework.org/schema/context | |
| http://www.springframework.org/schema/context/spring-context.xsd | |
| http://www.springframework.org/schema/mvc | |
| http://www.springframework.org/schema/mvc/spring-mvc.xsd"> | |
| <!-- Other beans as necessary --> | |
| <bean id="loggingViewResolver" | |
| class="edu.vt.middleware.ed.ws.soap.mvc.ConfigurableVelocityViewResolver" | |
| parent="velocityViewResolver" | |
| c:clazz="edu.vt.middleware.ed.ws.soap.mvc.LoggingWriter" | |
| p:prefix="template-path/" | |
| p:contentType="text/plain;charset=UTF-8"/> | |
| </beans> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment