Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classpath files not found in Undertow after migrating to Spring Boot 1.2.7 #4218

Closed
cbelleza opened this issue Oct 17, 2015 · 21 comments
Closed
Labels
status: feedback-provided Feedback has been provided

Comments

@cbelleza
Copy link

Hi,

I have migrated my Spring Boot application to 1.2.7 version and after that some html files which are inside my jar's could not be found in Undertow. My application tries to read those html files to use on my CustomLayout class (Vaadin framework).

I noticed there's a ticket called #4015 which says about something protecting files from classpath in Undertow. Before migrating it, the version 1.2.6 was working fine and did not face any error about files missing.

Is there any cause about it? What to do now?

Cheers,

@snicoll
Copy link
Member

snicoll commented Oct 17, 2015

you're not telling anything about the app and how it retrieves those files. One way to easily isolate #4015 would be to run your app on tomcat (or jetty) and see if the same issue happens (that is works in 1.2.6 and breaks in 1.2.7).

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Oct 17, 2015
@cbelleza
Copy link
Author

Hi @snicoll ,

I noticed this error only happens on Solaris sparc, if I try my application on Windows 7 it finds the html file normally.

The piece of code which tries to get the file is VaadinServletService.class :

    @Override
    public InputStream getThemeResourceAsStream(UI uI, String themeName,
            String resource) {
        VaadinServletService service = (VaadinServletService) uI.getSession()
                .getService();
        ServletContext servletContext = service.getServlet()
                .getServletContext();
        return servletContext.getResourceAsStream("/"
                + VaadinServlet.THEME_DIR_PATH + '/' + themeName + "/"
                + resource);
    }

As you can see the servletContext can not reach the resource, any idea?

Thanks!

@wilkinsona
Copy link
Member

Where is the resource that you're trying to load via the servlet context? If it's inside an embedded jar then it won't work.

@kkarwows
Copy link

Have same problem with keystore:
application.properties: server.ssl.key-store = classpath:embedded-tomcat-keystore
and embedded-tomcat-keystore file under resources in web/war module.

Error:

