Minimal sbt-web pipeline without Play - sbt

I'm using spray to create a single page app, and cannot get sbt-web to process any of my inputs. I started with WebJars, because, https://github.com/sbt/sbt-web/blob/master/README.md says:
One last thing regarding the public and public-test folders... any WebJar depended on by the project will be automatically extracted into these folders e.g. target/web/public/lib/jquery/jquery.js.
However, I see no such "web" folder in the target folder. I thought maybe WebJars was too complicated of an example to start with, so I instead added a jquery.js file to the root of the asset folder, and set up sbt-uglify to do some processing on it. Yet, still, I see no evidence that SbtWeb is working. I've run sbt --debug clean run and grepped the output for any output from SbtWeb or Uglify, but no errors or warnings and can't find anything wrt SbtWeb or Uglify. Just acknowledgement that it seems to "deduce" the plugins:
[debug] deducing auto plugins based on known facts [debug] :: sorting:: found:
...
[debug] :: sorted deduced result: List(sbt.plugins.CorePlugin, com.typesafe.sbt.web.SbtWeb, com.typesafe.sbt.jse.SbtJsEngine, net.ground5hark.sbt.concat.SbtConcat, sbt.plugins.IvyPlugin, com.typesafe.sbt.jse.SbtJsTask, sbt.plugins.JvmPlugin, com.typesafe.sbt.uglify.SbtUglify, sbt.plugins.JUnitXmlReportPlugin)
Here is my directory structure:
./build.sbt
./project/plugins.sbt
./src/main/assets/js/jquery.js
./src/main/resources/html/uikit/login.html
./src/main/scala/Boot.scala
./src/main/scala/main.scala
Here is my project/plugins.sbt:
resolvers += Resolver.sonatypeRepo("releases")
addSbtPlugin("com.typesafe.sbt" % "sbt-web" % "1.0.2")
addSbtPlugin("net.ground5hark.sbt" % "sbt-concat" % "0.1.8")
addSbtPlugin("com.typesafe.sbt" % "sbt-uglify" % "1.0.3")
Here is my ./build.sbt:
organization := "com.test123.spray"
version := "0.1"
scalaVersion := "2.11.6"
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")
libraryDependencies ++= {
val akkaV = "2.3.9"
val sprayV = "1.3.3"
Seq(
"io.spray" %% "spray-can" % sprayV,
"io.spray" %% "spray-routing" % sprayV,
"io.spray" %% "spray-testkit" % sprayV % "test",
"com.typesafe.akka" %% "akka-actor" % akkaV,
"com.typesafe.akka" %% "akka-testkit" % akkaV % "test",
// client side dependencies
"org.webjars" % "jquery" % "2.1.4",
"org.webjars" % "uikit" % "2.24.2"
)
}
lazy val root = (project.in(file("."))).enablePlugins(SbtWeb)
pipelineStages := Seq(uglify)
includeFilter in uglify := GlobFilter("js/*.js")
Here is what the root of my ./target folder looks like:
resolution-cache/
scala-2.11/
streams/
No ./target/web folder. Any ideas why?
References:
https://github.com/sbt/sbt-web/blob/master/README.md
http://mariussoutier.com/blog/2014/12/07/understanding-sbt-sbt-web-settings/

That'll learn me. I was using an old version of sbt-web. When I update it to the latest, it works as expected.
The lesson is not to copy/paste snippets like this:
addSbtPlugin("com.typesafe.sbt" % "sbt-web" % "1.0.2")
from the web. But, rather to find the latest version, manually, by one of the following methods:
If the GitHub (et al) page has a "Build Passing" badge, click on it to navigate to the build server where the latest versions are listed.
Look at the branches in GitHub
See if you can navigate to the repository for the dependency, such as Maven Central, and browse there. I didn't have luck with this one. The problem I had is that I knew it wasn't on Maven, and didn't know where else to look.
Plug in some bogus version in SBT, and look at the output for where SBT tried to look and failed:
[warn] module not found: com.typesafe.sbt#sbt-web;3.1.2
[warn] ==== typesafe-ivy-releases: tried
[warn] http://repo.typesafe.com/typesafe/ivy-releases/com.typesafe.sbt/sbt-web/scala_2.10/sbt_0.13/3.1.2/ivys/ivy.xml
[warn] ==== sbt-plugin-releases: tried
[warn] http://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/com.typesafe.sbt/sbt-web/scala_2.10/sbt_0.13/3.1.2/ivys/ivy.xml
I'm positive there are better ways to find the latest versions of things that I'm just unaware of. For those more experienced than me please comment with a better way.

Related

sbt aspectj with native packager

