Skip to content

Instantly share code, notes, and snippets.

Created August 8, 2014 22:55
  • Star 34 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save colestanfield/fac042d3108b0c06e952 to your computer and use it in GitHub Desktop.
sbt-assembly merge strategy for aop.xml files
// Create a new MergeStrategy for aop.xml files
val aopMerge: MergeStrategy = new MergeStrategy {
val name = "aopMerge"
import scala.xml._
import scala.xml.dtd._
def apply(tempDir: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]] = {
val dt = DocType("aspectj", PublicID("-//AspectJ//DTD//EN", ""), Nil)
val file = MergeStrategy.createMergeTarget(tempDir, path)
val xmls: Seq[Elem] =
val aspectsChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "aspects" \ "_")
val weaverChildren: Seq[Node] = xmls.flatMap(_ \\ "aspectj" \ "weaver" \ "_")
val options: String = => (x \\ "aspectj" \ "weaver" \ "@options").text).mkString(" ").trim
val weaverAttr = if (options.isEmpty) Null else new UnprefixedAttribute("options", options, Null)
val aspects = new Elem(null, "aspects", Null, TopScope, false, aspectsChildren: _*)
val weaver = new Elem(null, "weaver", weaverAttr, TopScope, false, weaverChildren: _*)
val aspectj = new Elem(null, "aspectj", Null, TopScope, false, aspects, weaver), aspectj, "UTF-8", xmlDecl = false, dt)
IO.append(file, IO.Newline.getBytes(IO.defaultCharset))
Right(Seq(file -> path))
// Use defaultMergeStrategy with a case for aop.xml
// I like this better than the inline version mentioned in assembly's README
val customMergeStrategy: String => MergeStrategy = {
case PathList("META-INF", "aop.xml") =>
case s =>
// Use the customMergeStrategy in your settings
mergeStrategy in assembly := customMergeStrategy
Copy link

rmarsch commented Nov 6, 2014

This is very helpful for people trying to get Kamon (or anything with multiple aop.xml) working with sbt-assembly. Thanks!

Copy link

tuler commented Dec 9, 2014

I tried to add this to my 'project/assembly.sbt' file, which only contained the line below:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")

I also deleted the blank line after "import scala.xml.dtd._".
But when I try to load sbt it says:

error: not found: type MergeStrategy

Copy link

Thanks, very nice!

@tuler - import sbtassembly.MergeStrategy at the top of your assembly.sbt file.

Copy link

Tried this and when running the app it could not find aspectj-weaver...

It seems like your application was not started with the -javaagent:/path-to-aspectj-weaver.jar option but Kamon detected the following modules which require AspectJ to work properly:

kamon-akka, kamon-spray, kamon-scala

If you need help on setting up the aspectj weaver go to for more info. On the other hand, if you are sure that you do not need or do not want to use the weaver then you can disable this error message by changing the setting in your configuration file.

I tried downloading the jar separately and pointing my java command at it, but to no avail. Anyone know anything about this?

Copy link

Thank you @colestanfield. I had a

case "META-INF/aop.xml"                                            => MergeStrategy.first

and it wouldn't work. Your aopMerge strategy works just fine!

Copy link

velvia commented Jun 23, 2016

Thanks @colestanfield... this works great! I would modify the first line to

val aopMerge = new sbtassembly.MergeStrategy {

so folks don't need to import MergeStrategy.

Copy link

dalegaspi commented Jun 25, 2016

ok first of all: major kudos to @colestanfield! 'found this thread because i ran into the same issue with aop.xml with Kamon libraries ...this is probably a stupid question: i copied the defaultMergeStrategy from the sbt-assembly README file because of missing reference to this function i supposed to do that or am i supposed to add some import?

I wasn't too thrilled about putting this code in can't add this to any .sbt file under project folder because sbt don't allow imports (at least for the current 0.13.11 version)...also, with the autoPlugins support...having a separate .sbt file (except for specific plugins that don't support autoplugin trait) is actually discouraged (i.e. you add sbt-assembly plugin in the plugins.sbt).

anyway, so i created a project/AssemblyMergeStrategies.scala and import that in the build.sbt file so i can use the assemblyMergeStrategy in assembly := customMergeStrategy line

BTW mergeStrategy is already deprecated; use assemblyMergeStrategy instead

Copy link

asethia commented Sep 13, 2016

It worked .. thanks @colestanfield for nice finding

Copy link

gidgid commented Jul 10, 2017

I've tried using this snippet and for some reason sbt assembly suspends while trying to read an XML file from a directory target/streams/$global making us unable to use that - does anyone knows what may be causing this to try and read this directory or why is it created?

Copy link

Hello @colestanfield
I notice that with sbt 1.4.9 this cause some problem
The error message during the build is
org.xml.sax.SAXParseExceptionpublicId: -//AspectJ//DTD//EN; systemId:; lineNumber: 1; columnNumber: 2; The markup declarations contained or pointed to by the document type declaration must be well-formed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment