Skip to content

Commit 51d5937

Browse files
committed
Add MvcMethod object for setMvcMethod and getMvcMethod.
- fix #3532 - jooby-apt option will be off by default in next major release
1 parent 7433c2c commit 51d5937

File tree

5 files changed

+85
-18
lines changed

5 files changed

+85
-18
lines changed

jooby/src/main/java/io/jooby/Route.java

+55-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
package io.jooby;
77

88
import java.io.Serializable;
9+
import java.lang.invoke.MethodHandle;
10+
import java.lang.invoke.MethodHandles;
11+
import java.lang.invoke.MethodType;
912
import java.lang.reflect.Method;
1013
import java.lang.reflect.Type;
1114
import java.util.ArrayList;
@@ -370,12 +373,55 @@ public interface Handler extends Serializable, Aware {
370373
if (contentType == null) {
371374
throw new UnsupportedMediaType(null);
372375
}
373-
if (!ctx.getRoute().getConsumes().stream().anyMatch(contentType::matches)) {
376+
if (ctx.getRoute().getConsumes().stream().noneMatch(contentType::matches)) {
374377
throw new UnsupportedMediaType(contentType.getValue());
375378
}
376379
}
377380
};
378381

382+
/**
383+
* Carry metadata for mvc/controller method.
384+
*
385+
* @param declaringClass Controller class.
386+
* @param name Method name.
387+
* @param returnType Method return type.
388+
* @param parameterTypes Method argument types.
389+
*/
390+
public record MvcMethod(
391+
@NonNull Class<?> declaringClass,
392+
@NonNull String name,
393+
@NonNull Class<?> returnType,
394+
Class<?>... parameterTypes) {
395+
396+
/**
397+
* Convert to {@link java.lang.reflect.Method}.
398+
*
399+
* @return A {@link java.lang.reflect.Method}.
400+
*/
401+
public Method toMethod() {
402+
try {
403+
return declaringClass.getDeclaredMethod(name, parameterTypes);
404+
} catch (NoSuchMethodException e) {
405+
throw SneakyThrows.propagate(e);
406+
}
407+
}
408+
409+
/**
410+
* Convert to {@link MethodHandle}.
411+
*
412+
* @return A {@link MethodHandle}.
413+
*/
414+
public MethodHandle toMethodHandle() {
415+
var lookup = MethodHandles.publicLookup();
416+
var methodType = MethodType.methodType(returnType, parameterTypes);
417+
try {
418+
return lookup.findVirtual(declaringClass, name, methodType);
419+
} catch (NoSuchMethodException | IllegalAccessException e) {
420+
throw SneakyThrows.propagate(e);
421+
}
422+
}
423+
}
424+
379425
/** Favicon handler as a silent 404 error. */
380426
public static final Handler FAVICON = ctx -> ctx.send(StatusCode.NOT_FOUND);
381427

