Using unboundid ldap in scala ... strange compile error - scala

I am trying to use LDAP via unboundid in scala but the compiler keeps crashing.
I just created an object that looks like this:
package utils
import com.unboundid.ldap.sdk._
object LdapHelper {
val ldap = LDAPConnection("ldap.example.com", 389)
}
I added this: "com.unboundid" % "unboundid-ldapsdk" % "2.3.1" to my appDependencies in Build.scala. I use Play 2.1 and Scala Version 2.10.1.
I get a very strange error message (see below):
The error message is so strange that i really dont know where to begin to look for hints.
Not sure if the problem is in unboundid, play, scala, sbt?
How can i successfully integrate unboundid in my scala project?
Thanks
Error in Scala compiler: assertion failed: while compiling: C:\play\todolist\app\utils\LdapHelper.scala during phase: global=typer, atPhase=parser library version: version 2.10.2 compiler version: version 2.10.2 reconstructed args: -classpath C:\play\todolist.target;C:\eclipse\scala-SDK-3.0.1-vfinal-2.10-win32.win32.x86_64\configuration\org.eclipse.
...
last tree to typer: Ident(LDAPConnection)
symbol: (flags: )
symbol definition:
symbol owners:
context owners: value ldap -> object LdapHelper -> package utils
== Enclosing template or block ==
Template( // val : in object LdapHelper
"java.lang.Object" // parents
ValDef(
private
"_"
)
// 3 statements
DefDef( // def : in object LdapHelper
""
[]
List(Nil)
Block(
Apply(
super.""
Nil
)
()
)
)
DefDef( // def x: in object LdapHelper
"x"
[]
Nil
()
)
ValDef( // private[this] val ldap: in object LdapHelper
private
"ldap"
Apply(
"LDAPConnection"
// 2 arguments
"ldap.example.com"
389
)
)
)

There was a warning that turned into an assert in Scala 2.10.2 causing this.
There is a bug open here:
https://issues.scala-lang.org/browse/SI-7014
And a fix staged for 2.10.4:
https://github.com/scala/scala/pull/2829
You can ask Play to use Scala 2.10.4-SNAPSHOT by using the following Build.scala:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "AppName"
val appVersion = "1.0-SNAPSHOT"
val mainDeps = Seq(
jdbc,
anorm,
cache
)
lazy val main = play.Project(appName, appVersion, mainDeps).settings(
scalaVersion := "2.10.4-SNAPSHOT"
)
}
If you are using build.sbt the file would look like:
import play.Project._
playScalaSettings
name := "AppName"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.4-SNAPSHOT"
libraryDependencies ++= Seq(jdbc, anorm, cache)
Note: if building from sbt (instead of play) you may have to add a repository resolver under the scalaVersion line such as:
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/repo/"

The answer from #jeckhart works.
Firstly I use Scala 2.10.4-RC1 to build the Play 2.3 SNAPSHOT. Then use the output to compile with UnboundID.
Finally everything compiles with no assertion or error.
To build Play 2.3 SNAPSHOT using Scala 2.10.4-RC1, I modified the file framework/project/Build.scala.
Change these two section from
val buildScalaVersion = propOr("scala.version", "2.10.3")
val buildScalaVersionForSbt = propOr("play.sbt.scala.version", "2.10.3")
to
val buildScalaVersion = propOr("scala.version", "2.10.4-RC1")
val buildScalaVersionForSbt = propOr("play.sbt.scala.version", "2.10.4-RC1")

Related

Issue in testing using scalatest

