How to map concepts and solutions from an enterprise Java app to Clojure?


Hello! I am writing a guide for experienced Java enterprise developers that are used to solving particular enterprisy problems in particular ways to understand how they would do that in Clojure, the premise being that there is no 1:1 mapping because in Clojure we do stuff differently (and have better tools :-)).

I have two questions:

  • Can you think of other important concerns than the ones I mention below?
  • Would you address a concern differently from what I propose? If so, how?

You can of course read the whole post: Translating an enterprise Spring webapp to Clojure but perhaps it suffices for further discussion to repeat here the summary table:

Concern Java Clojure
Code structure controller/, <domain>/, … Evolve as needed
Architecture 3-tiered: web, services, integration Similar but evolved as needed + Functional Core, Imperative Shell
IoC Spring’s @Component + @Autowired everything Typically not needed; use namespace-local “singletons” or pass around in a context object
AOP Use @Aspect + @Around, perhaps based on annotations Typically not needed; wrap with higher-order functions/macros. Use alter-var-root if you must
Cross-cutting concerns E.g. @Authorization, @Scheduled, @Timed Be explicit. Wrap with higher-order functions/macros.
Logging Logger in each class, XML/code config. Same, use the clojure/tools.logging facade
Request tracking ThreadLocal to store, AOP/Filter to set ThreadLocal or a context attribute to store, Ring middleware or a HoF to set
Resource pooling Inject the configured pool via IoC See IoC above
Request decoration Servlet Filters Ring middleware
Testing Mocks FTW! Call pure functions as-is. Set a namespace singleton/pass context attribute for the Imperative Shell

(You can read more about Functional Core, Imperative Shell here.)

Thank you!

(I will also go through the projects listed at Example "enterprise" Clojure (web) app? to find more concerns and solutions.)


XML config files -> …

POJO classes to hold stuff on the way to/from the database, XML, or JSON -> …

(Also, we frown on globals of any stripe, including singletons and ThreadLocals.)