Java Web MVC Framework Fork me on GitHub
About Documentation Downloads Javadocs Source FAQ Feedback

Routing

Routing, in the context of the Mojave framework, is the forwarding of a request from the front controller to its intended controller and action.

Routing is defined at the controller level. There is no routing definition file, or some other central place where routing rules are defined. In the Mojave framework, all routes have a mandatory controller and action specified as part of their path. This may sound constraining, but at the same time it also removes any ambiguity about what path maps to a particular action. It adds clarity, and simplifies the routing definition process.

The simplest example of a routing definition can be seen in the following class:

@StatelessController
public class HelloWorld {

  @Action
  public PlainText sayHello() {
    return new PlainText("Hello!");
  }
}

This controller's action method can be invoked by making a request to the following URL:

http://localhost/demo/HelloWorld/sayHello

NOTE: For all example URLs in this document, 'localhost' will refer to the host, and 'demo' is the url-pattern of the FrontController servlet. The context path is implicitly '/'.

By specifying a controller and an action, the path is automatically implied. Moreover, the path, in the example above, is case sensitive, and must match the case of the controller class name and action method name.

Optionally, to provide an alias for the controller and/or action, and as an alternative to using the class and method names, the controller and action annotations accept a String argument:

@StatelessController("main")
public class HelloWorld {

  @Action("hello")
  public PlainText sayHello() {
    return new PlainText("Hello!");
  }
}

This controller's action method can be invoked by making a request to the following URL:

http://localhost/demo/main/hello

It is common, however, especially for RESTful services, for URIs to carry more information, such as a customer ID, for example. To accomodate this, the Mojave framework provides the ParamPath annotation. Action parameters are identified by Param annotations in the action method signature. These parameters can be mapped to, and extracted from, the request path. As an example, consider the following controller:

@StatelessController
public class HelloWorld {

  @Action
  @ParamPath("to/:name")
  public PlainText sayHello(@Param("name") String name) {
    return new PlainText("Hello " + name);
  }
}

This controller's action method can be invoked by making a request to the following URL:

http://localhost/demo/HelloWorld/sayHello/to/John

The ParamPath annotation accepts an argument which should not start with a forward-slash, and defines the path which, when combined with the controller and action portions, map to the associated action method. The portions of the path which begin with a colon are treated as parameters, and their name must match a corresponding argument in the action method signature. Also, when an action method is obtaining its parameters through the request path, any matching HTTP request parameters are ignored. Therefore, matching path parameters and request parameters cannot both be used when invoking an action method.

Path parameters can also be defined with custom regular expression definitions. Take the following as an example:

@StatelessController
public class HelloWorld {

  @Action
  @ParamPath("to/:name<[a-z]+>")
  public PlainText sayHello(@Param("name") String name) {
    return new PlainText("Hello " + name);
  }
}

The value inside the angle brackets, next to ":name", is a custom regular expression definition. When no such definition exists, the regular expression [^/]+ is used by default. When a custom definition exists, it will be used to match an incoming path to the route. Thus, the following request will not match the action method above:

http://localhost/demo/HelloWorld/sayHello/to/123

It is important to note that there are exceptions to the framework routing rules described above. For instance, using default controllers and actions, and/or HTTP method action annotations, will provide alternative paths for routing. The following provides an example:

@StatelessController("customer")
public class CustomerController {

  @PUTAction
  @ParamPath("name/:name<[A-Za-z]+>/id/:id<[0-9]+>")
  public PlainText create(@Param("name") String name, @Param("id") long id) {
    return new PlainText("Created customer " + name + " with ID " + id);
  }
}

This controller's action method can be invoked by making an HTTP PUT request to the following URL:

http://localhost/demo/customer/name/John/id/123