I'm attempting to use the sbt-aspectj plugin with the sbt native packager and am running into an issue where the associated -javaagent path to the aspectj load time weaver jar references an ivy cache location rather than something packaged.
That is, after running sbt stage, executing the staged application via bash -x target/universal/stage/bin/myapp/ results in this javaagent:
exec java -javaagent:/home/myuser/.ivy2/cache/org.aspectj/aspectjweaver/jars/aspectjweaver-1.8.10.jar -cp /home/myuser/myproject/target/universal/stage/lib/org.aspectj.aspectjweaver-1.8.10.jar:/home/myuser/myproject/target/universal/stage/lib/otherlibs.jar myorg.MyMainApp args
My target platform is Heroku where the artifacts are built before being effectively 'pushed' out to individual 'dynos' (very analogous to a docker setup). The issue here is that the resulting -javaagent path was valid on the machine in which the 'staged' deployable was built, but will not exist where it's ultimately run.
How can one configure the sbt-aspectj plugin to reference a packaged lib rather than one from the ivy cache?
Current configuration:
project/plugins.sbt:
addSbtPlugin("com.typesafe.sbt" % "sbt-aspectj" % "0.10.6")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.1.5")
build.sbt (selected parts):
import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
aspectjSettings,
javaOptions in Runtime ++= { AspectjKeys.weaverOptions in Aspectj }.value,
// see: https://github.com/sbt/sbt-native-packager/issues/598#issuecomment-111584866
javaOptions in Universal ++= { AspectjKeys.weaverOptions in Aspectj }.value
.map { "-J" + _ },
fork in run := true
)
Update
I've tried several approaches including pulling the relevant output for javaOptions from existing mappings, but the result is a cyclical dependency error thrown by sbt.
I have something that technically solves my problem but feels unsatisfactory. As of now, I'm including an aspectjweaver dependency directly and using the sbt-native-packager concept of bashScriptExtraDefines to append an appropriate javaagent:
updated build.sbt:
import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
aspectjSettings,
bashScriptExtraDefines += scriptClasspath.value
.filter(_.contains("aspectjweaver"))
.headOption
.map("addJava -javaagent:${lib_dir}/" + _)
.getOrElse(""),
fork in run := true
)
You can add the following settings in your sbt config:
.settings(
retrieveManaged := true,
libraryDependencies += "org.aspectj" % "aspectjweaver" % aspectJWeaverV)
AspectJ weaver JAR will be copied to ./lib_managed/jars/org.aspectj/aspectjweaver/aspectjweaver-[aspectJWeaverV].jar in your project root.
I actually solved this by using the sbt-javaagent plugin to adding agents to the runtime

Apache commons-imaging;1.0-SNAPSHOT: not found

How can SBT builds be made reliable enough to use in a production environment?
Specifically, SBT normally builds without a problem, but every few weeks, the commons-imaging dependency is not found, halting the entire build.
In build.sbt:
libraryDependencies ++= Seq(
, "commons-io" % "commons-io" % "2.4"
, "org.apache.commons" % "commons-imaging" % "1.0-SNAPSHOT" withSources ()
)
resolvers in ThisBuild ++= Seq(
"Apache Development Snapshot Repository" at "https://repository.apache.org/content/repositories/snapshots/"
)
sbt.ResolveException: unresolved dependency: org.apache.commons#commons-imaging;1.0-SNAPSHOT: not found
This usually works fine. But recently started giving:
[warn] Unable to reparse org.apache.commons#commons-imaging;1.0-SNAPSHOT from Apache Development Snapshot Repository
(1) Why would it be so intermittent? Is it the Resolver URL that changes, or the Web site that serves the commons-imaging jar going down? (other maven resources are found without ever experiencing a hiccup.)
(2) What can be done to ensure that clean builds always succeed? (This is crucial for spinning up a new instance and expecting it to succeed.)
Edit: This doesn't answer the question, but I found a workaround for this particular issue in that deleting "withSources()" allows the build to succeed.

Play framework: Host repo.typesafe.com not found

