== MVC API

MVC API is an alternative way to define routes in Jooby. It uses annotations and byte code generation
to define and execute routes.

The package `io.jooby.annotations` contains all the annotations available for MVC routes.

.MVC API:
[source,java,role="primary"]
----
import io.jooby.annotations.*;

@Path("/mvc")                  // <1>
public class Controller {

  @GET                         // <2>
  public String sayHi() {
    return "Hello Mvc!";
  }
}

public class App extends Jooby {

  {
    mvc(new Controller());   // <3>
  }

  public static void main(String[] args) {
    runApp(args, App::new);
  }
}
----

.Kotlin
[source,kotlin,role="secondary"]
----

import io.jooby.annotations.*;

@Path("/mvc")                  // <1>
class Controller {

  @GET                         // <2>
  fun sayHi() : String {
    return "Hello Mvc!"
  }
}

fun main(args: Array<String>) {
  runApp(args) {
    mvc(MyController())        // <3>
  }
}
----

<1> Set a path pattern. The `@Path` annotation is enable at class or method level
<2> Add a HTTP method
<3> Register/install the controller in the main application

=== Getting Started

To create a new MVC project open the `jooby` console and type:

    jooby create myapp --mvc

The <<getting-started, jooby console>> takes care of all configuration steps required by the
annotation processing tool.

=== Registration

Mvc routes need to be registered (no classpath scanning). Registration is done from your application
class:

.Simple MVC route registration
[source, java, role = "primary"]
----
public class App extends Jooby {
  {
    mvc(new MyController());
  }

  public static void main(String[] args) {
    runApp(args, App::new);
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----

import io.jooby.*

fun main(args: Array<String>) {
  runApp(args) {
    mvc(MyController())
  }
}
----

The javadoc:Jooby[mvc, java.lang.Object] install the mvc route. As showed in the example there is
no dependency injection involved, you just instantiate a MVC route and register.

.Class MVC route registration
[source, java, role = "primary"]
----
public class App extends Jooby {
  {
    mvc(MyController.class);
  }

  public static void main(String[] args) {
    runApp(args, App::new);
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----

import io.jooby.*

fun main(args: Array<String>) {
  runApp(args) {
    mvc(MyController::class)
  }
}
----

The javadoc:Jooby[mvc, java.lang.Class] does the same job, but delegates route instantiation to a
dependency injection framework of your choice.

NOTE: Jooby 1.x was built around Guice, this is not the case for 2.x. The entire project was built
without dependency injection. This make DI optional and at same time give you freedom to choose the
one you like most.

.Provider MVC route registration
[source, java, role = "primary"]
----

import javax.inject.Provider;

public class App extends Jooby {
  {
    Provider<MyController> provider = ...;
  
    mvc(MyController.class, provider);
  }

  public static void main(String[] args) {
    runApp(args, App::new);
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
import javax.inject.Provider
import io.jooby.*

fun main(args: Array<String>) {
  runApp(args) {
    val provider = ...
    mvc(MyController::class, provider)
  }
}
----

The javadoc:Jooby[mvc, javax.inject.Provider] does the same job, might or might not delegate
instantiation to a dependency injection framework but most important let you control lifecycle of
MVC routes (Singleton vs Non-Singleton routes).

=== Parameters

HTTP parameter provision is available via `*Param` annotations.

==== Header

Provisioning of headers is available via javadoc:annotations.HeaderParam[] annotation:

.Headers
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@HeaderParam String token) {  // <1>
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@HeaderParam token: String) : Any {  // <1>
    ...
  }
}
----

<1> Access to HTTP header named `token`

Compared to JAX-RS the parameter name on `@*Param` annotation is completely optional, but required for
non valid Java names:


.Non valid Java name
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@HeaderParam("Last-Modified-Since") long lastModifiedSince) {
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@HeaderParam("Last-Modified-Since") lastModifiedSince: Long) : Any {
    ...
  }
}
----

==== Cookie

Provisioning of cookies is available via javadoc:annotations.CookieParam[] annotation:

.Cookies
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@CookieParam String token) {  // <1>
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@CookieParam token: String) : Any {  // <1>
    ...
  }
}
----

