Try my new project stubs for better DX, cloud compatibility and cleaner pom.xml

Hello Vaadin users!

I think we are not doing great job with our project builds and convetions related to our development mode. I’d like to change it a situation where no Vaadin specialities are needed (~ the production profile), the development mode starts implicitly when appropriate and the build file doesn’t look like a mess.

As an outcome of this, Vaadin would be out-of-the-box more compatible with various “cloud native tooling”, like buildpacks, it would be easier for new users to adapt and it would just appear cleaner than it does today. The full discussion is in Flow issue #17737.

To get some attention to it, I’m today presenting you viritin-sb, which is essentially a prototype of an end DX we should aim for. I’m already using that in couple of hobby and example projecs and today I baked in Hilla support. I would love to get some feedback for it.

Knonw limitations:

  • Spring Boot only
  • Maven only
  • Needs a custom project parent (which you can naturally override for your needs, inherits from spring boot project parent)

You can test it using the example project in the repository, planning to publish archetype(s) next. If you are a Java only user, I suggest to take the “viritin-project-parent” to use as you’ll get quite a lot faster project (in dev mode) and smaller artifacts. It might be possible to make a similar for Hilla only use, but didn’t try that yet.

Please share your comments, further ideas and test results, either here or in the GH project!

6 Likes

Thank you! Simplifying and speeding up for both the developer and customer is extremely essential. Most the times we forget the developer, and kudos to this efforts!!

1 Like

I think I’ll try to build another version with a different approach today or tomorrow. For DX (or end-developer-experience), the solution would feel exactly the same though.

My plan is to do it like Spring Boot now suggests to use Testcontainers during development time: a separate main method for development time. So in essense the “exclusions of dependencies” would be done with basic Maven (having them only on test scope), instead of the Spring Boot plugins repackage phase. The hack that enforces dev mode and Vaadin plugin doing “production compilation” in pre-package would remain the same.

This would be more stable as a PoC as wouldn’t have the keep the exclusion list up to date with whatever dependencies end up to the development mode…

Version 0.0.3 is now out with the above changes. For DX, it is almost at the same level, but the simplicity and stability of this is now so much better and I can suggest to try it (and then use it) even in production apps.

As a summary of changes:

  • exclusions now not depending on SB plugins repackage
  • Needs two Spring Boot app classes (~ main methods), on in normal sources that always runs in production mode and one on the test sources, that always runs development mode. The approach is exactly the same as introduced by Spring Boot team for the improved test containers support in SB 3.1 :sunglasses:

If @knoobie hasn’t yet learned how to “properly” start Spring Boot apps (via main method directly from IDE :wink:), the development mode kicks in if started with CLI command mvn spring-boot:test-run. This automatically picks a Spring Boot application from test sources.

I cannot use your approach in most of my customer projects because they have a custom parent and Spring Boot and Vaadin are included using dependencyManagement.

Usually, I build the custom parent as there is a lot that can be configured or the customer already has one. I also create customer-specific Spring Boot starters.

Wouldn’t executing the Vaadin plugin in the pre-package phase be enough?

Yeah, as expected, not possible for everybody.

Redeclaring the vaadin plugin phase is not enough, you’ll need to exclude vaadin-dev and redeclaring it to test scope. And you need the viritin-sb module that “forces dev mode” when applicaple (or similar hack to the dev mode main method)

There are two options in this kind of case (to achieve similar experience, today):

  • Make the used own parent pom (or whatever is its parent) extend this one. Not always possible, or hard to get through in large orgs. Multiple inheritanse for Maven would be great BTW.
  • Copy the same hacks as in project-parent/pom.xml (link highlights the relevant lines, you can ignore the release profile) directly to your own parent pom or to the project pom.

The latter is now (thanks to my re-write yesterday) much more appealing, as it is less hacky, shorter and more future proof. Should probably prepare another example that is not using parent pom (or uses SB parent pom). Also the dev mode enforcing is now very simple (could be almost a oneliner). I’ll try to set up one in a minute…

There is now “example-flattened”. No custom parent pom (SB is in use, but SB docs instruct how to get rid of that), thus bit ugly looking, but no extra dependencies and the DX should be pretty much the same.

I personally don’t like that I have to create additional code (DevDemoApp) just to develop :confused:

It feels like there must be a way for the maven plugin to understand the context where it is running and based on that… either do a dev or production build so that it allows local development and automatically creates production builds on Jenkins / docker and so on

Bit how I felt like when I saw the release post of Spring Boot 3.1, but when I used it in one of my demos (that was easiest to set up with Testcontainers), it didn’t feel that bad after all. In case of Testcontainers the setups makes it possible to configure the test DB using Java (instead of some non typed yml files) → big plus.

With this similar in nature Vaadin setup I have now played just today/yesterday, but I think I could learn to cope with this. And especially as I expect Testcontainer usage (during development, not just testing) still to increase → this fits very well with that concept (no extra main method needed then).

Build time logic/artifact “manglling” (the first iteration and my earlier non-finished trial in the winter the tried to provide the exclude list for SB pluging dynamically) would appear slightly more cleaner, that that I do agree. But this approach has its credits on stability, simplicity and agility. The price is that one extra Spring Boot main method (I expect us to get rid fo that class once JDK develops a bit :nerd_face:).

The extra main class is auto generated by start.spring.io if you add Testcontainers btw.

So this is not an issue

Reporting the next iteration here:

  • version 0.0.6 of the parent no more inherits from spring-boot-starter-parent. It felt good idea in the first place, but I’d need to be updating it every time spring boot is updated. Now the parent contains the most essential things from the spring-boot-starter-parent, but the spring boot version is overrieable easily. Some more exotic Spring Boot parent features might not be functioning, let me know if you are missing something.
  • There is now an archetype (I began to miss this myself when frequently creating examples/tests). This uses the viritin-project-parent by default, but can be easily “downgraded” to contain only plain Vaadin&SB. Generated project contains application classes and a tiny hello world template only. The “production” Application class also contains a small check for properly built production bundle (gives a better error message when started up without production bundle).

Bootstrap a new test project with CLI:

mvn archetype:generate -DinteractiveMode=false -DgroupId=org.example -DartifactId=my-great-project -Dversion=1.0-SNAPSHOT -DarchetypeGroupId=in.virit -DarchetypeArtifactId=viritin-vaadin-flow-spring-archetype -DarchetypeVersion=2.2

EDIT: updated to 0.0.7, with major front-end build optimisation

Hey Matti, this looks really interesting and I’d like to try it and/or understand where I might use it, but I’m not clear on its use case or exactly how to get started, especially the custom project parent. Individually I understand those words, but not together in this context.

Would you be willing to make a video demo?

I probably should to get more exposure for this rather relevant topic. I’ll be traveling next week and then on a vacay, but I’ll try to do one after that. Summarizing (and making notes for myself what I should highlight) the largest value in these:

Standard tooling produced deployable artifacts, without customisation. For example if you run “mvn spring-boot:build-image” with a “standard vaadin starter”, the built Docker image refuses to start properly. With these projects that works.

Also, if one manages to build the “production mode image once”, newbies can’t get back to the development mode.

PS. Did another tiny revision on the PoCs:

  • better compatibility with old Maven versions (thanks @Sami !)
  • better compatibility with upcoming Maven versions, now works (with some warnings) with 4.0.0-beta3

That sounds great. I’m really interested in deploying graalvm native images. And, I’m definitely a newbie.