j3d
j3d

Reputation: 9724

Play Framework: NoSuchFieldError when reverse routing

Here is my common.routes file:

GET     /emails/:deflated   controllers.common.Emails.viewInBrowser(deflated)

... and here my controller:

package controllers.common

object Emails extends Controller {

  def viewInBrowser(deflated: String) = Action { implicit request =>
    GZip.inflate(deflated) match {
      case Success(inflated) => Ok(Html(inflated))
      case Failure(e) => {
        Logger.warn(s"error inflating email from url", e)
        val support = configuration.getString("application.emails.support")
        BadRequest(views.html.badRequest(Messages("common.error.invalidOrMalformedUrl", support)))
      }
    }
  }
}

The code above works fine... but if I reverse route like this

import controllers.common.routes
...

val sslEnabled = configuration.getBoolean("ssl").getOrElse(false)
val emailUrl = routes.Emails.viewInBrowser(true).absoluteURL(sslEnabled)

... I always the the following exception:

java.lang.NoSuchFieldError: Emails
at utils.common.RoutesHelper$.emailUrl(RoutesHelper.scala:51)
at services.common.DefaultEmailComponent$DefaultRichBody.apply(EmailComponent.scala:64)
at services.common.DefaultEmailServiceComponent$DefaultEmailService.sendEmail(EmailServiceComponent.scala:81)
at utils.auth.EmailHelper$.sendUserVerificationEmail(EmailHelper.scala:32)
at controllers.auth.Users$$anonfun$create$1$$anonfun$8$$anonfun$apply$60$$anonfun$apply$61.apply(Users.scala:381)
at controllers.auth.Users$$anonfun$create$1$$anonfun$8$$anonfun$apply$60$$anonfun$apply$61.apply(Users.scala:379)
at scala.util.Success$$anonfun$map$1.apply(Try.scala:206)[ERROR] [05/30/2014 16:35:05.350] [play-akka.actor.default-dispatcher-4] [ActorSystem(play)] Uncaught error from thread [play-akka.actor.default-dispatcher-4] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled

Any idea? I verified everything I could (configuration files, routes, controllers)... but no way to figure out what the problem is. I'm using Play 2.2.3.

UPDATE

What's very strange is that I've tried to move my Emails controller into another package (i.e. models) and in that case reverse routing works again. Is there a bug somewhere in Play?

Upvotes: 2

Views: 736

Answers (2)

ps_ttf
ps_ttf

Reputation: 1094

As I understand, if there are routes defined in the same package in the root project and in one of the sub-projects the generated sub-project routes object hides the same object from root project and all the code referencing the old routes object becomes erroneous.

E.g. if the routes file in the root project contains a route

GET /path       mypackage.MyController.someAction

and the subproject.routes file contains a route

GET /otherPath  mypackage.MyOtherController.otherAction

both projects generate the mypackage.routes objects during build and one of them hides the another one in the runtime.

The solution is to define all the sub-project routes in its own packages that are not presented in the root project.

Upvotes: 5

j3d
j3d

Reputation: 9724

After having spent the whole night to figure out how to make this work, I've just modified the routes like this

GET     /emails/:deflated   controllers.common.webmail.Emails.viewInBrowser(deflated)

and my controller like this:

package controllers.common.webmail

object Emails extends Controller {
  ...
}

Renaming the package to controllers.common.webmail solves the problem and reverse routing works now... but don't ask me why :-(

I guess there should be a bug in Play. I hope that helps.

Upvotes: 1

Related Questions