<1> Access to cookie named `token`

Compared to JAX-RS the parameter name on `@*Param` annotation is completely optional, but required for
non valid Java names:


.Non valid Java name
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@CookieParam("token-id") String tokenId) {
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@CookieParam("token-id") tokenId: String) : Any {
    ...
  }
}
----

==== Path

For path parameters the javadoc:annotations.PathParam[] annotation is required:

.PathParam
[source, java, role = "primary"]
----
public class MyController {

  @Path("/{id}")
  public Object provisioning(@PathParam String id) {
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @Path("/{id}")
  fun provisioning(@PathParam id: String) : Any {
    ...
  }
}
----

==== Query

For query parameters the javadoc:annotations.QueryParam[] annotation is required:

.QueryParam
[source, java, role = "primary"]
----
public class MyController {

  @Path("/")
  public Object provisioning(@QueryParam String q) {
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @Path("/")
  fun provisioning(@QueryParam q: String) : Any {
    ...
  }
}
----

==== Formdata/Multipart

For formdata/multipart parameters the javadoc:annotations.FormParam[] annotation is required:

.QueryParam
[source, java, role = "primary"]
----
public class MyController {

  @Path("/")
  @POST
  public Object provisioning(@FormParam String username) {
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @Path("/")
  @POST
  fun provisioning(@FormParam username: String) : Any {
    ...
  }
}
----

==== Body

Body parameter doesn't require an annotation:

.HTTP Body
[source, java, role = "primary"]
----
public class MyController {

  @Path("/")
  @POST
  public Object provisioning(MyObject body) {
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @Path("/")
  @POST
  fun provisioning(body: MyObject) : Any {
    ...
  }
}
----

==== Flash

Provisioning of flash attribute is available via javadoc:annotations.FlashParam[] annotation:

.Flash
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@FlashParam String success) {  // <1>
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@FlashParam success: String) : Any {  // <1>
    ...
  }
}
----

<1> Access to flash named `success`

==== Session

Provisioning of session attribute is available via javadoc:annotations.SessionParam[] annotation:

.Session Attribute
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@SessionParam String userId) {  // <1>
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@SessionParam userId: String) : Any {  // <1>
    ...
  }
}
----

<1> Access to session attribute named `userId`

Provisioning of javadoc:Session[] is available too:

.Session Attribute
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(Session session) {  // <1>
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(session: Session) : Any {  // <1>
    ...
  }
}
----

<1> If no session exists yet, new session will be created

To avoid this, just use `java.util.Optional<Session>` as type.

==== Context

Provisioning of context attributes is available via javadoc:annotations.ContextParam[] annotation:

.Context Attribute
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@ContextParam String userId) {  // <1>
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@ContextParam userId: String) : Any {  // <1>
    ...
  }
}
----

<1> Access to context attribute named `userId`

Provisioning of all javadoc:Context[getAttributes, text="attributes"] is available too:

.Context Attributes
[source, java, role = "primary"]
----
public class MyController {

