Skip to content

Loading…

Ensure that reverse routing works with vanilla play idea from Java project in IntelliJ #969

Closed
jroper opened this Issue · 49 comments
@jroper
Play Framework member

In a Java project, IntelliJ seems to consider reverse routes as syntax errors in.

@nraychaudhuri
Play Framework member

What is the exact problem? I can open a plain play-java project into idea and access the reverse routing without problem. But I see some other problems:

  • routes.java shows error
  • ok(index.render(...)) also shows an error. I am surprised by this one.
@jroper
Play Framework member

I just happened to notice this too (the original request I made was for someone else).

It seems that IntelliJ 12.1 isn't able to infer the return type of Scala methods invoked from Java code if they return a generic type.

@nraychaudhuri
Play Framework member

The reason that the controller is complaining because the project is not compiled hence no reverse route files generated. So if you compile the project before opening in the IDE that error should go away. The second problem is if you try to build the project it fails because we don't add Scala Facet for Java projects. I think the proper fix for this should be to run the compile task before generating the IDEA project files automatically(we do that for eclipse) and add the Scala facet for both Scala and Java projects.

The problem is there is no mechanism to assign preTasks for SbtIdeaPlugin and I cannot find a way to hook into the "idea" command. So for the time being we can add the Scala facet and mention in the docs to run compile to fix any additional compilation problems. Thoughts?

@jroper
Play Framework member

It seems to be more than this. I had the scala facet enabled (I think), and I still get the highlighting error. In a Scala project it seems to work, but the routes.java generated file has errors in it. I think this is actually caused by an IntelliJ issue.

@NIA
NIA commented

It seems like on my machine this only affects routes.javascript.* and routes.ref.*. It can be easily seen when opening generated file target/scala-2.10/src_managed/main/controllers/routes.java in IDEA:

screen38

  • The first part of it is OK, and IDEA can easily navigate to definition of controllers.ReverseApplication, for example, which is in another generated file target/scala-2.10/src_managed/main/routes_reverseRouting.scala
  • The second and third part (javascript and ref) have all class names painted in red as syntax errors: IDEA cannot find classes like new controllers.javascript.ReverseApplication, while actually they are in the same routes_reverseRouting.scala file

So, my hypothesis is: might the issue be caused by the fact that many packages and classes are defined in the single Scala file routes_reverseRouting.scala? This indeed might be a known limitation of Scala-plugin of IntelliJ: if we do open this routes_reverseRouting.scala and navigate to any package xxx line in it, we will see it highlighted with a honest warning: "Package names doesn't correspond to directories structure, this may cause problems with resolve to classes from this file"

Not sure about how to solve this, but can we synchronize folder structure with package structure here? The file routes.java already lays in controller folder, and is treated well by IDEA, so probably routes_reverseRouting.scala can be split into three files ant put under this folder, too?

@NIA
NIA commented

Haha, even simpler workaround: I created empty directories javascript and ref under the controllers directory on the picture, and IDEA got it. Syntax errors both in routes.java and my controller disappeared, and completion works. So scala plugin actually can handle package structure not similar to directory structure, but stumbles over the names of packages that is not known to it.

@kamilafsar

I'm running a Scala project and actually have the same problem. It looks like my controllers don't have any methods defined (apart from those derived from java.lang.Object).

@huntc huntc was assigned
@huntc
Play Framework member

I'm unable to reproduce this issue with IntelliJ 12.1.4 and the Scala plugin 0.16.293. Please note that I also have the Play 2.0 Support plugin from JetBrains: 0.16.294

@huntc huntc closed this
@andrewboss

Exactly the same problem. IDEA 12.1.5 can't recognise controller methods from reverse routing. Tried recompiling and creating ref and javascript folders.

@OlegYch

this is still an issue even for scala projects with latest intellij-scala plugin and play 2.2.1-RC1

@huntc
Play Framework member

@OlegYch Including IntelliJ 13?

@OlegYch
@huntc
Play Framework member

The IntelliJ issue remains open so I think we can keep this as closed for now.

@TomasLinhart

Why don't you just generate ref and javascript folders to workaround it?

@jroper
Play Framework member

