Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit 188181a

Browse files
derKrischanjknack
authored andcommitted
847 - Added implementing class directly to MvcHandler (jooby-project#876)
* 847 - Added implementing class directly to MvcHandler instead of Method.getDeclaringclass to avoid abstract class instantiation attempts. Fixed some compiler warnings in modified classes. * 847 - Added else clause for non-MethodHandler routes
1 parent 2c699f1 commit 188181a

File tree

5 files changed

+85
-20
lines changed

5 files changed

+85
-20
lines changed

jooby/src/main/java/org/jooby/Jooby.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@
287287
import javax.inject.Singleton;
288288
import javax.net.ssl.SSLContext;
289289
import java.io.File;
290+
import java.lang.reflect.Modifier;
290291
import java.lang.reflect.Type;
291292
import java.nio.charset.Charset;
292293
import java.nio.file.Path;
@@ -3040,12 +3041,14 @@ private static Throwing.Consumer<? super Object> bindService(final Set<Object> s
30403041
Route.Definition rdef = (Definition) it;
30413042
Route.Filter h = rdef.filter();
30423043
if (h instanceof Route.MethodHandler) {
3043-
Class<?> routeClass = ((Route.MethodHandler) h).method().getDeclaringClass();
3044+
Class<?> routeClass = ((Route.MethodHandler) h).implementingClass();
30443045
if (routeClasses.add(routeClass)) {
30453046
binder.bind(routeClass);
30463047
}
3048+
definitions.addBinding().toInstance(rdef);
3049+
} else {
3050+
definitions.addBinding().toInstance(rdef);
30473051
}
3048-
definitions.addBinding().toInstance(rdef);
30493052
} else if (it instanceof WebSocket.Definition) {
30503053
sockets.addBinding().toInstance((WebSocket.Definition) it);
30513054
} else if (it instanceof Parser) {

jooby/src/main/java/org/jooby/Route.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1965,13 +1965,25 @@ default void handle(final Request req, final Response rsp, final Route.Chain cha
19651965

19661966
/**
19671967
* A handler for a MVC route, it extends {@link Handler} by adding a reference to the method
1968-
* behind this route.
1968+
* and class behind this route.
19691969
*
19701970
* @author edgar
19711971
* @since 0.6.2
19721972
*/
19731973
interface MethodHandler extends Handler {
1974+
/**
1975+
* Target method.
1976+
*
1977+
* @return Target method.
1978+
*/
19741979
Method method();
1980+
1981+
/**
1982+
* Target class.
1983+
*
1984+
* @return Target class.
1985+
*/
1986+
Class<?> implementingClass();
19751987
}
19761988

19771989
/**

jooby/src/main/java/org/jooby/internal/mvc/MvcHandler.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,27 @@
215215
import org.jooby.Status;
216216

217217
import com.google.common.base.Throwables;
218+
import org.jooby.funzy.Try;
218219

219220
public class MvcHandler implements Route.MethodHandler {
220221

221222
private Method handler;
222223

224+
private Class<?> implementingClass;
225+
223226
private RequestParamProvider provider;
224227

225-
public MvcHandler(final Method handler, final RequestParamProvider provider) {
228+
/**
229+
* Constructor for MvcHandler.
230+
*
231+
* @param handler the method to handle the request
232+
* @param implementingClass Target class (method owner).
233+
* @param provider the request parameter provider
234+
*/
235+
public MvcHandler(final Method handler, final Class<?> implementingClass,
236+
final RequestParamProvider provider) {
226237
this.handler = requireNonNull(handler, "Handler method is required.");
238+
this.implementingClass = requireNonNull(implementingClass, "Implementing class is required.");
227239
this.provider = requireNonNull(provider, "Param prodiver is required.");
228240
}
229241

@@ -232,6 +244,10 @@ public Method method() {
232244
return handler;
233245
}
234246

247+
public Class<?> implementingClass() {
248+
return implementingClass;
249+
}
250+
235251
@Override
236252
public void handle(final Request req, final Response rsp) throws Throwable {
237253

@@ -247,9 +263,9 @@ public void handle(final Request req, final Response rsp) throws Throwable {
247263
rsp.send(result);
248264
}
249265

250-
public Object invoke(final Request req, final Response rsp) throws Throwable {
251-
try {
252-
Object target = req.require(handler.getDeclaringClass());
266+
public Object invoke(final Request req, final Response rsp) {
267+
return Try.apply(() -> {
268+
Object target = req.require(implementingClass);
253269

254270
List<RequestParam> parameters = provider.parameters(handler);
255271
Object[] args = new Object[parameters.size()];
@@ -260,10 +276,7 @@ public Object invoke(final Request req, final Response rsp) throws Throwable {
260276
final Object result = handler.invoke(target, args);
261277

262278
return result;
263-
} catch (InvocationTargetException ex) {
264-
Throwable cause = ex.getCause();
265-
Throwables.propagateIfInstanceOf(cause, Exception.class);
266-
throw Throwables.propagate(cause);
267-
}
279+
}).unwrap(InvocationTargetException.class)
280+
.get();
268281
}
269282
}

jooby/src/main/java/org/jooby/internal/mvc/MvcRoutes.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ public class MvcRoutes {
244244

245245
private static final String[] EMPTY = new String[0];
246246

247-
@SuppressWarnings("unchecked")
248247
private static final Set<Class<? extends Annotation>> VERBS = ImmutableSet.of(GET.class,
249248
POST.class, PUT.class, DELETE.class, PATCH.class, HEAD.class, OPTIONS.class, TRACE.class,
250249
CONNECT.class);
@@ -312,11 +311,11 @@ public static List<Route.Definition> routes(final Env env, final RouteMetadata c
312311
String[] excludes = excludes(method, rootExcludes);
313312

314313
Definition definition = new Route.Definition(
315-
verb.getSimpleName(), rpath + "/" + path, new MvcHandler(method, paramProvider))
314+
verb.getSimpleName(), rpath + "/" + path, new MvcHandler(method, routeClass, paramProvider))
316315
.produces(produces)
317316
.consumes(consumes)
318317
.excludes(excludes)
319-
.declaringClass(method.getDeclaringClass().getName())
318+
.declaringClass(routeClass.getName())
320319
.line(classInfo.startAt(method) - 1)
321320
.name(name);
322321

jooby/src/test/java/org/jooby/internal/mvc/MvcHandlerTest.java

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ public class MvcHandlerTest {
2222

2323
@Test
2424
public void defaults() throws Exception {
25-
new MockUnit(Method.class, RequestParamProvider.class)
25+
new MockUnit(Method.class, Object.class, RequestParamProvider.class)
2626
.run(unit -> {
27-
new MvcHandler(unit.get(Method.class), unit.get(RequestParamProvider.class));
27+
new MvcHandler(unit.get(Method.class), unit.get(Object.class).getClass(), unit.get(RequestParamProvider.class));
2828
});
2929
}
3030

@@ -50,7 +50,35 @@ public void handle() throws Exception {
5050
expect(paramProvider.parameters(method)).andReturn(params);
5151
})
5252
.run(unit -> {
53-
new MvcHandler(method, unit.get(RequestParamProvider.class))
53+
new MvcHandler(method, handlerClass, unit.get(RequestParamProvider.class))
54+
.handle(unit.get(Request.class), unit.get(Response.class));
55+
});
56+
}
57+
58+
@SuppressWarnings({"rawtypes", "unchecked" })
59+
@Test
60+
public void handleAbstractHandlers() throws Exception {
61+
Class handlerClass = FinalMvcHandler.class;
62+
Class abstractHandlerClass = AbstractMvcHandler.class;
63+
FinalMvcHandler handler = new FinalMvcHandler();
64+
Method method = abstractHandlerClass.getDeclaredMethod("abstrStrHandle");
65+
new MockUnit(RequestParamProvider.class, Request.class, Response.class)
66+
.expect(unit -> {
67+
Request req = unit.get(Request.class);
68+
expect(req.require(FinalMvcHandler.class)).andReturn(handler);
69+
})
70+
.expect(unit -> {
71+
Response rsp = unit.get(Response.class);
72+
expect(rsp.status(Status.OK)).andReturn(rsp);
73+
rsp.send("abstrStrHandle");
74+
})
75+
.expect(unit -> {
76+
List<RequestParam> params = Collections.emptyList();
77+
RequestParamProvider paramProvider = unit.get(RequestParamProvider.class);
78+
expect(paramProvider.parameters(method)).andReturn(params);
79+
})
80+
.run(unit -> {
81+
new MvcHandler(method, handlerClass, unit.get(RequestParamProvider.class))
5482
.handle(unit.get(Request.class), unit.get(Response.class));
5583
});
5684
}
@@ -72,7 +100,7 @@ public void handleException() throws Exception {
72100
expect(paramProvider.parameters(method)).andReturn(params);
73101
})
74102
.run(unit -> {
75-
new MvcHandler(method, unit.get(RequestParamProvider.class))
103+
new MvcHandler(method, handlerClass, unit.get(RequestParamProvider.class))
76104
.handle(unit.get(Request.class), unit.get(Response.class));
77105
});
78106
}
@@ -94,7 +122,7 @@ public void throwableException() throws Exception {
94122
expect(paramProvider.parameters(method)).andReturn(params);
95123
})
96124
.run(unit -> {
97-
new MvcHandler(method, unit.get(RequestParamProvider.class))
125+
new MvcHandler(method, handlerClass, unit.get(RequestParamProvider.class))
98126
.handle(unit.get(Request.class), unit.get(Response.class));
99127
});
100128
}
@@ -110,5 +138,15 @@ public String errhandle() throws Exception {
110138
public String throwablehandle() throws Throwable {
111139
throw new Throwable("intentional err");
112140
}
141+
}
142+
143+
abstract class AbstractMvcHandler {
144+
public abstract String abstrStrHandle() throws Exception;
145+
146+
}
113147

148+
final class FinalMvcHandler extends AbstractMvcHandler {
149+
public String abstrStrHandle() throws Exception {
150+
return "abstrStrHandle";
151+
}
114152
}

0 commit comments

Comments
 (0)