Skip to content

Conversation

@cemo
Copy link
Contributor

@cemo cemo commented Dec 28, 2014

My Jetty 9 application throws java.net.MalformedURLException: no !/ in spec. It seems that / required at the end of url.

I have signed CLA.

@philwebb philwebb added the type: bug A general bug label Dec 28, 2014
@philwebb philwebb added this to the 1.2.1 milestone Dec 28, 2014
@philwebb
Copy link
Member

Could you please attach the stacktrace? Also do you have an example application? I've tried to make the Jetty sample fail in the same way but without any luck so far.

@cemo
Copy link
Contributor Author

cemo commented Dec 28, 2014

Jetty has JarResource as well. The usage:

JarResource.newJarResource(Resource.newResource(file))

The implementation of it:

    public static Resource newJarResource(Resource resource) throws IOException
    {
        if (resource instanceof JarResource)
            return resource;
        return Resource.newResource("jar:" + resource + "!/");
    }

It is probably a better idea to rely on their JarResource implementation. Do want me to update PR?

@philwebb
Copy link
Member

That does look safer. Yes please.

@cemo cemo force-pushed the fix-jetty9-jar-url branch 3 times, most recently from 2c3dca5 to 3a60944 Compare December 28, 2014 21:01
@cemo cemo force-pushed the fix-jetty9-jar-url branch from 3a60944 to 67df7d9 Compare December 28, 2014 21:02
@cemo
Copy link
Contributor Author

cemo commented Dec 28, 2014

I have updated.

@philwebb
Copy link
Member

Cheers, I'm still interested in a sample app if you have one?

@cemo
Copy link
Contributor Author

cemo commented Dec 28, 2014

I am actually in process for migrating a huge application code base. Basically, I have executable jetty9 application and trying to run at command line:

 java -jar -Dspring.config.location=/opt/test/application.yml application.jar

I will try to provide a sample application.

@philwebb
Copy link
Member

Thanks, I tried changing the spring-boot-jetty-sample but I couldn't replicate the exception. I've probably just not triggered that code path yet.

@cemo
Copy link
Contributor Author

cemo commented Dec 28, 2014

Shortly: Change your target/application.jar to target/application.war

Details:

Yes, you have not triggered because I think there still a mistake.
org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory#getValidDocumentRoot is checking executability of jar by this:

        // If document root not explicitly set see if we are running from a war archive
        file = file != null ? file : getWarFileDocumentRoot();

And this is just checking files ending with ".war". I think that ".jar" files must be supported as well.

@cemo
Copy link
Contributor Author

cemo commented Dec 28, 2014

Here are the changes I made on top of 1.2.0-RELEASE

cemo@88a9568

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is java.lang.IllegalStateException: java.net.MalformedURLException: no !/ in spec
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:124)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at sample.jetty.SampleJettyApplication.main(SampleJettyApplication.java:26)
Caused by: java.lang.IllegalStateException: java.net.MalformedURLException: no !/ in spec
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.configureDocumentRoot(JettyEmbeddedServletContainerFactory.java:271)
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.configureWebAppContext(JettyEmbeddedServletContainerFactory.java:230)
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.getEmbeddedServletContainer(JettyEmbeddedServletContainerFactory.java:118)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:148)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:121)
    ... 7 common frames omitted
Caused by: java.net.MalformedURLException: no !/ in spec
    at java.net.URL.<init>(URL.java:620)
    at java.net.URL.<init>(URL.java:483)
    at java.net.URL.<init>(URL.java:432)
    at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:166)
    at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:149)
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.configureDocumentRoot(JettyEmbeddedServletContainerFactory.java:263)
    ... 11 common frames omitted
Caused by: java.lang.NullPointerException: no !/ in spec
    at sun.net.www.protocol.jar.Handler.parseAbsoluteSpec(Handler.java:171)
    at sun.net.www.protocol.jar.Handler.parseURL(Handler.java:151)
    at java.net.URL.<init>(URL.java:615)
    ... 16 common frames omitted

Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is java.lang.IllegalStateException: java.net.MalformedURLException: no !/ in spec
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:124)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at sample.jetty.SampleJettyApplication.main(SampleJettyApplication.java:26)
Caused by: java.lang.IllegalStateException: java.net.MalformedURLException: no !/ in spec
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.configureDocumentRoot(JettyEmbeddedServletContainerFactory.java:271)
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.configureWebAppContext(JettyEmbeddedServletContainerFactory.java:230)
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.getEmbeddedServletContainer(JettyEmbeddedServletContainerFactory.java:118)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:148)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:121)
    ... 7 more
Caused by: java.net.MalformedURLException: no !/ in spec
    at java.net.URL.<init>(URL.java:620)
    at java.net.URL.<init>(URL.java:483)
    at java.net.URL.<init>(URL.java:432)
    at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:166)
    at org.eclipse.jetty.util.resource.Resource.newResource(Resource.java:149)
    at org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.configureDocumentRoot(JettyEmbeddedServletContainerFactory.java:263)
    ... 11 more
Caused by: java.lang.NullPointerException: no !/ in spec
    at sun.net.www.protocol.jar.Handler.parseAbsoluteSpec(Handler.java:171)
    at sun.net.www.protocol.jar.Handler.parseURL(Handler.java:151)
    at java.net.URL.<init>(URL.java:615)
    ... 16 more

@philwebb
Copy link
Member

Cheers, I'll give that a go. The .war check in AbstractEmbeddedServletContainerFactory.getValidDocumentRoot is intentional. We only want to expose the root of the archive if the war layout is used. For Jar files we expect resources to be served via the DispatcherServlet (see WebMvcAutoConfiguration).

@cemo
Copy link
Contributor Author

cemo commented Dec 28, 2014

I have been using jar files as an executable file. So this is not good practice in spring boot world, right?

@philwebb
Copy link
Member

No, that is good practice. It's just that the /src/main/static folder is not exposed by setting the document root on the Servlet Container but is rather handled using Spring's MVC infrastructure.

@cemo
Copy link
Contributor Author

cemo commented Dec 29, 2014

I am using a different layout than classic one. I put JSP files under /src/main/resources/view/jsp and using jar extension. The only problem is that not only static files but also JSP files are checked to be compiled at document root directory. Unfortunately this is causing a 404 at my side with jar extension file. Is there any chance to check not only war extension but also jar ones?

@philwebb
Copy link
Member

JSPs do tend to cause problems. I don't think that we can change the AbstractEmbeddedServletContainerFactory method to include jar files because it is likely to expose .class files. With war files the container is aware that classes and nested jars are under WEB-INF and it is able to protect that location so that people can't download them. With jar layouts .class files are just in the root of the archive.

@cemo
Copy link
Contributor Author

cemo commented Dec 29, 2014

You are right. It is better to let developer this choice by a customizer.

@philwebb philwebb closed this in 1fc9d38 Jan 7, 2015
philwebb added a commit that referenced this pull request Jan 7, 2015
* fix-jetty9-jar-url:
  Fix potential Jetty MalformedURLException
izeye pushed a commit to izeye/spring-boot that referenced this pull request Jan 10, 2015
Update JettyEmbeddedServletContainerFactory to use the JarResource
class to create the base resource. This prevents a potential
"java.lang.NullPointerException: no !/ in spec" error which can occur
when using shaded executable jars.

Fixes spring-projectsgh-2245
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: bug A general bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants