-
Notifications
You must be signed in to change notification settings - Fork 11
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
multi-module-app part 2: classpath resources #506
base: main
Are you sure you want to change the base?
multi-module-app part 2: classpath resources #506
Conversation
Add IDEA configuration for Multi module app. While at it, enable "netty3" as backend, but as "runtimeOnly" dependency to not to interfere with tests.
While the inclusion of 'icons/favicon.html' template itself working, the referenced '/img/favicon.png' -> 'public/images/favicon.png' file is served as HTTP 404.
All the PlayHandler.serverStatic() methods uses the common ServerHelper.findFile(). Let it know how to handle classpath resources with the logic from play.templates.TemplateLoader.loadTemplateFromClasspath().
While the #{include /} tag worked with the earlier example, it doesn't work with relative templates. To reproduce surely, please clean up the tmpDir before testing! An already existing ./meta.html in the tmpDir will success the test! play.template2.exceptions.GTRuntimeExceptionWithSourceInfo: Cannot find template ./meta.html at /tmp/hello.html.(line:6) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:146) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:110) at play.modules.gtengineplugin.gt_integration.GTJavaBase1xImpl.internalRenderTemplate(GTJavaBase1xImpl.java:96) at play.template2.GTJavaBase.renderTemplate(GTJavaBase.java:104) at play.modules.gtengineplugin.GTTemplate.renderGTTemplate(GTTemplate.java:67) at play.modules.gtengineplugin.GTTemplate.internalGTRender(GTTemplate.java:54) at play.modules.gtengineplugin.GTTemplate.internalRender(GTTemplate.java:38) at play.modules.gtengineplugin.GTTemplate.render(GTTemplate.java:73) at play.rebel.View.renderView(View.java:71) at play.rebel.View.apply(View.java:50) at play.mvc.ActionInvoker.applyResult(ActionInvoker.java:191) at play.mvc.ActionInvoker.invoke(ActionInvoker.java:158) at play.server.javanet.PlayHandler$JavaNetInvocation.execute(PlayHandler.java:434) at play.server.javanet.PlayHandler$JavaNetInvocation.lambda$run$0(PlayHandler.java:409) at play.db.jpa.JPA.withTransaction(JPA.java:271) at play.db.jpa.JPA.withinFilter(JPA.java:172) at play.server.javanet.PlayHandler$JavaNetInvocation.run(PlayHandler.java:407) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) Caused by: play.template2.exceptions.GTTemplateRuntimeException: Cannot find template ./meta.html at play.template2.compile.GTInternalFastTags.tag_include(GTInternalFastTags.java:119) ... 24 more
This comment was marked as outdated.
This comment was marked as outdated.
06b3e13
to
71aa0b9
Compare
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neat!
@@ -78,12 +80,32 @@ public GTTemplateLocationReal getTemplateLocationFromRelativePath(String relativ | |||
|
|||
// TODO find in classpath? | |||
File vf = Play.file(relativePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think vf
here is a remnant of the VirtualFile
that's no longer in RePlay. Maybe rename to file
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep its a remnant, but I don't care for now!
Maybe I'll add a cleanup commit at the end. 🙂
The referenced configuration files are both on local file system and on classpath. 20:48:18,288 WARN [play.PropertiesConfLoader] ~ Missing include: @include.core java.lang.NullPointerException: File not found in classpath: application.core.conf at java.base/java.util.Objects.requireNonNull(Objects.java:336) at play.ClasspathResource.<init>(ClasspathResource.java:42) at play.ClasspathResource.file(ClasspathResource.java:26) at play.PropertiesConfLoader.readOneConfigurationFile(PropertiesConfLoader.java:52) at play.PropertiesConfLoader.resolveIncludes(PropertiesConfLoader.java:143) at play.PropertiesConfLoader.readOneConfigurationFile(PropertiesConfLoader.java:71) at play.PropertiesConfLoader.readOneConfigurationFile(PropertiesConfLoader.java:47) at play.PropertiesConfLoader.readConfiguration(PropertiesConfLoader.java:43) at play.Play.readConfiguration(Play.java:221) at play.Play.start(Play.java:237) at hello.HelloWorldApp.start(HelloWorldApp.java:18) at hello.HelloWorldApp.main(HelloWorldApp.java:22) 20:48:18,288 WARN [play.PropertiesConfLoader] ~ Missing include: @include.app java.lang.NullPointerException: File not found in classpath: application.app.conf at java.base/java.util.Objects.requireNonNull(Objects.java:336) at play.ClasspathResource.<init>(ClasspathResource.java:42) at play.ClasspathResource.file(ClasspathResource.java:26) at play.PropertiesConfLoader.readOneConfigurationFile(PropertiesConfLoader.java:52) at play.PropertiesConfLoader.resolveIncludes(PropertiesConfLoader.java:143) at play.PropertiesConfLoader.readOneConfigurationFile(PropertiesConfLoader.java:71) at play.PropertiesConfLoader.readOneConfigurationFile(PropertiesConfLoader.java:47) at play.PropertiesConfLoader.readConfiguration(PropertiesConfLoader.java:43) at play.Play.readConfiguration(Play.java:221) at play.Play.start(Play.java:237) at hello.HelloWorldApp.start(HelloWorldApp.java:18) at hello.HelloWorldApp.main(HelloWorldApp.java:22)
Fixes: 4a43760 ("Add "filePrefix" parameter to play.PropertiesConfLoader")
1a5cb12
to
6ea9b52
Compare
cfb15b1
to
8797d8f
Compare
Fix Router.reverseWithCheck() calls for classpath resources with the help of ServerHelper.findFile() and with adding a custom route. While at it, improve ServerHelper.findFile() to reuse the extracted classpath resource files. To prevent unwanted leakage of classpath files, the custom route exposes only classpath files with path starting with "public/". This can be improved later.
JavaClassesScanner.allClassesInProject() is used by Play.classes.getAssignableClasses() extensively: $ git grep --files-with-matches 'Play.classes.getAssignableClasses(' fastergt/src/play/modules/gtengineplugin/gt_integration/GTFastTagResolver1x.java fastergt/src/play/modules/gtengineplugin/gt_integration/GTJavaExtensionMethodResolver1x.java fastergt/src/play/modules/gtengineplugin/gt_integration/GTLegacyFastTagResolver1X.java framework/src/play/Play.java framework/src/play/data/binding/Binder.java framework/src/play/db/jpa/JPAPlugin.java framework/src/play/jobs/JobsPlugin.java As the method name "allClassesInProject" says, it only find classes in the actual project, but not in the dependencies. Sure, no need to scan all the classpath, but it would be nice to add a few jars which should be scanned for project classes. In this example the "jobs.CoreJob" startup job (with @onApplicationStart annotation) from the "core" module isn't started. As I don't know how to add HTTP headers to Selenide.download(), the example adds a new route: /status.txt which renders the PlayStatusPlugin's output without authorization.
While tags in "app" detected, the tags in "core" are not found: 18:36:39,076 ERROR [play.server.javanet.PlayHandler] ~ Internal Server Error (500) for GET / (GTCompilationExceptionWithSourceInfo) play.template2.exceptions.GTCompilationExceptionWithSourceInfo: CompilationError: Cannot find tag-implementation for 'core.hello'. Template /my_tmpdir_in_the_workdir/classpathtemplates/hello.html:11 at play.template2.compile.GTPreCompiler.generateTagCode(GTPreCompiler.java:884) at play.template2.compile.GTPreCompiler.processTag(GTPreCompiler.java:727) at play.template2.compile.GTPreCompiler.processTag(GTPreCompiler.java:714) at play.template2.compile.GTPreCompiler.processNextFragment(GTPreCompiler.java:474) at play.template2.compile.GTPreCompiler.internalCompile(GTPreCompiler.java:184) at play.template2.compile.GTPreCompiler.compile(GTPreCompiler.java:135) at play.template2.compile.GTPreCompiler.compile(GTPreCompiler.java:128) at play.template2.compile.GTCompiler.compile(GTCompiler.java:57) at play.template2.GTTemplateRepo.compileTemplate(GTTemplateRepo.java:293) at play.template2.GTTemplateRepo.getTemplateInstance(GTTemplateRepo.java:181) at play.template2.GTTemplateRepo.getTemplateInstance(GTTemplateRepo.java:136) at play.modules.gtengineplugin.TemplateLoader.getGTTemplateInstance(TemplateLoader.java:82) at play.modules.gtengineplugin.TemplateLoader.load(TemplateLoader.java:75) at play.modules.gtengineplugin.GTEnginePlugin.loadTemplate(GTEnginePlugin.java:50) at play.plugins.PluginCollection.lambda$loadTemplate$29(PluginCollection.java:340) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602) at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129) at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647) at play.plugins.PluginCollection.loadTemplate(PluginCollection.java:342) at play.templates.TemplateLoader.load(TemplateLoader.java:42) at play.templates.TemplateLoader.getTemplateFromClasspath(TemplateLoader.java:104) at play.templates.TemplateLoader.load(TemplateLoader.java:84) at play.rebel.View.resolveTemplate(View.java:79) at play.rebel.View.renderView(View.java:60) at play.rebel.View.apply(View.java:50) at play.mvc.ActionInvoker.applyResult(ActionInvoker.java:191) at play.mvc.ActionInvoker.invoke(ActionInvoker.java:158) at play.server.javanet.PlayHandler$JavaNetInvocation.execute(PlayHandler.java:434) at play.server.javanet.PlayHandler$JavaNetInvocation.lambda$run$0(PlayHandler.java:409) at play.db.jpa.JPA.withTransaction(JPA.java:271) at play.db.jpa.JPA.withinFilter(JPA.java:172) at play.server.javanet.PlayHandler$JavaNetInvocation.run(PlayHandler.java:407) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840)
To allow the Framework find your project files in your dependencies, use the "play.classes.scanJars" property in application.conf! E.g: play.classes.scanJars=core-*.jar,my-other-optional-dependency-*.jar
8797d8f
to
b2748c7
Compare
play.templates.TemplateLoader.loadTemplateFromClasspath() uses "Play.tmpDir" for extracting files from classpath. Let use that in this GTFileResolver.Resolver too, with the "view/" search prefix logic. The new included "core.html" template and the tests are just a workaround as the "download()" command doesn't like the GitHub workflow, so that test is marked as @disabled. With the fix, the openHelloWorldPage() got timeout in netty4, so it had to be moved to another spec which is exluded.
This was (unintentionally?) fixed in PR replay-framework#524. For reference, the original description is below. Looks like it never worked since its debut in commit cfe9ff1 ("load "errors/40x.html" templates from classpath"). The serve500 is caused by the "missing" meta.html template, and then the NPE is caused by the "missing" errors/500.html template: 02:52:45,238 TRACE [play.server.netty4.PlayHandler] ~ serve500: begin 02:52:45,240 ERROR [play.server.netty4.PlayHandler] ~ Internal Server Error (500) for GET / (GTRuntimeExceptionWithSourceInfo) play.template2.exceptions.GTRuntimeExceptionWithSourceInfo: Cannot find template ./meta.html at /tmp/hello.html.(line:6) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:146) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:110) at play.modules.gtengineplugin.gt_integration.GTJavaBase1xImpl.internalRenderTemplate(GTJavaBase1xImpl.java:96) at play.template2.GTJavaBase.renderTemplate(GTJavaBase.java:104) at play.modules.gtengineplugin.GTTemplate.renderGTTemplate(GTTemplate.java:67) at play.modules.gtengineplugin.GTTemplate.internalGTRender(GTTemplate.java:54) at play.modules.gtengineplugin.GTTemplate.internalRender(GTTemplate.java:38) at play.modules.gtengineplugin.GTTemplate.render(GTTemplate.java:73) at play.rebel.View.renderView(View.java:71) at play.rebel.View.apply(View.java:50) at play.mvc.ActionInvoker.applyResult(ActionInvoker.java:191) at play.mvc.ActionInvoker.invoke(ActionInvoker.java:158) at play.server.netty4.PlayHandler$Netty4Invocation.execute(PlayHandler.java:278) at play.server.netty4.PlayHandler$Netty4Invocation.lambda$run$0(PlayHandler.java:247) at play.db.jpa.JPA.withTransaction(JPA.java:271) at play.db.jpa.JPA.withinFilter(JPA.java:172) at play.server.netty4.PlayHandler$Netty4Invocation.run(PlayHandler.java:245) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) Caused by: play.template2.exceptions.GTTemplateRuntimeException: Cannot find template ./meta.html at play.template2.compile.GTInternalFastTags.tag_include(GTInternalFastTags.java:119) ... 24 more 02:52:45,242 ERROR [play.server.netty4.PlayHandler] ~ Error during the 500 response generation java.lang.NullPointerException: Cannot invoke "java.io.File.getAbsolutePath()" because "file" is null at play.Play.relativePath(Play.java:376) at play.modules.gtengineplugin.TemplateLoader.load(TemplateLoader.java:69) at play.modules.gtengineplugin.GTEnginePlugin.loadTemplate(GTEnginePlugin.java:50) at play.plugins.PluginCollection.lambda$loadTemplate$29(PluginCollection.java:340) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602) at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129) at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647) at play.plugins.PluginCollection.loadTemplate(PluginCollection.java:342) at play.templates.TemplateLoader.load(TemplateLoader.java:35) at play.templates.TemplateLoader.loadTemplateFromClasspath(TemplateLoader.java:95) at play.templates.TemplateLoader.load(TemplateLoader.java:82) at play.server.ServerHelper.generateErrorResponse(ServerHelper.java:83) at play.server.netty4.PlayHandler.serve500(PlayHandler.java:625) at play.server.netty4.PlayHandler$Netty4Invocation.run(PlayHandler.java:260) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) 02:52:45,242 TRACE [play.server.netty4.PlayHandler] ~ serve500: end Refs: a6db7e1 ("fix concurrency issue in TemplateLoader")
play.templates.TemplateLoader.getTemplateFromClasspath() stores the found templates in the root of Play.tmpDir. Let's store them in the TemplateLoader's own subdirectory!
Tag '@{...}' is for reverse routing, see documentation: https://www.playframework.com/documentation/1.5.x/templates#Actionsor Calling '@{...}' with a resource on a classpath fails with play.exceptions.NoRouteFoundException: 09:54:56,765 ERROR [play.server.javanet.PlayHandler] ~ Internal Server Error (500) for GET / (GTAppClassException) play.template2.exceptions.GTAppClassException: No route found to display file /public/images/favicon.png (file not found) at play.mvc.Router.reverseWithCheck(Router.java:306) at play.modules.gtengineplugin.gt_integration.GTJavaBase1xImpl.__reverseWithCheck(GTJavaBase1xImpl.java:42) at play.modules.gtengineplugin.gt_integration.GTJavaBase1xImpl.__reverseWithCheck_absolute_false(GTJavaBase1xImpl.java:38) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:146) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:110) at play.modules.gtengineplugin.gt_integration.GTJavaBase1xImpl.internalRenderTemplate(GTJavaBase1xImpl.java:96) at play.template2.compile.GTInternalFastTags.tag_include(GTInternalFastTags.java:127) at /my_tmpdir_in_the_workdir/classpathtemplates/hello.html.(line:5) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:146) at play.template2.GTJavaBase.internalRenderTemplate(GTJavaBase.java:110) at play.modules.gtengineplugin.gt_integration.GTJavaBase1xImpl.internalRenderTemplate(GTJavaBase1xImpl.java:96) at play.template2.GTJavaBase.renderTemplate(GTJavaBase.java:104) at play.modules.gtengineplugin.GTTemplate.renderGTTemplate(GTTemplate.java:67) at play.modules.gtengineplugin.GTTemplate.internalGTRender(GTTemplate.java:54) at play.modules.gtengineplugin.GTTemplate.internalRender(GTTemplate.java:38) at play.modules.gtengineplugin.GTTemplate.render(GTTemplate.java:73) at play.rebel.View.renderView(View.java:71) at play.rebel.View.apply(View.java:50) at play.mvc.ActionInvoker.applyResult(ActionInvoker.java:191) at play.mvc.ActionInvoker.invoke(ActionInvoker.java:158) at play.server.javanet.PlayHandler$JavaNetInvocation.execute(PlayHandler.java:434) at play.server.javanet.PlayHandler$JavaNetInvocation.lambda$run$0(PlayHandler.java:409) at play.db.jpa.JPA.withTransaction(JPA.java:271) at play.db.jpa.JPA.withinFilter(JPA.java:172) at play.server.javanet.PlayHandler$JavaNetInvocation.run(PlayHandler.java:407) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:840) Caused by: play.template2.exceptions.GTAppClassException: No route found to display file /public/images/favicon.png (file not found) ... 31 more Caused by: play.exceptions.NoRouteFoundException: No route found to display file /public/images/favicon.png (file not found) ... 31 more
8b0cf08
to
80ddb6e
Compare
80ddb6e
to
4538c99
Compare
I already added a test with custom
How could I do this without duplicating all the test? Or at least, make only the minimal duplications. 🤔 |
77e663a
to
09405a8
Compare
@@ -87,7 +87,7 @@ public GTTemplateLocationReal getTemplateLocationFromRelativePath(String relativ | |||
URL url = null; | |||
if (vf == null) { | |||
try { | |||
final String classloadedPrefix = "/" + Play.tmpDir.getName() + "/"; | |||
final String classloadedPrefix = "/" + Play.tmpDir.getName() + "/" + TemplateLoader.CLASSPATH_LOADED_TEMPLATE_TMP_PATH_PREFIX; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dies with NPE when play.tmpDir=none
is set in the application.conf
, but a fix is ready, just a few tests need to be cooked.
09405a8
to
8d33fd9
Compare
Maybe it's not worth that? Maybe just don't test custom |
Thanks! |
cf906cd
to
9c87a64
Compare
This PR is now ready to review. The commit order is the following (separated by hand):
|
9c87a64
to
8016983
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
This is a continuation of #291's second point:
The "etc" emphasize is mine! 🙂
In the added
hello.html
there was a TODO:So I started to implement those missing bits!
More TODOs:
FastTags
on classpathRouter.reverseWithCheck()
's callers:(fastergt: removeExecutableTemplate
__reverseWithCheck*
methods fromExecutableTemplates
#525),GTJavaBase1xImpl
infastergt
moduleprecompiled/templates
on classpath