I just set up a new scala project with sbt in IntelliJ, and wrote the following basic class:
Person.scala:
package learning.functional
case class Person(
name: String
)
Main.scala:
package learning.functional
import learning.functional.person
object Main{
val p = Person("John")
}
PersonTest.scala:
import learning.functional.Person
import org.scalatest.FunSuite
class PersonTest extends FunSuite {
test("test person") {
val p = Person("John")
assert(p.name == "John")
}
}
When I try to run sbt test, it throws the following error:
## Exception when compiling 1 sources to /Users/johndooley/Desktop/Scala/scala-learning/target/scala-2.13/test-classes
[error] java.lang.AssertionError: assertion failed:
[error] unexpected value engine in trait FunSuite final <expandedname> private[this]
[error] while compiling: /Users/johndooley/Desktop/Scala/scala-learning/src/test/scala/PersonTest.scala
What could be the reason for this? My build.sbt file:
ThisBuild / scalaVersion := "2.13.10"
libraryDependencies += "org.scalatest" % "scalatest_2.10" % "1.9.1"
lazy val root = (project in file("."))
.settings(
name := "scala-learning"
)
Project structure:
I have tried invalidating cache and restarting, doing clean, update, compile, but nothing works.
I solved this by modifying my dependency to the following:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.14"
and completely reloading the sbt shell

Need to provide a SettingKey from a plugin I use in my sbt plugin

I am using the s3 resolver plugin and would like to override it in my AutoPlugin.
I have tried added the value to projectSettings and globalSettings.
Error
not found: value s3CredentialsProvider
[error] s3CredentialsProvider := s3CredentialsProviderChain
Code
lazy val s3CredentialsProviderChain = {bucket: String =>
new AWSCredentialsProviderChain(
new EnvironmentVariableCredentialsProvider(),
CustomProvider.create(bucket)
)
}
override lazy val projectSettings = Seq(
publishTo := {
if (Keys.isSnapshot.value) {
Some("my-snapshots" at "s3://rest-of-stuff")
} else {
Some("my-releases" at "s3://rest-of-stuff")
}
},
s3CredentialsProvider := s3CredentialsProviderChain
)
The plugin code I'm working on does not define any custom settings of it's own thus has no autoImport of it's own.
Update
I have been unable to resolve the fm.sbt.S3ResolverPlugin in MyPlugin and the code won't compile.
I have tried adding it to enablePlugins on MyPlugin's build.sbt as well as adding it to the dependencies like this:
libraryDependencies ++= Seq(
"com.amazonaws" % "aws-java-sdk-sts" % amazonSDKVersion,
"com.frugalmechanic" % "fm-sbt-s3-resolver" % "0.17.0"
)
I get an error from sbt which I've asked below:
sbt fails to resolve a plugin as dependency
If you create an AutoPlugin in project directory. You need to add this to plugins.sbt.
addSbtPlugin("com.frugalmechanic" % "fm-sbt-s3-resolver" % "0.16.0")
If you create an independent plugin, add this to build.sbt of the plugin
sbtPlugin := true
addSbtPlugin("com.frugalmechanic" % "fm-sbt-s3-resolver" % "0.16.0")
autoImport does not work in scala files that are compiled for sbt, ie plugins for example. You have specify imports statements as in simple scala program. Something like this
import fm.sbt.S3ResolverPlugin
import sbt._
object TestPlugin extends AutoPlugin {
override def requires = S3ResolverPlugin
override def trigger = allRequirements
override def projectSettings: Seq[Def.Setting[_]] = Seq(
S3ResolverPlugin.autoImport.s3CredentialsProvider := ???
)
}
Note that to enable TestPlugin, you have to call enablePlugins(S3ResolverPlugin) in build.sbt

Migrating from Play 2.1 to 2.5: Build.scala configuration issues

