@Override public void render(Node content, RenderableDefinition definition, Map<String, Object> contextObjects, OutputProvider out) throws RenderException { RenderableDefinition variation = variationResolver.resolveVariation(definition); definition = variation != null ? variation : definition; final Renderer renderer = getRendererFor(definition); final RenderingContext renderingContext = getRenderingContext(); renderingContext.push(content, definition, out); try { Collection<RenderingListenerReturnCode> listenerResults = renderingContext.before(content, definition, contextObjects, out); if (listenerResults.contains(RenderingListenerReturnCode.SKIP) || listenerResults.contains(RenderingListenerReturnCode.STOP)) { return; } renderer.render(renderingContext, contextObjects); } catch (RenderException e) { renderingContext.handleException(e); } finally { renderingContext.after(content, definition, contextObjects, out); renderingContext.pop(); } }
@Test public void testRenderExceptionHandlerIsInvokedOnRenderException() throws Exception { // GIVEN final Node content = new MockNode("parent"); TemplateDefinitionAssignment templateDefinitionAssignment = mock(TemplateDefinitionAssignment.class); RenderingContext renderingCtx = mock(RenderingContext.class); DefaultRenderingEngine renderingEngine = createDefaultRenderingEngine(rendererRegistry, templateDefinitionAssignment, renderingCtx); TemplateDefinition templateDefinition = mock(TemplateDefinition.class); when(templateDefinitionAssignment.getAssignedTemplateDefinition(content)).thenReturn(templateDefinition); Renderer renderer = registerMockRenderer(rendererRegistry); final StringBuilder builder = new StringBuilder(); OutputProvider builderWrapper = new AppendableOnlyOutputProvider(builder); final AppendableWriter writer = new AppendableWriter(builder); when(renderingCtx.getAppendable()).thenReturn(writer); when(templateDefinition.getRenderType()).thenReturn(FREEMARKER_RENDERER_TYPE); final RenderException e = new RenderException("TEST!"); doThrow(e).when(renderer).render(renderingCtx, DefaultRenderingEngine.EMPTY_CONTEXT); // WHEN renderingEngine.render(content, builderWrapper); // THEN verify(renderingCtx).handleException(e); }
@Test public void testRenderThrowsRenderExceptionAndTheExceptionHandlerIsInvocedInCaseOfInternalIOException() throws Exception { // GIVEN final Node content = new MockNode("parent"); TemplateDefinitionAssignment templateDefinitionAssignment = mock(TemplateDefinitionAssignment.class); RenderingContext renderingCtx = mock(RenderingContext.class); DefaultRenderingEngine renderingEngine = createDefaultRenderingEngine(rendererRegistry, templateDefinitionAssignment, renderingCtx); TemplateDefinition templateDefinition = mock(TemplateDefinition.class); when(templateDefinitionAssignment.getAssignedTemplateDefinition(content)).thenReturn(templateDefinition); when(templateDefinition.getRenderType()).thenReturn(FREEMARKER_RENDERER_TYPE); Renderer renderer = registerMockRenderer(rendererRegistry); final StringBuilder builder = new StringBuilder(); OutputProvider builderWrapper = new AppendableOnlyOutputProvider(builder); final AppendableWriter writer = new AppendableWriter(builder); when(renderingCtx.getAppendable()).thenReturn(writer); final RenderException renderException = new RenderException("oh - oh!"); doThrow(renderException).when(renderer).render(renderingCtx, DefaultRenderingEngine.EMPTY_CONTEXT); doThrow(new IOException()).when(renderingCtx).getAppendable(); // WHEN renderingEngine.render(content, builderWrapper); // THEN - no code here as we expect an Exception verify(renderingCtx).handleException(renderException); }