Documentation

URL Routing

The bemoko router matches URLs and allows for actions to be bound to given actions and context expressions.

This provides great flexibility in the URLs that you wish to use and get full control on how these interactions are handled.

For example:

URLIntent Description
/buy/1234
Buy product with ID 1234
/buy/1234/red-boots
Buy product with ID 1234, but make the URL descriptive with a slug
/article/travel/world/visiting-malaysia-for-the-first-time
Display the article called "/travel/world/visiting-malaysia-for-the-first-time"

Configuring URL matching

URLs can be mapped onto bemoko intent by defining routes in the intent configuration. For example the following buy intent configuration would bind URLs like /buy/my-product-id on to the controller called shop.BuyController

<intent name="buy" controller="controller">
  <route>/buy/{productId}</route>
  <source name="controller" plugin="shop.BuyController"/>
</intent>

The value of the productId parameter would then be available on the intent in a plugin using

Bemoko.intent.productId

or within a template or context expression as

intent.productId

You can bind multiple intent parameters, e.g.

<intent name="buy" controller="controller">
  <route>/buy/{productId}/{couponId}</route>
  <source name="controller" plugin="shop.BuyController"/>
</intent>

which binds the value of couponId in the URL onto the intent parameter intent.couponId. Note that if the route URL does not end with a / then the final parameter can include / characters. If the URL does end with a / then the parameter value be all character up to this /.

For example:

URLRouteIntent ParameterValue
/buy/1234
/buy/{productId}productId1234
/buy/1234/red-boots
/buy/{productId}productId1234/red-boots
/buy/1234/red-boots
/buy/{productId}/productId1234
/buy/1234/red-boots?src=5678
/buy/{productId}/productId1234
src5678
/buy/1234/red-boots
/buy/{productId}/{slug}productId1234
slugred-boots

Defaults can be specified for a route, for example the following sets a default productId if none is provided

<route defaults="productId=1234">/buy</route>    

Binding Actions

By default bemoko will call the execute method in a controller for each request. You can however bind other methods to execute instead under given conditions using the @Action annotation

 @Action(context-expr)

where context-expr is a context expression, e.g.

  • "request.method == 'POST'"
  • "intent.action == 'my-action'"
  • "device.isMobile"

For example if you wish to fire a different method on POST you can do:

import com.bemoko.live.platform.mwc.plugins.annotations.Action

class BuyController {
  ...
  @Action("request.method == 'POST'")
  void updateBasket() {
    // updateBasket logic
  }

  void execute() {
    // default logic
  }
  ...
}

Which action method is invoked is governed by the following rules:

  • The first method in controller that matches @Action context expression will be executed.
  • No other action methods are subsequently executed
  • The execute() method executes if no @Action methods are found
  • If multiple actions have expressions that could be fire then the the action methods are sorted alphabetically, or specified by the order property on the Action annotation

If order of action method is important then you can use the order argument in the @Action annotation to specify the order of precedence.

class FilmController {
  ...
  @Action(value="request.method == 'POST' and intent.param1='value1'",order=1)
  void saveSpecialFilm() {
  }

  @Action(value="request.method == 'POST'",order=2)
  void saveFilm() {
  }

  ...
}



More