zhuguowei
zhuguowei

Reputation: 8487

About modify spring boot 1.5.3 to support recognise jsp files

I used spring boot + jsp, and from this post I know if put jsp files in src/main/resources/META-INF/resources/ also could package as a executable jar.

Unfortunately when I modify spring boot version from 1.4.2 to 1.5.3, it cannot support and return 404. After hours tracing their source codes and compare I know why 1.5.3 cannot support it.

Spring boot 1.4.2

//org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.StoreMergedWebXmlListener#onStart
private void onStart(Context context) {
    ServletContext servletContext = context.getServletContext();
    if(servletContext.getAttribute("org.apache.tomcat.util.scan.MergedWebXml") == null) {
        servletContext.setAttribute("org.apache.tomcat.util.scan.MergedWebXml", this.getEmptyWebXml());
    }
    // only 1.4.2 has this line and with this code could recognise jsp files in /META-INF/resources/
    TomcatResources.get(context).addClasspathResources(); 
}

Spring boot 1.5.3

private void onStart(Context context) {
    ServletContext servletContext = context.getServletContext();
    if (servletContext.getAttribute(MERGED_WEB_XML) == null) {
        servletContext.setAttribute(MERGED_WEB_XML, getEmptyWebXml());
    }
}

So I want to know why after 1.4.2 have to remove this code?

TomcatResources.get(context).addClasspathResources(); 

And because I still want to use 1.5.3 so I have to manually add this code by below way

1.copy source code of TomcatEmbeddedServletContainerFactory to current classpath enter image description here

2.do below modify

private void onStart(Context context) {
    ServletContext servletContext = context.getServletContext();
    if (servletContext.getAttribute(MERGED_WEB_XML) == null) {
        servletContext.setAttribute(MERGED_WEB_XML, getEmptyWebXml());
    }
    // Add below code
    ClassLoader loader = getClass().getClassLoader();
    URL[] urLs = ((URLClassLoader) loader).getURLs();
    List<URL> list = new ArrayList<>();
    //String file = "file:/Users/zhugw/workspace/boot-jar-serving-jsp/boot-jar-serving-jsp-1.0-SNAPSHOT.jar!/";
    String file = urLs[0].getFile().replaceFirst("BOOT-INF/classes!/", "");
    URL jar = new URL("jar", "", file);
    list.add(0,jar);
    TomcatResources.get(context).addResourceJars(list);
} 

and it does works. And I want to know if could do this so?

Upvotes: 1

Views: 199

Answers (1)

S&#233;bastien PRAT
S&#233;bastien PRAT

Reputation: 449

We have the same pb here.

  1. We tried your solution but unsuccessfully. The following exception was raised when starting the application :

...

Caused by: java.lang.IllegalAccessError: tried to access class org.springframework.boot.context.embedded.tomcat.TldSkipPatterns from class org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.(TomcatEmbeddedServletContainerFactory.java:130)

...

  1. Finally it seems the call to "TomcatResources.get(context).addClasspathResources();" has not been removed but refactored.

Now in SpringBoot 1.5.8.RELEASE, you have the following lines in TomcatEmbeddedServletContainerFactory.prepareContext():

context.addLifecycleListener(new LifecycleListener() {
    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
            TomcatResources.get(context)
                    .addResourceJars(getUrlsOfJarsWithMetaInfResources());
        }
    }
});
  1. In our case, we were using a customized EmbeddedServletContainerFactory (override of some methods of TomcatEmbeddedServletContainerFactory) and for an unknown reason, the classloader retrieved in getUrlOfJarsWithMetaInfResources() was almost empty (only the classes folder with no jar file).

Solution: We've simply removed this override. Jar files areback in the classloader and consequently jsp files stored in those jar files are now correctly recognized by the app.

Upvotes: 1

Related Questions