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

Error when loading static content using AKKA-HTTP Java #2247

Open
chineduekwunife opened this issue Oct 8, 2018 · 17 comments
Open

Error when loading static content using AKKA-HTTP Java #2247

chineduekwunife opened this issue Oct 8, 2018 · 17 comments
Labels
1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted hackathon Issues that could be tackled during a hackathon help wanted Identifies issues that the core team will likely not have time to work on t:docs Issues related to the documentation t:routing Issues related to the routing DSL t:server Issues related to the HTTP server

Comments

@chineduekwunife
Copy link

chineduekwunife commented Oct 8, 2018

I'm trying out AKKA-Http in Java for the first time(akka-http_2.12 v 10.1.5, akka-stream_2.12 v 2.5.17), but can't seem to load static content for swagger UI. I've added the routes below and able to reach the json and yaml swagger endpoints via http://localhost:8080/api-docs/swagger.json and http://localhost:8080/api-docs/swagger.yaml However, the swagger UI endpoint i.e http://localhost:8080/swagger returns with 'There was an internal server error.' even though I have swagger-ui directory under src/main/resources folder. I've inspected the logs and don't quite understand what is happening..seems like a bug in getFromResource and getFromResourceDirectory functions. Similar issue was reported earlier

Route createRoute() {
        return route(
                path(PathMatchers.segment(generator.apiDocsPath()).slash("swagger.yaml"),
                () -> get(() -> complete(generator.generateSwaggerYaml()))),
                path(PathMatchers.segment(generator.apiDocsPath()).slash("swagger.json"),
                        () -> get(() -> complete(generator.generateSwaggerJson()))),
                path("swagger", () -> route (
                        getFromResource("swagger-ui/index.html"),
                        getFromResourceDirectory("swagger-ui")
                        )
                )
        );
    }

akka-spring-docker-system | 2018-10-06 08:27:11.292 ERROR 9 --- [lt-dispatcher-8] akka.actor.ActorSystemImpl               : Error during processing of request: 'java.lang.NullPointerException (No error message supplied)'. Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler.
akka-spring-docker-system | 
akka-spring-docker-system | java.lang.NullPointerException: null
akka-spring-docker-system |     at akka.http.scaladsl.server.directives.FileAndResourceDirectives$ResourceFile$.apply(FileAndResourceDirectives.scala:286) ~[akka-http_2.12-10.1.5.jar!/:10.1.5]
akka-spring-docker-system |     at akka.http.scaladsl.server.directives.FileAndResourceDirectives.$anonfun$getFromResource$2(FileAndResourceDirectives.scala:106) ~[akka-http_2.12-10.1.5.jar!/:10.1.5]
akka-spring-docker-system |     at scala.Option.flatMap(Option.scala:171) ~[scala-library-2.12.4.jar!/:na]
akka-spring-docker-system |     at akka.http.scaladsl.server.directives.FileAndResourceDirectives.$anonfun$getFromResource$1(FileAndResourceDirectives.scala:106) ~[akka-http_2.12-10.1.5.jar!/:10.1.5]
@johanandren
Copy link
Member

Trying to load a resource that isn't on the classpath returns null so it seems likely that is what is causing the NPE, if you look in your target directory, did the swagger-ui directory get copied somewhere there when you built your project? Also, when you run, is that somwhere added to the classpath (you can inspect your JVM process classpath with jvisualvm or jinfo)?

@chineduekwunife
Copy link
Author

Trying to load a resource that isn't on the classpath returns null so it seems likely that is what is causing the NPE, if you look in your target directory, did the swagger-ui directory get copied somewhere there when you built your project? Also, when you run, is that somwhere added to the classpath (you can inspect your JVM process classpath with jvisualvm or jinfo)?

@johanandren

I've inspected the jar file and can find swagger-ui files in the classpath

