I am currently taking over old Scala application with main goal to write new functionality in Java, but leveraging old common code. Up till now repository looked more-or-less like this:
├──common-scala-module-1
│ ├── src
│ │ ├── scala
│ │ │ ├── **/*.scala
│ │ ├── test
│ │ │ ├── **/*.scala
├──common-scala-module-2
│ ├── src
│ │ ├── scala
│ │ │ ├── **/*.scala
│ │ ├── test
│ │ │ ├── **/*.scala
├──scala-module-3
│ ├── src
│ │ ├── scala
│ │ │ ├── **/*.scala
│ │ ├── test
│ │ │ ├── **/*.scala
├──scala-module-4
│ ├── src
│ │ ├── scala
│ │ │ ├── **/*.scala
│ │ ├── test
│ │ │ ├── **/*.scala
├── build.sbt
├── .gitignore
└── (other scala files that doesn't matter for this problem)
All of those 4 produce jar modules, but the ones that really do matter for production code are from scala-module-3 and scala-module-4 (which depend on classes in both common modules). I need to start writing new code (new modules, like scala-module-3) but in Java from this point onward. I will still need however to maintain the old code if such need arises. There are two main concerns that I have and which I'd like to get architectural advice on (I wrote what I currently believe is the best path in parentheses after question):
- Shall I leave this repository alone and start a new one for Java modules? (I believe that makes much sense to split them: even though codebase should work just fine together if I leave it in one repo. IMO because I make new modules instead of just changing the old ones gives me a lot of reason to just add jar's from common modules as dependencies to Java code and leave old repository maintenance-only)
- Shall I migrate from SBT to Gradle/Maven and if so: which and why? Does answer change based on what will I do as result of question 1? (I used Maven and Gradle in all of my current projects, they are field-tested and they will help up a big time when managing builds and dependencies plus they are a standard in Java projects, so I gravitate towards Maven. Last but not least: I don't know SBT too much, which can give me additional headache)
NOTE: I do have pretty extensive Java background in multiple projects and I do know Scala basics (like that it leverages JVM technology and that SBT should work even if I'd just start putting Java code into the repository out of the blue). I am just looking for architectural advice in order to know the trade-offs and make my (and maybe someday others) life easier as this application is now leaving Scala behind (outside of bugs/maintenance).
Your primary problem is not to choose between Maven or Gradle.
Your primary problem is that you most likely cannot directly use any of those dependencies in your Java code (the fact that it compiles to JVM bytecode doesn't matter because you will not write your future packages in bytecode).
The reasons why you cannot directly use any of these dependencies are:
implicits /givens, let alone macros. Thus, exposing thegivens is like screaming into an abyss, and not getting any response back, i.e. noisy & pointless.One reasonable thing that you might attempt:
common-scala-module-1,common-scala-module-2etc.<P>, either create additional<P>-javaapisubproject (i.e.common-scala-module-1-javaapi,common-scala-module-2-javaapietc.), or create an additional<P>/javaapisubpackage (i.e.common-scala-module-1/src/main/java/org/whatever/tool/javaapi)<P>-javaapisubproject / subpackage:<P>, but written as idiomatic Java. Brace yourself forFactoryFactoriesand pages upon pages of repetitive generics.<P><P>-javaapiwith SBT (the-javaapiis a mixed Scala/Java project, so probably better to build it with SBT)-javaapipackages.This should work, because:
scala.jdk.CollectionConvertersetc. is trivial.-javaapipackages with SBT should work fine.By the end, you obtain bunch of packages
common-scala-module-1-javaapi...common-scala-module-N-javaapithat are practically indistinguishable from any Java packages not only on bytecode level, but also on the level of exported types, interfaces, and documentation. The only difference is that they would have weird dependencies (but you won't notice it while using them).Unless your code is a tightly coupled mess that prevents you from testing
common-scala-module-Ns without also modifying and rerunning all your non-common-modules, then it's probably better to create a separate repo with separatejava-module-0,java-module-1etc. and build them with Maven (or Gradle).