Conflicting deps in generated java code

I have two dars a.dar and b.dar, and the former is a dependency of the latter, i.e. data-dependency: - a.dar

These dars reside in separate projects, and when I run codegen for both, I end up with two copies of the generated code for a. When I then try to import both of these I get clashes e.g.:

error: duplicate class: codegen.da.set.types.Set

I can see some solutions to this:

  • In project b, exclude project as java code from the classpath somehow
  • Prevent the daml assistant from generating code for dependencies (how?)
  • Modify the java package (module) path during code-generation, so the genreated code for a lives in separate namespaces (but then I’ll have duplicate definitions of as classes).

Any tips/thoughts on how to avoid this sort of problem?

I have no familiarity with the codegen, so take all this with a spoonful of salt.

First off: do you need to generate both if generating b automatically produces a? Your description makes it sound like you could generate code only for b and then get to the a classes through that.

I can see how that would not scale, though. The next option I’d suggest is to give each dar its own prefix:

$ daml codegen java --help
Usage: codegen [options] <DAR-file[=package-prefix]>...
                           DAR file to use as input of the codegen with an optional, but recommend, package prefix for the generated sources.

That would indeed end up with a’s code generated twice, resulting in a slightly bigger JAR. On the bright side, if you somehow end up in a situation where the version of the “direct” a is not quite the same as the version of the “transitive” a, this should work transparently with b code getting the a version it expects while your code can use the other a. (I’m not sure how practical that would be as that would likely cause issues at the ledger level, but, again, my experience here is very limited.)

Yes that’s right, but we’re trying to keep these as re-usable modules. A more complex (but real) scenario is that we have a third package c which depends on both b and a.

Yes that’s the third bullet point above. The issue with this is that we end up having multiple copies of the class in separate namespaces and this is very confusing from a developer’s perspective - which one do you use? Also, the classes are not compatible even if they are the same. (I can’t call f( instead of f( ).