java.lang.NoSuchMethodError in Scalatra using Scalate with Markdown

1.4k views Asked by At

So I have a Scalatra app (using Scalatra 2.2.1). I'm building views using Scalate; I've decided to go with the Jade/Markdown one-two. Only one problem: if I try to use markdown in a jade template (started with the :markdown tag), I get this:

scala.Predef$.any2ArrowAssoc(Ljava/lang/Object;)Lscala/Predef$ArrowAssoc;
java.lang.NoSuchMethodError: scala.Predef$.any2ArrowAssoc(Ljava/lang/Object;)Lscala/Predef$ArrowAssoc;

at org.fusesource.scalamd.Markdown$.<init>(md.scala:119)
at org.fusesource.scalamd.Markdown$.<clinit>(md.scala:-1)
at org.fusesource.scalate.filter.ScalaMarkdownFilter$.filter(ScalaMarkdownFilter.scala:32)
at org.fusesource.scalate.RenderContext$class.filter(RenderContext.scala:276)
at org.fusesource.scalate.DefaultRenderContext.filter(DefaultRenderContext.scala:30)
at org.fusesource.scalate.RenderContext$class.value(RenderContext.scala:235)
at org.fusesource.scalate.DefaultRenderContext.value(DefaultRenderContext.scala:30)
at templates.views.$_scalate_$about_jade$.$_scalate_$render(about_jade.scala:37)
at templates.views.$_scalate_$about_jade.render(about_jade.scala:48)
at org.fusesource.scalate.DefaultRenderContext.capture(DefaultRenderContext.scala:92)
at org.fusesource.scalate.layout.DefaultLayoutStrategy.layout(DefaultLayoutStrategy.scala:45)
at org.fusesource.scalate.TemplateEngine$$anonfun$layout$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(TemplateEngine.scala:559)
at org.fusesource.scalate.TemplateEngine$$anonfun$layout$1$$anonfun$apply$mcV$sp$1.apply(TemplateEngine.scala:559)
at org.fusesource.scalate.TemplateEngine$$anonfun$layout$1$$anonfun$apply$mcV$sp$1.apply(TemplateEngine.scala:559)

So that's pretty cool. The error vanishes as soon as I remove the :markdown flag, and beyond that everything compiles (beyond markdown not getting rendered correctly).

Things I know and have found so far:

  1. There's some thought that this error is the biproduct of incompatible Scala versions somewhere in the build. My build.scala defines Scala version as 2.10.0, which Scalatra is explicitly compatible with.
  2. ...that said, I have no idea which version of Scalate Scalatra pulls in, and my attempts to override it have not worked so far. I know the current stable of Scalate (1.6.1) is only compatible up to Scala 2.10.0 -- but that's what I'm using.
  3. I am, however, sure that my classpath is clean. I have no conflicting Scala versions. Everything is 2.10.0 in the dependencies.

Has anybody worked with this one before? Any ideas?

EDIT

Per request, here are my build definitions:

//build.sbt 
libraryDependencies += "org.scalatest" %% "scalatest" % "2.0.M5b" % "test"                                                                                                                                     
                                                                                                                                                                                                           
libraryDependencies += "org.twitter4j" % "twitter4j-core" % "3.0.3"                                                                                                                                            
                                                                                                                                                                                                           
libraryDependencies += "org.fusesource.scalamd" % "scalamd" % "1.5" 

//build.properties
sbt.version=0.12.3

//build.scala
import sbt._                                                                                                                                                                                                   
import Keys._                                                                                                                                                                                                  
import org.scalatra.sbt._                                                                                                                                                                                      
import org.scalatra.sbt.PluginKeys._                                                                                                                                                                           
import com.mojolly.scalate.ScalatePlugin._                                                                                                                                                                     
import ScalateKeys._                                                                                                                                                                                           
                                                                                                                                                                                                               
object TheRangeBuild extends Build {                                                                                                                                                                           
  val Organization = "com.gastove"                                                                                                                                                                             
  val Name = "The Range"                                                                                                                                                                                       
  val Version = "0.1.0-SNAPSHOT"                                                                                                                                                                               
  val ScalaVersion = "2.10.0"                                                                                                                                                                                  
  val ScalatraVersion = "2.2.1"                                                                                                                                                                                
                                                                                                                                                                                                               
  lazy val project = Project (                                                                                                                                                                                 
    "the-range",                                                                                                                                                                                               
    file("."),                                                                                                                                                                                                 
    settings = Defaults.defaultSettings ++ ScalatraPlugin.scalatraWithJRebel ++ scalateSettings ++ Seq(                                                                                                        
      organization := Organization,                                                                                                                                                                            
      name := Name,                                                                                                                                                                                            
      version := Version,                                                                                                                                                                                      
      scalaVersion := ScalaVersion,                                                                                                                                                                            
      resolvers += Classpaths.typesafeReleases,                                                                                                                                                                
      libraryDependencies ++= Seq(                                                                                                                                                                             
        "org.scalatra" %% "scalatra" % ScalatraVersion,                                                                                                                                                        
        "org.scalatra" %% "scalatra-scalate" % ScalatraVersion,                                                                                                                                                
        "org.scalatra" %% "scalatra-specs2" % ScalatraVersion % "test",                                                                                                                                        
        "ch.qos.logback" % "logback-classic" % "1.0.6" % "runtime",                                                                                                                                            
        "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "compile;container",                                                                                                                        
        "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "compile;container;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar"))                                            
      ),                                                                                                                                                                                                       
      scalateTemplateConfig in Compile <<= (sourceDirectory in Compile){ base =>                                                                                                                               
        Seq(                                                                                                                                                                                                   
          TemplateConfig(                                                                                                                                                                                      
            base / "webapp" / "WEB-INF" / "templates",                                                                                                                                                         
            Seq.empty,  /* default imports should be added here */                                                                                                                                             
            Seq(                                                                                                                                                                                               
              Binding("context", "_root_.org.scalatra.scalate.ScalatraRenderContext", importMembers = true, isImplicit = true)                                                                                 
            ),  /* add extra bindings here */                                                                                                                                                                  
            Some("templates")                                                                                                                                                                                  
          )                                                                                                                                                                                                    
        )                                                                                                                                                                                                      
      }                                                                                                                                                                                                        
    ) ++ seq(com.typesafe.startscript.StartScriptPlugin.startScriptForClassesSettings: _*)                                                                                                                     
  )                                                                                                                                                                                                            
}
2

There are 2 answers

1
Stefan Ollinger On BEST ANSWER

When using the markdown filter, you need to add the scalamd library as runtime dependency:

"org.fusesource.scalamd" %% "scalamd" % "1.6"

The most recent version can be found on Maven Central

Also you can delete the build.sbt file and put the dependencies into build.scala file which makes things a bit simpler.

import sbt._
import Keys._
import org.scalatra.sbt._
import org.scalatra.sbt.PluginKeys._
import com.mojolly.scalate.ScalatePlugin._
import ScalateKeys._
object TheRangeBuild extends Build {
  val Organization = "com.gastove"
  val Name = "The Range"
  val Version = "0.1.0-SNAPSHOT"
  val ScalaVersion = "2.10.0"
  val ScalatraVersion = "2.2.1"
  lazy val project = Project(
    "the-range",
    file("."),
    settings = Defaults.defaultSettings ++ ScalatraPlugin.scalatraWithJRebel ++ scalateSettings ++ Seq(
      organization := Organization,
      name := Name,
      version := Version,
      scalaVersion := ScalaVersion,
      resolvers += Classpaths.typesafeReleases,
      libraryDependencies ++= Seq(  // adding this Seq to the libraryDependencies
        "org.scalatra" %% "scalatra" % ScalatraVersion,
        "org.scalatra" %% "scalatra-scalate" % ScalatraVersion,
        "org.scalatra" %% "scalatra-specs2" % ScalatraVersion % "test",
        "ch.qos.logback" % "logback-classic" % "1.0.6" % "runtime",
        "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "compile;container",
        "org.scalatest" %% "scalatest" % "2.0.M5b" % "test",
        "org.twitter4j" % "twitter4j-core" % "3.0.3",
        "org.fusesource.scalamd" % "scalamd" % "1.6",
        "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "compile;container;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar"))
      ),
      scalateTemplateConfig in Compile <<= (sourceDirectory in Compile){ base =>
        Seq(
          TemplateConfig(
            base / "webapp" / "WEB-INF" / "templates",
            Seq.empty,  /* default imports should be added here */
            Seq(
              Binding("context", "_root_.org.scalatra.scalate.ScalatraRenderContext", importMembers = true, isImplicit = true)
            ),  /* add extra bindings here */
            Some("templates")
          )
        )
      }
    ) ++ seq(com.typesafe.startscript.StartScriptPlugin.startScriptForClassesSettings: _*)
  )
}
0
gourlaysama On

This comes from:

libraryDependencies += "org.fusesource.scalamd" % "scalamd" % "1.5" 

Looking at the scalamd-1.5 pom.xml, it is built against Scala 2.8.1, which is not compatible with 2.10.

Dependency resolution keeps 2.10 and discard the 2.8.1 dependency, and you end up with this classpath issue.

The only solution you have is to try and build a new scalamd version against Scala 2.10, potentially fix a few things to get it there, and then publish it (at least locally).