Skip to content

Commit

Permalink
Fix static resource path for WAR deployment (#17573)
Browse files Browse the repository at this point in the history
Change-Id: I932794eb3a26eacfee538477937529465af1bb01
  • Loading branch information
Henri Sara committed Apr 24, 2015
1 parent d1e8294 commit 352b5d5
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.ServletForwardingController;
Expand All @@ -42,6 +43,20 @@
* Spring configuration that sets up a
* {@link com.vaadin.spring.server.SpringVaadinServlet}. If you want to
* customize the servlet, extend it and make it available as a Spring bean.
* <p>
* By default, unless a custom mapping of the Vaadin servlet is performed using
* the URL mapping configuration property
* {@link VaadinServletConfigurationProperties#getUrlMapping()}, the Vaadin
* servlet is mapped to a hidden path not to block requests destined to
* {@link DispatcherServlet}. {@link ServletForwardingController} is then mapped
* so that requests to all {@link SpringUI} paths are forwarded to the servlet
* for the generation of a bootstrap page, which internally uses the Vaadin
* servlet path for all other communication.
* <p>
* This approach currently relies on a hack that modifies request servlet path
* and path info on the fly as those produced by
* {@link ServletForwardingController} are not what {@link VaadinServlet}
* expects. See {@link SpringVaadinServlet} for more information on this.
*
* @author Petter Holmström (petter@vaadin.com)
* @author Henri Sara (hesara@vaadin.com)
Expand Down Expand Up @@ -161,7 +176,7 @@ protected String[] getUrlMappings() {
}

@Bean
ServletRegistrationBean vaadinServletRegistration() {
protected ServletRegistrationBean vaadinServletRegistration() {
return createServletRegistrationBean();
}

Expand All @@ -172,12 +187,7 @@ public void afterPropertiesSet() throws Exception {

@Bean
public VaadinServlet vaadinServlet() {
SpringVaadinServlet servlet = new SpringVaadinServlet();
// TODO should this rather be done when registering the servlet
if (isMappedToRoot()) {
servlet.setServiceUrl(DEFAULT_SERVLET_URL_BASE);
}
return servlet;
return new SpringVaadinServlet();
}

protected ServletRegistrationBean createServletRegistrationBean() {
Expand All @@ -186,6 +196,15 @@ protected ServletRegistrationBean createServletRegistrationBean() {
getLogger().info("Servlet will be mapped to URLs {}",
(Object) urlMappings);
final VaadinServlet servlet = vaadinServlet();

// this is a hack to make is possible for Vaadin and Spring MVC
// applications to co-exist in the same global "namespace"
if (servlet instanceof SpringVaadinServlet && isMappedToRoot()) {
SpringVaadinServlet vaadinServlet = (SpringVaadinServlet) servlet;
vaadinServlet.setServiceUrl(DEFAULT_SERVLET_URL_BASE);
vaadinServlet.setClearServletPath(true);
}

final ServletRegistrationBean registrationBean = new ServletRegistrationBean(
servlet, urlMappings);
addInitParameters(registrationBean);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@
* If you need a custom Vaadin servlet, you can either extend this servlet
* directly, or extend another subclass of {@link VaadinServlet} and just add
* the UI provider.
* <p>
* This servlet also implements a hack to get around the behavior of Spring
* ServletForwardingController/ServletWrappingController. Those controllers
* return null as the pathInfo of requests forwarded to the Vaadin servlet, and
* use the mapping as the servlet path whereas with Vaadin the mapping typically
* corresponds to a UI, not a virtual servlet. Thus, there is an option to clear
* the servlet path in requests and compute pathInfo accordingly. This is used
* by Vaadin Spring Boot to make it easier to use Vaadin and Spring MVC
* applications together in the same global "namespace".
*
* @author Petter Holmström (petter@vaadin.com)
* @author Josh Long (josh@joshlong.com)
Expand All @@ -53,6 +62,8 @@ public class SpringVaadinServlet extends VaadinServlet {

private String serviceUrl = null;

private boolean clearServletPath = false;

@Override
protected void servletInitialized() throws ServletException {
getService().addSessionInitListener(new SessionInitListener() {
Expand Down Expand Up @@ -111,10 +122,39 @@ public void setServiceUrl(String serviceUrl) {
this.serviceUrl = serviceUrl;
}

/**
* Return true if always forcing the servlet path to be the empty string,
* false otherwise.
*
* This API might change in future versions.
*
* @see SpringVaadinServlet
*
* @return true if clearing the servlet path
*/
public boolean isClearServletPath() {
return clearServletPath;
}

/**
* Make the servlet use empty string as the servlet path (needed when using
* ServletForwardingController). See the class level javadoc for
* {@link SpringVaadinServlet} for more information.
*
* This API might change in future versions.
*
* @param clearServletPath
* true to use empty servlet path and have the full path as
* pathInfo, false not to remap the servlet path
*/
public void setClearServletPath(boolean clearServletPath) {
this.clearServletPath = clearServletPath;
}

@Override
protected VaadinServletService createServletService(
DeploymentConfiguration deploymentConfiguration)
throws ServiceException {
throws ServiceException {
// this is needed when using a custom service URL
SpringVaadinServletService service = new SpringVaadinServletService(
this, deploymentConfiguration, getServiceUrl());
Expand All @@ -125,7 +165,8 @@ protected VaadinServletService createServletService(
@Override
protected VaadinServletRequest createVaadinRequest(
HttpServletRequest request) {
return new SpringVaadinServletRequest(request, getService());
return new SpringVaadinServletRequest(request, getService(),
isClearServletPath());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,44 @@
*/
public class SpringVaadinServletRequest extends VaadinServletRequest {

private UrlPathHelper urlPathHelper = new UrlPathHelper();
private boolean clearServletPath;

/**
* Construct a Spring servlet request
*
* @param request
* @param vaadinService
* @param clearServletPath
* true to use empty string as the servlet path (needed when
* using ServletForwardingController for bootstrap page
* requests), false to use the normal servlet path - for more
* information on this hack, see {@link SpringVaadinServlet}
*/
public SpringVaadinServletRequest(HttpServletRequest request,
VaadinServletService vaadinService) {
VaadinServletService vaadinService, boolean clearServletPath) {
super(request, vaadinService);
this.clearServletPath = clearServletPath;
}

@Override
public String getServletPath() {
if (clearServletPath) {
// the path where a ServletForwardingController is registered is not
// a real servlet path
return "";
} else {
return super.getServletPath();
}
}

@Override
public String getPathInfo() {
String pathInfo = super.getPathInfo();
if (pathInfo == null) {
pathInfo = new UrlPathHelper().getPathWithinApplication(this);
// this uses getServletPath() and should work both with and without
// clearServletPath
pathInfo = urlPathHelper.getPathWithinServletMapping(this);
}
return pathInfo;
}
Expand Down

0 comments on commit 352b5d5

Please sign in to comment.