diff options
author | Artur <artur@vaadin.com> | 2017-01-02 11:10:33 +0200 |
---|---|---|
committer | Pekka Hyvönen <pekka@vaadin.com> | 2017-01-02 11:10:33 +0200 |
commit | 86ed6cc475d9e9ee79fee4f2340c271ffa5c702e (patch) | |
tree | 94ee81c7c0747a53cc526d93ac5614a59326de90 | |
parent | 04febccaad259f78916cce6c447707dc3e1eb83d (diff) | |
download | vaadin-framework-86ed6cc475d9e9ee79fee4f2340c271ffa5c702e.tar.gz vaadin-framework-86ed6cc475d9e9ee79fee4f2340c271ffa5c702e.zip |
Call error handler for exceptions in UI.init() (#8055)
Fixes #4995
4 files changed, 210 insertions, 5 deletions
diff --git a/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java b/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java index f66dbe4107..aa167d137f 100644 --- a/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java @@ -211,10 +211,17 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { // Set thread local here so it is available in init UI.setCurrent(ui); - ui.doInit(request, uiId.intValue(), embedId); - + Exception initException = null; + try { + ui.doInit(request, uiId.intValue(), embedId); + } catch (Exception e) { + initException = e; + } session.addUI(ui); - + if (initException != null) { + ui.getSession().getCommunicationManager() + .handleConnectorRelatedException(ui, initException); + } // Warn if the window can't be preserved if (embedId == null && vaadinService.preserveUIOnRefresh(provider, event)) { diff --git a/server/src/test/java/com/vaadin/server/communication/ServletUIInitHandlerTest.java b/server/src/test/java/com/vaadin/server/communication/ServletUIInitHandlerTest.java new file mode 100644 index 0000000000..6c61922307 --- /dev/null +++ b/server/src/test/java/com/vaadin/server/communication/ServletUIInitHandlerTest.java @@ -0,0 +1,188 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.server.communication; + +import java.io.IOException; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import com.vaadin.server.DefaultDeploymentConfiguration; +import com.vaadin.server.ErrorEvent; +import com.vaadin.server.ErrorHandler; +import com.vaadin.server.LegacyCommunicationManager; +import com.vaadin.server.MockServletConfig; +import com.vaadin.server.UIClassSelectionEvent; +import com.vaadin.server.UICreateEvent; +import com.vaadin.server.UIProvider; +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinServlet; +import com.vaadin.server.VaadinServletRequest; +import com.vaadin.server.VaadinServletResponse; +import com.vaadin.server.VaadinServletService; +import com.vaadin.tests.util.AlwaysLockedVaadinSession; +import com.vaadin.ui.UI; + +public class ServletUIInitHandlerTest { + + public static class CommunicationMock { + + public final UI ui; + public final ServletConfig servletConfig; + public final VaadinServlet servlet; + public final DefaultDeploymentConfiguration deploymentConfiguration; + public final VaadinServletService service; + public final AlwaysLockedVaadinSession session; + + public CommunicationMock(final UI ui) throws Exception { + servletConfig = new MockServletConfig(); + servlet = new VaadinServlet(); + servlet.init(servletConfig); + + deploymentConfiguration = new DefaultDeploymentConfiguration( + UI.class, new Properties()); + + service = new VaadinServletService(servlet, + deploymentConfiguration); + session = new AlwaysLockedVaadinSession(service); + LegacyCommunicationManager communicationManager = new LegacyCommunicationManager( + session); + session.setCommunicationManager(communicationManager); + session.setConfiguration(deploymentConfiguration); + session.addUIProvider(new UIProvider() { + + @Override + public Class<? extends UI> getUIClass( + UIClassSelectionEvent event) { + return ui.getClass(); + } + + @Override + public UI createInstance(UICreateEvent event) { + return ui; + } + }); + this.ui = ui; + } + + public VaadinRequest createInitRequest() { + return new VaadinServletRequest( + Mockito.mock(HttpServletRequest.class), service) { + @Override + public String getMethod() { + return "POST"; + } + + @Override + public String getParameter(String name) { + if (UIInitHandler.BROWSER_DETAILS_PARAMETER.equals(name)) { + return "1"; + } + return super.getParameter(name); + } + + }; + } + + } + + @Test + public void errorHandlerForInitException() throws Exception { + final AtomicInteger pre = new AtomicInteger(0); + final AtomicInteger errorHandlerCalls = new AtomicInteger(0); + + UI ui = new UI() { + @Override + protected void init(VaadinRequest request) { + pre.incrementAndGet(); + throw new RuntimeException("Exception produced in init()"); + } + }; + + ui.setErrorHandler(new ErrorHandler() { + @Override + public void error(ErrorEvent event) { + errorHandlerCalls.incrementAndGet(); + } + }); + + CommunicationMock mock = new CommunicationMock(ui); + VaadinRequest initRequest = mock.createInitRequest(); + + ServletUIInitHandler servletUIInitHandler = new ServletUIInitHandler(); + servletUIInitHandler.handleRequest(mock.session, initRequest, + new VaadinServletResponse( + Mockito.mock(HttpServletResponse.class), mock.service) { + @Override + public ServletOutputStream getOutputStream() + throws IOException { + return new ServletOutputStream() { + @Override + public void write(int b) throws IOException { + } + }; + } + }); + + Assert.assertEquals(1, pre.getAndIncrement()); + Assert.assertEquals(1, errorHandlerCalls.getAndIncrement()); + Assert.assertEquals(mock.session, ui.getSession()); + } + + @Test + public void initExceptionNoErrorHandler() throws Exception { + final AtomicInteger pre = new AtomicInteger(0); + + UI ui = new UI() { + @Override + protected void init(VaadinRequest request) { + pre.incrementAndGet(); + throw new RuntimeException("Exception produced in init()"); + } + }; + + CommunicationMock mock = new CommunicationMock(ui); + VaadinRequest initRequest = mock.createInitRequest(); + + ServletUIInitHandler servletUIInitHandler = new ServletUIInitHandler(); + servletUIInitHandler.handleRequest(mock.session, initRequest, + new VaadinServletResponse( + Mockito.mock(HttpServletResponse.class), mock.service) { + @Override + public ServletOutputStream getOutputStream() + throws IOException { + return new ServletOutputStream() { + @Override + public void write(int b) throws IOException { + } + }; + } + }); + + Assert.assertEquals(1, pre.getAndIncrement()); + // Default error handler only logs the exception + Assert.assertEquals(mock.session, ui.getSession()); + } + +} diff --git a/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java b/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java index d5f26ade29..fa25d7e837 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java +++ b/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java @@ -1,12 +1,22 @@ package com.vaadin.tests.components.ui; +import com.vaadin.server.ErrorHandler; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Label; public class UIInitException extends AbstractTestUI { @Override protected void setup(VaadinRequest request) { + setErrorHandler(new ErrorHandler() { + @Override + public void error(com.vaadin.server.ErrorEvent event) { + addComponent(new Label("An exception occurred: " + + event.getThrowable().getMessage())); + + } + }); throw new RuntimeException("Catch me if you can"); } diff --git a/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java b/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java index c1d6aaa55b..064132d4c7 100644 --- a/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java +++ b/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java @@ -3,9 +3,9 @@ package com.vaadin.tests.components.ui; import org.junit.Assert; import org.junit.Test; -import com.vaadin.tests.tb3.MultiBrowserTest; +import com.vaadin.tests.tb3.SingleBrowserTest; -public class UIInitExceptionTest extends MultiBrowserTest { +public class UIInitExceptionTest extends SingleBrowserTest { @Test public void testExceptionOnUIInit() throws Exception { openTestURL(); |