Custom route not recognized when controller in sub-package
ipolevoy opened this issue · comments
It still fails to load the right action when using the latest 2.3-SNAPSHOT
version.
Here is my routes definition:
package app.config;
import app.controllers.api.v2.AuthorsController;
import app.controllers.api.v2.InterventionsController;
import org.javalite.activeweb.AbstractRouteConfig;
import org.javalite.activeweb.AppContext;
public class RouteConfig extends AbstractRouteConfig {
@Override
public void init(AppContext appContext) {
route("/{controller}/invoiceNumber/{invoiceNumber}").to(InterventionsController.class).action("findByInvoiceNumber");
route("/{controller}/documentNumber/{documentNumber}/states").to(InterventionsController.class).action("statesByDocumentNumber");
route("/{controller}/documentNumber/{documentNumber}/events").to(InterventionsController.class).action("eventsByDocumentNumber");
route("/{controller}/documentNumber/{documentNumber}").to(InterventionsController.class).action("findByDocumentNumber");
route("/{controller}/{aut_id}").to(AuthorsController.class).action("findById");
}
}
Here is the controller:
package app.controllers.api.v2;
...
public void findByInvoiceNumber() {
if (blank("invoiceNumber")) {
throw new RuntimeException("Invoice number is mandatory but was empty or null");
} else {
String invoiceNumber = takeFirst16digitsOf(param("invoiceNumber"));
final Intervention intervention = Intervention.findFirst("ITV_INVOICE = ?", invoiceNumber);
String jsonResponse = intervention.toJson(false);
respond(jsonResponse);
}
}
The error stack trace:
qtp437098149-24] INFO org.javalite.activeweb.RequestDispatcher - {"info":"executing controller","controller":"app.controllers.api.v2.InterventionsController","action":"invoiceNumber","method":"GET"}
[qtp437098149-24] INFO org.javalite.activejdbc.Configuration - Environment variable ACTIVE_ENV not provided, defaulting to 'development'
[qtp437098149-24] INFO org.javalite.activeweb.controller_filters.TimingFilter - Processed request in: 299 milliseconds, path: /api/v2/interventions/invoiceNumber/316838999866677400000000978000, method: GET
[qtp437098149-24] INFO org.javalite.activeweb.RequestDispatcher - {"controller":"app.controllers.api.v2.InterventionsController","duration_millis":839,"remote_ip":"0:0:0:0:0:0:0:1","method":"GET","action":"invoiceNumber","error":"java.lang.NoSuchMethodException: app.controllers.api.v2.InterventionsController.invoiceNumber(); app.controllers.api.v2.InterventionsController.invoiceNumber()","url":"http://localhost:8080/api/v2/interventions/invoiceNumber/316838999866677400000000978000","status":404}
[qtp437098149-24] INFO org.javalite.activeweb.freemarker.FreeMarkerTemplateManager - Rendering template: '/system/404.ftl' with layout: '/layouts/default_layout.ftl'.
...
Here is the snapshot of Maven dependencies:
The same error for AuthorsController
, it tries to call "action":"9"
when hitting url":"http://localhost:8080/api/v2/authors/9
It seems like the error comes from DynamicClassFactory#compileClass
method when calling compile.invoke((Object)null, args, out);
and throws the error:
Moreover, I have:
[qtp1661690256-22] ERROR org.javalite.activeweb.RequestDispatcher - ActiveWeb internal error:
java.lang.NoClassDefFoundError: org/javalite/common/JsonHelper
To reproduce the issue, I created a project here.
By the way, tools.jar
is in the right place on my Mac, OS X 10.13.6
:
/Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/lib
there is no more ned to use custom profiles as you proposed.
I found the issue. If you declare the custom route like this:
route("/api/v2/{controller}/{aut_id}").to(AuthorsController.class).action("findById");
then your calls will work just fine:
curl http://localhost:8080/api/v2/authors/9
The {controller}
segment in the custom route points to a "controller name", which is an underscored short name of the controller class. This needs to documented better.
I simplified code in controller so as not to deal with a database:
public class AuthorsController extends APIController {
public void findById() {
respond("hello: " + param("aut_id"));
}
}
and getting this response:
curl http://localhost:8080/api/v2/authors/9
hello: 9
so, this is working as expected.
You do not need to use TimingFilter
- the framework does the timing now, since 2.2. Also, register CatchAllFilter
before any other filter, so you catch and process any exceptions, including DB - related.
Great ! Thank you so much, Igor, - I updated the code source as you suggested. It works as needed now. Just one minor point (may be not related to the framework), - I'm getting the below error
no matter when using Restlet Client or Postman
not sure about that, try a different client, such as curl
:
curl http://localhost:8080/api/v2/authors/9
Yeah, it works just fine both with curl and HTTPie, thank you.
👍