Sure, add this to your build:

sourceGenerators in Compile <+= sourceManaged in Compile map { dir: File =>
  val dirs = Seq(dir / "ref", dir / "javascript")
  dirs.foreach(_.mkdirs)
  dirs
}
@tjjalava

I think that should be:

val dirs = Seq(dir / "main" / "controllers" / "ref", dir / "main" / "controllers" / "javascript")

right?

Anyways, compilation ends in error:

[error] source file '.../target/scala-2.10/src_managed/main/controllers/javascript' could not be found
@TomasLinhart

Yeah, it doesn't work.

@OlegYch

this should work

    sourceGenerators in Compile += task {
      val dir: File = (sourceManaged in Compile).value / "controllers"
      val dirs = Seq(dir / "ref", dir / "javascript")
      dirs.foreach(_.mkdirs)
      Seq[File]()
    }
@OlegYch

why is that so hard to release?
should every user be workarounding issues like this and #1784 ?

@m242

Easier fix-- unmark "controllers" and "views" as source roots in IntelliJ, and mark "main" as a source root. That fixes syntax highlighting/completion/etc.

@Kwestor

+10 (1 for each module in which I have to change it manually)

@huntc
Play Framework member

Please note that http://youtrack.jetbrains.com/issue/SCL-5635 remains open. If you feel we can work around this then please open an associated PR. Thanks.

@ghost

I found the solution to this issue by changing the source paths in the Module Settings of the IDEA project as explained here:
http://www.jensjaeger.com/2013/09/play-framework-2-2-in-intellij-errors-in-controllers-everywhere/

@ghost

This is an issue with sbt-idea. The workaround is to unmark the controllers directory (e.g. target/scala-2.11/src_managed/main/controllers) as a source root, and mark the main folder (e.g. target/scala-2.11/src_managed/main) as a source root. Then IntelliJ will find everything properly. This really should be fixed, either by changing where Play puts the compiled routes files (since sbt-idea expects everything to be put into subfolders within compile:managedSources), or to submit this as a bug in sbt-idea.

@jroper
Play Framework member

The bug is in sbt-idea. Play must put the compiled routes files in src_managed/main, because one of the generated files is a Java file, and the Java compiler requires that the folder structure matches the package structure, and SBT uses src_managed/main as the root folder for Java compilation. So the controllers.routes class must be in src_managed/main/controllers/routes.java, anything else and javac produces a compile error.

Note though that in master (Play 2.4), we're now using a completely different directory outside of src_managed, which I guess will make this issue go away.

@m242

Note that this is kind of a non-issue with IntelliJ 13 and the updated SBT support. Reverse routing support gets automatically picked up.

@moreindirection

@NIA's workaround works even in IntelliJ IDEA 14.

@cdraeger

This issue is very very confusing and I'm surprised it still hasn't been fixed. Yes, NIAs workaround works, but it took me quite some time until I found this issue. So for the sake of any future Play Java dev (and the chance is high they are using IntelliJ Idea), I really hope it'll go away with Play 2.4.

@milanaleksic

This is still going on in latest Intellij 14.1; NIAs workaround is still OK

@sunnykaka

I put @OlegYch 's answer in my Build.scala and reload the project.
My Intellij still not include "target/scala-2.11/src_managed/main" as source folder.
here is my Build.scala:
screenshot from 2015-04-02 15 23 10