I am upgrading from Play 2.1.3 to Play 2.5.4. I resolved multiple issues but I am now stuck at one last step I guess:
My project/Build.scala:
import sbt._
import Keys._
import play.sbt._
import Play.autoImport._
import PlayKeys._
object ApplicationBuild extends Build {
val appName = "dashboard"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
// Add your project dependencies here,
javaCore,
javaJdbc,
javaEbean
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
)
}
When I do activator run on my project, I get the following error:
[error] \project\Build.scala:19: object Project is not a member of package play
[error] val main = play.Project(appName, appVersion, apDependencies).settings(
[error] ^
[error] one error found
[debug] Compilation failed (CompilerInterface)
[error] (compile:compileIncremental) Compilation failed
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore?
Can someone please help?
play.Project was replaced by native sbt Project support at version 2.3:. From this version migration docs:
If you were previously using play.Project, for example a Scala project:
object ApplicationBuild extends Build {
val appName = "myproject"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq()
val main = play.Project(appName, appVersion, appDependencies).settings(
)
}
...then you can continue to use a similar approach via native sbt:
object ApplicationBuild extends Build {
val appName = "myproject"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq()
val main = Project(appName, file(".")).enablePlugins(play.PlayScala).settings(
version := appVersion,
libraryDependencies ++= appDependencies
)
}
But, since you are migrating from a very old version (Play 2.1 last release was in Sep 2013), I truly recommend you to use build.sbt instead of project/Build.scala. The migration would be something like:
name := """dashboard"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
javaJdbc,
cache,
javaWs
)
And, instead of adding javaEbean, you will need to use play-ebean instead. To do so, just add the following line to your project/plugins.sbt file (this was changed at Play 2.4 and you have to use the updated version as documented for Play 2.5):
addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.0")
After that, change your root project definition to something like this:
lazy val myProject = (project in file(".")).enablePlugins(PlayJava, PlayEbean)
This will automatically add Ebean dependencies. Finally, I can't recommend enough that you read all the migration guides for version between 2.1 and 2.5.

"Reference to undefined setting" error with custom task using a custom configuration in SBT?

I'm trying to create a task in sbt that will output the full classpath of a custom Configuration, but I get an undefined setting error when sbt tries to load the project definition. I can't figure out which setting has to be defined:
import sbt.Keys._
import sbt._
object FoobarBuild extends Build {
lazy val ZK = config("zk")
lazy val fcp = TaskKey[String]("fcp", "create formatted classpath")
lazy val fcpTask = fcp <<= (fullClasspath in ZK) map { cp =>
println(cp.files.absString)
cp.files.absString
}
lazy val project = Project("foobar", file(".")).
configs(ZK).
settings(
name := "foobar",
version := "1.0",
scalaVersion := "2.11.7"
).
settings(fcpTask)
}
Error:
[info] Loading project definition from foobar/project
Reference to undefined setting:
zk:fullClasspath from *:fcp (/Users/gaston/mesosphere/foobar/project/Build.scala:7)
zk:fullClasspath on the 7th line of this file is, of course, fullClasspath in ZK. It's undefined because it isn't set or inherited from any other config, I believe.

Play Framework and scala.tools.nsc

I have to use scala parser inside Play Framework application.
import scala.tools.nsc._
trait Foo
class Parser {
def parse(code: String) = {
val settings = new Settings
settings.embeddedDefaults[Foo]
val interpreter = new Interpreter(settings)
interpreter.parse(code)
}
}
I have following dependency in Build.scala
"org.scala-lang" % "scala-compiler" % "2.9.1"
This code works when build using SBT. In Play it ends with NullPointerException and:
Failed to initialize compiler: object scala not found.
** Note that as of 2.8 scala does not assume use of the java classpath.
** For the old behavior pass -usejavacp to scala, or if using a Settings
** object programatically, settings.usejavacp.value = true.
Build.scala
import sbt._
import Keys._
import PlayProject._
object ApplicationBuild extends Build {
val appName = "com.qwerty.utils"
val appVersion = "1.0-SNAPSHOT"
val scalaVersion = "2.9.1"
val appDependencies = Seq(
"org.scala-lang" % "scala-compiler" % "2.9.1"
)
val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
// Add your own project settings here
)
}
For background on embeddedDefaults, see the original proposal.
The container (Play) must define the 'app.class.path' and 'boot.class.path' resources and then embeddedDefaults will use them to configure the interpreter properly for the environment. So, this is an enhancement for Play.
If you can pass the necessary classpaths into your application, you can configure classpaths and classloaders explicitly yourself with something like:
val settings = new Settings
settings.classpath.value = "<classpath>"
settings.bootclasspath.value =
settings.bootclasspath.value + File.pathSeparator +
"<extra-bootclasspath>"
val interpreter = new Interpreter(settings) {
override def parentClassLoader = classOf[Foo].getClassLoader
}
interpreter.parse(code)
The bootclasspath should generally contain scala-library.jar and the classpath should contain the application jars.