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 e6d4728
Show file tree
Hide file tree
Showing 14 changed files with 76 additions and 38 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[].

* 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
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 @@ -110,7 +111,7 @@ class NonHTMLViewRendererSpec extends Specification {
@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 @@ -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 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 All @@ -31,5 +31,5 @@ public interface ViewsRenderer<T> extends Ordered {
* @param viewName view name to be rendered
* @return true if a template can be found for the supplied view name.
*/
boolean canRender(@NonNull String viewName);
boolean exists(@NonNull String viewName);
}
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 @@ -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 @@ -91,7 +91,7 @@ public boolean exists(@NonNull String viewName) {
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,7 +50,7 @@ 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
Expand Down
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,7 +63,7 @@ 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MediaType;
import io.micronaut.http.MutableHttpResponse;
import io.micronaut.http.annotation.Filter;
import io.micronaut.http.annotation.Produces;
import io.micronaut.views.ModelAndView;
import io.micronaut.views.ReactiveViewRenderer;
import io.micronaut.views.ReactiveViewsRenderer;
import io.micronaut.views.ViewsConfiguration;
import io.micronaut.views.ViewsResolver;
import io.micronaut.views.csp.CspConfiguration;
import io.micronaut.views.csp.CspFilter;
import io.micronaut.views.exceptions.ViewRenderingException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import jakarta.inject.Singleton;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -65,12 +65,12 @@
* @since 1.2.1
* @param <T> The model type
*/
@Filter(Filter.MATCH_ALL_PATTERN)
@Singleton
@Produces(MediaType.TEXT_HTML)
@Requires(property = SoyViewsRendererConfigurationProperties.PREFIX + ".enabled", notEquals = "false")
@Requires(property = SoyViewsRendererConfigurationProperties.PREFIX + ".engine", notEquals = "tofu")
@SuppressWarnings({"WeakerAccess", "UnstableApiUsage"})
public class SoySauceViewsRenderer<T> implements ReactiveViewRenderer<T> {
public class SoySauceViewsRenderer<T> implements ReactiveViewsRenderer<T> {
private static final Logger LOG = LoggerFactory.getLogger(SoySauceViewsRenderer.class);
private static final String INJECTED_NONCE_PROPERTY = "csp_nonce";
private static final String SOY_CONTEXT_SENTINEL = "__soy_context__";
Expand Down Expand Up @@ -221,6 +221,7 @@ public Map<String, Object> modelOf(@Nullable Object data) {
* @param response HTTP response object assembled so far.
* @return A writable where the view will be written to.
*/
@Override
@NonNull
public Publisher<MutableHttpResponse<?>> render(@NonNull String viewName,
@Nullable T data,
Expand Down Expand Up @@ -253,7 +254,7 @@ public Publisher<MutableHttpResponse<?>> render(@NonNull String viewName,
Map dataMap = (Map) data;
if (dataMap.size() == 1 && dataMap.containsKey(SOY_CONTEXT_SENTINEL)) {
// it's a packaged soy context
context = (SoyContextMediator)dataMap.get(SOY_CONTEXT_SENTINEL);
context = (SoyContextMediator) dataMap.get(SOY_CONTEXT_SENTINEL);
} else {
// otherwise, use it directly as a map
//noinspection unchecked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,26 @@
* limitations under the License.
*/
package io.micronaut.views.thymeleaf;

import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.io.ResourceLoader;
import io.micronaut.core.io.Writable;
import io.micronaut.core.io.scan.ClassPathResourceLoader;
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.views.WritableViewsRenderer;
import io.micronaut.views.exceptions.ViewRenderingException;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.IContext;
import org.thymeleaf.exceptions.TemplateEngineException;
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

import java.io.Writer;
import java.util.Locale;

Expand All @@ -47,7 +48,7 @@
* @param <T> The model type
*/
@Singleton
public class ThymeleafViewsRenderer<T> implements ViewsRenderer<T> {
public class ThymeleafViewsRenderer<T> implements WritableViewsRenderer<T> {

protected final AbstractConfigurableTemplateResolver templateResolver;
protected final TemplateEngine engine;
Expand Down Expand Up @@ -75,7 +76,7 @@ public Writable render(@NonNull String viewName,
ArgumentUtils.requireNonNull("viewName", viewName);
ArgumentUtils.requireNonNull("request", request);
return (writer) -> {
IContext context = new WebContext(request, request.getLocale().orElse(Locale.US), modelOf(data));
IContext context = new WebContext(request, request.getLocale().orElse(Locale.US), ViewUtils.modelOf(data));
render(viewName, context, writer);
};
}
Expand Down
Loading

0 comments on commit e6d4728

Please sign in to comment.