Resource Not Found after Spring 4.1.2 Update when deploy with JRebel 6.0.0

时光毁灭记忆、已成空白 提交于 2019-12-05 07:44:07

Thank you for very good problem description!

Looks like this Spring change introduced the incompatibility into the JRebel. I am from JRebel team and will make sure this will be fixed!

As a workaround you can use <exclude> tag in your rebel.xml <web> element to tell JRebel not to touch these specific files. Here is more info of how to configure it http://manuals.zeroturnaround.com/jrebel/standalone/config.html#exclude

Other easier workaround is just removing the <web> element altogether.

Based on smartman's anwser I configured rebel.xml as follows:

   <classpath>
         <dir name="${rebel.workspace.path}/myproject/target/classes">
         </dir>
         <dir name="${rebel.workspace.path}/myproject/target/test-classes">
         </dir>
   </classpath>

   <web>
         <link target="/">
                <dir name="${rebel.workspace.path}/myproject/src/main/webapp">
                       <exclude name="resources/**"/>
                </dir>
         </link>
   </web>

This will exclude all resources, but at least it will update the views (jsp- and tag-files). But when I do lots of frontend development, where I need to change controller, views and styles simultaniously, this configuration is useless and I have to turn off jrebel all together.

The problem is fixed in JRebel (I can not reproduce it with the current JRebel 6.1.1) - I guess it is fixed since 6.0.2 (23rd December 2014)

Fixed an issue where Spring ResourceHttpRequestHandler could not serve resources outside of webroot.

(JRebel Changelog https://zeroturnaround.com/software/jrebel/download/changelog/6-x/)


For the one that are interested how they solved it:

I can only guess because it is strange. Spring 4.1.6 (that is the version I used for the test) has the class org.springframework.web.servlet.resource.PathResourceResolver has the method checkResource(Resource resource, Resource location):

protected boolean checkResource(Resource resource, Resource location) throws IOException {
    if (isResourceUnderLocation(resource, location)) {
        return true;
    }
    if (getAllowedLocations() != null) {
        for (Resource current : getAllowedLocations()) {
            if (isResourceUnderLocation(resource, current)) {
                return true;
            }
        }
    }
    return false;
}

The first if: isResourceUnderLocation... is the method that check whether or not the request is accessing a resource outside the configured resource folder

isResourceUnderLocation(Resource resource, Resource location) {
    ...
    resourcePath = ((ServletContextResource) resource).getPath();
    locationPath = StringUtils.cleanPath(((ServletContextResource) location).getPath());
    ...
    if (!resourcePath.startsWith(locationPath)) {
        return false;
    }
    ...
 }

When I use the debugger to check what is going on, while JRebel is active, then something strange happend: when the JVM hit the line if (isResourceUnderLocation(resource, location)) {, then the method isResourceUnderLocation gets not invoked!

So I came to the conclusion that JRebel does some bytecode manipulation to prevent that the check (and the whole isResourceUnderLocation method) gets executed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!