Skip to content

Commit 86f5c8e

Browse files
committed
reactive: Reactive types must support side-effect handlers #3486
- fix #3486
1 parent a37a7d5 commit 86f5c8e

5 files changed

Lines changed: 125 additions & 14 deletions

File tree

jooby/src/main/java/io/jooby/internal/handler/ConcurrentHandler.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ public Route.Handler apply(@NonNull Route.Handler next) {
4141
Throwable exception = unwrap((Throwable) x);
4242
ctx.sendError(exception);
4343
} else {
44-
ctx.render(value);
44+
// See https://github.com/jooby-project/jooby/issues/3486
45+
if (!ctx.isResponseStarted() && value != ctx) {
46+
ctx.render(value);
47+
}
4548
}
4649
} catch (Throwable cause) {
4750
ctx.sendError(cause);

modules/jooby-mutiny/src/main/java/io/jooby/mutiny/Mutiny.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@ public Route.Handler apply(@NonNull Route.Handler next) {
5555
value -> {
5656
// fire after:
5757
after(ctx, value, null);
58-
// render:
59-
ctx.render(value);
58+
// See https://github.com/jooby-project/jooby/issues/3486
59+
if (!ctx.isResponseStarted() && value != ctx) {
60+
// render:
61+
ctx.render(value);
62+
}
6063
},
6164
failure -> {
6265
// fire after:

modules/jooby-reactor/src/main/java/io/jooby/reactor/Reactor.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,12 @@ public Route.Handler apply(@NonNull Route.Handler next) {
5959
value -> {
6060
// fire after:
6161
after(ctx, value, null);
62-
// render:
63-
ctx.render(value);
62+
// See https://github.com/jooby-project/jooby/issues/3486
63+
if (!ctx.isResponseStarted() && value != ctx) {
64+
65+
// render:
66+
ctx.render(value);
67+
}
6468
},
6569
failure -> {
6670
// fire after:

modules/jooby-rxjava3/src/main/java/io/jooby/internal/rxjava3/RxSubscriber.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818

1919
public class RxSubscriber implements MaybeObserver<Object>, SingleObserver<Object> {
2020

21-
private final Context context;
21+
private final Context ctx;
2222

2323
private Disposable subscription;
2424

25-
public RxSubscriber(Context context) {
26-
this.context = context;
25+
public RxSubscriber(Context ctx) {
26+
this.ctx = ctx;
2727
}
2828

2929
@Override
@@ -33,14 +33,17 @@ public void onSubscribe(Disposable d) {
3333

3434
@Override
3535
public void onSuccess(Object value) {
36-
after(context, value, null);
37-
context.render(value);
36+
after(ctx, value, null);
37+
// See https://github.com/jooby-project/jooby/issues/3486
38+
if (!ctx.isResponseStarted() && value != ctx) {
39+
ctx.render(value);
40+
}
3841
}
3942

4043
@Override
4144
public void onError(Throwable x) {
42-
after(context, null, unwrap(x));
43-
context.sendError(x);
45+
after(ctx, null, unwrap(x));
46+
ctx.sendError(x);
4447
subscription.dispose();
4548
}
4649

@@ -53,9 +56,9 @@ private Throwable unwrap(Throwable x) {
5356

5457
@Override
5558
public void onComplete() {
56-
if (!context.isResponseStarted()) {
59+
if (!ctx.isResponseStarted()) {
5760
// assume it is a maybe response:
58-
context.send(StatusCode.NOT_FOUND);
61+
ctx.send(StatusCode.NOT_FOUND);
5962
}
6063
subscription.dispose();
6164
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package io.jooby.i3486;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
10+
import java.util.concurrent.CompletableFuture;
11+
12+
import io.jooby.ReactiveSupport;
13+
import io.jooby.junit.ServerTest;
14+
import io.jooby.junit.ServerTestRunner;
15+
import io.jooby.mutiny.Mutiny;
16+
import io.jooby.reactor.Reactor;
17+
import io.jooby.rxjava3.Reactivex;
18+
import io.reactivex.rxjava3.core.Single;
19+
import io.smallrye.mutiny.Uni;
20+
import reactor.core.publisher.Mono;
21+
22+
public class Issue3486 {
23+
@ServerTest
24+
public void reactiveShouldWorkWithSideEffectsHandler(ServerTestRunner runner) {
25+
runner
26+
.define(
27+
app -> {
28+
app.use(ReactiveSupport.concurrent());
29+
app.use(Mutiny.mutiny());
30+
app.use(Reactor.reactor());
31+
app.use(Reactivex.rx());
32+
33+
app.get(
34+
"/3486/completablefuture",
35+
ctx ->
36+
CompletableFuture.supplyAsync(
37+
() -> {
38+
ctx.send("top page");
39+
return ctx;
40+
}));
41+
42+
app.get(
43+
"/3486/mutiny",
44+
ctx ->
45+
Uni.createFrom()
46+
.item(
47+
() -> {
48+
ctx.send("top page");
49+
return ctx;
50+
}));
51+
52+
app.get(
53+
"/3486/reactor",
54+
ctx ->
55+
Mono.fromSupplier(
56+
() -> {
57+
ctx.send("top page");
58+
return ctx;
59+
}));
60+
61+
app.get(
62+
"/3486/reactivex",
63+
ctx ->
64+
Single.fromSupplier(
65+
() -> {
66+
ctx.send("top page");
67+
return ctx;
68+
}));
69+
})
70+
.ready(
71+
client -> {
72+
client.get(
73+
"/3486/completablefuture",
74+
rsp -> {
75+
assertEquals(200, rsp.code());
76+
assertEquals("top page", rsp.body().string());
77+
});
78+
client.get(
79+
"/3486/mutiny",
80+
rsp -> {
81+
assertEquals(200, rsp.code());
82+
assertEquals("top page", rsp.body().string());
83+
});
84+
client.get(
85+
"/3486/reactor",
86+
rsp -> {
87+
assertEquals(200, rsp.code());
88+
assertEquals("top page", rsp.body().string());
89+
});
90+
client.get(
91+
"/3486/reactivex",
92+
rsp -> {
93+
assertEquals(200, rsp.code());
94+
assertEquals("top page", rsp.body().string());
95+
});
96+
});
97+
}
98+
}

0 commit comments

Comments
 (0)