Skip to content

Commit

Permalink
Qute - build the reactive part of the API on top of Mutiny
Browse files Browse the repository at this point in the history
- add TemplateInstance.createMulti()
- get rid of io.quarkus.qute.PublisherFactory
- resolves quarkusio#10457
  • Loading branch information
mkouba committed Jul 6, 2020
1 parent f3ced2d commit 5b0d419
Show file tree
Hide file tree
Showing 18 changed files with 89 additions and 160 deletions.
13 changes: 11 additions & 2 deletions docs/src/main/asciidoc/reactive-routes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,24 @@ The `@Route` annotation is repeatable and so you can declare several routes for

[source,java]
----
@Route(path = "/first")
@Route(path = "/first") <1>
@Route(path = "/second")
public void route(RoutingContext rc) {
// ...
}
----
<1> Each route can use different paths, methods...

Each route can use different paths, methods...
If no content-type header is set then we will try to use the most acceptable content type as defined by `io.vertx.ext.web.RoutingContext.getAcceptableContentType()`.

[source,java]
----
@Route(path = "/person", produces = "text/html") <1>
String person() {
// ...
}
----
<1> If the `accept` header matches `text/html` we set the content type automatically.

=== Handling conflicting routes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
import io.quarkus.deployment.builditem.ServiceStartBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.util.JandexUtil;
import io.quarkus.gizmo.ClassOutput;
import io.quarkus.qute.Engine;
Expand All @@ -81,7 +80,6 @@
import io.quarkus.qute.LoopSectionHelper;
import io.quarkus.qute.ParserHelper;
import io.quarkus.qute.ParserHook;
import io.quarkus.qute.PublisherFactory;
import io.quarkus.qute.ResultNode;
import io.quarkus.qute.SectionHelper;
import io.quarkus.qute.SectionHelperFactory;
Expand All @@ -99,7 +97,6 @@
import io.quarkus.qute.deployment.TypeInfos.Info;
import io.quarkus.qute.generator.ExtensionMethodGenerator;
import io.quarkus.qute.generator.ValueResolverGenerator;
import io.quarkus.qute.mutiny.MutinyPublisherFactory;
import io.quarkus.qute.runtime.EngineProducer;
import io.quarkus.qute.runtime.QuteConfig;
import io.quarkus.qute.runtime.QuteRecorder;
Expand Down Expand Up @@ -854,11 +851,6 @@ TemplateVariantsBuildItem collectTemplateVariants(List<TemplatePathBuildItem> te
return new TemplateVariantsBuildItem(baseToVariants);
}

@BuildStep
ServiceProviderBuildItem registerPublisherFactory() {
return new ServiceProviderBuildItem(PublisherFactory.class.getName(), MutinyPublisherFactory.class.getName());
}

