Skip to content

Commit

Permalink
guide: webjars stimulus (#1412)
Browse files Browse the repository at this point in the history
* webjars stimulus

* guide stimulus with webjars

* remove buildTools

* License and whitespace

---------

Co-authored-by: Tim Yates <[email protected]>
  • Loading branch information
sdelamo and timyates authored Jan 9, 2024
1 parent 9f2d722 commit 3170f82
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.micronaut.guides.feature;

import io.micronaut.starter.build.dependencies.Scope;
import jakarta.inject.Singleton;

@Singleton
public class WebJarsStimulus extends AbstractFeature {
protected WebJarsStimulus() {
super("webjars-stimulus", "hotwired__stimulus", Scope.RUNTIME);
}
}
5 changes: 5 additions & 0 deletions buildSrc/src/main/resources/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>hotwired__stimulus</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.micronaut;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.views.View;

import java.util.Collections;
import java.util.Map;

@Controller // <1>
class HomeController {

@Get // <2>
@View("index.html") // <3>
Map<String, Object> index() {
return Collections.emptyMap();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.micronaut;

import io.micronaut.http.client.BlockingHttpClient;
import io.micronaut.http.client.HttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertTrue;

@MicronautTest
class HomeControllerTest {

@Test
void rootPathServesHtml(@Client("/") HttpClient httpClient) {
BlockingHttpClient client = httpClient.toBlocking();
String html = assertDoesNotThrow(() -> client.retrieve("/"));
assertTrue(html.contains("<!DOCTYPE html>"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.micronaut;

import io.micronaut.http.client.BlockingHttpClient;
import io.micronaut.http.client.HttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

@MicronautTest
class WebJarsStimulusTest {

@Test
void stimulusViaWebJarsAvailable(@Client("/") HttpClient httpClient) {
BlockingHttpClient client = httpClient.toBlocking();
assertDoesNotThrow(() -> client.exchange("/webjars/hotwired__stimulus/3.2.1/dist/stimulus.js"));
}
}
15 changes: 15 additions & 0 deletions guides/micronaut-webjars-stimulus/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "Stimulus with WebJars",
"intro": "Learn how to load Stimulus Javascript library with WebJars",
"authors": ["Sergio del Amo"],
"categories": ["Views"],
"publicationDate": "2024-01-08",
"languages": ["java"],
"apps": [
{
"name": "default",
"features": ["views-thymeleaf"],
"invisibleFeatures": ["webjars-stimulus"]
}
]
}
100 changes: 100 additions & 0 deletions guides/micronaut-webjars-stimulus/micronaut-webjars-stimulus.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
common:header.adoc[]

common:requirements.adoc[]

common:completesolution.adoc[]

common:create-app-features.adoc[]

common:micronaut-views-thymeleaf.adoc[]

== Stimulus

This tutorial uses https://stimulus.hotwired.dev[Stimulus] in a Micronaut application.

____
Stimulus is a JavaScript framework with modest ambitions. It doesn’t seek to take over your entire front-end—in fact, it’s not concerned with rendering HTML at all. Instead, it’s designed to augment your HTML with just enough behavior to make it shine.
____

== WebJars

We use https://www.webjars.org[WebJars] to load Stimulus into our application.

____
WebJars are client-side web libraries (e.g. jQuery & Bootstrap) packaged into JAR (Java Archive) files.
* Explicitly and easily manage the client-side dependencies in JVM-based web applications
* Use JVM-based build tools (e.g. Maven, Gradle, sbt, ...) to download your client-side dependencies
* Know which client-side dependencies you are using
* Transitive dependencies are automatically resolved and optionally loaded via RequireJS
* Deployed on Maven Central
____

== WebJars via Static Resources

To use https://www.webjars.org[WebJars], we need to add a https://docs.micronaut.io/latest/guide/#staticResources[static resources] entry in the application's configuration.

resource:application.properties[tag=webjars]

== Stimulus via WebJars

You can obtain the https://stimulus.hotwired.dev[Stimulus] Maven coordinate in the https://www.webjars.org[WebJars] website and add it to your application as you will any other Java library.

dependency:hotwired__stimulus[groupId=org.webjars.npm,scope=runtimeOnly,version=@hotwired__stimulusVersion@]

== WebJars Test

You can test the Javascript library is exposed:

test:WebJarsStimulusTest[]

== Controller

Create a controller which renders a https://micronaut-projects.github.io/micronaut-views/latest/guide[View].

source:HomeController[]
callout:controller[number=1,arg0=/]
callout:get-generic[2]
callout:view[3]

== View

The view builds a simple controller described in the https://stimulus.hotwired.dev/handbook/hello-stimulus[`Hello Stimulus`] tutorial on the Stimulus website.

resource:views/index.html[]

== Controller Test

The controller test verifies the application renders an HTML page.

test:HomeControllerTest[]

common:testApp.adoc[]

common:runapp.adoc[]

Go to http://localhost:8080 enter your name and click the button. You will see in the console a message:

image::micronaut-webjars-stimulus.png[]

common:graalvm-resource-config.adoc[]

common:nativetest.adoc[]

common:graal-with-plugins.adoc[]

:exclude-for-languages:groovy

Go to http://localhost:8080 enter your name and click the button. You will see in the console a message.

:exclude-for-languages:groovy

common:next.adoc[]

Read more about:

- https://micronaut-projects.github.io/micronaut-views/latest/guide/[Micronaut Views].
- https://stimulus.hotwired.dev[Stimulus]
- https://www.webjars.org[WebJars]

common:helpWithMicronaut.adoc[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"resources": {
"includes": [
{"pattern": "META-INF/resources/webjars/hotwired__stimulus/3.2.1/dist/stimulus.js$"}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
micronaut.application.name=micronaut-guide
#tag::webjars[]
micronaut.router.static-resources.webjars.paths=classpath:/META-INF/resources/webjars
micronaut.router.static-resources.webjars.mapping=/webjars/**
#end::webjars[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en" th:fragment="layout(title, script, content)" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="module">
import { Application, Controller } from "/webjars/hotwired__stimulus/3.2.1/dist/stimulus.js"
window.Stimulus = Application.start()

Stimulus.register("hello", class extends Controller {
static targets = [ "name" ]

greet() {
const element = this.nameTarget
const name = element.value
console.log(`Hello, ${name}!`)
}
})
</script>

</head>
<body>
<div data-controller="hello">
<input data-hello-target="name" type="text">
<button data-action="click->hello#greet">Greet</button>
</div>
</body>
</html>
Binary file added src/docs/images/micronaut-webjars-stimulus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3170f82

Please sign in to comment.