Play 2.7.0: Base64 - NoClassDefFoundError

Hello,

the moment I switch my project from Play 2.6.21 to Play 2.7.0, I get several errors of the form
1) Error injecting constructor, java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
when the server starts inside sbt. This happens with JDK 8 (on a Mac) and also with JDK 11.
The class Base64 is nowhere used by my own code. It looks like Guice is using it somewhere, since the problem appears when a class with dependency injection gets initialized. This class gets a parameter of class “Configuration” injected.

Has anybody a idea what goes wrong here - and why it only happens with Play 2.7.0?

Thanks in advance.

Detailed error output from sbt:

2019-02-11 16:07:32,386 [error]
! @7ap5h1g4m - Internal server error, for (GET) [/query?access_token=rexis-ene] ->
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) Error injecting constructor, java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
at com.gms.rre.utils.DataAccess.<init>(DataAccess.scala:28)
at com.gms.rre.utils.DataAccess.class(DataAccess.scala:27)
while locating com.gms.rre.utils.DataAccess
for the 2nd parameter of com.gms.rre.dispatch.RREHolder.<init>(RREHolder.scala:27)
at com.gms.rre.dispatch.RREHolder.class(RREHolder.scala:26)
while locating com.gms.rre.dispatch.RREHolder
for the 1st parameter of com.gms.rre.RREInitializer.<init>(RREInitializer.scala:10)
at com.gms.rre.EagerRRE.configure(EagerRRE.scala:8) (via modules: com.google.inject.util.Modules$OverrideModule -> com.gms.rre.EagerRRE)
while locating com.gms.rre.RREInitializer

1 error]
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:196)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:127)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:253)
at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:149)
at akka.stream.impl.fusing.MapAsync$$anon$30.onPush(Ops.scala:1207)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:519)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:411)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:588)
at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:472)
at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:563)
at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:745)
at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:760)
at akka.actor.Actor.aroundReceive(Actor.scala:517)
at akka.actor.Actor.aroundReceive$(Actor.scala:515)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:670)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:588)
at akka.actor.ActorCell.invoke(ActorCell.scala:557)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:258)
at akka.dispatch.Mailbox.run(Mailbox.scala:225)
at akka.dispatch.Mailbox.exec(Mailbox.scala:235)
at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
at com.gms.rre.utils.DataAccess.<init>(DataAccess.scala:28)
at com.gms.rre.utils.DataAccess.class(DataAccess.scala:27)
while locating com.gms.rre.utils.DataAccess
for the 2nd parameter of com.gms.rre.dispatch.RREHolder.<init>(RREHolder.scala:27)
at com.gms.rre.dispatch.RREHolder.class(RREHolder.scala:26)
while locating com.gms.rre.dispatch.RREHolder
for the 1st parameter of com.gms.rre.RREInitializer.<init>(RREInitializer.scala:10)
at com.gms.rre.EagerRRE.configure(EagerRRE.scala:8) (via modules: com.google.inject.util.Modules$OverrideModule -> com.gms.rre.EagerRRE)
while locating com.gms.rre.RREInitializer

1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:543)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:186)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:109)
at com.google.inject.Guice.createInjector(Guice.java:87)
at com.google.inject.Guice.createInjector(Guice.java:78)
at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:186)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:139)
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
at play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:176)
at play.utils.Threads$.withContextClassLoader(Threads.scala:22)
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:168)
... 23 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
at org.apache.http.impl.auth.BasicScheme.authenticate(BasicScheme.java:163)
at org.apache.http.impl.auth.BasicScheme.authenticate(BasicScheme.java:135)
at org.apache.http.client.protocol.RequestTargetAuthentication.process(RequestTargetAuthentication.java:99)
at org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor.java:251)
at org.apache.http.protocol.HttpRequestExecutor.preProcess(HttpRequestExecutor.java:168)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:458)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at com.fourspaces.couchdb.SessionEx.http(SessionEx.java:181)
at com.fourspaces.couchdb.Session.get(Session.java:361)
at com.fourspaces.couchdb.SessionEx.getDatabase(SessionEx.java:228)
at com.gms.connector.couchdb.Connector.getDatabase(Connector.java:329)
at com.gms.connector.couchdb.Connector.getDatabase(Connector.java:303)
at com.gms.connector.couchdb.CommandData.getDatabase(CommandData.java:63)
at com.gms.connector.couchdb.CommandData.getDocument(CommandData.java:92)
at com.gms.connector.couchdb.transactions.ReadDocument.execute(ReadDocument.java:37)
at com.gms.connector.AbstractInvoker.call(AbstractInvoker.java:73)
at com.gms.connector.Connector.call(Connector.java:312)
at com.gms.ase.geo.GeoTool2.<init>(GeoTool2.java:101)
at com.gms.ase.geo.GeoTool2.createGeoTool2(GeoTool2.java:132)
at com.gms.ase.geo.GeoToolFactory.createInstance(GeoToolFactory.java:35)
at com.gms.rre.utils.DataAccess.<init>(DataAccess.scala:53)
at com.gms.rre.utils.DataAccess$$FastClassByGuice$$e6010aa2.newInstance(<generated>)
at com.google.inject.internal.DefaultConstructionProxyFactory$FastClassProxy.newInstance(DefaultConstructionProxyFactory.java:89)
at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:91)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:306)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:168)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:39)
at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:42)
at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:65)
at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:113)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:91)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:306)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:168)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:39)
at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:42)
at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:65)
at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:113)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:91)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:306)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:168)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:39)
at com.google.inject.internal.InternalInjectorCreator.loadEagerSingletons(InternalInjectorCreator.java:211)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:182)
... 32 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 80 common frames omitted
2019-02-11 16:08:44,676 [info] Stopping server...
2019-02-11 16:08:44,696 [warn] Task [shutdown-application-dev-mode] failed in phase [service-stop]: Unexpected exception[CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
at com.gms.rre.utils.DataAccess.<init>(DataAccess.scala:28)
at com.gms.rre.utils.DataAccess.class(DataAccess.scala:27)
while locating com.gms.rre.utils.DataAccess
for the 2nd parameter of com.gms.rre.dispatch.RREHolder.<init>(RREHolder.scala:27)
at com.gms.rre.dispatch.RREHolder.class(RREHolder.scala:26)
while locating com.gms.rre.dispatch.RREHolder
for the 1st parameter of com.gms.rre.RREInitializer.<init>(RREInitializer.scala:10)
at com.gms.rre.EagerRRE.configure(EagerRRE.scala:8) (via modules: com.google.inject.util.Modules$OverrideModule -> com.gms.rre.EagerRRE)
while locating com.gms.rre.RREInitializer

1 error]

As described in https://www.playframework.com/documentation/2.7.x/Migration27#Apache-Commons-(commons-lang3-and-commons-codec) the library was removed and you need to add it manually if you still want to use it.

Thanks, I added “commons-codec” to my library dependencies, and my server is now working with Play 2.7.0!

But:
Since I don’t use the class “Base64” in my own code (it is apparently only used by Guice), shouldn’t this dependency be resolved automatically? Guice is, after all, more or less a standard component of Play.

It’s not used by Guice. If you look at the stack trace here:

Caused by: java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
at org.apache.http.impl.auth.BasicScheme.authenticate(BasicScheme.java:163)

It’s used by org.apache.http.impl.auth.BasicScheme.

Ah, finally I get it:

The class DataAccess uses a CouchDB driver that internally uses BasicScheme. But since DataAccess is initialized when it is injected by Guice into another class, the bug seems (at first sight) to be in the injection.

Thanks for clearing that up for me!