@BuildStep
void excludeTypeChecks(BuildProducer<TypeCheckExcludeBuildItem> excludes) {
// Exclude all checks that involve built-in value resolvers
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.quarkus.qute.deployment;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.math.BigDecimal;
import java.math.RoundingMode;
Expand All @@ -13,14 +12,13 @@
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.reactivestreams.Publisher;

import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateData;
import io.quarkus.test.QuarkusUnitTest;
import io.smallrye.mutiny.Multi;

public class PublisherTest {
public class MultiTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
Expand All @@ -33,11 +31,10 @@ public class PublisherTest {
Template foo;

@Test
public void testTemplateData() {
Publisher<String> publisher = foo.data("roundingMode", RoundingMode.HALF_UP)
.data("foo", new TemplateDataTest.Foo(new BigDecimal("123.4563"))).publisher();
assertTrue(publisher instanceof Multi);
assertEquals("123.4563 is not 123.46", Multi.createFrom().publisher(publisher)
public void testCreateMulti() {
Multi<String> multi = foo.data("roundingMode", RoundingMode.HALF_UP)
.data("foo", new TemplateDataTest.Foo(new BigDecimal("123.4563"))).createMulti();
assertEquals("123.4563 is not 123.46", multi
.collectItems().in(StringBuffer::new, StringBuffer::append)
.onItem().apply(StringBuffer::toString)
.await().indefinitely());
Expand Down
4 changes: 0 additions & 4 deletions extensions/qute/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@
<groupId>io.quarkus.qute</groupId>
<artifactId>qute-core</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus.qute</groupId>
<artifactId>qute-mutiny</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import javax.inject.Singleton;

import org.jboss.logging.Logger;
import org.reactivestreams.Publisher;

import io.quarkus.qute.Engine;
import io.quarkus.qute.Expression;
Expand All @@ -29,6 +28,7 @@
import io.quarkus.qute.Variant;
import io.quarkus.qute.api.ResourcePath;
import io.quarkus.qute.runtime.QuteRecorder.QuteContext;
import io.smallrye.mutiny.Multi;

@Singleton
public class TemplateProducer {
Expand Down Expand Up @@ -154,8 +154,8 @@ public CompletionStage<String> renderAsync() {
}

@Override
public Publisher<String> publisher() {
return templateInstance().publisher();
public Multi<String> createMulti() {
return templateInstance().createMulti();
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions independent-projects/qute/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<groupId>io.smallrye.reactive</groupId>
<artifactId>mutiny</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.jboss.logging.Logger;

/**
Expand All @@ -38,7 +34,6 @@ class EngineImpl implements Engine {
private final Map<String, Template> templates;
private final List<TemplateLocator> locators;
private final List<ResultMapper> resultMappers;
private final PublisherFactory publisherFactory;
private final AtomicLong idGenerator = new AtomicLong(0);
private final List<ParserHook> parserHooks;
final boolean removeStandaloneLines;
Expand All @@ -50,18 +45,6 @@ class EngineImpl implements Engine {
this.evaluator = new EvaluatorImpl(this.valueResolvers);
this.templates = new ConcurrentHashMap<>();
this.locators = sort(builder.locators);
ServiceLoader<PublisherFactory> loader = ServiceLoader.load(PublisherFactory.class);
Iterator<PublisherFactory> iterator = loader.iterator();
if (iterator.hasNext()) {
this.publisherFactory = iterator.next();
} else {
this.publisherFactory = null;
}
if (iterator.hasNext()) {
throw new IllegalStateException(
"Multiple reactive factories found: " + StreamSupport.stream(loader.spliterator(), false)
.map(Object::getClass).map(Class::getName).collect(Collectors.joining(",")));
}
this.resultMappers = sort(builder.resultMappers);
this.sectionHelperFunc = builder.sectionHelperFunc;
this.parserHooks = ImmutableList.copyOf(builder.parserHooks);
Expand Down Expand Up @@ -129,10 +112,6 @@ public void removeTemplates(Predicate<String> test) {
templates.keySet().removeIf(test);
}

PublisherFactory getPublisherFactory() {
return publisherFactory;
}

String generateId() {
return "" + idGenerator.incrementAndGet();
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.qute;

import io.smallrye.mutiny.Multi;
import java.util.List;
import java.util.Optional;
import java.util.Set;
Expand All @@ -9,7 +10,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import org.reactivestreams.Publisher;

class TemplateImpl implements Template {

Expand Down Expand Up @@ -68,12 +68,15 @@ public String render() {
}

@Override
public Publisher<String> publisher() {
PublisherFactory factory = engine.getPublisherFactory();
if (factory == null) {
throw new UnsupportedOperationException();
}
return factory.createPublisher(this);
public Multi<String> createMulti() {
return Multi.createFrom().emitter(emitter -> consume(emitter::emit)
.whenComplete((r, f) -> {
if (f == null) {
emitter.complete();
} else {
emitter.fail(f);
}
}));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.qute;

import io.smallrye.mutiny.Multi;
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;
import org.reactivestreams.Publisher;
Expand Down Expand Up @@ -79,8 +80,19 @@ public interface TemplateInstance {
*
* @return a publisher that can be used to consume chunks of the rendered template
* @throws UnsupportedOperationException If no {@link PublisherFactory} service provider is found
* @deprecated Use {@link #createMulti()} instead
*/
Publisher<String> publisher();
@Deprecated
default Publisher<String> publisher() {
return createMulti();
}

/**
* Each subscription triggers rendering.
*
* @return a Multi that can be used to consume chunks of the rendered template
*/
Multi<String> createMulti();

/**
* Triggers rendering.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,41 @@
package com.github.mkouba.qute.mutiny;
package io.quarkus.qute;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import io.quarkus.qute.Engine;
import io.quarkus.qute.Template;
import io.smallrye.mutiny.Multi;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
import org.reactivestreams.Publisher;

public class SimplePublisherTest {
public class CreateMultiTest {

@Test
public void test() throws InterruptedException {
Engine engine = Engine.builder().addDefaultSectionHelpers().addDefaultValueResolvers().build();
Template template = engine.parse("{#each}{it}{/}");
List<String> data = Arrays.asList("foo", "foo", "alpha");
Publisher<String> publisher = template.instance().data(data).publisher();
Multi<String> multi = template.instance().data(data).createMulti();

assertPublisher(() -> Multi.createFrom().publisher(publisher), "foofooalpha");
assertPublisher(() -> Multi.createFrom().publisher(publisher)
.transform().byDroppingDuplicates(), "fooalpha");
assertPublisher(() -> Multi.createFrom().publisher(publisher)
.transform().byTakingFirstItems(1), "foo");
assertMulti(multi, "foofooalpha");
assertMulti(multi.transform().byDroppingDuplicates(), "fooalpha");
assertMulti(multi.transform().byTakingFirstItems(1), "foo");
}

private void assertPublisher(Supplier<Publisher<String>> test, String expected) throws InterruptedException {
private void assertMulti(Multi<String> multi, String expected) throws InterruptedException {
StringBuilder builder = new StringBuilder();
CountDownLatch latch = new CountDownLatch(1);

Multi.createFrom().publisher(test.get())
multi
.subscribe().with(
builder::append,
latch::countDown);

if (latch.await(2, TimeUnit.SECONDS)) {
assertEquals(expected, builder.toString());
} else {
fail();
}
}

}
}
34 changes: 0 additions & 34 deletions independent-projects/qute/mutiny/pom.xml

This file was deleted.

Loading

0 comments on commit 5b0d419

Please sign in to comment.