c@c-VirtualBox:~/Projects/java/akka-spring-docker/code/akka-spring-docker-system/target$ jar -tf akka-spring-docker-system-1.0-SNAPSHOT.jar | grep swagger
BOOT-INF/classes/swagger-ui/
BOOT-INF/classes/swagger-ui/lib/
BOOT-INF/classes/swagger-ui/css/
BOOT-INF/classes/swagger-ui/images/
BOOT-INF/classes/swagger-ui/fonts/
BOOT-INF/classes/swagger-ui/lib/highlight.7.3.pack.js
BOOT-INF/classes/swagger-ui/lib/swagger-oauth.js
BOOT-INF/classes/swagger-ui/lib/underscore-min.map
BOOT-INF/classes/swagger-ui/index.html
BOOT-INF/classes/swagger-ui/images/pet_store_api.png
BOOT-INF/classes/swagger-ui/images/logo_small.png
BOOT-INF/classes/swagger-ui/images/favicon.ico
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.woff2
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.svg
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.ttf
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.eot
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.svg
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.woff
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.ttf
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.woff
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.woff2
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.eot
BOOT-INF/classes/swagger-ui/lib/marked.js
BOOT-INF/classes/swagger-ui/lib/underscore-min.js
BOOT-INF/classes/swagger-ui/lib/backbone-min.js
BOOT-INF/classes/swagger-ui/lib/jquery.slideto.min.js
BOOT-INF/classes/swagger-ui/lib/jquery-1.8.0.min.js
BOOT-INF/classes/swagger-ui/lib/handlebars-2.0.0.js
BOOT-INF/classes/swagger-ui/lib/jquery.wiggle.min.js
BOOT-INF/classes/swagger-ui/lib/jquery.ba-bbq.min.js
BOOT-INF/classes/swagger-ui/css/reset.css
BOOT-INF/classes/swagger-ui/css/print.css
BOOT-INF/classes/swagger-ui/css/screen.css
BOOT-INF/classes/swagger-ui/css/typography.css
BOOT-INF/classes/swagger-ui/images/favicon-32x32.png
BOOT-INF/classes/swagger-ui/images/throbber.gif
BOOT-INF/classes/swagger-ui/images/wordnik_api.png
BOOT-INF/classes/swagger-ui/images/explorer_icons.png
BOOT-INF/classes/swagger-ui/images/favicon-16x16.png
BOOT-INF/classes/swagger-ui/o2c.html
BOOT-INF/classes/swagger-ui/swagger-ui.js
BOOT-INF/classes/swagger-ui/swagger-ui.min.js
BOOT-INF/lib/swagger-akka-http_2.12-0.14.0.jar
BOOT-INF/lib/swagger-core-1.5.18.jar
BOOT-INF/lib/swagger-annotations-1.5.18.jar
BOOT-INF/lib/swagger-models-1.5.18.jar
BOOT-INF/lib/swagger-jaxrs-1.5.18.jar

@chineduekwunife
Copy link
Author

chineduekwunife commented Oct 8, 2018

@johanandren

A closer look at the code in FileAndResourceDirectives.scala, seems that null is returned for directories, which might explain the NPE.

case "jar" ⇒
        val path = new URI(url.getPath).getPath // remove "file:" prefix and normalize whitespace
        val bangIndex = path.indexOf('!')
        val filePath = path.substring(0, bangIndex)
        val resourcePath = path.substring(bangIndex + 2)
        val jar = new java.util.zip.ZipFile(filePath)
        try {
          val entry = jar.getEntry(resourcePath)
          if (entry.isDirectory) None
          else Option(jar.getInputStream(entry)) map { is ⇒
            is.close()
            ResourceFile(url, entry.getSize, entry.getTime)
          }
        } finally jar.close()

@johanandren
Copy link
Member

johanandren commented Oct 9, 2018

Doc on ZipFile.getEntry says null if not found. So I think the entry you expect is missing somehow. We should probably handle that and return a None if entry is null rather than fail though.

@jrudolph jrudolph added bug 1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted t:server Issues related to the HTTP server t:routing Issues related to the routing DSL labels Oct 9, 2018
@jrudolph
Copy link
Contributor

jrudolph commented Oct 9, 2018

Doc on ZipFile.getEntry says null if not found. So I think the entry you expect is missing somehow. We should probably handle that and return a None if entry is null rather than fail though.