Environment: Play framework; activator-1.3.2; Play-Java Web Application
build.sbt -
name := """ProjectDemoNew"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
scalaVersion := "2.11.1"
resolvers +="Local Maven Repository" at "file:///home/shiva/.m2/repository"
libraryDependencies ++= Seq(
javaJdbc,
javaEbean,
cache,
javaWs,
"org.springframework" % "spring-context" % "3.2.3.RELEASE",
"org.springframework" % "spring-aop" % "3.2.3.RELEASE",
"org.springframework" % "spring-expression" % "3.2.3.RELEASE",
"org.springframework" % "spring-test" % "3.2.3.RELEASE",
"com.mycomp.config"%"platform-config"%"0.0.1-SNAPSHOT"
)
$ activator run
gives the following error(s) when the internet is down..
--
--
[info] You probably access the destination server through a proxy server that is not well configured.
[warn] Host repo.typesafe.com not found. url=https://repo.typesafe.com/typesafe/releases/com/mycomp/conf/i/platform-config/0.0.1-SNAPSHOT/...-SNAPSHOT.pom
--
--
I am not seeing any errors in case the internet is up.
There are lots of posts, but the answers seem to vary a lot.
All jars ( spring, application-specific, third party..) are in my local repository. But it always connects internet for refreshing dependencies, build is slow when the internet speed is not good
How to make Play go through Local repository without going through internet/offline? This helps me doing the build quickly with no or weak internet connectivity.
It automatically checks the internet for SNAPSHOT dependencies.
If you don't want it to do it, add :
offline := true
to your build.sbt file.

sbt assembly command not found

I'm trying to run sbt assembly. According to https://github.com/sbt/sbt-assembly , for sbt 0.13.6+ (I'm on 0.13.7) this should be included automatically for anything with the JvmPlugin. According to sbt plugins I have the JvmPlugin enabled in root. When I run sbt assembly I get "Not a valid commamdn: assembly". I've tried using old methods of including sbt-assembly with all the different types of sbt configurations, but none seem to work. Here's what my build files look like (note sbt package works fine)
assembly.sbt
addSbtPlugin("com.eed3si8n" % "sbt-assembly" % "0.13.0")
build.sbt
lazy val commonSettings = Seq(
organization := "com.test",
version := "1.0",
scalaVersion := "2.10.4"
)
lazy val root = (project in file(".")).
settings(commonSettings: _*).
settings(
name := "test",
resolvers ++= Seq(
...
),
libraryDependencies ++= Seq(
...
)
)
Here is the error:
[error] Not a valid command: assembly
[error] Not a valid project ID: assembly
[error] Expected ':' (if selecting a configuration)
[error] Not a valid key: assembly
[error] assembly
[error]
Any ideas? Running on Linux. Thanks
Did you create a assembly.sbt at the root of your project? Alongside your build.sbt?
If so, then that's the problem. You want to have it inside the project directory.
Having done that it worked out the box as expected with the rest of your setup:
> assembly
[info] Including: scala-library.jar
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
[warn] Strategy 'discard' was applied to a file
[info] SHA-1: 1ae0d7a9c433e439e81ce947659bf05aa62a2892
[info] Packaging /Users/dnw/Desktop/t-2015-04-08.2340/target/scala-2.10/test-assembly-1.0.jar ...
[info] Done packaging.
[success] Total time: 2 s, completed 08-Apr-2015 23:45:59
Since the introduction of auto plugins in 0.13.5, adding explicit .sbt files for plugins (except for specific cases where the plugin does not implement auto-plugin trait) is not recommended per sbt documentation.
Add the addSbtPlugin("com.eed3si8n" % "sbt-assembly" % "0.13.0") back to plugins.sbt under project directory and remove assembly.sbt. if you still see the error, explicitly enable the plugin in the build.sbt:
lazy val root = (project in file(".")).
settings(commonSettings: _*).
settings(
name := "test",
).
enablePlugins(AssemblyPlugin)
lazy val root = (project in file(".")).
settings(commonSettings: _*).
settings(
assemblySettings ++ Seq(
jarName in assembly := "roobricks-spark.jar",
test in assembly := {}
).
enablePlugins(AssemblyPlugin)
can you once with this.
Same thing happened to me. Move assembly.sbt from the root to inside your project/ directory
Came across the same error. The reason was I executing it from the wrong inside target folder
You should normally have a plugins.sbt file at the root level alongside your build.properties where you should have the following:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
From sparkour:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.4") with assembly.plugin does work

Unresolved dependency: net.sourceforge.htmlunit in SBT

My build.sbt has the following content:
name := "hello-world"
version := "1.0"
scalaVersion := "2.10.3"
libraryDependencies += "net.sourceforge.htmlunit" %% "htmlunit" % "2.13"
When I perform update in sbt console it says:
[error] (*:update) sbt.ResolveException: unresolved dependency: net.sourceforge.htmlunit#htmlunit_2.10;2.13: not found
What should I do to make sbt find this library?
Just use a single % instead of double %% in the dependency.
libraryDependencies += "net.sourceforge.htmlunit" % "htmlunit" % "2.13"
%% is only required when the path of the jar contains Scala version which is not a case for the dependency. I figured it out consulting mvnrepository - http://mvnrepository.com/artifact/net.sourceforge.htmlunit/htmlunit/2.13. Just hover over the 'Download(JAR)' link and you can see the full path.
Note: By default sbt uses the standard Maven2 repository. In case you have dependent jars that cannot be found in the default repo, then you need to add custom resolvers like this
resolvers += "custom_repo" at "url"
For this particular example resolvers are not required since htmlunit is present in default repo.

Resources