Skip to content

Commit f78d45d

Browse files
committed
Merge branch 'main' into pullrequests/sgammon/soy/async-chunked-v2
2 parents e5011bb + 54a76c9 commit f78d45d

File tree

15 files changed

+86
-48
lines changed

15 files changed

+86
-48
lines changed

src/main/docs/guide/breaks.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@ This section outlines the breaking changes done in major versions of Micronaut V
22

33
=== 3.0.0
44

5+
* A Reactive Views renderer api:views.ReactiveViewsRenderer[] has been introduced. `Soy` implementation uses it. Other template engine implementation render to a `Writable`
6+
by implementing `api:views.WritableViewsRenderer[]`. `ViewsRenderer` is now a interface class extended by both pi:views.ReactiveViewsRenderer[]` and api:views.WritableViewsRenderer[]. `ViewsRenderer:exists(String)` methods has been renamed to `ViewsRenderer:canRender(String)`.
7+
58
* api:views.model.ViewModelProcessor[] no longer assumes a `Map<String,Object>` model and must be typed to the exact type of the model you would like to process.
69

710
* api:views.model.ViewsRenderer[] are now typed. Moreover, provided `ViewsRenderer` don't specify `@Produces(MediaType.TEXT_HTML)` and responses content type respect the content type defined for the route.
811

12+
* `ViewsRenderer::modelOf` method has been moved to `ViewUtils::modelOf`
13+
14+
* Constant `EXTENSION_SEPARATOR` has been moved from `ViewsRenderer` to `ViewUtils`
15+
916
== 2.0.0
1017

1118
* The `micronaut-views` dependency is no longer published. Replace the dependency with the one specific to the view implementation being used.

test-suite/src/test/groovy/views/NonHTMLViewRendererSpec.groovy

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import io.micronaut.http.client.HttpClient
1717
import io.micronaut.runtime.server.EmbeddedServer
1818
import io.micronaut.views.View
1919
import io.micronaut.views.ViewsRenderer
20+
import io.micronaut.views.WritableViewsRenderer
2021
import spock.lang.AutoCleanup
2122
import spock.lang.Shared
2223
import spock.lang.Specification
@@ -88,7 +89,7 @@ class NonHTMLViewRendererSpec extends Specification {
8889
@Produces(MediaType.TEXT_XML)
8990
@Requires(property = "spec.name", value = "CsvViewRendererSpec")
9091
@Singleton
91-
static class XmlViewRenderer implements ViewsRenderer<Library> {
92+
static class XmlViewRenderer implements WritableViewsRenderer<Library> {
9293
@Override
9394
Writable render(@NonNull String viewName, @Nullable Library data, @NonNull HttpRequest<?> request) {
9495
new Writable() {
@@ -102,15 +103,15 @@ class NonHTMLViewRendererSpec extends Specification {
102103
}
103104

104105
@Override
105-
boolean exists(@NonNull String viewName) {
106+
boolean canRender(@NonNull String viewName) {
106107
return "books".equalsIgnoreCase(viewName)
107108
}
108109
}
109110

110111
@Produces(MediaType.TEXT_CSV)
111112
@Requires(property = "spec.name", value = "CsvViewRendererSpec")
112113
@Singleton
113-
static class SingleBookViewRenderer implements ViewsRenderer<Book> {
114+
static class SingleBookViewRenderer implements WritableViewsRenderer<Book> {
114115
// this renderer should not be used because it specifies a different type
115116

116117
@Override
@@ -124,7 +125,7 @@ class NonHTMLViewRendererSpec extends Specification {
124125
}
125126

126127
@Override
127-
boolean exists(@NonNull String viewName) {
128+
boolean canRender(@NonNull String viewName) {
128129
return true
129130
}
130131

@@ -137,7 +138,7 @@ class NonHTMLViewRendererSpec extends Specification {
137138
@Produces(MediaType.TEXT_CSV)
138139
@Requires(property = "spec.name", value = "CsvViewRendererSpec")
139140
@Singleton
140-
static class CsvViewRenderer implements ViewsRenderer<Library> {
141+
static class CsvViewRenderer implements WritableViewsRenderer<Library> {
141142
@Override
142143
Writable render(@NonNull String viewName, @Nullable Library data, @NonNull HttpRequest<?> request) {
143144
new Writable() {
@@ -151,7 +152,7 @@ class NonHTMLViewRendererSpec extends Specification {
151152
}
152153

153154
@Override
154-
boolean exists(@NonNull String viewName) {
155+
boolean canRender(@NonNull String viewName) {
155156
return "books".equalsIgnoreCase(viewName)
156157
}
157158
}

views-core/src/main/java/io/micronaut/views/DefaultViewsRendererLocator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public Optional<ViewsRenderer> resolveViewsRenderer(@NonNull String view,
6464
return null;
6565
}
6666
Optional<ViewsRenderer> result = viewsRenderers.stream()
67-
.filter(viewsRenderer -> viewsRenderer.exists(view))
67+
.filter(viewsRenderer -> viewsRenderer.canRender(view))
6868
.findFirst();
6969
if (result.isPresent()) {
7070
return result.get();

views-core/src/main/java/io/micronaut/views/ReactiveViewsRenderer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
/**
2525
* Reactive implementation of {@link ViewsRenderer}.
2626
* @author Sergio del Amo
27+
* @param <T> The model type
2728
* @since 3.0.0
2829
*/
2930
public interface ReactiveViewsRenderer<T> extends ViewsRenderer<T> {

views-core/src/main/java/io/micronaut/views/ViewUtils.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
import io.micronaut.core.annotation.NonNull;
1919
import io.micronaut.core.annotation.Nullable;
20+
import io.micronaut.core.beans.BeanMap;
21+
22+
import java.util.HashMap;
23+
import java.util.Map;
2024

2125
/**
2226
* Utility methods for views.
@@ -25,6 +29,26 @@
2529
* @since 1.1.0
2630
*/
2731
public class ViewUtils {
32+
/**
33+
* Extension separator.
34+
*/
35+
public static final String EXTENSION_SEPARATOR = ".";
36+
37+
/**
38+
* Creates a view model for the given data.
39+
* @param data The data
40+
* @return The model
41+
*/
42+
@NonNull
43+
public static Map<String, Object> modelOf(@Nullable Object data) {
44+
if (data == null) {
45+
return new HashMap<>(0);
46+
}
47+
if (data instanceof Map) {
48+
return (Map<String, Object>) data;
49+
}
50+
return BeanMap.of(data);
51+
}
2852

2953
/**
3054
* Returns a path with unix style folder

views-core/src/main/java/io/micronaut/views/ViewsRenderer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import io.micronaut.core.order.Ordered;
2020

2121
/**
22-
* Interface to be implemented by View Engines implementations.
23-
* Implemented by either {@link WritableViewsRender} or {@link ReactiveViewsRenderer}
22+
* Base Interface to be implemented by View Engines implementations.
23+
* You should implement either {@link WritableViewsRenderer} or {@link ReactiveViewsRenderer}.
2424
* @param <T> The model type
2525
* @author Sergio del Amo
2626
* @since 1.0

views-core/src/main/java/io/micronaut/views/WritableViewsRenderer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* Writes the view into {@link Writable}.
2525
* @author Sergio del Amo
2626
* @since 3.0.0
27+
* @param <T> The model type
2728
*/
2829
public interface WritableViewsRenderer<T> extends ViewsRenderer<T> {
2930

views-freemarker/src/main/java/io/micronaut/views/freemarker/FreemarkerViewsRenderer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import io.micronaut.http.HttpRequest;
2828
import io.micronaut.views.ViewUtils;
2929
import io.micronaut.views.ViewsConfiguration;
30-
import io.micronaut.views.ViewsRenderer;
30+
import io.micronaut.views.WritableViewsRenderer;
3131
import io.micronaut.views.exceptions.ViewRenderingException;
3232

3333
import io.micronaut.core.annotation.Nullable;
@@ -47,7 +47,7 @@
4747
@Requires(property = FreemarkerViewsRendererConfigurationProperties.PREFIX + ".enabled", notEquals = "false")
4848
@Requires(classes = Configuration.class)
4949
@Singleton
50-
public class FreemarkerViewsRenderer<T> implements ViewsRenderer<T> {
50+
public class FreemarkerViewsRenderer<T> implements WritableViewsRenderer<T> {
5151

5252
protected final ViewsConfiguration viewsConfiguration;
5353
protected final FreemarkerViewsRendererConfigurationProperties freemarkerMicronautConfiguration;
@@ -70,7 +70,7 @@ public FreemarkerViewsRenderer(ViewsConfiguration viewsConfiguration,
7070
public Writable render(@NonNull String viewName, @Nullable T data, @NonNull HttpRequest<?> request) {
7171
ArgumentUtils.requireNonNull("viewName", viewName);
7272
return (writer) -> {
73-
Map<String, Object> context = modelOf(data);
73+
Map<String, Object> context = ViewUtils.modelOf(data);
7474
String location = viewLocation(viewName);
7575
Template template = freemarkerMicronautConfiguration.getTemplate(location);
7676
try {
@@ -83,7 +83,7 @@ public Writable render(@NonNull String viewName, @Nullable T data, @NonNull Http
8383
}
8484

8585
@Override
86-
public boolean exists(@NonNull String view) {
86+
public boolean canRender(@NonNull String view) {
8787
try {
8888
freemarkerMicronautConfiguration.getTemplate(viewLocation(view));
8989
} catch (ParseException | MalformedTemplateNameException e) {
@@ -96,7 +96,7 @@ public boolean exists(@NonNull String view) {
9696

9797
private String viewLocation(String name) {
9898
return ViewUtils.normalizeFile(name, extension) +
99-
EXTENSION_SEPARATOR +
99+
ViewUtils.EXTENSION_SEPARATOR +
100100
extension;
101101
}
102102

views-handlebars/src/main/java/io/micronaut/views/handlebars/HandlebarsViewsRenderer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727
import io.micronaut.http.HttpRequest;
2828
import io.micronaut.views.ViewUtils;
2929
import io.micronaut.views.ViewsConfiguration;
30-
import io.micronaut.views.ViewsRenderer;
30+
import io.micronaut.views.WritableViewsRenderer;
3131
import io.micronaut.views.exceptions.ViewRenderingException;
3232
import io.micronaut.core.annotation.Nullable;
3333
import jakarta.inject.Inject;
3434
import jakarta.inject.Singleton;
3535

3636
/**
37-
* Renders Views with with Handlebars.java.
37+
* Renders Views with Handlebars.java.
3838
*
3939
* @author Sergio del Amo
4040
* @see <a href="https://jknack.github.io/handlebars.java/">https://jknack.github.io/handlebars.java/</a>
@@ -44,7 +44,7 @@
4444
@Requires(property = HandlebarsViewsRendererConfigurationProperties.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
4545
@Requires(classes = Handlebars.class)
4646
@Singleton
47-
public class HandlebarsViewsRenderer<T> implements ViewsRenderer<T> {
47+
public class HandlebarsViewsRenderer<T> implements WritableViewsRenderer<T> {
4848

4949
protected final ViewsConfiguration viewsConfiguration;
5050
protected final ResourceLoader resourceLoader;
@@ -86,12 +86,12 @@ public Writable render(@NonNull String viewName, @Nullable T data, @NonNull Http
8686
}
8787

8888
@Override
89-
public boolean exists(@NonNull String viewName) {
89+
public boolean canRender(@NonNull String viewName) {
9090
//noinspection ConstantConditions
9191
if (viewName == null) {
9292
return false;
9393
}
94-
String location = viewLocation(viewName) + EXTENSION_SEPARATOR + extension();
94+
String location = viewLocation(viewName) + ViewUtils.EXTENSION_SEPARATOR + extension();
9595
return resourceLoader.getResource(location).isPresent();
9696
}
9797

views-pebble/src/main/java/io/micronaut/views/pebble/PebbleEngineFactory.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import java.util.List;
1919
import java.util.Optional;
20+
21+
import io.micronaut.views.ViewUtils;
2022
import jakarta.inject.Inject;
2123
import jakarta.inject.Singleton;
2224
import com.mitchellbosecke.pebble.PebbleEngine;
@@ -30,7 +32,6 @@
3032
import io.micronaut.core.annotation.Nullable;
3133
import io.micronaut.scheduling.TaskExecutors;
3234
import io.micronaut.views.ViewsConfiguration;
33-
import io.micronaut.views.ViewsRenderer;
3435
import java.util.concurrent.ExecutorService;
3536
import jakarta.inject.Named;
3637

@@ -110,7 +111,7 @@ public PebbleEngine create() {
110111
} else {
111112
Loader<?> loader = new ClasspathLoader();
112113
loader.setPrefix(viewsConfiguration.getFolder());
113-
loader.setSuffix(ViewsRenderer.EXTENSION_SEPARATOR + configuration.getDefaultExtension());
114+
loader.setSuffix(ViewUtils.EXTENSION_SEPARATOR + configuration.getDefaultExtension());
114115
builder.loader(loader);
115116
}
116117

0 commit comments

Comments
 (0)