Fork me on GitHub
#polylith
<
2021-03-29
>
seancorfield01:03:28

I have brick tests generating and running correctly now but when I try to run the project tests, I get a weird pathing error on the bases/components:

(! 762)-> clojure -X:new :template polylith :name seancorfield/polyex
Generating a project called polyex based on the 'polylith' template.
(! 763)-> (cd polyex/; clojure -M:deps:poly test :all :dev)
Projects to run tests from: development, polyex

Running tests from the development project, including 2 bricks and 1 project: greeter, cli, polyex

Testing seancorfield.polyex.cli.main-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Test results: 1 passes, 0 failures, 0 errors.

Testing seancorfield.polyex.greeter.interface-test

Ran 1 tests containing 2 assertions.
0 failures, 0 errors.

Test results: 2 passes, 0 failures, 0 errors.
Couldn't resolve libraries for the polyex project: clojure.lang.ExceptionInfo: Manifest type not detected when finding deps for net.clojars.seancorfield/component-greeter in coordinate #:local{:root "/Developer/workspace/components/greeter"} {:lib net.clojars.seancorfield/component-greeter, :coord #:local{:root "/Developer/workspace/components/greeter"}}
Manifest type not detected when finding deps for net.clojars.seancorfield/component-greeter in coordinate #:local{:root "/Developer/workspace/components/greeter"}
My projects/polyex/deps.edn file:
{:paths [] ; no src or resources

 :deps {org.clojure/clojure {:mvn/version "1.10.1"}
        net.clojars.seancorfield/component-greeter {:local/root "../../components/greeter"}
        net.clojars.seancorfield/base-cli {:local/root "../../bases/cli"}}

 :aliases {:test {:extra-paths ["test"]
                  :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"}}}

           :uberjar {:replace-deps {com.github.seancorfield/depstar {:mvn/version "2.0.206"}}
                     :exec-fn hf.depstar/uberjar
                     :exec-args {:jar polyex.jar
                                 :aot true
                                 :main-class seancorfield.polyex.cli.main}}}}
Note that I can build the project just fine, so the :deps work when I’m in the project:
(! 767)-> (cd polyex/projects/polyex/; clojure -X:uberjar)
[main] INFO hf.depstar.uberjar - Compiling seancorfield.polyex.cli.main ...
[main] INFO hf.depstar.uberjar - Building uber jar: polyex.jar
[main] INFO hf.depstar.uberjar - Processing pom.xml for {net.clojars.seancorfield/polyex {:mvn/version "0.1.0-SNAPSHOT"}}
and that runs just fine too.

seancorfield01:03:28

(I’ll take a look at the poly source on the issue-66 branch to see if I can debug this maybe later tonight or tomorrow)

seancorfield04:03:07

If you want to try the wip version: {:git/url "" :sha "5a63e5b1786cb1dda28eb00b79f5c8ff91f277b3"}

seancorfield04:03:26

clojure -Sdeps '{:deps {seancorfield/clj-new {:git/url "" :sha "5a63e5b1786cb1dda28eb00b79f5c8ff91f277b3"}}}' -X clj-new/create :template polylith :name seancorfield/polyex

tengstrand04:03:31

Okay, I will check it out and see if I can reproduce the problem.

seancorfield04:03:12

Hopefully these three commands will repro for you:

$  clojure -Sdeps '{:deps {seancorfield/clj-new {:git/url "" :sha "5a63e5b1786cb1dda28eb00b79f5c8ff91f277b3"}}}' -X clj-new/create :template polylith :name seancorfield/polyex
 $  cd polyex/
 $  clojure -M:poly test :all :dev 

tengstrand04:03:46

Yes, I got the same error. Will have a look.

tengstrand05:03:03

Found the problem @U04V70XH6. You should remove the dependency to the greeter component in bases/cli/deps.edn:

{:paths ["src" "resources"]

 :deps {}

 :aliases {:test {:extra-paths ["test"]
                  :extra-deps {}}}}
You only need to add dependencies to libraries in bases and components. Bases and components only know about interfaces, and should not know about what concrete implementations (components) they depend on. This is decided by the projects.

seancorfield05:03:32

Ah, OK. Will update the template stuff…

seancorfield05:03:24

Yup, that was it:

(! 726)-> clojure -X:new :template polylith :name seancorfield/polyex
Generating a project called polyex based on the 'polylith' template.
Initialized the project for use with 'git'.
(! 727)-> (cd polyex/; clojure -Sforce -M:poly test :all :dev)
Projects to run tests from: development, polyex

Running tests from the development project, including 2 bricks and 1 project: greeter, cli, polyex

Testing seancorfield.polyex.cli.main-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Test results: 1 passes, 0 failures, 0 errors.

Testing seancorfield.polyex.greeter.interface-test

Ran 1 tests containing 2 assertions.
0 failures, 0 errors.

Test results: 2 passes, 0 failures, 0 errors.
Running tests from the polyex project, including 2 bricks and 1 project: greeter, cli, polyex

Testing seancorfield.polyex.cli.main-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Test results: 1 passes, 0 failures, 0 errors.

Testing seancorfield.polyex.greeter.interface-test

Ran 1 tests containing 2 assertions.
0 failures, 0 errors.

Test results: 2 passes, 0 failures, 0 errors.

Testing seancorfield.polyex.polyex-test
{:result true, :num-tests 100, :seed 1616997235595, :time-elapsed-ms 50, :test-var "greeting-test"}

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Test results: 1 passes, 0 failures, 0 errors.
Execution time: 3 seconds
That runs a generative test in the project folder just as example of non-unit style tests not being in the bricks.

🙌 3
seancorfield05:03:08

That needs to be a bit clearer in the documentation I think — but it does also make the whole projects thing a bit more obvious to me now!

tengstrand06:03:10

Okay, good to hear! I will add a note about that in the doc.

seancorfield06:03:24

The fixed version of clj-new is available on this SHA for anyone who wants to try it out and provide feedback:

$ clojure -Sdeps '{:deps {seancorfield/clj-new {:git/url "" :sha "07309e06893c35de6bf1418c05b453c02a796cc4"}}}' -X clj-new/create :template polylith :name seancorfield/polyex
Checking out:  at 3ecda39da612c2ee2069c372b3a935e4a78804fd
Generating a project called polyex based on the 'polylith' template.
Initialized the project for use with 'git'.
$ cd polyex
$ clojure -M:poly info
  ...
$ clojure -M:poly test :all :dev
Projects to run tests from: development, polyex
  ...
$ (cd projects/polyex/ && clojure -X:uberjar)
[main] INFO hf.depstar.uberjar - Synchronizing pom.xml
Skipping coordinate: #:local{:root ../../components/greeter}
Skipping coordinate: #:local{:root ../../bases/cli}
[main] INFO hf.depstar.uberjar - Compiling seancorfield.polyex.cli.main ...
[main] INFO hf.depstar.uberjar - Building uber jar: polyex.jar
[main] INFO hf.depstar.uberjar - Processing pom.xml for {net.clojars.seancorfield/polyex {:mvn/version "0.1.0-SNAPSHOT"}}
$ java -jar projects/polyex/polyex.jar 
Hello, World!
$ java -jar projects/polyex/polyex.jar Lisa
Hello, Lisa!
(esp. the README and the structure/correctness of the generated example project)

👍 6
seancorfield06:03:50

Something that is missing from the docs is an example of building a library as a deployable artifact from the workspace. Am I right that it would be “just” another project that specified maybe a base for the library API and the necessary components, and then have a :jar alias to build something that could be deployed to Clojars (via a :deploy alias).

tengstrand06:03:18

The api project does that in the Polylith repo.

tengstrand06:03:36

The api (the functions that you expose) will go into a component of that library - the api component in this case.

tengstrand06:03:32

Because the final artifact (the library) is only consumed as code, we don’t add a base to it, because bases are used to expose code/functionality to the outside world via a public API. Libraries are just “frozen code” and that’s why we expose it as a component.

tengstrand06:03:12

Another thing @U04V70XH6. I would recommend you to prefix the Polylith dependencies like this (prefix them with poly):

:deps {org.clojure/clojure {:mvn/version "1.10.1"}
       poly/component-greeter {:local/root "../../components/greeter"}
       poly/base-cli {:local/root "../../bases/cli"}}
This will communicate that it’s an “internal” Polylith brick . It would be good if you follow the same pattern in your example application that we recommend in the Polylith documentation (because people will probably copy it).

👍 3
seancorfield06:03:21

If so, I’ll add that to the clj-new template as well (tomorrow).

seancorfield17:03:31

clj-new has been updated, based on feedback from @tengstrand and can be tested at this :sha "9ee232b94b3d6b7e00ab6e6ad58e0f3c7bf5487d" — it now contains a library project as well as an application project, which is set up for deployment to Clojars out of the box, just like the regular lib template that clj-new has had for a while.

👍 15
🎉 12
polylith 12
seancorfield17:03:44

@pez Since you sent a PR about .gitignore stuff, when that’s resolved however it turns out, if you want to send a similar PR to clj-new that would be awesome (there’s a gitignore template in each of app, lib, polylith, and template — as well as an hgignore which I may drop, certainly from the polylith template since it seems pretty opinionated about using git, but maybe from the others too… does anyone use Mercurial these days?).

pez18:03:51

Will do!

pez18:03:29

(I think mercurial is dead.)

seancorfield18:03:43

Hah! Maybe I’ll just excise those files then.

🙂 3
dharrigan19:03:00

Hi. Just familiarising myself with Polylith. Read the documentation and watched the "Polylith - last architecture...." video. This may have been asked, apologies (happy to be pointed to the relevant discussion).

dharrigan19:03:13

Would it play nicely with something like component, or integrant, clip or mount? Is the idea not to use these types of lifecycle managment libraries?

furkan3ayraktar19:03:14

I use my own version of https://github.com/tolitius/mount where I tweaked it a bit to play nicely with Datomic Cloud. I think it’s totally fine to do lifecycle management when needed and Polylith doesn’t prevent that.

pez19:03:16

@dharrigan I think you are pointing to a need for the Polylith documentation to state what it is not about. Saying this because as far as I have understood things, Polylith has no opinion about the choice of life cycle management. (I could of course be wrong, I am quite new to the concept).

dharrigan19:03:52

Right. For example, I have an embyronic application that I've started to put together. As a bit of an experiment I reordered it to "fit" nearly into the polylith directory structure/architecture. I also use JUXT Clip and I'm still able to "wire" together my namespaces/functions (i.e., to spin up a connection to a database, and a redis server and the ring handler and do a bit of pre-start, application boot type of thing)

seancorfield19:03:38

Although the documentation suggests Mount I would expect it’s easy to use Polylith with Component or Integrant (both of which I would prefer over Mount).

dangercoder19:03:36

I’m porting an integrant project to use polylith right now. I keep the integrant system definition in the “base” and its working just fine right now

dangercoder19:03:28

still work in progress though, not 100% done with this experiment.

tengstrand19:03:38

We plan to add a section at the first page where we describe what Polylith is not. @pez is right. Polylith itself doesn’t “write”/provide any code for you, so it’s not what e.g. Spring is for Java. @furkan3ayraktar is the one of us in the Polylith team that has worked with most Polylith systems (around five) and he uses a forked Mount and has adjusted it to work nicely with Datomic Ions. We have discussed if we should add a section about this in the documentation, but hesitated, because we haven’t used so many of the different alternatives ourselves, and Polylith doesn’t care if you use any or what you use. Mount has served us well, but it’s possible that other alternatives could be as good or even better.

furkan3ayraktar19:03:47

Yeah, exactly, I haven’t experimented with others so I wouldn’t say mount is the best. I just picked it since it felt lightweight/straightforward at the time.

seancorfield19:03:59

I might make a Polylith version of my “usermanager” example app and see how that works out, with Component…

👍 9
seancorfield02:03:37

Started on this https://github.com/seancorfield/usermanager-example/tree/polylith following the migration guide at https://polylith.gitbook.io/polylith/conclusion/should-you-convert-your-system and it’s going pretty smoothly (although I confused myself by picking usermanager as the initial (monolithic) component name for everything “not web” when I’d already set usermanager as the top namespace 🙂).

seancorfield02:03:10

I am tagging the code after each complete step of the migration so folks can “follow along at home”.

tengstrand03:03:08

Wow, this is really good news! Initiatives like this is what we need right now, so that people more easily can adopt Polylith. Thanks for contributing to the Polylith echo system @U04V70XH6!

dharrigan19:03:47

Right. You see, when I was looking at it, I was confused. - but now, I'm like okay, I have this directory structure, with components and bases okay. So, now I have my application "main" in a base, which is the gen-class-ified class used for depstar. That main function (when used via java -jar... invokes JUXT clip which now pulls together all the component interfaces (i.e., creating a connection to a database via a ....database.interface/create-connection function call, and spinning up the ring/jetty by a ....rest-api.interface/start-jetty function call). So JUXT Clip is still "managing" the lifecycle in the sense of starting (including post-starting, like migrating my database) and stopping the application.

dharrigan19:03:13

clip, which uses aero underneath, gives me the ability to merge in different configuration values and runtime, i.e., a set of values for local development, a set of values for test environment and a set of values for production environment. I say that because I noticed in the real-world example the use of env and a env.edn file in the realworld example on github. So I suppose I get that functionality already.

seancorfield02:03:37

Started on this https://github.com/seancorfield/usermanager-example/tree/polylith following the migration guide at https://polylith.gitbook.io/polylith/conclusion/should-you-convert-your-system and it’s going pretty smoothly (although I confused myself by picking usermanager as the initial (monolithic) component name for everything “not web” when I’d already set usermanager as the top namespace 🙂).