=== Router

The javadoc:Router[] is the heart of Jooby and consists of:

* A routing algorithm (radix tree)
* One or more javadoc:Route[text="routes"]
* A collection of operators over javadoc:Route[text="routes"]

==== Route

A javadoc:Route[] consists of three parts:

.Routes:
[source, java, role="primary"]
----
{
 // <1> <2>
  get("/foo", ctx -> {
    return "foo"; // <3>
  });

  // Get example with path variable
  get("/foo/{id}", ctx -> {
    return ctx.path("id").value();
  });
  
  // Post example
  post("/", ctx -> {
    return ctx.body().value();
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{ 
 // <1> <2>
  get("/foo") {
    "foo" // <3>
  }

  // Get example with path variable
  get("/foo/{id}") {
    ctx.path("id").value()
  }
  
  // Post example
  post("/") {
    ctx.body().value()
  }
}
----

<1> HTTP method/verb (e.g., `GET`, `POST`)
<2> Path pattern (e.g., `/foo`, `/foo/{id}`)
<3> Handler function

The javadoc:Route.Handler[text="handler"] function always produces a result, which is sent back to the client.

===== Attributes

Attributes allow you to annotate a route at application bootstrap time. They function as static metadata available at runtime:

.Java
[source, java, role="primary"]
----
{
  get("/foo", ctx -> "Foo")
    .setAttribute("foo", "bar");
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/foo") {
    "Foo"
  }.setAttribute("foo", "bar")
}
----

An attribute consists of a name and a value. Values can be any object. Attributes can be accessed during the request/response cycle. For example, a security module might check for a role attribute.

.Java
[source, java, role="primary"]
----
{
  use(next -> ctx -> {
    User user = ...;
    String role = ctx.getRoute().getAttribute("Role"); 
    
    if (user.hasRole(role)) {
        return next.apply(ctx);
    }      
    
    throw new StatusCodeException(StatusCode.FORBIDDEN);                              
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  use {
    val user = ...
    val role = ctx.route.getAttribute("Role")

    if (user.hasRole(role)) {
      next.apply(ctx)
    } else {      
      throw StatusCodeException(StatusCode.FORBIDDEN)
    }
  }
}
----

In MVC routes, you can set attributes via annotations:

.Java
[source, java, role="primary"]
----
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
  String value();
}

@Path("/path")
public class AdminResource {

  @Role("admin")
  public Object doSomething() {
    ...
  }

}

{
  use(next -> ctx -> {
    System.out.println(ctx.getRoute().getAttribute("Role"));
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Role (val value: String)

@Path("/path")
class AdminResource {

  @Role("admin")
  fun doSomething() : Any {
    ...
  }

}

{
  use {
    println(ctx.route.getAttribute("Role"))
  }
}
----

The previous example prints `admin`. You can retrieve all attributes of a route by calling `ctx.getRoute().getAttributes()`.

Any runtime annotation is automatically added as a route attribute following these rules:

* If the annotation has a `value` method, the annotation’s name becomes the attribute name.
* Otherwise, the method name is used as the attribute name.

==== Path Pattern

===== Static

.Java
[source, java, role="primary"]
----
{
  get("/foo", ctx -> "Foo");
}
----

.Koltin
[source, kotlin, role="secondary"]
----
{
  get("/foo") { "Foo" }
}
----

===== Variable

.Single path variable:
[source, java, role="primary"]
----
{
  // <1>
  get("/user/{id}", ctx -> {
    int id = ctx.path("id").intValue(); // <2>
    return id;
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  // <1>
  get("/user/{id}") {
    val id = ctx.path("id").intValue() // <2>
    id
  }
}
----

<1> Defines a path variable `id`.
<2> Retrieves the variable `id` as an `int`.

.Multiple path variables:
[source, java,role="primary"]
----
{
  // <1>
  get("/file/{file}.{ext}", ctx -> {
    String filename = ctx.path("file").value(); // <2>
    String ext = ctx.path("ext").value();   // <3>
    return filename + "." + ext;
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  // <1>
  get("/file/{file}.{ext}") {
    val filename = ctx.path("file").value() // <2>
    val ext = ctx.path("ext").value()       // <3>
    filename + "." + ext
  }
}
----

<1> Defines two path variables: `file` and `ext`.
<2> Retrieves the string variable `file`.
<3> Retrieves the string variable `ext`.

.Optional path variable:
[source, java, role="primary"]
----
{
  // <1>
  get("/profile/{id}?", ctx -> {
    String id = ctx.path("id").value("self"); // <2>
    return id;
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  // <1>
  get("/profile/{id}?") {
    val id = ctx.path("id").value("self") // <2>
    id
  }
}
----

<1> Defines an optional path variable `id`. The trailing `?` makes it optional.
<2> Retrieves the variable `id` as a `String` if present, or uses the default value: `self`.

The trailing `?` makes the path variable optional. The route matches both:

* `/profile`
* `/profile/eespina`

===== Regex

.Regex path variable:
[source, java, role="primary"]
----
{
  // <1>
  get("/user/{id:[0-9]+}", ctx -> {
    int id = ctx.path("id").intValue(); // <2>
    return id;
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  // <1>
  get("/user/{id:[0-9]+}") {
    val id = ctx.path("id").intValue() // <2>
    id
  }
}`
----

<1> Defines a path variable `id`. The regex expression is everything after the first `:` (e.g., `[0-9]+`).
<2> Retrieves the `int` value.

The optional syntax is also supported for regex path variables (e.g., `/user/{id:[0-9]+}?`). This matches:

* `/user`
* `/user/123`

===== * Catchall

.Catchall:
[source, java, role="primary"]
----
{
  // <1>
  get("/articles/*", ctx -> {
    String catchall = ctx.path("*").value(); // <2>
    return catchall;
  });
  
  get("/articles/*path", ctx -> {
    String path = ctx.path("path").value(); // <3>
    return path;
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  // <1>
  get("/articles/*") {
    val catchall = ctx.path("*").value() // <2>
    catchall
  }
  
  get("/articles/*path") {
    val path = ctx.path("path").value()  // <3>
    path
  }
}
----

<1> The trailing `*` defines a `catchall` pattern.
<2> We access the `catchall` value using the `*` character.
<3> In this example, we named the `catchall` pattern and access it using the `path` variable name.

[NOTE]
====
A `catchall` pattern must be defined at the end of the path pattern.
====

==== Handler

Application logic belongs inside a javadoc:Route.Handler[text=handler]. A javadoc:Route.Handler[text=handler] is a function that accepts a javadoc:Context[text=context] object and produces a result.

A javadoc:Context[text=context] allows you to interact with the HTTP request and manipulate the HTTP response.

[NOTE]
====
An incoming request matches exactly **ONE** route handler. If no handler matches, it produces a `404` response.
====

.Java
[source,java,role="primary"]
----
{
  get("/user/{id}", ctx -> ctx.path("id").value());  // <1>
  
  get("/user/me", ctx -> "my profile");              // <2>
  
  get("/users", ctx -> "users");                     // <3>
  
  get("/users", ctx -> "new users");                 // <4>
}
---- 

.Kotlin
[source,kotlin,role="secondary"]
----
{
  get("/user/{id}") { ctx.path("id").value() }  // <1>
  
  get("/user/me") { "my profile" }              // <2>
  
  get("/users") { "users" }                     // <3>
  
  get("/users") { "new users" }                 // <4>
}
----

Output:

<1> `GET /user/ppicapiedra` => `ppicapiedra`
<2> `GET /user/me` => `my profile`
<3> Unreachable => overridden by the next route.
<4> `GET /users` => `new users` (not `users`).

Routes with a more specific path pattern (`2` vs `1`) have higher precedence. Also, if multiple routes share the same path pattern (like `3` and `4`), the last registered route overrides the previous ones.

===== Filter

Cross-cutting concerns such as response modification, verification, security, and tracing are available via javadoc:Route.Filter[].

A `filter` takes the `next` handler in the pipeline and produces a `new` handler:

[source,java]
----
interface Filter {
  Handler apply(Handler next);
}
----

.Timing filter example:
[source,java,role="primary"]
----
{
  use(next -> ctx -> {
    long start = System.currentTimeMillis();       // <1>

    Object response = next.apply(ctx);             // <2>

    long end = System.currentTimeMillis();
    long took = end - start;

    System.out.println("Took: " + took + "ms");   // <3>

    return response;                              // <4>
  });
  
  get("/", ctx -> {
    return "filter";
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  /** Kotlin uses implicit variables: `ctx` and `next` */
  use {
    val start = System.currentTimeMillis()  // <1>

    val response = next.apply(ctx)          // <2>

    val end = System.currentTimeMillis()
    val took = end - start

    println("Took: " + took + "ms")         // <3>

    response                                // <4>
  }
  
  get("/") {
    "filter"
  }
}
----

<1> Saves the start time.
<2> Proceeds with execution (the pipeline).
<3> Computes and prints latency.
<4> Returns a response.

[NOTE]
====
One or more filters applied on top of a handler produce a new handler.
====

===== Before

The javadoc:Route.Before[text=before] filter runs before a `handler`.

A `before` filter takes a `context` as an argument and does not produce a response. It is expected to operate via side effects (usually modifying the HTTP request/response).

[source,java]
----
interface Before {
  void apply(Context ctx);
}
----

.Example
[source,java,role="primary"]
----
{
  before(ctx -> {
    ctx.setResponseHeader("Server", "Jooby");
  });

  get("/", ctx -> {
    return "...";
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  before {
    ctx.setResponseHeader("Server", "Jooby")
  }

  get("/") {
    "..."
  }
}
----

===== After

The javadoc:Route.After[text=after] filter runs after a `handler`.

An `after` filter takes three arguments. The first is the `HTTP context`, the second is the result from a **functional handler** (or `null` for a **side-effect** handler), and the third is any exception generated by the handler.

It is expected to operate via side effects, usually modifying the HTTP response (if possible) or cleaning up/tracing execution.

[source,java]
----
interface After {
  void apply(Context ctx, Object result, Throwable failure);
}
----

.Functional Handler:
[source,java,role="primary"]
----
{
  after((ctx, result, failure) -> {
    System.out.println(result);          // <1>
    ctx.setResponseHeader("foo", "bar"); // <2>
  });

  get("/", ctx -> {
    return "Jooby";
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  after {
    println("Hello $result")             // <1>
    ctx.setResponseHeader("foo", "bar")  // <2>
  }

  get("/") {
    "Jooby"
  }
}
----

<1> Prints `Jooby`.
<2> Adds a response header (modifies the HTTP response).

If the target handler is a **functional** handler, modifying the HTTP response is allowed.

For **side-effect** handlers, the after filter is invoked with a `null` result and is not allowed to modify the HTTP response.

.Side-Effect Handler:
[source,java,role="primary"]
----
{
  after((ctx, result, failure) -> {
    System.out.println(result);          // <1>
    ctx.setResponseHeader("foo", "bar"); // <2>
  });

  get("/", ctx -> {
    return ctx.send("Jooby");
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  after {
    println("Hello $result")             // <1>
    ctx.setResponseHeader("foo", "bar")  // <2>
  }

  get("/") {
    ctx.send("Jooby")
  }
}
----

<1> Prints `null` (no value).
<2> Produces an error/exception.

An exception occurs here because the response was already started, and it is impossible to alter it. Side-effect handlers are those that use the `send` methods, `responseOutputStream`, or `responseWriter`.

You can check whether you can modify the response by checking the state of javadoc:Context[isResponseStarted]:

.Safe After:
[source,java,role="primary"]
----
{
  after((ctx, result, failure) -> {
    if (ctx.isResponseStarted()) {
      // Do not modify response
    } else {
      // Safe to modify response
    }
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  after {
    if (ctx.isResponseStarted) {
      // Do not modify response
    } else {
      // Safe to modify response
    }
  }
}
----

[NOTE]
====
An `after` handler is always invoked.
====

The next examples demonstrate some use cases for dealing with errored responses. Keep in mind that an `after` handler is not a mechanism for handling and reporting exceptions; that is the task of an <<core-error-handler, Error Handler>>.

.Run code depending on success or failure responses:
[source,java,role="primary"]
----
{
  after((ctx, result, failure) -> {
    if (failure == null) {
      db.commit();                   // <1>
    } else {
      db.rollback();                 // <2>
    }
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  after {
    if (failure == null) {
      db.commit()                    // <1>
    } else {
      db.rollback()                  // <2>
    }
  }
}
----

Here, the exception is still propagated, giving the <<core-error-handler, Error Handler>> a chance to jump in.

.Recover from an exception and produce an alternative output:
[source,java,role="primary"]
----
{
  after((ctx, result, failure) -> {
    if (failure instanceof MyBusinessException) {
      ctx.send("Recovering from something");        // <1>
    }
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  after {
    if (failure is MyBusinessException) {
      ctx.send("Recovering from something")         // <1>
    }
  }
}
----

<1> Recovers and produces an alternative output.

Here, the exception won't be propagated because we produce a response, meaning the error handler will not execute.

If the `after` handler produces a new exception, that exception will be added to the original exception as a suppressed exception.

.Suppressed exceptions:
[source,java,role="primary"]
----
{
  after((ctx, result, failure) -> {
    // ...
    throw new AnotherException();
  });

  get("/", ctx -> {
    // ...
    throw new OriginalException();
  });

  error((ctx, failure, code) -> {
    Throwable originalException = failure;                       // <1>
    Throwable anotherException  = failure.getSuppressed()[0];    // <2>
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  after {
    // ...
    throw AnotherException()
  }

  get("/") { ctx ->
    // ...
    throw OriginalException()
  }

  error { ctx, failure, code ->
    val originalException = failure                              // <1>
    val anotherException  = failure.suppressed[0]                // <2>
  }
}
----

<1> Will be `OriginalException`.
<2> Will be `AnotherException`.

===== Complete

The javadoc:Route.Complete[text=complete] listener runs at the completion of a request/response cycle (i.e., when the request has been completely read and the response fully written).

At this point, it is too late to modify the exchange. They are attached to a running context (unlike `before`/`after` filters).

.Example
[source, java, role="primary"]
----
{
   use(next -> ctx -> {
     long start = System.currentTimeMillis();
     ctx.onComplete(context -> {                      // <1>
       long end = System.currentTimeMillis();         // <2>
       System.out.println("Took: " + (end - start));
     });
     return next.apply(ctx);
   });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
   use {
     val start = System.currentTimeMillis()
     ctx.onComplete {                                 // <1>
       val end = System.currentTimeMillis()           // <2>
       println("Took: " + (end - start))
     }
     next.apply(ctx)
   }
}
----

<1> Attaches a completion listener.
<2> Runs after the response has been fully written.

Completion listeners are invoked in reverse order.

==== Pipeline

The route pipeline (a.k.a. route stack) is a composition of one or more `use` statements tied to a single `handler`:

.Java
[source, java, role="primary"]
----
{
  // Increment +1
  use(next -> ctx -> {
    Number n = (Number) next.apply(ctx);
    return 1 + n.intValue();
  });

  // Increment +1
  use(next -> ctx -> {
    Number n = (Number) next.apply(ctx);
    return 1 + n.intValue();
  });
  
  get("/1", ctx -> 1); // <1>
  
  get("/2", ctx -> 2); // <2>
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  // Increment +1
  use {
    val n = next.apply(ctx) as Int
    1 + n
  }

  // Increment +1
  use {
    val n = next.apply(ctx) as Int
    1 + n
  }
  
  get("/1") { 1 } // <1>
  
  get("/2") { 2 } // <2>
}
----

Output:

<1> `/1` => `3`
<2> `/2` => `4`

Behind the scenes, Jooby builds something like this:

[source, java]
----
{
  // Increment +1
  var increment = use(next -> ctx -> {
    Number n = (Number) next.apply(ctx);
    return 1 + n.intValue();
  });

  Handler one = ctx -> 1;
  
  Handler two = ctx -> 2;
  
  Handler handler1 = increment.then(increment).then(one);
  Handler handler2 = increment.then(increment).then(two);
  
  get("/1", handler1);
  
  get("/2", handler2);
}
----

Any `filter` defined on top of the handler will be chained into a new handler.

[NOTE]
.Filter without path pattern
====
This was a hard decision, but it is the right one. Jooby 1.x used a path pattern to define a `filter`.

In Jooby 1.x, the `pipeline` consisted of multiple filters and handlers matched sequentially. The following `filter` was always executed:

.Jooby 1.x
[source, java]
----
{
   use("/*", (req, rsp, chain) -> {
     // remote call, db call 
   });

   // ...
}
----

If a bot tried to access missing pages (causing `404`s), Jooby 1.x executed the filter for every single request before realizing there was no matching route.

In Jooby 2.x+, this no longer happens. The `pipeline` is only executed if there is a matching handler. Otherwise, nothing is executed!
====

===== Order

Order follows a **what you see is what you get** approach. Routes are stacked in the order they are defined.

.Order example:
[source, java, role="primary"]
----
{
  // Increment +1
  use(next -> ctx -> {
    Number n = (Number) next.apply(ctx);
    return 1 + n.intValue();
  });

  get("/1", ctx -> 1);                // <1>
  
  // Increment +1
  use(next -> ctx -> {
    Number n = (Number) next.apply(ctx);
    return 1 + n.intValue();
  });

  get("/2", ctx -> 2);               // <2>
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  // Increment +1
  use {
    val n = next.apply(ctx) as Int
    1 + n
  }

  get("/1") { 1 }                // <1>
  
  // Increment +1
  use {
    val n = next.apply(ctx) as Int
    1 + n
  }

  get("/2") { 2 }                // <2>
}
----

Output:

<1> `/1` => `2`
<2> `/2` => `4`

===== Scoped Filter

The javadoc:Router[routes, java.lang.Runnable] and javadoc:Router[path, java.lang.String, java.lang.Runnable] operators group one or more routes.

A `scoped filter` looks like this:

.Scoped filter:
[source, java, role="primary"]
----
{
  // Increment +1
  use(next -> ctx -> {
    Number n = (Number) next.apply(ctx);
    return 1 + n.intValue();
  });

  routes(() -> {                          // <1>
    // Multiply by 2
    use(next -> ctx -> {
      Number n = (Number) next.apply(ctx);
      return 2 * n.intValue();
    });
    
    get("/4", ctx -> 4);                 // <2>
  });
  
  get("/1", ctx -> 1);                   // <3>
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  // Increment +1
  use {
    val n = next.apply(ctx) as Int
    return 1 + n
  }

  routes {                                // <1>
    // Multiply by 2
    use {
      val n = next.apply(ctx) as Int
      2 * n
    }
    
    get("/4") { 4 }               // <2>
  }
  
  get("/1") { 1 }                 // <3>
}
----

Output:

<1> Introduces a new scope via the `routes` operator.
<2> `/4`  => `9`
<3> `/1`  => `2`

It functions as a normal `filter` inside a group operator.

==== Grouping Routes

As shown previously, the javadoc:Router[routes, java.lang.Runnable] operator pushes a new route `scope` and allows you to selectively apply logic to one or more routes.

.Route operator
[source,java,role="primary"]
----
{
  routes(() -> {   
    get("/", ctx -> "Hello");
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  routes {
    get("/") {
      "Hello"
    }
  }
}
----

The `routes` operator is for grouping routes and applying cross-cutting concerns to all of them.

Similarly, the javadoc:Router[path, java.lang.String, java.lang.Runnable] operator groups routes under a common path pattern.

.Routes with path prefix:
[source,java,role="primary"]
----
{
   path("/api/user", () -> {    // <1>
     get("/{id}", ctx -> ...);  // <2>
     get("/", ctx -> ...);      // <3>
     post("/", ctx -> ...);     // <4>
     // ...
   }); 
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
   path("/api/user") {     // <1>
     get("/{id}") { ...}   // <2>
     get("/") { ...}       // <3>
     post("/") { ...}      // <4>
     // ...
   }); 
}
----

<1> Sets the common prefix `/api/user`.
<2> `GET /api/user/{id}`
<3> `GET /api/user`
<4> `POST /api/user`

==== Composing

===== Mount

Composition is a technique for building modular applications. You can compose one or more routers into a new one using the javadoc:Router[mount, io.jooby.Router] operator:

.Composing
[source, java, role="primary"]
----
public class Foo extends Jooby {
  {
    get("/foo", Context::getRequestPath);
  }
}

public class Bar extends Jooby {
  {
    get("/bar", Context::getRequestPath);
  }
}

public class App extends Jooby {
  {
    mount(new Foo());                       // <1>
    mount(new Bar());                       // <2>
    get("/app", Context::getRequestPath);   // <3>
  }
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
class Foo: Kooby({
  get("/foo") { ctx.getRequestPath() }
})

class Bar: Kooby({
  get("/bar") { ctx.getRequestPath() }
})

class App: Kooby({
  mount(Foo())                         // <1>
  mount(Bar())                         // <2>
  get("/app") { ctx.getRequestPath() } // <3>
})
----

<1> Imports all routes from `Foo`. Output: `/foo` => `/foo`
<2> Imports all routes from `Bar`. Output: `/bar` => `/bar`
<3> Adds more routes. Output: `/app` => `/app`

.Composing with path prefix
[source,java,role="primary"]
----
public class Foo extends Jooby {
  {
    get("/foo", Context::getRequestPath);
  }
}

public class App extends Jooby {
  {
    mount("/prefix", new Foo());  // <1>
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
class Foo: Kooby({
  get("/foo") { ctx.getRequestPath() }
})

class App: Kooby({
  mount("/prefix", Foo())  // <1>
})
----

<1> Now all routes from `Foo` will be prefixed with `/prefix`. Output: `/prefix/foo` => `/prefix/foo`

The `mount` operator only imports routes. Services and callbacks are not imported. The main application is responsible for assembling all resources and services required by the imported applications.

===== Install

Alternatively, you can install a standalone application into another one using the javadoc:Jooby[install, io.jooby.SneakyThrows.Supplier] operator:

.Installing
[source, java, role="primary"]
----
public class Foo extends Jooby {
  {
    get("/foo", ctx -> ...);
  }
}

public class Bar extends Jooby {
  {
    get("/bar", ctx -> ...);
  }
}

public class App extends Jooby {
  {
    install(Foo::new);                       // <1>
    install(Bar::new);                       // <2>
  }
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
class Foo: Kooby({
  get("/foo") { ... }
})

class Bar: Kooby({
  get("/bar") { ... }
})

class App: Kooby({
  install(::Foo)                         // <1>
  install(::Bar)                         // <2>
})
----

<1> Imports all routes, services, callbacks, etc. from `Foo`. Output: `/foo` => `/foo`
<2> Imports all routes, services, callbacks, etc. from `Bar`. Output: `/bar` => `/bar`

This operator lets you, for example, deploy `Foo` as a standalone application or integrate it into a main application.

The `install` operator shares the state of the main application, so lazy initialization (and therefore _instantiation_) of any child applications is **mandatory**.

For example, this won't work:

.Java
[source, java]
----
{
  Foo foo = new Foo();
  install(() -> foo);        // Won't work
}
----

The `Foo` application must be lazily initialized:

.Java
[source, java]
----
{
  install(() -> new Foo());  // Works!
}
----

==== Dynamic Routing

Dynamic routing looks similar to <<core-router-composing, composition>> but enables/disables routes at runtime using a `predicate`.

Suppose you own two versions of an `API` and need to support both the `old` and `new` versions concurrently based on a header:

.Dynamic Routing
[source,java,role="primary"]
----
public class V1 extends Jooby {
  {
    get("/api", ctx -> "v1");
  }
}

public class V2 extends Jooby {
  {
    get("/api", ctx -> "v2");
  }
}

public class App extends Jooby {
  {
    mount(ctx -> ctx.header("version").value().equals("v1"), new V1()); // <1>
    mount(ctx -> ctx.header("version").value().equals("v2"), new V2()); // <2>
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
class V1: Kooby({
  get("/api") { "v1" }
})

class V2: Kooby({
  get("/api") { "v2" }
})

class App: Kooby({
  mount(ctx -> ctx.header("version").value().equals("v1"), V1()); // <1>
  mount(ctx -> ctx.header("version").value().equals("v2"), V2()); // <2>
})
----

Output:

<1> `/api` => `v1`; when `version` header is `v1`
<2> `/api` => `v2`; when `version` header is `v2`

Done! {love}

==== Multiple Routers

This model lets you run multiple applications on a single server instance. Each application works like a standalone application; they do not share any services.

.Multiple routers
[source, java,role="primary"]
----
public class Foo extends Jooby {
  {
    setContextPath("/foo");
    get("/hello", ctx -> ...);
  }
}

public class Bar extends Jooby {
  {
    setContextPath("/bar");
    get("/hello", ctx -> ...);
  }
}

import static io.jooby.Jooby.runApp;

public class MultiApp {
  public static void main(String[] args) {
    runApp(args, List.of(Foo::new, Bar::new));
  }
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
import io.jooby.kt.Kooby.runApp

fun main(args: Array<String>) {
  runApp(args, ::Foo, ::Bar)
}
----

You write your application as usual and then deploy them using the `runApp` method.

[IMPORTANT]
====
Due to the nature of logging frameworks (static loading and initialization), logging bootstrap might not work as expected. It is recommended to just use the `logback.xml` or `log4j2.xml` file.
====

==== Options

include::router-options.adoc[]

include::router-hidden-method.adoc[]