  @GET
  public Object provisioning(@ContextParam Map<String, Object> attributes) {  // <1>
    ...
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
class MyController {

  @GET
  fun provisioning(@ContextParam attributes: Map<String, Object>) : Any {  // <1>
    ...
  }
}
----

<1> All context attributes must be set as arguments. They must be declared as `Map<String, Object>`

=== Responses

==== Status Code

The default status code is `Success(200)`, except for `void` methods with the `@DELETE` annotation which is set to `No Content(204)`.

There are two options if you need a different status code:

- Add a javadoc:Context[] parameter and set the javadoc:Context[setResponseCode, io.jooby.StatusCode]
- Returns a javadoc:StatusCode[] instance

==== NonBlocking

Method returning a `CompletableFuture`, `Single`, `Maybe`, `Flowable`, `Mono` or `Flux` is
considered a non-blocking route.

Kotlin suspend functions are supported too: 

.Kotlin Coroutines
[source, kotlin]
----
class SuspendMvc {
  @GET
  @Path("/delay")
  suspend fun delayed(ctx: Context): String {
    delay(100)
    return ctx.getRequestPath()
  }
}

fun main(args: Array<String>) {
  runApp(args) {
    use(SuspendMvc())
  }
}
----

A non-blocking route run on the event loop (by default) where *blocking is NOT allowed*. For more 
details please checkout the <<responses-nonblocking, non-blocking responses>> section.

=== Execution model

The MVC routes follows the execution model described in <<Execution Model>>. To run application
logic in the javadoc:ExecutionMode[EVENT_LOOP]:

.EventLoop MVC route
[source, java, role = "primary"]
----

public class App extends Jooby {
  {
    mvc(new MyController());
  }

  public static void main(String[] args) {
    runApp(args, EVENT_LOOP, App::new);  <1>
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
import io.jooby.*

fun main(args: Array<String>) {
  runApp(args, EVENT_LOOP) {             <1>
    mvc(MyController())
  }
}
----

<1> Start the application in the EVENT_LOOP execution mode

Similarly, if you need to run all mvc routes in the javadoc:ExecutionMode[WORKER] execution mode:

.Worker mode MVC route
[source, java, role = "primary"]
----

public class App extends Jooby {
  {
    dispatch(() -> {
      mvc(new MyBlockingController());  <1>
    });
  }

  public static void main(String[] args) {
    runApp(args, EVENT_LOOP, App::new);
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
import io.jooby.*

fun main(args: Array<String>) {
  runApp(args, EVENT_LOOP) {
    dispatch {
      mvc(MyBlockingController())        <1>
    }
  }
}
----

<1> Wrap the controller using the dispatch operator

One drawback with this approach is that the entire controller is now going to be executed in the worker or custom executor.
For more fine grain control use the javadoc:annotations.Dispatch[] annotation:

.Dispatch annotation
[source, java, role = "primary"]
----

public class MyController {
  @GET("/nonblocking")
  public String nonblocking() {  <1>
    return "I'm nonblocking";
  }

  @GET("/blocking")
  @Dispatch
  public String blocking() {     <2>
    return "I'm blocking";
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
import io.jooby.annotations.*

class MyController {

  @GET("/nonblocking")
  fun nonblocking() : String {   <1>
    return "I'm nonblocking";
  }

  @GET("/blocking")
  @Dispatch
  fun blocking() : String {      <2>
    return "I'm blocking";
  }
}
----

<1> MVC route run in EVENT_LOOP mode. Blocking is NOT allowed it.
<2> MVC route run in WORKER mode. Blocking is allowed it.

The javadoc:annotations.Dispatch[] annotation supports custom executor using an executor name.

.Dispatch to custom executor
[source, java, role = "primary"]
----

public class MyController {
  @GET("/blocking")
  @Dispatch("single")         <1>
  public String blocking() {
    return "I'm blocking";
  }
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
import io.jooby.annotations.*

class MyController {

  @GET("/blocking")
  @Dispatch("single")          <1>
  fun blocking() : String {
    return "I'm blocking";
  }
}
----

<1> Dispatch to an executor named it `single`

Executor must be registered using via services or executor utility method:

.Custom executor registration
[source, java, role = "primary"]
----
{
  executor("single", Executors.newSingleThreadExecutor());

  mvc(new MyController());
}
----

.Kotlin
[source, kotlin, role = "secondary"]
----
{
  executor("single", Executors.newSingleThreadExecutor())

  mvc(MyController())
}
----

The executor must be registered before the MVC route/controller.

=== JAX-RS Annotations

Alternative you can use JAX-RS annotations to define MVC routes.

.Resource
[source, java, role="primary"]
----

import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/jaxrs")
public class Resource {

  @GET
  public String getIt() {
    return "Got it!";
  }
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
import javax.ws.rs.GET
import javax.ws.rs.Path

@Path("/jaxrs")
class Resource {

  @GET
  fun getIt() : String {
    return "Got it!"
  }
}
----

Annotations work exactly like the Jooby MVC annotations, but keep in mind we don't implement the
JAX-RS specification and there is no immediate plan to do it.

The main reason to support JAX-RS annotations is to let you plug-in third-party tools that rely
on them (mostly annotations processors).
