Skip to content

Commit

Permalink
major: Remove ViewsFilter, switch to MessageBodyWriters and extract T…
Browse files Browse the repository at this point in the history
…urbo module (#712)
  • Loading branch information
timyates authored Feb 23, 2024
1 parent 3d8c424 commit d3a4368
Show file tree
Hide file tree
Showing 93 changed files with 2,166 additions and 751 deletions.
668 changes: 614 additions & 54 deletions config/accepted-api-changes.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
projectVersion=5.2.0-SNAPSHOT
projectVersion=6.0.0-SNAPSHOT
projectGroup=io.micronaut.views

title=Micronaut Views
Expand Down
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ include 'views-fieldset-tck'
include 'views-freemarker'
include 'views-handlebars'
include 'views-thymeleaf'
include 'views-turbo'
include 'views-velocity'
include 'views-rocker'
include 'views-pebble'
Expand Down
13 changes: 13 additions & 0 deletions src/main/docs/guide/breaks.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
This section outlines the breaking changes done in major versions of Micronaut Views.

=== 6.0.0

- Turbo integration has been moved to its own dependency. To use the Turbo integration, add the following
dependency:
+
dependency:micronaut-views-turbo[groupId="io.micronaut.views"]
+
The annotation `@TurboView` has been renamed to ann:views.turbo.TurboStreamView[].

- The `ViewsModelDecorator` and `TurboStreamRenderer` now have generic types for their data and Request type, which breaks binary compatibility.

- The global `ViewsFilter` has been removed and replaced with individual `ResponseFilters`.

=== 4.0.0

* The Soy dependency has been upgraded to version _2022-10-26_, which includes breaking changes. Among others, `.` is no longer allowed before template names. To know the full changes, we suggest link:https://github.com/google/closure-templates/compare/release-2022-03-02%E2%80%A6release-2022-03-07[looking at the commits] since there exist no release notes.
Expand Down
6 changes: 5 additions & 1 deletion src/main/docs/guide/views/turbo.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ Micronaut Views simplifies working with https://turbo.hotwired.dev[Turbo], the h

____
A set of complementary techniques for speeding up page changes and form submissions, dividing complex pages into components, and stream partial page updates over WebSocket. All without writing any JavaScript at all. And designed from the start to integrate perfectly with native hybrid applications for iOS and Android.
____
____

To add the Micronaut Views Turbo integration, add the following dependency on your classpath.

dependency:micronaut-views-turbo[groupId="io.micronaut.views"]
6 changes: 3 additions & 3 deletions src/main/docs/guide/views/turbo/turboView.adoc
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
You can render https://turbo.hotwired.dev/reference/streams[Turbo Streams] easily by annotating a controller route with
api:views.turbo.TurboView[]

snippet::io.micronaut.views.docs.turbo.TurboViewTest[tags="turboview",indent=0]
snippet::io.micronaut.views.docs.turbo.TurboStreamViewTest[tags="turboview",indent=0]

Given the HTTP Request:

snippet::io.micronaut.views.docs.turbo.TurboViewTest[tags="turboviewrequest",indent=0]
snippet::io.micronaut.views.docs.turbo.TurboStreamViewTest[tags="turboviewrequest",indent=0]

The previous controller returns:

snippet::io.micronaut.views.docs.turbo.TurboViewTest[tags="turboviewresponse",indent=0]
snippet::io.micronaut.views.docs.turbo.TurboStreamViewTest[tags="turboviewresponse",indent=0]

with content type `text/vnd.turbo-stream.html`.

1 change: 1 addition & 0 deletions test-suite-groovy/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ dependencies {

testImplementation('org.apache.groovy:groovy-json')
testImplementation projects.micronautViewsSoy
testImplementation(projects.micronautViewsTurbo)
testImplementation projects.micronautViewsVelocity
testImplementation projects.micronautViewsHandlebars
testRuntimeOnly(mnLogging.logback.classic)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class ModelAndViewSpec extends Specification {

@Requires(property = "spec.name", value = "ModelAndViewSpec")
@Singleton
static class CustomViewModelProcessor implements ViewModelProcessor<AbstractView> {
static class CustomViewModelProcessor implements ViewModelProcessor<AbstractView, HttpRequest<?>> {

private final ApplicationConfiguration config

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ package io.micronaut.views.docs.turbo

import io.micronaut.context.annotation.Property
import io.micronaut.context.annotation.Requires
import io.micronaut.core.annotation.Nullable
import io.micronaut.core.util.StringUtils
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Consumes
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Header
import io.micronaut.http.annotation.Part
import io.micronaut.http.annotation.Post
import io.micronaut.http.annotation.Produces
Expand All @@ -19,11 +16,9 @@ import io.micronaut.http.client.HttpClient
import io.micronaut.http.client.annotation.Client
import io.micronaut.http.client.multipart.MultipartBody
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import io.micronaut.views.ModelAndView
import io.micronaut.views.View
import io.micronaut.views.turbo.TurboFrame
import io.micronaut.views.turbo.TurboFrameView
import io.micronaut.views.turbo.TurboView
import io.micronaut.views.turbo.TurboStreamView
import io.micronaut.views.turbo.http.TurboHttpHeaders
import io.micronaut.views.turbo.http.TurboMediaType
import jakarta.inject.Inject
Expand Down Expand Up @@ -94,7 +89,7 @@ class TurboFrameTest extends Specification {

//tag::turboFramePost[]
@Consumes(MediaType.MULTIPART_FORM_DATA)
@TurboView("view")
@TurboStreamView("view")
@Produces(value = [MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM])
@Post("/messages/{id}")
Map<String, Object> processEdit(@Part int id, @Part String title, @Part String body) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.micronaut.views.docs.turbo

import io.micronaut.context.ApplicationContext
import io.micronaut.context.annotation.Requires
import io.micronaut.core.annotation.Introspected
import io.micronaut.core.util.CollectionUtils
import io.micronaut.core.util.StringUtils
import io.micronaut.http.HttpRequest
Expand All @@ -16,12 +15,12 @@ import io.micronaut.http.client.BlockingHttpClient
import io.micronaut.http.client.HttpClient
import io.micronaut.runtime.server.EmbeddedServer
import io.micronaut.views.turbo.TurboStreamAction
import io.micronaut.views.turbo.TurboView
import io.micronaut.views.turbo.TurboStreamView
import io.micronaut.views.turbo.http.TurboHttpHeaders
import io.micronaut.views.turbo.http.TurboMediaType
import spock.lang.Specification

class TurboViewTest extends Specification {
class TurboStreamViewTest extends Specification {

void "you can use TurboView annotation"() throws IOException {
given:
Expand Down Expand Up @@ -65,7 +64,7 @@ class TurboViewTest extends Specification {

//tag::turboview[]
@Produces(value = [MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM])
@TurboView(value = "fruit", action = TurboStreamAction.APPEND)
@TurboStreamView(value = "fruit", action = TurboStreamAction.APPEND)
@Get("/turbofruit")
Map<String, Object> show() {
return Collections.singletonMap("fruit", new Fruit("Banana", "Yellow"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import java.util.Map;
@Requires(property = "spec.name", value = "ModelAndViewSpec")
//tag::class[]
@Singleton // <1>
public class ConfigViewModelProcessor implements ViewModelProcessor<Map<String, Object>> {
public class ConfigViewModelProcessor implements ViewModelProcessor<Map<String, Object>, HttpRequest<?>> {
private final ApplicationConfiguration config;

ConfigViewModelProcessor(ApplicationConfiguration environment) {
Expand Down
1 change: 1 addition & 0 deletions test-suite-http/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies {
testImplementation(projects.micronautViewsJte)
// testImplementation(projects.micronautViewsPebble)
testImplementation(projects.micronautViewsRocker)
testImplementation(projects.micronautViewsTurbo)
// testImplementation(projects.micronautViewsThymeleaf)
// testImplementation(projects.micronautViewsSoy)
// testImplementation(projects.micronautViewsVelocity)
Expand Down
1 change: 1 addition & 0 deletions test-suite-kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies {
testImplementation(mn.micronaut.http.server.netty)
testImplementation(mn.micronaut.http.client)
testImplementation projects.micronautViewsSoy
testImplementation(projects.micronautViewsTurbo)
testImplementation(libs.kotlinx.coroutines.core)
testImplementation projects.micronautViewsVelocity
testImplementation projects.micronautViewsHandlebars
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ class ModelAndViewTest {
@Singleton
@Requires(property = "spec.name", value = "ModelAndViewSpec")
class CustomViewModelProcessor(private val config: ApplicationConfiguration) :
ViewModelProcessor<AbstractView> {
ViewModelProcessor<AbstractView, HttpRequest<*>> {

override fun process(request: HttpRequest<*>, modelAndView: ModelAndView<AbstractView>) {
modelAndView.model.ifPresent { model: AbstractView ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.views.View
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async

@Requires(property = "spec.name", value = "AsyncSpec")
Expand All @@ -15,10 +16,8 @@ class AsyncController {
@View("index")
@Get("/")
suspend fun index(): HttpResponse<Map<String, String>> = run {
val futureResponse = GlobalScope.async {
CoroutineScope(Dispatchers.IO).async {
HttpResponse.ok(mapOf("name" to "world"))
}
futureResponse.await()
}.await()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import io.micronaut.http.client.multipart.MultipartBody
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
import io.micronaut.views.View
import io.micronaut.views.turbo.TurboFrameView
import io.micronaut.views.turbo.TurboView
import io.micronaut.views.turbo.TurboStreamView
import io.micronaut.views.turbo.http.TurboHttpHeaders
import io.micronaut.views.turbo.http.TurboMediaType
import jakarta.inject.Inject
Expand Down Expand Up @@ -88,7 +88,7 @@ class TurboFrameTest {

//tag::turboFramePost[]
@Consumes(MediaType.MULTIPART_FORM_DATA)
@TurboView("view")
@TurboStreamView("view")
@Produces(value = [MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM])
@Post("/messages/{id}")
fun processEdit(@Part id: Int, @Part title: String, @Part body: String): Map<String, Any> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import io.micronaut.http.client.annotation.Client
import io.micronaut.runtime.server.EmbeddedServer
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
import io.micronaut.views.turbo.TurboStreamAction
import io.micronaut.views.turbo.TurboView
import io.micronaut.views.turbo.TurboStreamView
import io.micronaut.views.turbo.http.TurboHttpHeaders
import io.micronaut.views.turbo.http.TurboMediaType
import jakarta.inject.Inject
Expand All @@ -27,7 +27,7 @@ import org.junit.jupiter.api.Assertions.assertTrue
@Property(name = "spec.name", value = "TurboViewTest")
@Property(name = "micronaut.security.enabled", value = StringUtils.FALSE)
@MicronautTest
class TurboViewTest {
class TurboStreamViewTest {

@Inject
lateinit var server: EmbeddedServer
Expand Down Expand Up @@ -70,7 +70,7 @@ class TurboViewTest {

//tag::turboview[]
@Produces(value = [MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM])
@TurboView(value = "fruit", action = TurboStreamAction.APPEND)
@TurboStreamView(value = "fruit", action = TurboStreamAction.APPEND)
@Get("/turbofruit")
fun show() = mapOf("fruit" to Fruit("Banana", "Yellow"))
//end::turboview[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import javax.inject.Singleton
//tag::class[]
@Singleton // <1>
class ConfigViewModelProcessor internal constructor(private val config: ApplicationConfiguration) :
ViewModelProcessor<MutableMap<String, Any>> {
ViewModelProcessor<MutableMap<String, Any>, HttpRequest<*>> {

override fun process(request: HttpRequest<*>, modelAndView: ModelAndView<MutableMap<String, Any>>) {
modelAndView.model
Expand Down
1 change: 1 addition & 0 deletions test-suite/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies {

testImplementation projects.micronautViewsVelocity
testImplementation projects.micronautViewsCore
testImplementation(projects.micronautViewsTurbo)
testImplementation projects.micronautViewsSoy
testImplementation projects.micronautViewsHandlebars
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,14 @@ static class Fruit extends AbstractView {

@Requires(property = "spec.name", value = "ModelAndViewSpec")
@Singleton
static class CustomViewModelProcessor implements ViewModelProcessor<AbstractView> {
static class CustomViewModelProcessor<R> implements ViewModelProcessor<AbstractView, R> {
private final ApplicationConfiguration config;
CustomViewModelProcessor(ApplicationConfiguration environment) {
this.config = environment;
}

@Override
public void process(@NonNull HttpRequest<?> request,
public void process(@NonNull R request,
@NonNull ModelAndView<AbstractView> modelAndView) {
modelAndView.getModel()
.ifPresent(model -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
import io.micronaut.views.View;
import io.micronaut.views.turbo.TurboFrame;
import io.micronaut.views.turbo.TurboFrameView;
import io.micronaut.views.turbo.TurboView;
import io.micronaut.views.turbo.TurboStreamView;
import io.micronaut.views.turbo.http.TurboHttpHeaders;
import io.micronaut.views.turbo.http.TurboMediaType;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;

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

import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -104,7 +103,7 @@ Map<String, Object> index() {

//tag::turboFramePost[]
@Consumes(MediaType.MULTIPART_FORM_DATA)
@TurboView("view")
@TurboStreamView("view")
@Produces(value = {MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM})
@Post("/messages/{id}")
Map<String, Object> processEdit(@Part int id, @Part String title, @Part String body) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.core.util.StringUtils;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
Expand All @@ -16,7 +14,7 @@
import io.micronaut.http.client.HttpClient;
import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.views.turbo.TurboStreamAction;
import io.micronaut.views.turbo.TurboView;
import io.micronaut.views.turbo.TurboStreamView;
import io.micronaut.views.turbo.http.TurboHttpHeaders;
import io.micronaut.views.turbo.http.TurboMediaType;
import org.junit.jupiter.api.Test;
Expand All @@ -28,7 +26,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class TurboViewTest {
class TurboStreamViewTest {

@Test
void turboView() throws IOException {
Expand Down Expand Up @@ -73,7 +71,7 @@ static class FruitController {

//tag::turboview[]
@Produces(value = {MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM})
@TurboView(value = "fruit", action = TurboStreamAction.APPEND)
@TurboStreamView(value = "fruit", action = TurboStreamAction.APPEND)
@Get("/turbofruit")
Map<String, Object> show() {
return Collections.singletonMap("fruit", new Fruit("Banana", "Yellow"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
@Requires(property = "spec.name", value = "ModelAndViewSpec")
//tag::class[]
@Singleton // <1>
public class ConfigViewModelProcessor implements ViewModelProcessor<Map<String, Object>> {
public class ConfigViewModelProcessor<R> implements ViewModelProcessor<Map<String, Object>, R> {
private final ApplicationConfiguration config;

ConfigViewModelProcessor(ApplicationConfiguration environment) {
this.config = environment;
}

@Override
public void process(@NonNull HttpRequest<?> request,
public void process(@NonNull R request,
@NonNull ModelAndView<Map<String, Object>> modelAndView) {
modelAndView.getModel()
.ifPresent(model -> {
Expand Down
Loading

0 comments on commit d3a4368

Please sign in to comment.