From e6e48301ecd0588df76ee0f3e65bdc0b611ad7ab Mon Sep 17 00:00:00 2001 From: Denis Anisimov Date: Wed, 25 Nov 2020 08:32:46 +0300 Subject: [PATCH] fix: don't initialize Vaadin servlet until Lookup is not available --- .../com/vaadin/flow/server/VaadinServlet.java | 36 +++++--- .../vaadin/flow/server/VaadinServletTest.java | 86 +++++++++++++++++++ 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/flow-server/src/main/java/com/vaadin/flow/server/VaadinServlet.java b/flow-server/src/main/java/com/vaadin/flow/server/VaadinServlet.java index 7905a3f42b1..9b2ad0817bd 100644 --- a/flow-server/src/main/java/com/vaadin/flow/server/VaadinServlet.java +++ b/flow-server/src/main/java/com/vaadin/flow/server/VaadinServlet.java @@ -16,6 +16,7 @@ package com.vaadin.flow.server; import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -27,6 +28,7 @@ import java.util.Properties; import com.vaadin.flow.component.UI; +import com.vaadin.flow.di.Lookup; import com.vaadin.flow.function.DeploymentConfiguration; import com.vaadin.flow.internal.CurrentInstance; import com.vaadin.flow.server.HandlerHelper.RequestType; @@ -64,23 +66,35 @@ public class VaadinServlet extends HttpServlet { @Override public void init(ServletConfig servletConfig) throws ServletException { CurrentInstance.clearAll(); - super.init(servletConfig); - try { - servletService = createServletService(); - } catch (ServiceException e) { - throw new ServletException("Could not initialize VaadinServlet", e); + if (getServletConfig() == null) { + super.init(servletConfig); + } + + ServletContext servletContext = getServletConfig().getServletContext(); + if (new VaadinServletContext(servletContext) + .getAttribute(Lookup.class) == null) { + return; } - // Sets current service as it is needed in static file server even - // though there are no request and response. - servletService.setCurrentInstances(null, null); + if (servletService == null) { + try { + servletService = createServletService(); + } catch (ServiceException e) { + throw new ServletException("Could not initialize VaadinServlet", + e); + } - staticFileHandler = createStaticFileHandler(servletService); + // Sets current service as it is needed in static file server even + // though there are no request and response. + servletService.setCurrentInstances(null, null); - servletInitialized(); - CurrentInstance.clearAll(); + staticFileHandler = createStaticFileHandler(servletService); + servletInitialized(); + } + + CurrentInstance.clearAll(); } /** diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletTest.java index d975940da47..486ac408ce9 100644 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletTest.java @@ -15,14 +15,20 @@ */ package com.vaadin.flow.server; +import javax.servlet.ServletConfig; import javax.servlet.ServletContext; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; +import java.util.concurrent.atomic.AtomicBoolean; + import net.jcip.annotations.NotThreadSafe; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; +import com.vaadin.flow.di.Lookup; + @NotThreadSafe public class VaadinServletTest { @@ -64,6 +70,86 @@ public void testGetLastPathParameter() { .getLastPathParameter("http://myhost.com/a;hello/;b=1,c=2/")); } + @Test + public void init_superInitCalledOnce() throws ServletException { + AtomicBoolean called = new AtomicBoolean(); + VaadinServlet servlet = new VaadinServlet() { + + @Override + public void init() throws ServletException { + Assert.assertFalse(called.get()); + called.set(true); + } + }; + + ServletConfig config = mockConfig(); + servlet.init(config); + + Assert.assertTrue(called.get()); + + servlet.init(mockConfig()); + + Assert.assertSame(config, servlet.getServletConfig()); + } + + @Test + public void init_noLookup_servletIsNotInitialized() + throws ServletException { + AtomicBoolean called = new AtomicBoolean(); + VaadinServlet servlet = new VaadinServlet() { + + @Override + protected void servletInitialized() throws ServletException { + called.set(true); + } + }; + + ServletConfig config = mockConfig(); + servlet.init(config); + + Assert.assertFalse(called.get()); + } + + @Test + public void init_contextHasLookup_servletIsInitialized() + throws ServletException { + AtomicBoolean called = new AtomicBoolean(); + VaadinServlet servlet = new VaadinServlet() { + + @Override + protected VaadinServletService createServletService() + throws ServletException, ServiceException { + return Mockito.mock(VaadinServletService.class); + } + + @Override + protected StaticFileHandler createStaticFileHandler( + VaadinServletService servletService) { + return Mockito.mock(StaticFileHandler.class); + } + + @Override + protected void servletInitialized() throws ServletException { + called.set(true); + } + }; + + ServletConfig config = mockConfig(); + ServletContext servletContext = config.getServletContext(); + Mockito.when(servletContext.getAttribute(Lookup.class.getName())) + .thenReturn(Mockito.mock(Lookup.class)); + servlet.init(config); + + Assert.assertTrue(called.get()); + } + + private ServletConfig mockConfig() { + ServletConfig config = Mockito.mock(ServletConfig.class); + ServletContext context = Mockito.mock(ServletContext.class); + Mockito.when(config.getServletContext()).thenReturn(context); + return config; + } + private HttpServletRequest createRequest( MockServletServiceSessionSetup mocks, String path) { HttpServletRequest httpServletRequest = Mockito