OSX Play Framework Auto-Reload

2019-02-25 01:04发布

问题:

I've been scouring the internet for hours now, there is lots of "helpful" advice...that cause nothing but problems.

This is me, almost exactly:

Play framework auto-loading in docker container

I'm running the latest (I think, don't know how to check but downloaded < a week ago) version of the Play! Framework inside a ubuntu docker container with Java 8, built with the following dockerfile:

FROM ubuntu:latest
MAINTAINER [REDACTED]
RUN sudo apt-get update
RUN sudo apt-get -y install software-properties-common
RUN sudo apt-add-repository ppa:webupd8team/java
RUN sudo apt-get update
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
RUN sudo apt-get -y install oracle-java8-installer
RUN java -version

Multiple sources across the internet show the same or similar issues, and more or less arrive at the same conclusion. I'm starting my play application as follows:

I'm not going to repeat what's linked above, it's basically an identical situation. (The file changes are detected, it's showing a compile, though webpage doesn't reflect changes.) Further, I'm verifying a correct compile by decompiling the generated .class files, it's showing the correct code.

Now, when I say the magic words: Adding the following line to my build.sbt file

PlayKeys.playWatchService := play.sbtplugin.run.PlayWatchService.sbt(pollInterval.value)

I get an overall build.sbt of:

name := """cms-work"""

version := "1.0-SNAPSHOT"

retrieveManaged := true

lazy val root = (project in file(".")).enablePlugins(PlayJava)

scalaVersion := "2.11.6"

libraryDependencies ++= Seq(
  javaJdbc,
  cache,
  javaWs
)

// Play provides two styles of routers, one expects its actions to be injected, the
// other, legacy style, accesses its actions statically.
routesGenerator := InjectedRoutesGenerator

// Polling for auto-reload, because networked filesystem.
PlayKeys.playWatchService := play.sbtplugin.run.PlayWatchService.sbt(pollInterval.value)

Running ./activator in my project directory causes it to reevaluate my build file and generate the following:

/root/cms-work/build.sbt:23: error: value playWatchService is not a member of object play.sbt.Play.autoImport.PlayKeys
PlayKeys.playWatchService := play.sbtplugin.run.PlayWatchService.sbt(pollInterval.value)
         ^
[error] Type error in expression

As is apparent, the one-size-fits-all solution is no longer applicable. I've been stumped since. I've found absolutely no notice of any changes since 2.3.x that would make this command invalid. Instead, I see things mentioning "works after 2.3.2", which I am.

PS:

Can anyone explain the odd Ctrl-D behavior described at the end of the linked post. I'm experiencing the same, seems very odd considering the fact that Ctrl-D is supposed to exit...

回答1:

Ok, more internet scouring, and I finally broke down and dug through the Play! Framework github to find their test built.sbt, which happened to be using the new option.

Apparently, buried deep in the migration guide this was noted. (Took me a while to retrospectively find it.)

My mistake, apparently, lied in the assumption that 2.4.0 was included in 2.3.2+, without checking the well-hidden (in my humble opinion) documentation. For anyone else who comes stumbling along with a similar situation, look no further:

PlayKeys.fileWatchService := play.sbtplugin.run.PlayWatchService.sbt(pollInterval.value)

This is the new syntax for the play polling, as of 2.4.0. Check the migration reports up to the version you are using if this causes another error to see if they've changed it again.


Just wondering, am I crazy to have expected some sort of This is Deprecated message to be spit out instead of just blind condemnation of all that I've done? That seems like something that would be good to add for the future.



回答2:

error: value playWatchService is not a member of object play.sbt.Play.autoImport.PlayKeys

error: object sbtplugin is not a member of package play

In the Playframework 2.4.X, the SBT setting key playWatchService has been renamed to fileWatchService.

Also the corresponding class has changed. To set the FileWatchService to poll every two seconds, use it like this:

scala PlayKeys.fileWatchService := play.runsupport.FileWatchService.sbt(2000)

Extracted from: https://www.playframework.com/documentation/2.4.x/Migration24#playWatchService-renamed