`Caused by: java.io.FileNotFoundException: /tmp/tomcat.9125735851658783265.8443/file:/****/test-project/web-module/target/classes/embedded-tomcat-keystore (Nie ma takiego pliku ani katalogu)
    at java.io.FileInputStream.open0(Native Method) ~[na:1.8.0_45]
    at java.io.FileInputStream.open(FileInputStream.java:195) ~[na:1.8.0_45]
    at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[na:1.8.0_45]
    at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getStore(JSSESocketFactory.java:430) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeystore(JSSESocketFactory.java:336) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:594) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:534) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:363) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:739) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:472) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.coyote.http11.Http11NioProtocol.start(Http11NioProtocol.java:81) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:986) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
    ... 18 common frames omitted

In Spring Boot 1.2.6 it works fine.

@wilkinsona
Copy link
Member

@kkarwows I don't think you have the same problem as you're using Tomcat and this issue is specific to Undertow. Perhaps you're being affected by this change but it's impossible to say from the information you've provided. If you'd like us to investigate please open a separate issue with a sample project that reproduces the problem.

@wilkinsona
Copy link
Member

@kkarwows I've just noticed you're using Tomcat 8.0.20. Why are you overriding the version? You should let Spring Boot provide the version for you. If you use the version that Boot provides, 8.0.28, then I suspect your problem will go away.

@kkarwows
Copy link

@wilkinsona: I remove tomcat version overriding and it works now, Thanks.

@cbelleza
Copy link
Author

Hi, @wilkinsona

Why in Spring Boot 1.2.6 does it work? My html resource is inside the jar.

By the way, I create a fat jar with all resources inside.

<profiles>
        <profile>
            <id>external</id>
            <build>
                <resources>
                    <resource>
                        <directory>src/main/resources</directory>
                        <excludes>
                            <exclude>application.properties</exclude>
                            <exclude>jboss-ejb-client.properties</exclude>
                            <exclude>logback.xml</exclude>
                        </excludes>
                    </resource>
                    <resource>
                        <directory>src/main/webapp</directory>
                        <includes>
                            <include>**/*.*</include>
                        </includes>
                    </resource>
                </resources>
            </build>
        </profile>
    </profiles>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <layout>ZIP</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Thks!

@philwebb
Copy link
Member

@ofbizbrazil I suspect your code accidentally worked in 1.2.6 because #4015 had not been fixed. You probably either need to update your code to use war packaging or change VaadinServletService so that it loads resource using Classpath.getResourceAsStream().

Following @snicoll's suggestion in #4218 (comment) and trying Jetty/Tomcat would also help in diagnosing if this is something that behaves differently only for Undertow.

@cbelleza
Copy link
Author

hi @philwebb,

Sadly I cant change the code VaadinServletService, cause is part of Vaadin framework and not mine code. Please see at. vaadin.com
At the moment I am packaging my project as fat jar using a zip structure to load external application properties.

About the bug #4015 why was it a problem?

Thanks

@philwebb
Copy link
Member

Bug #4015 was a security concern. It basically exposed every resource (including application.properties) to the public. It's easy to imagine for example that sensitive password information could be exposed.

I know that @joshlong did quite a bit of work with the Vaadin team to offer Spring Boot support. I'm not sure what packaging he used. Perhaps he can comment here.

Did you manage to try your app with Jetty or Tomcat yet? That would be very helpful in letting us know if the different container engines work in the same way.

@snicoll
Copy link
Member

snicoll commented Oct 20, 2015

Vaadin based apps are working fine with both jar and war deployment. We've been working with them on the Spring Boot support.

I don't think it's fair to say that the issue is on either our side or Vaadin's until we can actually see the problem. As we asked three times already, please try your app with Tomcat or Jetty. It's a three lines change in your project.

@cbelleza
Copy link
Author

Hi @philwebb,

I tried with Jetty and the same error happens.

If I try to change my pom to WAR, the zip format can not load external resources (application.properties).

How to solve it?

@philwebb
Copy link
Member

@ofbizbrazil I've no idea how to fix your specific issue without looking in detail at the code. Perhaps you could create a minimal project that reproduces the issue.

There's also this Getting Started Guide which might help.

@cbelleza
Copy link
Author

@philwebb,

Let's suppose if I want to load a resource via servletContext, for example:

servletContext.getResourceAsStream("/image.png");

This will it not work anymore? From now on, I can only do via Classpath.getResourceAsStream()?

Tks

@wilkinsona
Copy link
Member

@ofbizbrazil If you'd like us to investigate this any further, please provide the requested sample project that reproduces the issue. As things stand we're just going round in circles wasting our time and yours.

@cbelleza
Copy link
Author

@wilkinsona,

But my point is: servletContext.getResourceAsStream("/image.png") will not work anymore?

By the way I changed my pom to war, and the error still persists, when tries to load the resource from servletContext.getResourceAsStream. It seems fat JAR/WAR is not working.

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.xxx.TestApp</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

@cbelleza
Copy link
Author

Hi all.

So, my html files are located inside the WAR at \VAADIN\themes\test\layouts*.

For example:

/META-INF
/org
/VAADIN
/WEB-INF

When I try to access a screen, on console says:

ERROR com.vaadin.server.communication.ResourceWriter - CustomLayout not found: layouts/monitorTabReceived.html

This error happens because Vaadin class tried to get a resource using servletContext.getResourceAsStream from \VAADIN\themes\test\layouts folder

Is there any solution to fix it?

@hesara
Copy link

hesara commented Oct 21, 2015

Vaadin looks for the template files for CustomLayout in /VAADIN/themes/test/layouts, where the whole /VAADIN tree with its contained themes etc. should be directly exposed to the user - and is if any theming of your application works. However, unlike most files that are served from /VAADIN directly by Undertow or the servlet container, the CustomLayout templates are first loaded from the directory/JAR/WAR on the server side by VaadinServletService.getThemeResourceAsStream() and then separately sent to the client by Vaadin (in ResourceWriter).

As these files are in published directories anyway (you should be able to load /VAADIN/themes/test/layouts/monitorTabReceived.html directly with your browser), perhaps the restriction on the Spring side is unnecessarily strict in this case. However, you could try to override the loading of the layout files to see if it helps.

With Vaadin Spring 1.0 final release, you can customize the VaadinServletService if you need to test an alternative implementation. This requires:

  1. creating a custom subclass of VaadinServletService with the method getThemeResourceAsStream(...) overridden and
  2. creating a subclass of VaadinSpringServlet with createServletService() overridden to create your custom VSS instance and call init() on it before returning it and
  3. defining a bean with the name "vaadinServlet" in your configuration to use your custom servlet class (this step requires the 1.0 release version of Vaadin Spring)

If you use Classpath.getResourceAsStream(), you might need to place the custom layout files (including the parent directory hierarchy /VAADIN/...) somewhere on the classpath in the JAR/WAR file.

If this helps, please let us know so that we (at Vaadin and/or Pivotal) can try to find a way to fix this for other users.

Note that another workaround would be to use the constructor CustomLayout(InputStream) and load the template yourself, but that would require changes everywhere you instantiate a CustomLayout.

@cbelleza
Copy link
Author

Hi @hesara,

Excellent explanation, I tried to use CustomLayout(InputStream) but I noticed it gets the files from resource folder. As I am settting on webapp folder the template files it will only find them when I create the fat jar.

My next step is to test is create a VaadinServletService and see what happens, but I am afraid about the location of resources.

Tks

@cbelleza
Copy link
Author

cbelleza commented Oct 23, 2015

I still wonder if servletContext.getResourceAsStream("/image.png"); will not work anymore?

Tks!

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 8, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: feedback-provided Feedback has been provided
Projects
None yet
Development

No branches or pull requests

7 participants