So I have to add source folder manually every time after project reload : (

@kflorence

FWIW, none of these solutions work for me with Play 2.3.8 and IJ 14.1.x :(

@bpgriner

I'm not sure if this is the same problem, but when trying to perform a return redirect(routes.Application.index());, routes is not a known variable that can used.

I'm attempting to follow the basic play framework example (YouTube video on front page of playframework.com) with IntelliJ 14.0.4 and latest version of Play (2.3.8?).

@PeterRangelov

Yet my application compiles and runs as expected!! Red squiggles are annoying; guys please fix dis :)

cannot resolve symbol routes

@bpgriner

+1 @PeterRangelov

I should have provided a screen shot, I'm having the exact same issue. Everything compiles and runs fine, just annoying to look at in IntelliJ.

@jwsher

FYI, This is still a problem on play 2.4. The classes compile fine but it's annoying to look at and the previously mentioned workaround of creating the fake directories doesn't work.

screen shot 2015-06-20 at 8 29 31 pm

@vicaba

Yep, I have the same problem using intellij idea 14

@hossamahamid

I had the same problem with Intellij Idea 14.1.4 and play framework 2.4.2 but I managed to solve the issue with the help of the link @ghost added but it was old so I had to make little changes, here is what I did.
right click on "target" directory from the project navigator in intellij and choose "mark directory as" then "Cancel Exclusion". After that, right click on "scala-2.11/routes/main" folder and choose "mark directory as sources root". I also excluded "resolution-cache" and "streams".

@vicaba

@hossamahamid I can't exclude the "./target" directory but I can exclude "project->target", nevertheless, the file "scala-2.11/routes/main" is in the "./target" directory. When you refer to "target" are you referring to the "target" directory placed at the root directory of the project?
If you can, take a look at my images and tell me if that was your situation (menu shown when I right-clicked the item highlighted in blue in the project navigator):

screen shot 2015-07-15 at 11 06 28

screen shot 2015-07-15 at 11 06 36

screen shot 2015-07-15 at 11 07 46

Maybe I can't do the expected operations because I added a related project in the build.sbt:

name := """WHTTP-front"""

version := "1.0-SNAPSHOT"

lazy val wcommon = RootProject(file("../WCommon"))

val root = (project in file(".")).enablePlugins(PlayScala).dependsOn(wcommon)

scalaVersion := "2.11.6"

//val whttp_front = Project(id = "root", base = file("."))

libraryDependencies ++= Seq(
  jdbc,
  cache,
  ws,
  specs2 % Test
)

libraryDependencies +=
  "com.typesafe.akka" %% "akka-remote" % "2.4-SNAPSHOT"

resolvers += "Akka Snapshot Repository" at "http://repo.akka.io/snapshots/"

resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"

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


fork in run := true

@adis-me

I have cancelled exlusion for the target folder in the root of my project. And now it works fine!

@hossamahamid

@vicaba yes I mean the target directory at the root. That's weird but try to exclude the target directory from the module settings window. You can open it by right click on the project directory and choosing "Open Module Settings", or by selecting "Project Structure" from "File" menu then "Modules".

@vicaba

@hossamahamid I've tried it and nothing changes. I've tried several combinations too, but I can't get it working.
But while I was searching for the solution I came out with two discoveries:
The first one is that if I change my default application class controller to an object, I get the correct code hints when typing the routes, but the application does not compile :S. In earlier versions of Play, the controllers where objects .
The other interesting thing I discovered is that at the moment, I can disable Play route inspections:
screen shot 2015-07-15 at 14 26 04

Change the inspections configuration by clicking on the man with a hat at the bottom right.

I'll give it another try in a few days after doing a OS clean install.

Thank you all for the support anyway.

@thobson

@vicaba I have the same issue, I think we need to wait for Jetbrans to fix this (in the ultimate version) because I don't see how it could work without some form of "hack" from the tool vendor. As controllers are now classes the statement route..method will always be invalid because in Scala you can't call a method on a class.

@vicaba

@thobson Yep, that's just what I was thinking... We will have to wait.

@thobson

@vicaba I just found an EAP version of the plugin which seems to work in most cases. Take a look here and download the 1.5.2.3.EAP version of the plugin. You will need to uninstall the exisiting Scala plugin then copy this new version into the plugins directory, giving it the folder name "Scala". Of course it's EAP software so it's not perfect but it does seem to work ok for me (so far!)

@vicaba

@thobson Thanks, I'll try it as soon as I can :)

@kgambrah

Scala plugin 1.5.2.3.EAP version didn't work for me. I went with disabling disabiling the play routing action inspection rather.

@pschichtel

This problem still exists in intellij 15-eap and with the scala plugin on version 1.8.

I wonder why this issue is still closed even though it is still very much a problem.

javascript-red

@jroper
Play Framework member

It's closed because it's a problem with the way IntelliJ imports projects, not with Play, so the issue doesn't belong in Play's issue tracker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.