Probably, it's because the BOOT-INF part of the resource path is missing?

I guess, before we added the entry.isDirectory part, Option(jar.getInputStream(entry)) was actually guarding against missing files but now it fails even before and it seems we are missing a test case for the case when getFromResource points to a missing file.

Btw:

path("swagger", () -> route (
                        getFromResource("swagger-ui/index.html"),
                        getFromResourceDirectory("swagger-ui")
                        )

I wonder why that works at all. Shouldn't getFromResource("swagger-ui/index.html"), be guarded by pathEndOrSingleSlash or something else?

@chineduekwunife
Copy link
Author

chineduekwunife commented Oct 9, 2018

@johanandren @jrudolph

The exception is thrown at line 286 of FileAndResourceDirectives.scala if (entry.isDirectory) None
Which suggests that the entry is present, but because it is a directory, None was returned which will cause a NPE.

Also, I added pathEndOrSingleSlash and got the same NPE result as before.

 Route createRoute() {
        return route(
                path(PathMatchers.segment(generator.apiDocsPath()).slash("swagger.yaml"),
                () -> get(() -> complete(generator.generateSwaggerYaml()))),
                path(PathMatchers.segment(generator.apiDocsPath()).slash("swagger.json"),
                        () -> get(() -> complete(generator.generateSwaggerJson()))),
                path("swagger", () -> route (
                        pathEndOrSingleSlash(() -> getFromResource("swagger-ui/index.html")),
                        pathEndOrSingleSlash(() -> getFromResourceDirectory("swagger-ui"))
                        )
                )
        );
    }

@johanandren
Copy link
Member

johanandren commented Oct 9, 2018

It's not because None is returned, it is because entry is null, which causes a NPE when we try to call isDirectory on it.

@chineduekwunife
Copy link
Author

OK then, so below comment from @jrudolph could be the fix for jar files

Probably, it's because the BOOT-INF part of the resource path is missing?

@jrudolph
Copy link
Contributor

jrudolph commented Oct 9, 2018

Probably, it's because the BOOT-INF part of the resource path is missing?

Actually, that statement was a bit sloppy. In fact, it depends how your classloaders are set up. It seems you are using some spring stuff, so it will depend on how your application is deployed exactly (we cannot really help with that).

Regarding your routes, this is still not correct:

                path("swagger", () -> route (
                        pathEndOrSingleSlash(() -> getFromResource("swagger-ui/index.html")),
                        pathEndOrSingleSlash(() -> getFromResourceDirectory("swagger-ui"))
                        )

It should be more like this:

pathPrefix("swagger", () -> route ( // everything that's inside `/swagger`
                        pathEndOrSingleSlash(() -> getFromResource("swagger-ui/index.html")), // `/swagger/` or `/swagger`
                        getFromResourceDirectory("swagger-ui") // everything else in `/swagger/...`
                        )

I marked this issue as a bug, because we need to improve the error message and not throw an NPE when a resource cannot be found.

@jrudolph
Copy link
Contributor

jrudolph commented Oct 9, 2018

The classloader / spring issue probably isn't a bug so it would make sense to continue those discussions on discuss.akka.io.

@chineduekwunife
Copy link
Author

@jrudolph Most java applications use Spring, so I think it'll make sense to add support for Spring class loaders. For reference, below is the full content of the files in my jar file

c@c-VirtualBox:~/Projects/java/akka-spring-docker/code/akka-spring-docker-system/target$ jar -tf akka-spring-docker-system-1.0-SNAPSHOT.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/springframework/
org/springframework/boot/
org/springframework/boot/loader/
org/springframework/boot/loader/data/
org/springframework/boot/loader/data/RandomAccessDataFile$1.class
org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class
org/springframework/boot/loader/jar/
org/springframework/boot/loader/jar/JarFileEntries$1.class
org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class
org/springframework/boot/loader/jar/JarFileEntries.class
org/springframework/boot/loader/jar/CentralDirectoryVisitor.class
org/springframework/boot/loader/jar/JarEntryFilter.class
org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class
org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class
org/springframework/boot/loader/jar/CentralDirectoryParser.class
org/springframework/boot/loader/jar/ZipInflaterInputStream.class
org/springframework/boot/loader/jar/Handler.class
org/springframework/boot/loader/archive/
org/springframework/boot/loader/archive/Archive$Entry.class
org/springframework/boot/loader/archive/Archive$EntryFilter.class
org/springframework/boot/loader/archive/Archive.class
org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator$EntryComparator.class
org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator.class
org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class
org/springframework/boot/loader/archive/ExplodedArchive$1.class
org/springframework/boot/loader/archive/ExplodedArchive.class
org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class
org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class
org/springframework/boot/loader/archive/JarFileArchive.class
org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class
org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class
org/springframework/boot/loader/PropertiesLauncher$1.class
org/springframework/boot/loader/PropertiesLauncher.class
org/springframework/boot/loader/Launcher.class
org/springframework/boot/loader/MainMethodRunner.class
org/springframework/boot/loader/ExecutableArchiveLauncher.class
org/springframework/boot/loader/WarLauncher.class
org/springframework/boot/loader/JarLauncher.class
org/springframework/boot/loader/util/
org/springframework/boot/loader/util/SystemPropertyUtils.class
org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
org/springframework/boot/loader/LaunchedURLClassLoader.class
org/springframework/boot/loader/data/RandomAccessData.class
org/springframework/boot/loader/jar/AsciiBytes.class
org/springframework/boot/loader/data/RandomAccessDataFile.class
org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class
org/springframework/boot/loader/jar/JarURLConnection$1.class
org/springframework/boot/loader/jar/Bytes.class
org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class
org/springframework/boot/loader/jar/JarURLConnection.class
org/springframework/boot/loader/jar/JarFile$1.class
org/springframework/boot/loader/jar/JarFile$2.class
org/springframework/boot/loader/jar/JarFile$JarFileType.class
org/springframework/boot/loader/jar/JarFile.class
org/springframework/boot/loader/jar/JarEntry.class
org/springframework/boot/loader/jar/FileHeader.class
org/springframework/boot/loader/jar/StringSequence.class
BOOT-INF/
BOOT-INF/classes/
BOOT-INF/classes/com/
BOOT-INF/classes/com/nedu/
BOOT-INF/classes/com/nedu/akkahttp/
BOOT-INF/classes/com/nedu/akkahttp/config/
BOOT-INF/classes/com/nedu/akkahttp/routes/
BOOT-INF/classes/swagger-ui/
BOOT-INF/classes/swagger-ui/lib/
BOOT-INF/classes/swagger-ui/css/
BOOT-INF/classes/swagger-ui/images/
BOOT-INF/classes/swagger-ui/fonts/
META-INF/maven/
META-INF/maven/com.nedu.akka-http/
META-INF/maven/com.nedu.akka-http/akka-spring-docker-system/
BOOT-INF/classes/application.conf
BOOT-INF/classes/com/nedu/akkahttp/config/SpringActorProducer.class
BOOT-INF/classes/com/nedu/akkahttp/config/AkkaSpringConfig.class
BOOT-INF/classes/com/nedu/akkahttp/Application.class
BOOT-INF/classes/com/nedu/akkahttp/SwaggerRunner.class
BOOT-INF/classes/com/nedu/akkahttp/routes/UserRoutes.class
BOOT-INF/classes/com/nedu/akkahttp/routes/AppRoutes.class
BOOT-INF/classes/com/nedu/akkahttp/AppRunner.class
BOOT-INF/classes/com/nedu/akkahttp/SwaggerRunner$1.class
BOOT-INF/classes/application.properties
BOOT-INF/classes/swagger-ui/lib/highlight.7.3.pack.js
BOOT-INF/classes/swagger-ui/lib/swagger-oauth.js
BOOT-INF/classes/swagger-ui/lib/underscore-min.map
BOOT-INF/classes/swagger-ui/lib/marked.js
BOOT-INF/classes/swagger-ui/lib/underscore-min.js
BOOT-INF/classes/swagger-ui/lib/backbone-min.js
BOOT-INF/classes/swagger-ui/lib/jquery.slideto.min.js
BOOT-INF/classes/swagger-ui/lib/jquery-1.8.0.min.js
BOOT-INF/classes/swagger-ui/lib/handlebars-2.0.0.js
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.woff2
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.svg
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.ttf
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.eot
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.svg
BOOT-INF/classes/com/nedu/akkahttp/Supervisor.class
BOOT-INF/classes/swagger-ui/css/reset.css
BOOT-INF/classes/swagger-ui/css/print.css
BOOT-INF/classes/swagger-ui/css/typography.css
BOOT-INF/classes/swagger-ui/index.html
BOOT-INF/classes/swagger-ui/images/throbber.gif
BOOT-INF/classes/swagger-ui/images/favicon.ico
BOOT-INF/classes/swagger-ui/o2c.html
BOOT-INF/classes/swagger-ui/swagger-ui.min.js
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.woff
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.ttf
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.woff
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-regular.woff2
BOOT-INF/classes/swagger-ui/fonts/droid-sans-v6-latin-700.eot
BOOT-INF/classes/git.properties
META-INF/maven/com.nedu.akka-http/akka-spring-docker-system/pom.xml
META-INF/maven/com.nedu.akka-http/akka-spring-docker-system/pom.properties
BOOT-INF/classes/com/nedu/akkahttp/config/SpringExtension.class
BOOT-INF/classes/swagger-ui/lib/jquery.wiggle.min.js
BOOT-INF/classes/swagger-ui/lib/jquery.ba-bbq.min.js
BOOT-INF/classes/swagger-ui/css/screen.css
BOOT-INF/classes/swagger-ui/images/favicon-32x32.png
BOOT-INF/classes/swagger-ui/images/pet_store_api.png
BOOT-INF/classes/swagger-ui/images/logo_small.png
BOOT-INF/classes/swagger-ui/images/wordnik_api.png
BOOT-INF/classes/swagger-ui/images/explorer_icons.png
BOOT-INF/classes/swagger-ui/images/favicon-16x16.png
BOOT-INF/classes/swagger-ui/swagger-ui.js
BOOT-INF/lib/
BOOT-INF/lib/actor-common-1.0-SNAPSHOT.jar
BOOT-INF/lib/event-log-1.0-SNAPSHOT.jar
BOOT-INF/lib/user-registry-1.0-SNAPSHOT.jar
BOOT-INF/lib/swagger-akka-http_2.12-0.14.0.jar
BOOT-INF/lib/scala-library-2.12.4.jar
BOOT-INF/lib/scala-java8-compat_2.12-0.8.0.jar
BOOT-INF/lib/swagger-core-1.5.18.jar
BOOT-INF/lib/commons-lang3-3.7.jar
BOOT-INF/lib/jackson-annotations-2.9.0.jar
BOOT-INF/lib/validation-api-2.0.1.Final.jar
BOOT-INF/lib/swagger-annotations-1.5.18.jar
BOOT-INF/lib/swagger-models-1.5.18.jar
BOOT-INF/lib/slf4j-api-1.7.25.jar
BOOT-INF/lib/jackson-module-scala_2.12-2.9.6.jar
BOOT-INF/lib/scala-reflect-2.12.6.jar
BOOT-INF/lib/jackson-core-2.9.6.jar
BOOT-INF/lib/jackson-module-paranamer-2.9.6.jar
BOOT-INF/lib/paranamer-2.8.jar
BOOT-INF/lib/jackson-dataformat-yaml-2.9.6.jar
BOOT-INF/lib/swagger-jaxrs-1.5.18.jar
BOOT-INF/lib/jackson-databind-2.9.6.jar
BOOT-INF/lib/jsr311-api-1.1.1.jar
BOOT-INF/lib/reflections-0.9.11.jar
BOOT-INF/lib/javassist-3.21.0-GA.jar
BOOT-INF/lib/guava-20.0.jar
BOOT-INF/lib/javax.ws.rs-api-2.1.1.jar
BOOT-INF/lib/akka-http-cors_2.12-0.3.0.jar
BOOT-INF/lib/spring-boot-starter-2.0.5.RELEASE.jar
BOOT-INF/lib/spring-boot-2.0.5.RELEASE.jar
BOOT-INF/lib/spring-boot-autoconfigure-2.0.5.RELEASE.jar
BOOT-INF/lib/spring-boot-starter-logging-2.0.5.RELEASE.jar
BOOT-INF/lib/logback-classic-1.2.3.jar
BOOT-INF/lib/logback-core-1.2.3.jar
BOOT-INF/lib/log4j-to-slf4j-2.10.0.jar
BOOT-INF/lib/log4j-api-2.10.0.jar
BOOT-INF/lib/jul-to-slf4j-1.7.25.jar
BOOT-INF/lib/javax.annotation-api-1.3.2.jar
BOOT-INF/lib/spring-core-5.0.9.RELEASE.jar
BOOT-INF/lib/spring-jcl-5.0.9.RELEASE.jar
BOOT-INF/lib/snakeyaml-1.19.jar
BOOT-INF/lib/spring-boot-starter-jdbc-2.0.5.RELEASE.jar
BOOT-INF/lib/spring-jdbc-5.0.9.RELEASE.jar
BOOT-INF/lib/spring-tx-5.0.9.RELEASE.jar
BOOT-INF/lib/akka-http_2.12-10.1.5.jar
BOOT-INF/lib/akka-http-core_2.12-10.1.5.jar
BOOT-INF/lib/akka-parsing_2.12-10.1.5.jar
BOOT-INF/lib/akka-stream_2.12-2.5.17.jar
BOOT-INF/lib/akka-actor_2.12-2.5.17.jar
BOOT-INF/lib/config-1.3.3.jar
BOOT-INF/lib/akka-protobuf_2.12-2.5.17.jar
BOOT-INF/lib/reactive-streams-1.0.2.jar
BOOT-INF/lib/ssl-config-core_2.12-0.2.4.jar
BOOT-INF/lib/scala-parser-combinators_2.12-1.1.1.jar
BOOT-INF/lib/akka-http-jackson_2.12-10.1.5.jar
BOOT-INF/lib/akka-slf4j_2.12-2.5.17.jar
BOOT-INF/lib/lombok-1.18.2.jar
BOOT-INF/lib/jool-java-8-0.9.13.jar
BOOT-INF/lib/spring-context-5.0.9.RELEASE.jar
BOOT-INF/lib/spring-aop-5.0.9.RELEASE.jar
BOOT-INF/lib/spring-beans-5.0.9.RELEASE.jar
BOOT-INF/lib/spring-expression-5.0.9.RELEASE.jar
BOOT-INF/lib/jooq-3.10.8.jar
BOOT-INF/lib/jooq-meta-extensions-3.10.8.jar
BOOT-INF/lib/h2-1.4.197.jar
BOOT-INF/lib/hibernate-core-5.2.17.Final.jar
BOOT-INF/lib/jboss-logging-3.3.2.Final.jar
BOOT-INF/lib/hibernate-jpa-2.1-api-1.0.2.Final.jar
BOOT-INF/lib/antlr-2.7.7.jar
BOOT-INF/lib/jboss-transaction-api_1.2_spec-1.0.1.Final.jar
BOOT-INF/lib/jandex-2.0.3.Final.jar
BOOT-INF/lib/classmate-1.3.4.jar
BOOT-INF/lib/dom4j-1.6.1.jar
BOOT-INF/lib/hibernate-commons-annotations-5.0.1.Final.jar
BOOT-INF/lib/jooq-meta-3.10.8.jar
BOOT-INF/lib/jooq-codegen-maven-3.10.8.jar
BOOT-INF/lib/jooq-codegen-3.10.8.jar
BOOT-INF/lib/maven-plugin-api-2.2.1.jar
BOOT-INF/lib/maven-project-2.2.1.jar
BOOT-INF/lib/maven-settings-2.2.1.jar
BOOT-INF/lib/maven-profile-2.2.1.jar
BOOT-INF/lib/maven-model-2.2.1.jar
BOOT-INF/lib/maven-artifact-manager-2.2.1.jar
BOOT-INF/lib/maven-repository-metadata-2.2.1.jar
BOOT-INF/lib/wagon-provider-api-1.0-beta-6.jar
BOOT-INF/lib/backport-util-concurrent-3.1.jar
BOOT-INF/lib/maven-plugin-registry-2.2.1.jar
BOOT-INF/lib/plexus-interpolation-1.11.jar
BOOT-INF/lib/plexus-utils-1.5.15.jar
BOOT-INF/lib/maven-artifact-2.2.1.jar
BOOT-INF/lib/plexus-container-default-1.0-alpha-9-stable-1.jar
BOOT-INF/lib/classworlds-1.1-alpha-2.jar
BOOT-INF/lib/postgresql-42.2.5.jar
BOOT-INF/lib/HikariCP-3.2.0.jar
BOOT-INF/lib/junit-4.12.jar
BOOT-INF/lib/hamcrest-core-1.3.jar

@jrudolph
Copy link
Contributor

jrudolph commented Oct 9, 2018

It doesn't only depend on the contents of jar files but how the custom classloaders in your environment deal with those jar files. That's something we cannot debug here (but if you find out, it would make sense to add to the documentation).

@chineduekwunife
Copy link
Author

@jrudolph I got it working by adding BOOT-INF to the path as follows

  return route(
                path(PathMatchers.segment(generator.apiDocsPath()).slash("swagger.yaml"),
                () -> get(() -> complete(generator.generateSwaggerYaml()))),
                path(PathMatchers.segment(generator.apiDocsPath()).slash("swagger.json"),
                        () -> get(() -> complete(generator.generateSwaggerJson()))),
                pathPrefix("swagger", () -> route ( // everything that's inside `/swagger`
                        pathEndOrSingleSlash(() -> getFromResource("BOOT-INF/classes/swagger-ui/index.html")), // `/swagger/` or `/swagger`
                        getFromResourceDirectory("BOOT-INF/classes/swagger-ui") // everything else in `/swagger/...`
                )
        ));

@jrudolph
Copy link
Contributor

@chineduekwunife-kcom great!

@baseman
Copy link

baseman commented Dec 7, 2018

Ran into the exact same problem. When trying to pull a resource using getFromResource when in a spring boot classloader is in the mix... null reference is throw when it cannot find the resourcePath.

I don't think it's been said... Spring Boot class loader is doing this to the resource url ...
BOOT-INF/classes!/swagger/index.html
----notice the ! -----^

I know this is an implementation detail brought to you by Spring Boot & Company (see spring-projects/spring-boot#7096), but can't akka-http team provide a simple directive for handling boot loader implementation rather than guys like us having to write hacks or custom directives for a spring boot class loader? The above direct path to BOOT-INF is kinda hacky and will only work when referring to resource directory from jar.

@jrudolph jrudolph added help wanted Identifies issues that the core team will likely not have time to work on t:docs Issues related to the documentation hackathon Issues that could be tackled during a hackathon and removed bug labels Aug 6, 2019
@jrudolph
Copy link
Contributor

jrudolph commented Aug 6, 2019

Maybe, even if it's completely unrelated to akka-http, let's document for the getFromResource* directives that your resources might have different paths than expected? For getFromResource we should create a better exception if a resource isn't found.

@jrudolph
Copy link
Contributor

jrudolph commented Aug 6, 2019

For getFromResource we should create a better exception if a resource isn't found.

I guess it already works correctly for simple class loaders. It seems that the spring class loader delivers an invalid URL for ClassLoader.getResource even if a resource cannot be found (when it should return null). Not sure if we can or should do something about this (other than adding documentation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted hackathon Issues that could be tackled during a hackathon help wanted Identifies issues that the core team will likely not have time to work on t:docs Issues related to the documentation t:routing Issues related to the routing DSL t:server Issues related to the HTTP server
Projects
None yet
Development

No branches or pull requests

4 participants