Mvc routes are similar to controllers in Spring and resources in Jersey with some minor enhancements and simplifications.
@Path("/")
public class MyRoutes {
@GET
public Result home() {
return Results.html("home").put("model", model);
}
}Annotations are identical to Jersey/JAX-RS and they can be found under the package org.jooby.mvc.
NOTE: Jooby doesn't implement the JAX-RS specification. That is why it has its own version of the annotations.
An mvc route can be injected by {{guice}}:
@Path("/")
public class MyRoutes {
@Inject
public MyRoutes(DepA a, DepB) {
...
}
@GET
public Result home() {
return Results.html("home").put("model", model);
}
@GET
@Path("/search")
public List<SearchResult> search() {
List<SearchResult> result = ...;
return result;
}
@POST
@Path("/form")
public MyObject submit(MyObject form) {
...
return Results.html("success");
}
}NOTE: MVC routes are NOT singleton, unless you explicitly annotated the route as a Singleton:
import javax.inject.Singleton;
@Singleton
@Path("/")
public class MyRoutes {
@Inject
public MyRoutes(DepA a, DepB) {
...
}
@GET
public Result home() {
return Results.html("home").put("model", model);
}
@GET
@Path("/search")
public List<SearchResult> search() {
List<SearchResult> result = ...;
return result;
}
@POST
@Path("/form")
public MyObject submit(MyObject form) {
...
return Results.html("success");
}
}Mvc routes must be registered, there is no auto-discover feature, no classpath scanning, ..., etc.
The order in which you define your routes is very important and it defines how your app will work.
This is one of the reason why mvc routes need to be explicitly registered.
The other reason is that declaring the route explicitly helps to reduce bootstrap time.
So, how do I register an mvc route?
In the same way everything else is registered in {{jooby}}, from your application class:
public class App extends Jooby {
{
use(MyRoutes.class);
}
}Again, handlers are registered in the order they are declared, so:
@Path("/routes")
public class MyRoutes {
@GET
public void first() {
log.info("first");
}
@GET
public void second() {
log.info("second");
}
@GET
public String third() {
return "third";
}
}A call to /routes will print: first, second and produces a response of third.
If you find the explicit registration odd or have too many MVC routes, checkout the classpath scanner module which automatically find and register MVC routes.
A method parameter represents a HTTP parameter:
@GET
public List<Object> search(String q) {
return searcher.doSearch(q);
}Here q can be any of the available parameter types and it will resolved as described in the request parameters section.
Optional parameters work in the same way, all you have to do is to declare them as java.util.Optional:
@GET
public List<Object> search(Optional<String> q) {
return searcher.doSearch(q.orElse("*:*"));
}Same for multi-value parameters, just declare them as java.util.List, java.util.Set or java.util.SortedSet:
@GET
public List<Object> search(List<String> q) {
return searcher.doSearch(q);
}NOTE: The injected collection is immutable.
Same for {{file_upload}}
@POST
public Object formPost(Upload file) {
...
}Jooby uses the method parameter name and binds that name to a request parameter. If you want an explicit mapping or if the request parameter isn't a valid Java identifier:
@GET
public List<Object> search(@Named("req-param") String reqParam) {
...
}A form submitted as {{formurlencoded}} or {{formmultipart}} doesn't require anything:
@POST
public Result create(MyObject form) {
...
}Annotate the method parameter with the @Body annotation:
@POST
public MyObject create(@Body MyObject object) {
... do something with my object
}Annotate the method parameter with the @Header annotation:
@GET
public List<Object> search(@Header String myHeader) {
...
}Or, if the header name isn't a valid Java identifier:
@GET
public List<Object> search(@Header("Last-Modified-Since") long lastModifedSince) {
...
}A methods return type is sent to the client. Some examples:
@GET
public String sayHi(String name) {
// OK(200)
return "Hi " + name;
}
@GET
public Result dontSayGoodbye(String name) {
// NO_CONTENT(204)
return Results.noContent();
}If you want to render a view, just return a view instance:
@GET
public Result home() {
return Results.html("home").put("model", model);
}If you need to deal with HTTP metadata like: status code, headers, etc... use a [result] as the return type:
@GET
public Result handler() {
// 201 = created
return Results.with(model, 201);
}