We assemble our bricks (components and bases) in deployable projects from which we build artifacts.
The base (a project typically has a single base) acts as the runtime entry point.
The poly
tool has no say in what type of artifacts we build or how we build them.
Some artifact examples are:
REST APIs
Lambda functions
Command line tools
Libraries
There are challenges associated with building more than one library from a single workspace. But let’s start with the simple case.
Let’s say we have a workspace with three components:
Now we can easily build a library of these components (e.g. libx.jar
) and everything will work just as well as if we had a traditional monolithic codebase:
It’s natural to use a base to expose a library’s functionality, as they are meant for that job (exposing APIs).
For instance, we can use a libx-api
base to expose the functionality of the libx
library above.
Alternatively, we can use a component to expose the functionality, as demonstrated by the clj-poly library.
Let’s say we release 1.1
of library libx
and liby
, and then after a while we release 1.2
.
If someone out there now includes libx-1.1
and liby-1.2
in their classpath, we will get this situation:
Here the c
component is used by both libx
and liby
and depending on which library that comes first in the classpath, we will get either 1.1
or 1.2
of c
.
If the interface of c
has changed between 1.1
and 1.2
then libx
may even fail to compile.
Even if it does compile, it remains problematic, because
c
may exhibit new behavior that hasn’t been tested from the 1.1
context.
There is another alternative, and that is to build one library/jar per brick:
Let’s say we have built and released 1.1
of all these five libraries, and then after a while, we release 1.2
. Let’s say someone has included version 1.1
of "libx" by including liba
, libb
, and libc
, and version 1.2
of "liby" by including libc
, libd
and libe
.
Now, we can’t be certain which version of component c
will be picked up by the classloader, as it depends on the order in which the libraries are specified:
This means we experience the same problem as if we build libx
and liby
separately.
The most solid solution is probably to build a single jar out of the entire workspace that includes all the bricks (myws.jar
in this example) and thus all the libraries:
This will ensure that the same version of all libraries is used, regardless of which one(s) the user is interested in.
The last alternative is to adjust the top namespace for each library, when building the jar. We should keep the namespace of the API base though, so that people don’t have to change their :require
statements when they use the library.
This approach comes with its own challenges, which is discussed in issue 212.
If you have intended to build two or more libraries from a Polylith workspace, we recommend that you build one library per workspace.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close