@@ -423,7 +469,7 @@ public interface Handler extends Serializable, Aware {
423469

424470
private Boolean nonBlocking;
425471

426-
private Method mvcMethod;
472+
private MvcMethod mvcMethod;
427473

428474
private boolean httpHead;
429475

@@ -655,7 +701,9 @@ public boolean isNonBlockingSet() {
655701
* Route return type.
656702
*
657703
* @return Return type.
704+
* @deprecated Marked for removal on 4.0
658705
*/
706+
@Deprecated
659707
public @Nullable Type getReturnType() {
660708
return returnType;
661709
}
@@ -665,7 +713,9 @@ public boolean isNonBlockingSet() {
665713
*
666714
* @param returnType Return type.
667715
* @return This route.
716+
* @deprecated Marked for removal on 4.0
668717
*/
718+
@Deprecated
669719
public @NonNull Route setReturnType(@Nullable Type returnType) {
670720
this.returnType = returnType;
671721
return this;
@@ -1046,7 +1096,7 @@ public boolean isTransactional(boolean defaultValue) {
10461096
*
10471097
* @return Method for MVC/Controller. Not available for lambda routes.
10481098
*/
1049-
public @Nullable Method getMvcMethod() {
1099+
public @Nullable MvcMethod getMvcMethod() {
10501100
return mvcMethod;
10511101
}
10521102

@@ -1056,7 +1106,7 @@ public boolean isTransactional(boolean defaultValue) {
10561106
* @param mvcMethod Mvc/controller method.
10571107
* @return This route
10581108
*/
1059-
public @NonNull Route setMvcMethod(@Nullable Method mvcMethod) {
1109+
public @NonNull Route setMvcMethod(@Nullable MvcMethod mvcMethod) {
10601110
this.mvcMethod = mvcMethod;
10611111
return this;
10621112
}
@@ -1067,7 +1117,7 @@ public boolean isTransactional(boolean defaultValue) {
10671117
* @param mvcMethod Mvc/controller method.
10681118
* @return This route
10691119
*/
1070-
public @NonNull Route mvcMethod(@Nullable Method mvcMethod) {
1120+
public @NonNull Route mvcMethod(@Nullable MvcMethod mvcMethod) {
10711121
return setMvcMethod(mvcMethod);
10721122
}
10731123

modules/jooby-apt/src/main/java/io/jooby/internal/apt/MvcContext.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public MvcContext(
4545
this.debug = Options.boolOpt(processingEnvironment, Options.DEBUG, false);
4646
this.incremental = Options.boolOpt(processingEnvironment, Options.INCREMENTAL, true);
4747
this.returnType = Options.boolOpt(processingEnvironment, Options.RETURN_TYPE, false);
48-
this.mvcMethod = Options.boolOpt(processingEnvironment, Options.MVC_METHOD, false);
48+
this.mvcMethod = Options.boolOpt(processingEnvironment, Options.MVC_METHOD, true);
4949
this.services = Options.boolOpt(processingEnvironment, Options.SERVICES, true);
5050
this.routerPrefix = Options.string(processingEnvironment, Options.ROUTER_PREFIX, "");
5151
this.routerSuffix = Options.string(processingEnvironment, Options.ROUTER_SUFFIX, "_");

modules/jooby-apt/src/main/java/io/jooby/internal/apt/MvcRoute.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,15 @@ public List<String> generateMapping(boolean kt) {
156156
CodeBlock.of(
157157
indent(2),
158158
".setMvcMethod(",
159-
router.getTargetType().getSimpleName(),
159+
kt ? "" : "new ",
160+
"io.jooby.Route.MvcMethod(",
161+
router.getTargetType().getQualifiedName().toString(),
160162
clazz(kt),
161-
".getMethod(",
163+
", ",
162164
string(getMethodName()),
165+
", ",
166+
type(kt, returnType.getRawType().toString()),
167+
clazz(kt),
163168
paramString.isEmpty() ? "" : ", " + paramString,
164169
"))",
165170
semicolon(kt),

modules/jooby-apt/src/test/java/tests/i2629/Issue2629.java

+11-5
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
*/
66
package tests.i2629;
77

8-
import static org.junit.jupiter.api.Assertions.assertEquals;
9-
import static org.junit.jupiter.api.Assertions.assertNotNull;
8+
import static org.junit.jupiter.api.Assertions.*;
109

1110
import java.util.List;
1211
import java.util.Map;
@@ -30,9 +29,16 @@ public void shouldSetMvcMethod() throws Exception {
3029
assertEquals("foo:[12]:true", router.get("/2629", ctx).value().toString());
3130
var route = app.getRoutes().get(0);
3231
assertNotNull(route.getMvcMethod());
33-
assertEquals(
34-
"foo:[14]:false",
35-
route.getMvcMethod().invoke(new C2629(), "foo", List.of(14), false));
32+
try {
33+
assertEquals(
34+
"foo:[14]:false",
35+
route
36+
.getMvcMethod()
37+
.toMethodHandle()
38+
.invoke(new C2629(), "foo", List.of(14), Boolean.FALSE));
39+
} catch (Throwable cause) {
40+
fail(cause);
41+
}
3642
});
3743
}
3844
}

modules/jooby-apt/src/test/java/tests/i2629/Issue2629b.java

+11-5
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
*/
66
package tests.i2629;
77

8-
import static org.junit.jupiter.api.Assertions.assertEquals;
9-
import static org.junit.jupiter.api.Assertions.assertNotNull;
8+
import static org.junit.jupiter.api.Assertions.*;
109

1110
import java.util.Map;
1211

@@ -29,9 +28,16 @@ public void shouldSetMvcMethod() throws Exception {
2928
assertEquals("foo/1/2.0/GET/3/4.0/true", router.get("/2629", ctx).value().toString());
3029
var route = app.getRoutes().get(0);
3130
assertNotNull(route.getMvcMethod());
32-
assertEquals(
33-
"bar/5/6.0/GET/7/8.0/false",
34-
route.getMvcMethod().invoke(new C2629b(), "bar", 5, 6d, ctx, 7l, 8f, false));
31+
try {
32+
assertEquals(
33+
"bar/5/6.0/GET/7/8.0/false",
34+
route
35+
.getMvcMethod()
36+
.toMethodHandle()
37+
.invoke(new C2629b(), "bar", 5, 6d, ctx, 7l, 8f, false));
38+
} catch (Throwable e) {
39+
fail(e);
40+
}
3541
});
3642
}
3743
}

0 commit comments

Comments
 (0)