Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coverage for Resteasy Qute, Resteasy Qute Reactive and Qute templating #845

Merged
merged 1 commit into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
qute/** text=input
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,10 @@ in order to instantiate these templates by your self (as an example).
need it to be deployed into ocp or some other platform.

### `Qute`
Coverage for Qute template engine
Coverage for Qute template engine.
Module `qute/synchronous` contains coverage for Qute templating and integration with RESTEasy.
Module `qute/reactive` contains coverage for Qute templating and integration with RESTEasy reactive.
Module `qute/multimodule` provides coverage for complicated issue of having localised messages in separate modules.

### `spring/spring-data`
- Spring Data JPA: CRUD repository operation (default and custom), mapped superclass, query over embedded camelCase field, HTTP response filter.
Expand Down
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,8 @@
<module>logging/jboss</module>
<module>cache/caffeine</module>
<module>qute/multimodule</module>
<module>qute/synchronous</module>
<module>qute/reactive</module>
<module>helm/helm-minimum</module>
</modules>
</profile>
Expand Down
19 changes: 19 additions & 0 deletions qute/reactive/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.quarkus.ts.qe</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qute-reactive</artifactId>
<packaging>jar</packaging>
<name>Quarkus QE TS: Reactive Qute</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-qute</artifactId>
</dependency>
</dependencies>
</project>
230 changes: 230 additions & 0 deletions qute/reactive/src/main/java/io/quarkus/ts/qute/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
package io.quarkus.ts.qute;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletionStage;

import javax.inject.Inject;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;

import io.quarkus.qute.Engine;
import io.quarkus.qute.Location;
import io.quarkus.qute.Qute;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
fedinskiy marked this conversation as resolved.
Show resolved Hide resolved
import io.quarkus.qute.i18n.Localized;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;

@Path("")
public class Application {

@Inject
Template basic;

@Location("1.i18n.html")
Template multiLanguage;

@Inject
Engine engine;

@Localized("he")
Messages hebrew;

@GET
@Path("/basic")
@Produces(MediaType.TEXT_HTML)
public TemplateInstance base() {
return basic.data("server", "Quarkus");
}

@GET
@Path("/location")
@Produces(MediaType.TEXT_HTML)
public TemplateInstance located() {
return multiLanguage.data("server", "Quarkus");
}

@GET
@Path("/engine/{name}")
@Produces(MediaType.TEXT_HTML)
public Response engine(@PathParam("name") String name) {
final Template template = engine.getTemplate(name);
if (template == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
return Response.ok(template.data("server", name + " engine")).build();
}

@POST
@Path("/engine/{name}")
@Produces(MediaType.TEXT_HTML)
public Response registerNew(@PathParam("name") String name, String body) {
Response.ResponseBuilder result;
if (engine.getTemplate(name) == null) {
engine.putTemplate(name, engine.parse(body));
result = Response.created(getUri("/engine/" + name));
} else {
result = Response.status(Response.Status.CONFLICT);
}
return result.build();
}

@PUT
@Path("/engine/{name}")
@Produces(MediaType.TEXT_HTML)
public Response register(@PathParam("name") String name, String body) {
Template existing = engine.putTemplate(name, engine.parse(body));
if (existing == null) {
return Response.created(getUri("/engine/" + name)).build();
} else {
return Response.noContent().build();
}
}

@DELETE
@Path("/engine/{name}")
@Produces(MediaType.TEXT_HTML)
public Response delete(@PathParam("name") String name) {
engine.removeTemplates(templateName -> templateName.equals(name));
return Response.ok().build();
}

@GET
@Path("/format")
@Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN })
public String format(@QueryParam("name") String name) {
return Qute.fmt("This page is rendered for \"{}\" by Qute", name);
}

@GET
@Path("/format-advanced")
@Produces(MediaType.TEXT_HTML)
public String formatHtml(@QueryParam("name") String name) {
return Qute.fmt("This text is fluently rendered for \"{name}\" by Qute")
.data("name", name)
.render();
}

@GET
@Path("/book")
@Produces(MediaType.TEXT_HTML)
public CompletionStage<String> book() {
Book musketeers = new Book("The Three Musketeers", "Alexandre Dumas", "d'Artagnan", "Athos", "Porthos", "Aramis");
return engine.getTemplate("expressions")
.data("server", "engine")
.data("book", musketeers)
.renderAsync();
}

@GET
@Path("/encoding")
@Produces(MediaType.TEXT_HTML)
public Uni<String> encoding() {
return engine.getTemplate("нелатынь")
.data("English", "hello")
.data("česky", "čau")
.data("по-русски", "привет")
.data("בעברית", "שלום")
.createUni();
}

@GET
@Path("/map")
@Produces(MediaType.TEXT_HTML)
public Multi<String> map(@QueryParam("name") @DefaultValue("islands") String region) {
Map<String, String> map = new HashMap<>();
if (region.equals("islands")) {
map.put("Tasmania", "Hobart");
map.put("Java", "Jakarta");
map.put("The Great Britain", "London");
}
return engine
.getTemplate("maps")
.data("map", map)
.createMulti();
}

@GET
@Path("/inheritance")
@Produces(MediaType.TEXT_HTML)
public TemplateInstance inheritance(@QueryParam("name") @DefaultValue("detail") String template) {
return engine.getTemplate(template).instance();
}

@GET
@Path("/annotated")
public TemplateInstance annotated() {
final Fish trout = new Fish("trout");
return engine
.getTemplate("annotations")
.data("fish", trout)
.data("wrapper", new StringWrapper("A quick brown fox jumps over the lazy dog"));
}

@GET
@Path("/enums/{city}")
@Produces(MediaType.TEXT_HTML)
public TemplateInstance enums(@PathParam("city") String city) {
final City destination = City.valueOf(city.toUpperCase());
return engine.parse("Good news, we will{#if city == City:BRUGES} not{/if} spend a week in {city.naturalName}!")
.data("city", destination);
}

@GET
@Path("/message/{locale}")
@Produces(MediaType.TEXT_PLAIN)
public TemplateInstance message(@PathParam("locale") String tag) {
return engine
.parse(String.format("{greeting:hello('%s')}", "Dr. Livingstone"))
.instance()
.setAttribute("locale", Locale.forLanguageTag(tag));
}

@GET
@Path("/message/long/{locale}")
@Produces(MediaType.TEXT_PLAIN)
public Uni<String> longMessage(@PathParam("locale") String tag) {
return engine
.parse(String.format("{greeting:long_hello('%s')}", "Dr. Livingstone"))
.instance()
.setAttribute("locale", Locale.forLanguageTag(tag))
.createUni();
}

@GET
@Path("/message/")
@Produces(MediaType.TEXT_PLAIN)
public String injectedLocalization() {
return hebrew.hello("אדם");
}

private static URI getUri(String path) {
final Config system = ConfigProvider.getConfig();
final String host = system.getValue("quarkus.http.host", String.class);
final Integer port = system.getValue("quarkus.http.port", Integer.class);
try {
return new URL("http", host, port, path).toURI();
} catch (URISyntaxException | MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
16 changes: 16 additions & 0 deletions qute/reactive/src/main/java/io/quarkus/ts/qute/Book.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.quarkus.ts.qute;

import io.quarkus.qute.TemplateData;

@TemplateData
public class Book {
public final String title;
public final String author;
public final String[] characters;

public Book(String title, String author, String... characters) {
this.title = title;
this.author = author;
this.characters = characters;
}
}
17 changes: 17 additions & 0 deletions qute/reactive/src/main/java/io/quarkus/ts/qute/City.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.quarkus.ts.qute;

import io.quarkus.qute.TemplateEnum;

@TemplateEnum
public enum City {
BRUGES,
DUBLIN,
MOMBASA;

public String naturalName() {
String full = this.name();
String firstLetter = full.substring(0, 1);
String rest = full.substring(1).toLowerCase();
return firstLetter + rest;
}
}
20 changes: 20 additions & 0 deletions qute/reactive/src/main/java/io/quarkus/ts/qute/Fish.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.ts.qute;

import io.quarkus.qute.TemplateData;

@TemplateData
public class Fish {
private final String name;

public Fish(String name) {
this.name = name;
}

public String saySomething() {
return String.format("This %s stays silent", this.name);
}

public String slap(String user, String target) {
return String.format("%s slaps %s around a bit with a large %s", user, target, this.name);
}
}
14 changes: 14 additions & 0 deletions qute/reactive/src/main/java/io/quarkus/ts/qute/Messages.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.ts.qute;

import io.quarkus.qute.i18n.Message;
import io.quarkus.qute.i18n.MessageBundle;

@MessageBundle("greeting")
public interface Messages {
@Message("Hello, {name}!")
String hello(String name);

@Message("Hello, {name}! \n How are you, {name}?")
String long_hello(String name);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.quarkus.ts.qute;

import io.quarkus.qute.i18n.Localized;
import io.quarkus.qute.i18n.Message;

@Localized("es")
public interface SpanishMessages extends Messages {

@Override
@Message("Hola, {name}!")
String hello(String name);
}
13 changes: 13 additions & 0 deletions qute/reactive/src/main/java/io/quarkus/ts/qute/StringWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.ts.qute;

import io.quarkus.qute.TemplateData;

@TemplateData(target = String.class)
@TemplateData //required for native
public class StringWrapper {
public final String content;

public StringWrapper(String content) {
this.content = content;
}
}
13 changes: 13 additions & 0 deletions qute/reactive/src/main/java/io/quarkus/ts/qute/Variables.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.ts.qute;

import io.quarkus.qute.TemplateGlobal;

@TemplateGlobal
public class Variables {
static final int airspeedVelocityOfAnUnladenSwallow = 11;

@TemplateGlobal(name = "random")
static int getRandomNumber() {
return 5;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello=Ahoj, {name}!
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hello=שלם, {name}!
long_hello=שלם, {name}, \
מה נשמע?
3 changes: 3 additions & 0 deletions qute/reactive/src/main/resources/templates/1.i18n.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<html>
<p>This page is fetched and rendered by {server}</p>
</html>
Loading