Fork me on GitHub

If anyone is curious, I resumed the "polylith in java" experiment I was doing 5 months ago. Details in thread

polylith 2

The strategy is still that a "brick" in polylith translates to a module in Java


For Interface bricks:


It is expected that four things are exposed 1. A "service" with all the methods that the component requires.

public interface ArticleService {
    Article findById(long id);
2. A "factory" which makes the service
public interface ArticleServiceFactory {
    ArticleService create(DataSource dataSource);
3. A mechanical interface for something which just "has" the service
public interface HasArticleService {
    ArticleService articleService();
4. Any classes which are needed to model the domain
public record Article(
        long articleId,
        ExternalId externalId,
        String title,
        String description,
        String body,
        LocalDateTime createdAt,
        LocalDateTime updatedAt,
        long userId
) {
    public ArticleSlug slug() {
        return new ArticleSlug(externalId, title);
Then in the module, requires and exports as needed
module jolly.articles {
    exports dev.mccue.polylith.articles;
    requires transitive java.sql;
In addition to a "uses" declaration for the factory interface
module jolly.articles {
    exports dev.mccue.polylith.articles;

    requires transitive java.sql;

    uses dev.mccue.polylith.articles.ArticleServiceFactory;
And in the interface for the service, have a static method which delegates to a factory found via the service loader
public interface ArticleService {
    static ArticleService create(DataSource dataSource) {
        return ServiceLoader.load(ArticleServiceFactory.class)


For Component/implementation bricks:


In the module nothing should be exposed directly, just a transitive require of the interface

module jolly.articles.impl {
    requires transitive jolly.articles;
And implementations should be provided for both the factory and service interfaces
public final class ArticleServiceImpl implements ArticleService {
    private final DataSource dataSource;
    public ArticleServiceImpl(DataSource dataSource) {
        this.dataSource = dataSource;
    // ...
public final class ArticleServiceFactoryImpl implements ArticleServiceFactory {
    public ArticleService create(DataSource context) {
        return new ArticleServiceImpl(context);
And the service factory should be declared in the module
module jolly.articles.impl {
    requires transitive jolly.articles;

    provides ArticleServiceFactory with ArticleServiceFactoryImpl;


For "Base" bricks:


Basically everything but the main, taking in some "ctx" object which holds all the services started or whatever else

public final class Handler<Ctx extends HasArticleService>
        implements Function<Request, IntoResponse> {
    private final Ctx ctx;

    public Handler(Ctx ctx) {
        this.ctx = ctx;

    public IntoResponse apply(Request request) {
        return new Response(Body.fromString(
                "Hello Polylith! " + ctx.articleService()
And export the "entrypoint"
module jolly.handler {
    exports dev.mccue.polylith.handler;
    requires transitive jolly.articles;

    requires transitive dev.mccue.rosie;


For project bricks: Actually select implementation bricks in the module

module jolly.main {
    requires jolly.articles.impl;
    requires jolly.db.impl;

    requires jolly.handler;
    requires dev.mccue.rosie;
    requires rosie.microhttp;
    requires org.microhttp;
    requires org.xerial.sqlitejdbc;
And start the server/whatever
public record Context(
        DataSource dataSource
) implements HasArticleService {
    public Context() {

    public ArticleService articleService() {
        return ArticleService.create(dataSource);
public class Main {
    public static void main(String[] args) {
                new Handler<>(new Context()),
                new Options().withPort(1123),


Doing this is, I think understandably, a bit exhausting


like, not the technique, but working on something that isn't real for no benefit


so I doubt i will ever finish the real world spec at this pace


but I think I have a grasp of at least one way "it can be done"


The Has interfaces are to avoid the need for DI


and the dynamic linkage means some annoying stuff, but all in all I find it okay