Understanding the shared steps in the project setup is crucial before delving into the specifics of each client-augmenting technology. My requirements from the last post were quite straightforward:
\
\ It's important to note that the technology I'll be detailing, except Vaadin, follows a similar approach. Vaadin, with its unique paradigm, really stands out among the approaches.
WebJarsWebJars is a technology designed in 2012 by James Ward to handle these exact requirements.
\
WebJars are client-side web libraries (e.g. jQuery & Bootstrap) packaged into JAR (Java Archive) files.
\
\ -- Webjars website
\ A WebJar is a regular JAR containing web assets. Adding a WebJar to a project's dependencies is nothing specific:
\
\ The framework's responsibility is to expose the assets under a URL. For example, Spring Boot does it in the WebMvcAutoConfiguration class:
\
public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(), //1 "classpath:/META-INF/resources/webjars/"); addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocations()); if (this.servletContext != null) { ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION); registration.addResourceLocations(resource); } }); }\
Inside the JAR, you can reach assets by their respective path and name. The agreed-upon structure is to store the assets inside resources/webjars/
\
META-INF |_ MANIFEST.MF |_ maven.org.webjars.npm.alpinejs |_ resources.webjars.alpinejs.3.14.1 |_ builds |_ dist |_ cdn.js |_ cdn.min.js |_ src |_ package.json\ Within Spring Boot, you can access the non-minified version with /webjars/alpinejs/3.14.1/dist/cdn.js.
\ Developers release client-side libraries quite often. When you change a dependency version in the POM, you must change the front-end path, possibly in multiple locations. It's boring, has no added value, and you risk missing a change.
\ The WebJars Locator project aims to avoid all these issues by providing a path with no version, i.e., /webjars/alpinejs/dist/cdn.js. You can achieve this by adding the webjars-locator JAR to your dependencies:
\
\ I'll use this approach for every front-end technology. I'll also add the Bootstrap CSS library to provide a better-looking user interface.
ThymeleafThymeleaf is a server-side rendering technology.
\
Thymeleaf is a modern server-side Java template engine for both web and standalone environments.
\ Thymeleaf's main goal is to bring elegant natural templates to your development workflow — HTML that can be correctly displayed in browsers and also work as static prototypes, allowing for stronger collaboration in development teams.
\ With modules for Spring Framework, a host of integrations with your favourite tools, and the ability to plug in your own functionality, Thymeleaf is ideal for modern-day HTML5 JVM web development — although there is much more it can do.
\ -- Thymeleaf
\ I was still a consultant when I first learned about Thymeleaf. At the time, Java Server Pages were at the end of their life. Java Server Faces were trying to replace them; IMHO, they failed.
\ I thought Thymeleaf was a fantastic approach: it allows you to see the results in a static environment at design time and in a server environment at development time. Even better, you can seamlessly move between one and the other using the same file. I've never seen this capability used.
\ However, Spring Boot fully supports Thymeleaf. The icing on the cake: the latter is available via an HTML namespace on the page. If you didn't buy into JSF (spoiler: I didn't), Thymeleaf is today's go-to SSR templating language.
\ Here's the demo sample from the website:
\
Name | Price |
---|---|
Oranges | 0.99 |
\ Here is a Thymeleaf 101, in case you need to familiarize yourself with the technology.
\
Most, if not all, front-end frameworks work with a client-side model. We need to bridge between the server-side model and the client-side one.
\ The server-side code I'm using is the following:
\
data class Todo(val id: Int, var label: String, var completed: Boolean = false) //1 fun config() = beans { bean { mutableListOf( //2 Todo(1, "Go to the groceries", false), Todo(2, "Walk the dog", false), Todo(3, "Take out the trash", false) ) } bean { router { GET("/") { ok().render( //3 "index", //4 mapOf("title" to "My Title", "todos" to refDefine the Todo class.
\
Add an in-memory list to the bean factory. In a regular app, you'd use a Repository to read from the database.
\
Render an HTML template.
\
The template is src/main/resources/templates/index.html with Thymeleaf attributes.
\
Put the model in the page's context.
\ \ Thymeleaf offers a th:inline="javascript" attribute on the
\ The /*[[...]]*/ syntax, instructs Thymeleaf to evaluate the contained expression. But there are more implications here:
\
Being a javascript comment (/*...*/), our expression will be ignored when displaying the page statically in a browser.
The code after the inline expression ('Sebastian') will be executed when displaying the page statically.
Thymeleaf will execute the expression and insert the result, but it will also remove all the code in the line after the inline expression itself (the part that is executed when displayed statically).
\
\ If we apply the above to our code, we can get the model attributes passed by Spring as:
\
\ When rendered server-side, the result is:
\
SummaryIn this post, I've described two components I'll be using throughout the rest of this series:
\
\
\ The complete source code for this post can be found on GitHub.
https://github.com/ajavageek/compare-frontends?embedable=true
\ Go further:
Originally published at A Java Geek on September 15th, 2024
All Rights Reserved. Copyright , Central Coast Communications, Inc.