Closed ForNeVeR closed 3 years ago
I'm throwing in the towel. I did some work, overcame a bunch of compilation errors, made it run (sort of), but nothing actually works. I pushed the code to feature/make-loglist-buidable-again branch anyway, but the history is extremely dirty.
What I managed to achieve:
sbt scalajs/fastOptJS
apparently can't find dependencies);"migrated" scalajvm subproject to Play framework 2.7. The latest version is 2.8, but it gives an extra 40 compilation errors, so I decided to cut myself some slack and upgrade to the previous one. The code compiles and even runs, but only /licenses
endpoint works. All other endpoints result in a seemingly unrelated exception:
[error] application - Error while handling error
java.lang.ClassCastException: class xsbti.BasicVirtualFileRef cannot be cast to class java.io.File (xsbti.BasicVirtualFileRef is in unnamed module of loader sbt.internal.MetaBuildLoader @24313fcc; java.io.File is in module java.base of loader 'bootstrap')
at play.sbt.run.PlayReload$.$anonfun$sourceMap$1(PlayReload.scala:69)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:260)
at play.runsupport.Reloader.$anonfun$findSource$1(Reloader.scala:547)
at scala.Option.flatMap(Option.scala:271)
at play.runsupport.Reloader.findSource(Reloader.scala:546)
at play.core.server.DevServerStart$$anon$1$$anon$2.sourceOf(DevServerStart.scala:172)
at play.core.SourceMapper.$anonfun$sourceFor$1(ApplicationProvider.scala:21)
at play.core.SourceMapper.$anonfun$sourceFor$1$adapted(ApplicationProvider.scala:21)
at scala.collection.ArrayOps$.find$extension(ArrayOps.scala:684)
at play.core.SourceMapper.sourceFor(ApplicationProvider.scala:21)
Needless to say, our code doesn't use java.io.File
and/or xsbti.BasicVirtualFileRef
. I couldn't figure out how to get more details from Play; increasing the log levels doesn't affect the output. (I get the above stacktrace when I run docker-compose up
and open http://localhost:9000 in the browser.)
Googling for ClassCastException
, I found that the two most common causes are wrong class loader and SBT (which ostensibly messes up the class loader). Our code doesn't seem to manipulate the class loader, so I don't know what's up with that. As for SBT, I tried to avoid it by compiling a fat JAR using sbt-assembly, but that failed because of duplicate files:
[error] (scalajvm / assembly) deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/javax/xml/bind/jaxb-api/2.3.1/jaxb-api-2.3.1.jar:module-info.class
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/org/joda/joda-convert/2.2.1/joda-convert-2.2.1.jar:module-info.class
[error] deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:org/apache/commons/logging/Log.class
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/jcl-over-slf4j/1.7.26/jcl-over-slf4j-1.7.26.jar:org/apache/commons/logging/Log.class
[error] deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:org/apache/commons/logging/LogConfigurationException.class
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/jcl-over-slf4j/1.7.26/jcl-over-slf4j-1.7.26.jar:org/apache/commons/logging/LogConfigurationException.class
[error] deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:org/apache/commons/logging/LogFactory.class
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/jcl-over-slf4j/1.7.26/jcl-over-slf4j-1.7.26.jar:org/apache/commons/logging/LogFactory.class
[error] deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:org/apache/commons/logging/impl/NoOpLog.class
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/jcl-over-slf4j/1.7.26/jcl-over-slf4j-1.7.26.jar:org/apache/commons/logging/impl/NoOpLog.class
[error] deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:org/apache/commons/logging/impl/SimpleLog$1.class
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/jcl-over-slf4j/1.7.26/jcl-over-slf4j-1.7.26.jar:org/apache/commons/logging/impl/SimpleLog$1.class
[error] deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:org/apache/commons/logging/impl/SimpleLog.class
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/jcl-over-slf4j/1.7.26/jcl-over-slf4j-1.7.26.jar:org/apache/commons/logging/impl/SimpleLog.class
[error] deduplicate: different file contents found in the following:
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/com/typesafe/play/play-akka-http-server_2.13/2.7.5/play-akka-http-server_2.13-2.7.5.jar:play/reference-overrides.conf
[error] /home/minoru/.cache/coursier/v1/https/repo1.maven.org/maven2/com/typesafe/play/play_2.13/2.7.5/play_2.13-2.7.5.jar:play/reference-overrides.conf
The fact that /license
endpoint works gives me a tiny sliver of hope, but just barely. I'm convinced I'm out of my depth here, and won't be able to fix this on my own.
@ForNeVeR, do you have any ideas offhand? I know you're busy right now, so I could try some for you. Otherwise I'll just wait for you to get a spare minute and take a look yourself.
Wow, it's been quite a while since I last saw errors like these latter ones. The deal with them is basically this: there's duplicates of some files in your classpath because SBT pulls redundant dependencies, like commons-logging
(the Apache Foundation logging library) and jcl-over-slf4j
(basically a drop-in replacement for the former). Best solution here would be to to investigate your dependency tree and see who's pulling these artifacts. Alternatively you could just explicitly exclude, say, commons-logging
(which you probably should do anyway, since it was not updated since 2014) and see what breaks (or not breaks).
As for the former error... While our code does not do anything funny with classloaders, looks like Play sbt plugin does. That should be expected, seeing as how it needs to reload updated code into the VM. I think sbt does some weird magicks with a virtual filesystem and offers an ersatz file handle to the Play code reloader. The reloader then tries to cast it to io.File
and it's not working out. If so, choosing another version of sbt and/or Play sbt plugin would solve this. But don't quote me on that.
Thanks for the suggestions!
like commons-logging (the Apache Foundation logging library) and jcl-over-slf4j (basically a drop-in replacement for the former). Best solution here would be to to investigate your dependency tree and see who's pulling these artifacts.
commons-logging
is pulled in by scalikejdbc, jcl-over-slf4f
is pulled by the Play framework itself. Same situation with joda.org:joda-convert
and javax.xml.bind:jaxb-api
. I excluded the deps from scalikejdbc
, and that resolved most of the conflicts.
The only remaining conflict is baffling, though: our scalajvm subprojects pulls play
which then pulls play-akka-http-server
. Weird.
While looking into that, I discovered that Play actually has a dist
task that zips the whole thing into an archive. So I replaced sbt-assembly plugin with that, and it does work! The project even starts, but when I request http://localhost:9000 I get the following error:
[error] application -
! @7hdlaoi3p - Internal server error, for (GET) [/] ->
play.api.UnexpectedException: Unexpected exception[IllegalStateException: Connection pool is not yet initialized.(name:Symbol(default))]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:340)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:263)
at play.core.server.AkkaHttpServer$$anonfun$1.applyOrElse(AkkaHttpServer.scala:443)
at play.core.server.AkkaHttpServer$$anonfun$1.applyOrElse(AkkaHttpServer.scala:441)
at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:453)
at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:92)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:94)
at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:92)
Caused by: java.lang.IllegalStateException: Connection pool is not yet initialized.(name:Symbol(default))
at scalikejdbc.ConnectionPool$.$anonfun$get$1(ConnectionPool.scala:78)
at scala.collection.mutable.HashMap.getOrElse(HashMap.scala:428)
at scalikejdbc.ConnectionPool$.get(ConnectionPool.scala:76)
at scalikejdbc.ConnectionPool$.apply(ConnectionPool.scala:66)
at scalikejdbc.DB$.connectionPool(DB.scala:151)
at scalikejdbc.DB$.localTx(DB.scala:260)
at helpers.ActionWithTx.invokeBlock(ActionWithTx.scala:13)
at helpers.ActionWithTx.invokeBlock(ActionWithTx.scala:11)
at play.api.mvc.ActionBuilder$$anon$10.apply(Action.scala:419)
at play.api.mvc.Action.$anonfun$apply$2(Action.scala:95)
This is in the same docker-compose containers that I used previously. It's somewhat likely that I misconfigured the DB or scalajdbc, I'll dig into that.
I'll try to migrate this thing to Play 2.8 later today. That's the latest release, and we'll be using all the latest tools then — if that doesn't fix it, I don't know what will.
Status update:
I discovered that Play actually has a dist task that zips the whole thing into an archive. So I replaced sbt-assembly plugin with that
I keep using this approach for now, as it indeed works.
I'll try to migrate this thing to Play 2.8 later today.
Done. It was actually pretty easy: I fixed all the warnings I saw on 2.7, updated the Play plugin, and that was it. No new warnings, by the way.
I'm slightly worried about some of my changes, though, e.g. replacing object
s with @Singleton class
es. But I guess we'll get to discussing that when I actually make this thing fully functional again.
It's somewhat likely that I misconfigured the DB or scalajdbc
It's both and then some. I didn't enable pgcrypto extension in the DB, I didn't include scalikejdbc-play-initializer that configures the connection pool, and I didn't run evolutions. With all of that fixed, I can finally see not just /licenses but other endpoints as well :tada:
Next steps:
sleep
s with an SQL script that will enable pgcrypo on container creationTime for another status update!
I finished three out of the four steps outlined above. What remains is to teach SBT to copy the JS files into public/javascript/
. Our old trick doesn't work anymore: it copies to conf/
instead of public/javascripts
. I'll dig further into that tomorrow.
I also chatted to Orchideus on XMPP and he agreed to review the final PR. This migration is very risky, so I'm happy we'll have plenty of reviewers for it. (I assume ForNeVeR and Hagane will review as well).
We've recently found that our builds are absolutely, completely broken.
@codingteam/minoru are investigating, I am assisting.