Skip to content

Commit

Permalink
Merge branch 'main' into pullrequests/sgammon/soy/async-chunked-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
sdelamo committed Aug 10, 2021
2 parents e5011bb + 54a76c9 commit f78d45d
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 48 deletions.
7 changes: 7 additions & 0 deletions src/main/docs/guide/breaks.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ This section outlines the breaking changes done in major versions of Micronaut V

=== 3.0.0

* A Reactive Views renderer api:views.ReactiveViewsRenderer[] has been introduced. `Soy` implementation uses it. Other template engine implementation render to a `Writable`
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)`.

* 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.

* 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.

* `ViewsRenderer::modelOf` method has been moved to `ViewUtils::modelOf`

* Constant `EXTENSION_SEPARATOR` has been moved from `ViewsRenderer` to `ViewUtils`

== 2.0.0

* The `micronaut-views` dependency is no longer published. Replace the dependency with the one specific to the view implementation being used.
Expand Down
13 changes: 7 additions & 6 deletions test-suite/src/test/groovy/views/NonHTMLViewRendererSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import io.micronaut.http.client.HttpClient
import io.micronaut.runtime.server.EmbeddedServer
import io.micronaut.views.View
import io.micronaut.views.ViewsRenderer
import io.micronaut.views.WritableViewsRenderer
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification
Expand Down Expand Up @@ -88,7 +89,7 @@ class NonHTMLViewRendererSpec extends Specification {
@Produces(MediaType.TEXT_XML)
@Requires(property = "spec.name", value = "CsvViewRendererSpec")
@Singleton
static class XmlViewRenderer implements ViewsRenderer<Library> {
static class XmlViewRenderer implements WritableViewsRenderer<Library> {
@Override
Writable render(@NonNull String viewName, @Nullable Library data, @NonNull HttpRequest<?> request) {
new Writable() {
Expand All @@ -102,15 +103,15 @@ class NonHTMLViewRendererSpec extends Specification {
}

@Override
boolean exists(@NonNull String viewName) {
boolean canRender(@NonNull String viewName) {
return "books".equalsIgnoreCase(viewName)
}
}

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

@Override
Expand All @@ -124,7 +125,7 @@ class NonHTMLViewRendererSpec extends Specification {
}

@Override
boolean exists(@NonNull String viewName) {
boolean canRender(@NonNull String viewName) {
return true
}

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

@Override
boolean exists(@NonNull String viewName) {
boolean canRender(@NonNull String viewName) {
return "books".equalsIgnoreCase(viewName)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public Optional<ViewsRenderer> resolveViewsRenderer(@NonNull String view,
return null;
}
Optional<ViewsRenderer> result = viewsRenderers.stream()
.filter(viewsRenderer -> viewsRenderer.exists(view))
.filter(viewsRenderer -> viewsRenderer.canRender(view))
.findFirst();
if (result.isPresent()) {
return result.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
/**
* Reactive implementation of {@link ViewsRenderer}.
* @author Sergio del Amo
* @param <T> The model type
* @since 3.0.0
*/
public interface ReactiveViewsRenderer<T> extends ViewsRenderer<T> {
Expand Down
24 changes: 24 additions & 0 deletions views-core/src/main/java/io/micronaut/views/ViewUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.beans.BeanMap;

import java.util.HashMap;
import java.util.Map;

/**
* Utility methods for views.
Expand All @@ -25,6 +29,26 @@
* @since 1.1.0
*/
public class ViewUtils {
/**
* Extension separator.
*/
public static final String EXTENSION_SEPARATOR = ".";

/**
* Creates a view model for the given data.
* @param data The data
* @return The model
*/
@NonNull
public static Map<String, Object> modelOf(@Nullable Object data) {
if (data == null) {
return new HashMap<>(0);
}
if (data instanceof Map) {
return (Map<String, Object>) data;
}
return BeanMap.of(data);
}

/**
* Returns a path with unix style folder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
import io.micronaut.core.order.Ordered;

/**
* Interface to be implemented by View Engines implementations.
* Implemented by either {@link WritableViewsRender} or {@link ReactiveViewsRenderer}
* Base Interface to be implemented by View Engines implementations.
* You should implement either {@link WritableViewsRenderer} or {@link ReactiveViewsRenderer}.
* @param <T> The model type
* @author Sergio del Amo
* @since 1.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Writes the view into {@link Writable}.
* @author Sergio del Amo
* @since 3.0.0
* @param <T> The model type
*/
public interface WritableViewsRenderer<T> extends ViewsRenderer<T> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import io.micronaut.http.HttpRequest;
import io.micronaut.views.ViewUtils;
import io.micronaut.views.ViewsConfiguration;
import io.micronaut.views.ViewsRenderer;
import io.micronaut.views.WritableViewsRenderer;
import io.micronaut.views.exceptions.ViewRenderingException;

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

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

@Override
public boolean exists(@NonNull String view) {
public boolean canRender(@NonNull String view) {
try {
freemarkerMicronautConfiguration.getTemplate(viewLocation(view));
} catch (ParseException | MalformedTemplateNameException e) {
Expand All @@ -96,7 +96,7 @@ public boolean exists(@NonNull String view) {

private String viewLocation(String name) {
return ViewUtils.normalizeFile(name, extension) +
EXTENSION_SEPARATOR +
ViewUtils.EXTENSION_SEPARATOR +
extension;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@
import io.micronaut.http.HttpRequest;
import io.micronaut.views.ViewUtils;
import io.micronaut.views.ViewsConfiguration;
import io.micronaut.views.ViewsRenderer;
import io.micronaut.views.WritableViewsRenderer;
import io.micronaut.views.exceptions.ViewRenderingException;
import io.micronaut.core.annotation.Nullable;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

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

protected final ViewsConfiguration viewsConfiguration;
protected final ResourceLoader resourceLoader;
Expand Down Expand Up @@ -86,12 +86,12 @@ public Writable render(@NonNull String viewName, @Nullable T data, @NonNull Http
}

@Override
public boolean exists(@NonNull String viewName) {
public boolean canRender(@NonNull String viewName) {
//noinspection ConstantConditions
if (viewName == null) {
return false;
}
String location = viewLocation(viewName) + EXTENSION_SEPARATOR + extension();
String location = viewLocation(viewName) + ViewUtils.EXTENSION_SEPARATOR + extension();
return resourceLoader.getResource(location).isPresent();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import java.util.List;
import java.util.Optional;

import io.micronaut.views.ViewUtils;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import com.mitchellbosecke.pebble.PebbleEngine;
Expand All @@ -30,7 +32,6 @@
import io.micronaut.core.annotation.Nullable;
import io.micronaut.scheduling.TaskExecutors;
import io.micronaut.views.ViewsConfiguration;
import io.micronaut.views.ViewsRenderer;
import java.util.concurrent.ExecutorService;
import jakarta.inject.Named;

Expand Down Expand Up @@ -110,7 +111,7 @@ public PebbleEngine create() {
} else {
Loader<?> loader = new ClasspathLoader();
loader.setPrefix(viewsConfiguration.getFolder());
loader.setSuffix(ViewsRenderer.EXTENSION_SEPARATOR + configuration.getDefaultExtension());
loader.setSuffix(ViewUtils.EXTENSION_SEPARATOR + configuration.getDefaultExtension());
builder.loader(loader);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@

import io.micronaut.core.annotation.NonNull;
import io.micronaut.http.HttpRequest;
import io.micronaut.views.WritableViewsRenderer;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import com.mitchellbosecke.pebble.PebbleEngine;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.io.Writable;
import io.micronaut.core.util.StringUtils;
import io.micronaut.views.ViewUtils;
import io.micronaut.views.ViewsRenderer;

/**
* Renders Views with Pebble.
Expand All @@ -37,7 +37,7 @@
@Singleton
@Requires(property = PebbleConfigurationProperties.ENABLED, notEquals = StringUtils.FALSE)
@Requires(classes = PebbleEngine.class)
public class PebbleViewsRenderer<T> implements ViewsRenderer<T> {
public class PebbleViewsRenderer<T> implements WritableViewsRenderer<T> {

private final String extension;
private final PebbleEngine engine;
Expand All @@ -50,11 +50,11 @@ public PebbleViewsRenderer(PebbleConfiguration configuration, PebbleEngine engin

@Override
public Writable render(String name, T data, @NonNull HttpRequest<?> request) {
return (writer) -> engine.getTemplate(ViewUtils.normalizeFile(name, extension)).evaluate(writer, modelOf(data));
return (writer) -> engine.getTemplate(ViewUtils.normalizeFile(name, extension)).evaluate(writer, ViewUtils.modelOf(data));
}

@Override
public boolean exists(String name) {
public boolean canRender(String name) {
return engine.getLoader().resourceExists(ViewUtils.normalizeFile(name, extension));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
import io.micronaut.core.io.Writable;
import io.micronaut.core.util.ArgumentUtils;
import io.micronaut.http.HttpRequest;
import io.micronaut.views.ViewUtils;
import io.micronaut.views.ViewsConfiguration;
import io.micronaut.views.ViewsRenderer;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.views.WritableViewsRenderer;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.util.Map;
Expand All @@ -35,7 +36,7 @@
* @param <T> The model type
*/
@Singleton
public class RockerViewsRenderer<T> implements ViewsRenderer<T> {
public class RockerViewsRenderer<T> implements WritableViewsRenderer<T> {

protected final RockerEngine rockerEngine;
protected final ViewsConfiguration viewsConfiguration;
Expand All @@ -62,15 +63,15 @@ public RockerViewsRenderer(ViewsConfiguration viewsConfiguration,
public Writable render(@NonNull String view, @Nullable T data, @NonNull HttpRequest<?> request) {
ArgumentUtils.requireNonNull("view", view);

Map<String, Object> context = modelOf(data);
Map<String, Object> context = ViewUtils.modelOf(data);
BindableRockerModel model = rockerConfiguration.isRelaxed()
? rockerEngine.template(view).relaxedBind(context)
: rockerEngine.template(view).bind(context);
return new RockerWritable(model);
}

@Override
public boolean exists(@NonNull String viewName) {
public boolean canRender(@NonNull String viewName) {
return rockerEngine.exists(viewName);
}

Expand Down
Loading

0 comments on commit f78d45d

Please sign in to comment.