@@ -265,13 +265,33 @@ public List<String> generateHandlerCall(boolean kt) {
265265 returnTypeString = Types .PROJECTED + "<" + returnType + ">" ;
266266 }
267267
268- // Add the TrpcResponse generic wrapper for the generated method return type
268+ var reactive = isTrpc ? context .getReactiveType (returnType .getRawType ()) : null ;
269+ var isReactiveVoid = false ;
270+ var innerReactiveType = "Object" ;
271+
272+ // 1. Resolve Target Signature
269273 var methodReturnTypeString = returnTypeString ;
270274 if (isTrpc ) {
271- methodReturnTypeString =
272- "io.jooby.trpc.TrpcResponse<"
273- + (returnType .isVoid () ? (kt ? "Unit" : "Void" ) : returnTypeString )
274- + ">" ;
275+ if (reactive != null ) {
276+ var rawReactiveType = type (kt , returnType .getRawType ().toString ());
277+ if (!returnType .getArguments ().isEmpty ()) {
278+ innerReactiveType = type (kt , returnType .getArguments ().get (0 ).getRawType ().toString ());
279+ if (innerReactiveType .equals ("java.lang.Void" ) || innerReactiveType .equals ("Void" )) {
280+ isReactiveVoid = true ;
281+ innerReactiveType = kt ? "Unit" : "Void" ;
282+ }
283+ } else if (rawReactiveType .contains ("Completable" )) {
284+ isReactiveVoid = true ;
285+ innerReactiveType = kt ? "Unit" : "Void" ;
286+ }
287+ methodReturnTypeString =
288+ rawReactiveType + "<io.jooby.trpc.TrpcResponse<" + innerReactiveType + ">>" ;
289+ } else {
290+ methodReturnTypeString =
291+ "io.jooby.trpc.TrpcResponse<"
292+ + (returnType .isVoid () ? (kt ? "Unit" : "Void" ) : returnTypeString )
293+ + ">" ;
294+ }
275295 }
276296
277297 var nullable =
@@ -366,6 +386,7 @@ public List<String> generateHandlerCall(boolean kt) {
366386
367387 controllerVar (kt , buffer , controllerIndent );
368388
389+ // 2. Resolve Return Flow
369390 if (returnType .isVoid ()) {
370391 String statusCode =
371392 annotationMap .size () == 1
@@ -451,7 +472,6 @@ public List<String> generateHandlerCall(boolean kt) {
451472 ? ""
452473 : customReturnType .getArgumentsString (kt , false , Set .of (TypeKind .TYPEVAR ));
453474
454- // Ensure projections are ignored by the kotlin hardcast, as they handle their own wrapper
455475 var needsCast =
456476 !castStr .isEmpty ()
457477 || (kt
@@ -480,7 +500,6 @@ public List<String> generateHandlerCall(boolean kt) {
480500 indent (controllerIndent ),
481501 "return io.jooby.trpc.TrpcResponse.of(" ,
482502 projected ,
483- kt && nullable ? "!!" : "" ,
484503 ")" ,
485504 semicolon (kt )));
486505 } else {
@@ -493,7 +512,62 @@ public List<String> generateHandlerCall(boolean kt) {
493512 semicolon (kt )));
494513 }
495514 } else {
496- if (isTrpc ) {
515+
516+ if (isTrpc && reactive != null ) {
517+ if (isReactiveVoid ) {
518+ // Ensure empty void streams systematically resolve into an empty TrpcResponse
519+ var handler = reactive .handlerType ();
520+ if (handler .contains ("Reactor" )) {
521+ buffer .add (
522+ statement (
523+ indent (controllerIndent ),
524+ "return " ,
525+ call ,
526+ ".then(reactor.core.publisher.Mono.just(io.jooby.trpc.TrpcResponse.empty()))" ,
527+ semicolon (kt )));
528+ } else if (handler .contains ("Mutiny" )) {
529+ buffer .add (
530+ statement (
531+ indent (controllerIndent ),
532+ "return " ,
533+ call ,
534+ ".replaceWith(io.jooby.trpc.TrpcResponse.empty())" ,
535+ semicolon (kt )));
536+ } else if (handler .contains ("ReactiveSupport" )) {
537+ buffer .add (
538+ statement (
539+ indent (controllerIndent ),
540+ "return " ,
541+ call ,
542+ ".thenApply(x -> io.jooby.trpc.TrpcResponse.empty())" ,
543+ semicolon (kt )));
544+ } else if (handler .contains ("Reactivex" )) {
545+ buffer .add (
546+ statement (
547+ indent (controllerIndent ),
548+ "return " ,
549+ call ,
550+ ".toSingleDefault(io.jooby.trpc.TrpcResponse.empty())" ,
551+ semicolon (kt )));
552+ } else {
553+ buffer .add (
554+ statement (
555+ indent (controllerIndent ),
556+ "return " ,
557+ call ,
558+ ".map(x -> io.jooby.trpc.TrpcResponse.empty())" ,
559+ semicolon (kt )));
560+ }
561+ } else {
562+ buffer .add (
563+ statement (
564+ indent (controllerIndent ),
565+ "return " ,
566+ call ,
567+ reactive .mapOperator (),
568+ semicolon (kt )));
569+ }
570+ } else if (isTrpc ) {
497571 buffer .add (
498572 statement (
499573 indent (controllerIndent ),
0 commit comments