Repository: jooby-project/jooby
Pull request #3330 (2024-01-16 13:34:07)

:scroll: Fixed imports of MockRouter in docs
From `io.jooby.MockRouter` to `io.jooby.test.MockRouter`


Patch:
diff --git a/.github/workflows/full-build.yml b/.github/workflows/full-build.yml
index 2116f8a0f..374b68dac 100644
--- a/.github/workflows/full-build.yml
+++ b/.github/workflows/full-build.yml
@@ -11,7 +11,7 @@ jobs:
         jre: [17]
         os: [ubuntu-latest, windows-latest, macOS-latest]
         include:
-          - jre: 21
+          - jre: 20
             os: ubuntu-latest
 
     steps:
diff --git a/docs/asciidoc/dependency-injection.adoc b/docs/asciidoc/dependency-injection.adoc
index 93b3f01ae..719115049 100644
--- a/docs/asciidoc/dependency-injection.adoc
+++ b/docs/asciidoc/dependency-injection.adoc
@@ -1,7 +1,5 @@
 == Dependency Injection
 
-include::di-avaje.adoc[]
-
 include::di-dagger.adoc[]
 
 include::modules/guice.adoc[]
diff --git a/docs/asciidoc/di-avaje.adoc b/docs/asciidoc/di-avaje.adoc
deleted file mode 100644
index 24823604b..000000000
--- a/docs/asciidoc/di-avaje.adoc
+++ /dev/null
@@ -1,136 +0,0 @@
-=== Avaje Inject
-
-1) Add Avaje Inject to your project
-
-[dependency, groupId="io.avaje", artifactId="avaje-inject", version="9.8"]
-.
-
-2) Configure annotation processor
-
-.Maven
-[source, xml, role = "primary"]
-----
-<build>
-  <plugins>
-    <plugin>
-      <groupId>org.apache.maven.plugins</groupId>
-      <artifactId>maven-compiler-plugin</artifactId>
-      <version>...</version>
-      <configuration>
-        <annotationProcessorPaths>
-          <path>
-            <groupId>io.avaje</groupId>
-            <artifactId>avaje-inject-generator</artifactId>
-            <version>9.8</version>
-          </path>
-        </annotationProcessorPaths>
-      </configuration>
-    </plugin>
-  </plugins>
-</build>
-----
-
-.Gradle
-[source, kotlin, role = "secondary"]
-----
-plugins {
-  id "org.jetbrains.kotlin.kapt" version "1.9.10"
-}
-
-dependencies {
-  kapt 'io.avaje:avaje-inject-generator:9.8'
-}
-----
-
-3) Bootstrap Avaje from application:
-
-.Java
-[source, java, role = "primary"]
-----
-import static io.jooby.Jooby.runApp;
-
-public class App extends Jooby {
-
-  {
-     /** Avaje: */
-     BeanScope beanScope = BeanScope.builder()      <1>
-         .build();
-      
-     MyService service = beanScope.get(MyService.class);            <2>
-       
-     get("/", ctx -> {
-       return service.doSomething();
-     });
-  }
-
-  public static void main(String[] args) {
-    runApp(args, App::new);
-  }
-}
-----
-
-.Kotlin
-[source, kotlin, role = "secondary"]
-----
-import io.jooby.kt.runApp
-
-fun main(args: Array<String>) {
-  runApp(args) {
-    val beanScope = BeanScope.builder() <1>
-        .build()
-    
-    val service = beanScope.getMyService()     <2>
-      
-    get("/") {
-      service.doSomething()
-    }
-  }
-}
-----
-
-<1> Bootstrap avaje inject bean container
-<2> Use Avaje provided objects
-
-==== MVC routes
-
-Integration of MVC routes with Avaje is as simple as:
-
-.MVC and Avaje
-[source, java, role = "primary"]
-----
-
-import static io.jooby.Jooby.runApp;
-
-public class App extends Jooby {
-
-  {
-    /** Avaje: */
-    BeanScope beanScope = BeanScope.builder()  <1>
-        .build();
-    
-    mvc(beanScope.get(MyController.class));                         <2>
-  }
-
-  public static void main(String[] args) {
-    runApp(args, App::new);
-  }
-}
-----
-
-.Kotlin
-[source, kotlin, role = "secondary"]
-----
-import io.jooby.kt.runApp
-
-fun main(args: Array<String>) {
-  runApp(args) {
-    val beanScope = BeanScope.builder() <1>
-        .build()
-    
-    mvc(beanScope.get(MyController.class))                <2>
-  }
-}
-----
-
-<1> Bootstrap Avaje bean container
-<2> Register MVC route provided by Avaje
diff --git a/docs/asciidoc/di-dagger.adoc b/docs/asciidoc/di-dagger.adoc
index 0f792dee7..3ecceedbc 100644
--- a/docs/asciidoc/di-dagger.adoc
+++ b/docs/asciidoc/di-dagger.adoc
@@ -34,11 +34,11 @@
 [source, kotlin, role = "secondary"]
 ----
 plugins {
-  id "org.jetbrains.kotlin.kapt" version "1.9.10"
+  id "net.ltgt.apt" version "0.21"
 }
 
 dependencies {
-  kapt 'com.google.dagger:dagger-compiler:2.20'
+  apt 'com.google.dagger:dagger-compiler:2.20'
 }
 ----
 
@@ -89,12 +89,6 @@ fun main(args: Array<String>) {
 <1> Bootstrap dagger component
 <2> Use dagger provided objects
 
-[NOTE]
-====
-`DaggerAppComponent` in the example above is a generated source.
-Check out the https://dagger.dev/tutorial[Dagger tutorial] to learn more.
-====
-
 ==== MVC routes
 
 Integration of MVC routes with Dagger is as simple as:
diff --git a/docs/asciidoc/getting-started.adoc b/docs/asciidoc/getting-started.adoc
index 0e5f28f4f..dd1109b74 100644
--- a/docs/asciidoc/getting-started.adoc
+++ b/docs/asciidoc/getting-started.adoc
@@ -26,7 +26,7 @@ to make it globally accessible from any location.
 
 [NOTE]
 ====
-To simplify documentation we use `jooby` as command, it requires Java 17 as minimum. Windows users must use `jooby.bat`
+To simplify documentation we use `jooby` as command. Windows users must use `jooby.bat`
 ====
 
 .Setting workspace:
diff --git a/docs/asciidoc/index.adoc b/docs/asciidoc/index.adoc
index 83977c17e..74d166443 100644
--- a/docs/asciidoc/index.adoc
+++ b/docs/asciidoc/index.adoc
@@ -61,7 +61,7 @@ fun main(args: Array<String>) {
 ====
 Latest Release: https://github.com/jooby-project/jooby/releases/tag/v{joobyVersion}[{joobyVersion}].
 
-Looking for a previous version?
+Looking for previous version?
 
 * Access to link:v2[2.x] documentation. See link:/migration/3.x[migrating from 2.x to 3.x]
 * Access to link:v1[1.x] documentation.
@@ -73,16 +73,15 @@ Looking for a previous version?
 * Increase productivity with <<development-compilation-restart, Hot-Reload for development>>
 * Script/lambda routes using fluent API
 * <<mvc-api, MVC routes>> using Jooby or JAX-RS annotations
-* link:modules/openapi[OpenAPI 3] support
+* link:modules/openapi[OpenAPI 3] supports
 * <<execution-model, Event Loop and blocking execution modes>>
 * <<responses, Reactive responses>> (Completable Futures, RxJava, Reactor, SmallRye types and Kotlin Coroutines)
 * <<server, Multi-server>> including https://www.eclipse.org/jetty[Jetty], https://netty.io[Netty] and http://undertow.io[Undertow]
-* Make the jump to full-stack framework with the extension/plugin mechanism and a variety of link:modules[]
+* Jump to full-stack framework with extension/plugin mechanism and variety of link:modules[]
 
 === Script API
 
-Script API (a.k.a. script routes) provides a fluent DSL based on `lambda` functions, free of
-reflection and annotations.
+Script API (a.k.a script routes) provides a fluent DSL, reflection and annotation free based on `lambda` functions.
 
 We usually extend `Jooby` and define routes in the instance initializer:
 
@@ -120,10 +119,10 @@ fun main(args: Array<String>) {
 }
 ----
 
-For Java applications we favor extending `Jooby` because the DSL looks better (no need
-to prefix the `get` method with a variable).
+For Java applications we favor extending `Jooby` because DSL looks better (no need
+prefix the `get` method with a variable)
 
-This is not strictly necessary (of course); you may prefer to do it without extending `Jooby`:
+This is not strictly necessary (of course), you may prefer to do it without extending `Jooby`:
 
 .Script without subclass:
 [source,java,role="primary"]
@@ -156,12 +155,12 @@ fun main(args: Array<String>) {
 }
 ----
 
-For Kotlin, it doesn't matter which one you choose. The DSL looks great with or without extending
+In case of Kotlin, it doesn't matter which one you choose. DSL looks great with or without extending
 `Kooby`.
 
 === MVC API
 
-The MVC API (a.k.a. MVC routes) uses annotation to define routes and byte code generation to execute
+The MVC API (a.k.a mvc routes) uses annotation to define routes and byte code generation to execute
 them.
 
 .MVC API:
@@ -212,7 +211,7 @@ fun main(args: Array<String>) {
 }
 ----
 
-Read more about MVC and JAX-RS support in the <<mvc-api, MVC API>> chapter.
+More about MVC and JAX-RS support in the <<mvc-api, MVC API>> chapter.
 
 
 include::getting-started.adoc[]
diff --git a/docs/asciidoc/migration/3.x.adoc b/docs/asciidoc/migration/3.x.adoc
index beed7da3d..54e40ac2f 100644
--- a/docs/asciidoc/migration/3.x.adoc
+++ b/docs/asciidoc/migration/3.x.adoc
@@ -50,12 +50,10 @@ Kotlin was removed from core, you need to the `jooby-kotlin` dependency:
 |===
 |2.x|3.x|Module
 |io.jooby.annotations| io.jooby.annotation | jooby (core)
-|io.jooby | io.jooby.test | jooby-test
 |io.jooby (Kotlin)| io.jooby.kt | removed from jooby, now in jooby-kotlin
 |io.jooby.graphql| io.jooby.graphiql | jooby-graphiql
 |io.jooby.graphql| io.jooby.graphql.playground | jooby-graphql-playground
 |io.jooby.json| io.jooby.gson | jooby-gson
-|io.jooby.json| io.jooby.jackson | jooby-jackson
 |io.jooby.di| io.jooby.guice | jooby-guice
 |io.jooby.di| io.jooby.spring | jooby-spring
 |io.jooby.aws| io.jooby.awssdkv1| jooby-awssdk-v1
diff --git a/docs/asciidoc/modules/ebean.adoc b/docs/asciidoc/modules/ebean.adoc
index dde4fe5d9..84d217cea 100644
--- a/docs/asciidoc/modules/ebean.adoc
+++ b/docs/asciidoc/modules/ebean.adoc
@@ -11,7 +11,7 @@ Persistence module using Ebean: https://ebean.io
 
 2) Add database driver (mySQL here):
 
-[dependency, groupId="mysql", artifactId="mysql-connector-java", version="${mysql-connector-java.version}"]
+[dependency, artifactId="mysql-connector-j"]
 .
 
 3) Set database properties
diff --git a/docs/asciidoc/modules/flyway.adoc b/docs/asciidoc/modules/flyway.adoc
index 6a75594d6..e661add14 100644
--- a/docs/asciidoc/modules/flyway.adoc
+++ b/docs/asciidoc/modules/flyway.adoc
@@ -11,7 +11,7 @@ https://flywaydb.org[Flyway] database migrations module.
 
 2) Add database driver (mySQL here):
 
-[dependency, groupId="mysql", artifactId="mysql-connector-java", version="${mysql-connector-java.version}"]
+[dependency, artifactId="mysql-connector-j"]
 .
 
 3) Set database properties
diff --git a/docs/asciidoc/modules/hibernate.adoc b/docs/asciidoc/modules/hibernate.adoc
index 055015684..45d6f519e 100644
--- a/docs/asciidoc/modules/hibernate.adoc
+++ b/docs/asciidoc/modules/hibernate.adoc
@@ -11,7 +11,7 @@ https://hibernate.org/orm/[Hibernate ORM] module.
 
 2) Add database driver (mySQL here):
 
-[dependency, groupId="mysql", artifactId="mysql-connector-java", version="${mysql-connector-java.version}"]
+[dependency, artifactId="mysql-connector-j"]
 .
 
 3) Set database properties
diff --git a/docs/asciidoc/modules/hikari.adoc b/docs/asciidoc/modules/hikari.adoc
index b9ccd6c0a..b043c5d7d 100644
--- a/docs/asciidoc/modules/hikari.adoc
+++ b/docs/asciidoc/modules/hikari.adoc
@@ -11,7 +11,7 @@ https://github.com/brettwooldridge/HikariCP[HikariCP] is a high-performance JDBC
 
 2) Add database driver (MySQL here):
 
-[dependency, groupId="mysql", artifactId="mysql-connector-java", version="${mysql-connector-java.version}"]
+[dependency, artifactId="mysql-connector-j"]
 .
 
 3) Set database properties
diff --git a/docs/asciidoc/modules/jdbi.adoc b/docs/asciidoc/modules/jdbi.adoc
index 35680baa0..f59f737f3 100644
--- a/docs/asciidoc/modules/jdbi.adoc
+++ b/docs/asciidoc/modules/jdbi.adoc
@@ -11,7 +11,7 @@ https://github.com/jdbi/jdbi[Jdbi] module.
 
 2) Add database driver (mySQL here):
 
-[dependency, groupId="mysql", artifactId="mysql-connector-java", version="${mysql-connector-java.version}"]
+[dependency, artifactId="mysql-connector-j"]
 .
 
 3) Set database properties
diff --git a/docs/pom.xml b/docs/pom.xml
index ab808c2d9..cc1ebd5d6 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -26,7 +26,7 @@
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
-      <version>1.4.12</version>
+      <version>1.4.2</version>
     </dependency>
 
     <dependency>
diff --git a/jooby/pom.xml b/jooby/pom.xml
index 1c93471fe..ab74b7d86 100644
--- a/jooby/pom.xml
+++ b/jooby/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>jooby-project</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -99,7 +99,7 @@
     <dependency>
       <groupId>org.webjars.npm</groupId>
       <artifactId>vue</artifactId>
-      <version>3.3.11</version>
+      <version>3.3.4</version>
       <scope>test</scope>
     </dependency>
 
diff --git a/jooby/src/main/java/io/jooby/Router.java b/jooby/src/main/java/io/jooby/Router.java
index cf90cd866..457549656 100644
--- a/jooby/src/main/java/io/jooby/Router.java
+++ b/jooby/src/main/java/io/jooby/Router.java
@@ -725,17 +725,11 @@ public interface Router extends Registry {
    * @param sources additional Asset sources.
    * @return A route.
    */
-  default @NonNull Route assets(
-      @NonNull String pattern, @NonNull AssetSource source, @NonNull AssetSource... sources) {
-    AssetSource[] allSources;
-    if (sources.length == 0) {
-      allSources = new AssetSource[] {source};
-    } else {
-      allSources = new AssetSource[1 + sources.length];
-      allSources[0] = source;
-      System.arraycopy(sources, 0, allSources, 1, sources.length);
-    }
-    return assets(pattern, new AssetHandler(allSources));
+  default @NonNull Route assets(@NonNull String pattern, @NonNull AssetSource source, @NonNull AssetSource... sources) {
+    AssetSource[] array = new AssetSource[1 + sources.length];
+    array[0] = source;
+    System.arraycopy(sources, 0, array, 1, sources.length);
+    return assets(pattern, new AssetHandler(array));
   }
 
   /**
diff --git a/jooby/src/main/java/io/jooby/handler/AssetHandler.java b/jooby/src/main/java/io/jooby/handler/AssetHandler.java
index 704cad16d..19cdfe54d 100644
--- a/jooby/src/main/java/io/jooby/handler/AssetHandler.java
+++ b/jooby/src/main/java/io/jooby/handler/AssetHandler.java
@@ -10,12 +10,10 @@ import static java.util.Objects.requireNonNull;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.List;
-import java.util.Objects;
 import java.util.function.Function;
 
 import edu.umd.cs.findbugs.annotations.NonNull;
 import io.jooby.Context;
-import io.jooby.MediaType;
 import io.jooby.Route;
 import io.jooby.StatusCode;
 
@@ -40,8 +38,6 @@ public class AssetHandler implements Route.Handler {
 
   private Function<String, CacheControl> cacheControl = path -> defaults;
 
-  private Function<Asset, MediaType> mediaTypeResolver = Asset::getContentType;
-
   /**
    * Creates a new asset handler that fallback to the given fallback asset when the asset is not
    * found. Instead of produces a <code>404</code> its fallback to the given asset.
@@ -95,7 +91,7 @@ public class AssetHandler implements Route.Handler {
 
     // handle If-None-Match
     if (cacheParams.isEtag()) {
-      String ifnm = ctx.header("If-None-Match").valueOrNull();
+      String ifnm = ctx.header("If-None-Match").value((String) null);
       if (ifnm != null && ifnm.equals(asset.getEtag())) {
         ctx.send(StatusCode.NOT_MODIFIED);
         asset.close();
@@ -130,7 +126,7 @@ public class AssetHandler implements Route.Handler {
     if (length != -1) {
       ctx.setResponseLength(length);
     }
-    ctx.setResponseType(mediaTypeResolver.apply(asset));
+    ctx.setResponseType(asset.getContentType());
     return ctx.send(asset.stream());
   }
 
@@ -145,34 +141,6 @@ public class AssetHandler implements Route.Handler {
     return this;
   }
 
-  /**
-   * Allow to customize the default media type and/or the charset of it.
-   *
-   * <pre>{@code
-   * // GBK
-   * var gbk = MediaType.valueOf("text/html;charset=GBK");
-   *
-   * Function<Asset, MediaType> overrideCharset = asset -> {
-   *     var defaultType = asset.getContentType();
-   *     // Choose what is best for you
-   *     if (defaultType.matches(gbk)) {
-   *         return gbk;
-   *     }
-   *     return defaultType;
-   * };
-   * app.assets("/3267/gbk/?*", new AssetHandler(source).setMediaTypeResolver(overrideCharset));
-   *
-   * }</pre>
-   *
-   * @param mediaTypeResolver Type resolver.
-   * @return This handler.
-   */
-  public AssetHandler setMediaTypeResolver(Function<Asset, MediaType> mediaTypeResolver) {
-    this.mediaTypeResolver =
-        Objects.requireNonNull(mediaTypeResolver, "Media type resolver is required.");
-    return this;
-  }
-
   /**
    * Turn on/off handling of {@code If-Modified-Since} header.
    *
diff --git a/modules/jooby-apt/pom.xml b/modules/jooby-apt/pom.xml
index 028e5482f..3defd3171 100644
--- a/modules/jooby-apt/pom.xml
+++ b/modules/jooby-apt/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-avaje-jsonb/pom.xml b/modules/jooby-avaje-jsonb/pom.xml
index 5e4002b63..ff4dd94c5 100644
--- a/modules/jooby-avaje-jsonb/pom.xml
+++ b/modules/jooby-avaje-jsonb/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-awssdk-v1/pom.xml b/modules/jooby-awssdk-v1/pom.xml
index d6d256dbe..76826bb87 100644
--- a/modules/jooby-awssdk-v1/pom.xml
+++ b/modules/jooby-awssdk-v1/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-bom/pom.xml b/modules/jooby-bom/pom.xml
index 170d56415..1359961cc 100644
--- a/modules/jooby-bom/pom.xml
+++ b/modules/jooby-bom/pom.xml
@@ -7,13 +7,13 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <groupId>io.jooby</groupId>
   <artifactId>jooby-bom</artifactId>
   <packaging>pom</packaging>
-  <version>3.0.8-SNAPSHOT</version>
+  <version>3.0.7-SNAPSHOT</version>
   <description>Jooby (Bill of Materials)</description>
   <url>https://jooby.io</url>
 
diff --git a/modules/jooby-caffeine/pom.xml b/modules/jooby-caffeine/pom.xml
index 4b34306d3..0e42f198a 100644
--- a/modules/jooby-caffeine/pom.xml
+++ b/modules/jooby-caffeine/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-camel/pom.xml b/modules/jooby-camel/pom.xml
index d7120bc2b..b97f03061 100644
--- a/modules/jooby-camel/pom.xml
+++ b/modules/jooby-camel/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-cli/pom.xml b/modules/jooby-cli/pom.xml
index cdcad3886..a2f7e5d53 100644
--- a/modules/jooby-cli/pom.xml
+++ b/modules/jooby-cli/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
 
   <properties>
     <Module-Name>io.jooby.cli</Module-Name>
-    <jline.version>3.25.0</jline.version>
+    <jline.version>3.23.0</jline.version>
     <picocli.version>4.7.5</picocli.version>
   </properties>
 
@@ -94,7 +94,7 @@
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>properties-maven-plugin</artifactId>
-        <version>1.2.1</version>
+        <version>1.2.0</version>
         <executions>
           <execution>
             <phase>generate-resources</phase>
diff --git a/modules/jooby-commons-email/pom.xml b/modules/jooby-commons-email/pom.xml
index a6f52e65d..289fdba29 100644
--- a/modules/jooby-commons-email/pom.xml
+++ b/modules/jooby-commons-email/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-conscrypt/pom.xml b/modules/jooby-conscrypt/pom.xml
index 74712088f..e5ed84b2f 100644
--- a/modules/jooby-conscrypt/pom.xml
+++ b/modules/jooby-conscrypt/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-distribution/pom.xml b/modules/jooby-distribution/pom.xml
index a25cec371..9c4fc4c45 100644
--- a/modules/jooby-distribution/pom.xml
+++ b/modules/jooby-distribution/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-ebean/pom.xml b/modules/jooby-ebean/pom.xml
index 35e300345..ce98d8976 100644
--- a/modules/jooby-ebean/pom.xml
+++ b/modules/jooby-ebean/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -38,5 +38,12 @@
       <classifier>runtime</classifier>
       <scope>test</scope>
     </dependency>
+
+    <!-- mySQL -->
+    <dependency>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/modules/jooby-flyway/pom.xml b/modules/jooby-flyway/pom.xml
index 8ac48cd44..aae8b7471 100644
--- a/modules/jooby-flyway/pom.xml
+++ b/modules/jooby-flyway/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -39,5 +39,12 @@
       <classifier>runtime</classifier>
       <scope>test</scope>
     </dependency>
+
+    <!-- mySQL -->
+    <dependency>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/modules/jooby-freemarker/pom.xml b/modules/jooby-freemarker/pom.xml
index b9dc57bba..085ab9505 100644
--- a/modules/jooby-freemarker/pom.xml
+++ b/modules/jooby-freemarker/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-gradle-setup/pom.xml b/modules/jooby-gradle-setup/pom.xml
index a593369ad..643c146df 100644
--- a/modules/jooby-gradle-setup/pom.xml
+++ b/modules/jooby-gradle-setup/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-graphiql/pom.xml b/modules/jooby-graphiql/pom.xml
index b19e93088..60b993ecb 100644
--- a/modules/jooby-graphiql/pom.xml
+++ b/modules/jooby-graphiql/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-graphql-playground/pom.xml b/modules/jooby-graphql-playground/pom.xml
index 7bc938dc6..5baf5ccfc 100644
--- a/modules/jooby-graphql-playground/pom.xml
+++ b/modules/jooby-graphql-playground/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-graphql/pom.xml b/modules/jooby-graphql/pom.xml
index 7b5473ea7..a960a02d0 100644
--- a/modules/jooby-graphql/pom.xml
+++ b/modules/jooby-graphql/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-graphql/src/main/java/io/jooby/internal/graphql/GraphQLHandler.java b/modules/jooby-graphql/src/main/java/io/jooby/internal/graphql/GraphQLHandler.java
index 0d9335f59..0be68018e 100644
--- a/modules/jooby-graphql/src/main/java/io/jooby/internal/graphql/GraphQLHandler.java
+++ b/modules/jooby-graphql/src/main/java/io/jooby/internal/graphql/GraphQLHandler.java
@@ -44,7 +44,7 @@ public class GraphQLHandler implements Route.Handler {
           ctx.query("variables")
               .toOptional()
               .filter(string -> !string.equals("{}"))
-              .map(str -> json.<Map<String, Object>>fromJson(str, Map.class))
+              .map(str -> json.fromJson(str, Map.class))
               .orElseGet(Collections::emptyMap);
       request.setOperationName(operationName);
       request.setQuery(query);
@@ -52,7 +52,7 @@ public class GraphQLHandler implements Route.Handler {
     }
     return ExecutionInput.newExecutionInput(request.getQuery())
         .operationName(request.getOperationName())
-        .graphQLContext(Map.of(Context.class, ctx))
+        .context(ctx)
         .variables(request.getVariables())
         .build();
   }
diff --git a/modules/jooby-gson/pom.xml b/modules/jooby-gson/pom.xml
index 3a78f48dd..b593b8896 100644
--- a/modules/jooby-gson/pom.xml
+++ b/modules/jooby-gson/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-guice/pom.xml b/modules/jooby-guice/pom.xml
index 66a7707dc..83703a35b 100644
--- a/modules/jooby-guice/pom.xml
+++ b/modules/jooby-guice/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-handlebars/pom.xml b/modules/jooby-handlebars/pom.xml
index 9214cd282..e901b6919 100644
--- a/modules/jooby-handlebars/pom.xml
+++ b/modules/jooby-handlebars/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-hibernate/pom.xml b/modules/jooby-hibernate/pom.xml
index 22b437d09..7dc3d89dd 100644
--- a/modules/jooby-hibernate/pom.xml
+++ b/modules/jooby-hibernate/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -38,5 +38,12 @@
       <classifier>runtime</classifier>
       <scope>test</scope>
     </dependency>
+
+    <!-- mySQL -->
+    <dependency>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/modules/jooby-hikari/pom.xml b/modules/jooby-hikari/pom.xml
index ed28eb889..68a377750 100644
--- a/modules/jooby-hikari/pom.xml
+++ b/modules/jooby-hikari/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -39,6 +39,13 @@
       <scope>test</scope>
     </dependency>
 
+    <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
+    <dependency>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <scope>test</scope>
+    </dependency>
+
     <!-- log4jdbc -->
     <dependency>
       <groupId>com.googlecode.log4jdbc</groupId>
diff --git a/modules/jooby-jackson/pom.xml b/modules/jooby-jackson/pom.xml
index b397dbac1..5f4bba3a7 100644
--- a/modules/jooby-jackson/pom.xml
+++ b/modules/jooby-jackson/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-jasypt/pom.xml b/modules/jooby-jasypt/pom.xml
index aa9d7f210..d2bab7ae4 100644
--- a/modules/jooby-jasypt/pom.xml
+++ b/modules/jooby-jasypt/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-jdbi/pom.xml b/modules/jooby-jdbi/pom.xml
index f55d67018..fa33597c9 100644
--- a/modules/jooby-jdbi/pom.xml
+++ b/modules/jooby-jdbi/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -39,5 +39,11 @@
       <scope>test</scope>
     </dependency>
 
+    <!-- mySQL -->
+    <dependency>
+      <groupId>com.mysql</groupId>
+      <artifactId>mysql-connector-j</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/modules/jooby-jetty/pom.xml b/modules/jooby-jetty/pom.xml
index fb23190f1..17faf4976 100644
--- a/modules/jooby-jetty/pom.xml
+++ b/modules/jooby-jetty/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-jstachio/pom.xml b/modules/jooby-jstachio/pom.xml
index a91d57029..31d031c79 100644
--- a/modules/jooby-jstachio/pom.xml
+++ b/modules/jooby-jstachio/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/ByteBufferedOutputStream.java b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/ByteBufferedOutputStream.java
new file mode 100644
index 000000000..bead99478
--- /dev/null
+++ b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/ByteBufferedOutputStream.java
@@ -0,0 +1,117 @@
+/*
+ * Jooby https://jooby.io
+ * Apache License Version 2.0 https://jooby.io/LICENSE.txt
+ * Copyright 2014 Edgar Espina
+ */
+package io.jooby.jstachio;
+
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * This is basically the same as Rockers byte buffer but as an OutputStream because JStachio wants
+ * that interface. Currently it is internal.
+ *
+ * @author agentgt
+ */
+class ByteBufferedOutputStream extends OutputStream {
+
+  /** Default buffer size: <code>4k</code>. */
+  public static final int BUFFER_SIZE = 4096;
+
+  /**
+   * The maximum size of array to allocate. Some VMs reserve some header words in an array. Attempts
+   * to allocate larger arrays may result in OutOfMemoryError: Requested array size exceeds VM limit
+   */
+  private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+  /** The buffer where data is stored. */
+  protected byte[] buf;
+
+  /** The number of valid bytes in the buffer. */
+  protected int count;
+
+  ByteBufferedOutputStream(int bufferSize) {
+    this.buf = new byte[bufferSize];
+  }
+
+  void reset() {
+    count = 0;
+  }
+
+  @Override
+  public void close() {
+    this.reset();
+  }
+
+  @Override
+  public void write(byte[] bytes) {
+    int len = bytes.length;
+    ensureCapacity(count + len);
+    System.arraycopy(bytes, 0, buf, count, len);
+    count += len;
+  }
+
+  public int size() {
+    return count;
+  }
+
+  /**
+   * Copy internal byte array into a new array.
+   *
+   * @return Byte array.
+   */
+  public byte[] toByteArray() {
+    byte[] array = new byte[count];
+    System.arraycopy(buf, 0, array, 0, count);
+    return array;
+  }
+
+  /**
+   * Get a view of the byte buffer.
+   *
+   * @return Byte buffer.
+   */
+  public ByteBuffer toBuffer() {
+    return ByteBuffer.wrap(buf, 0, count);
+  }
+
+  private void ensureCapacity(int minCapacity) {
+    // overflow-conscious code
+    if (minCapacity - buf.length > 0) {
+      grow(minCapacity);
+    }
+  }
+
+  /**
+   * Increases the capacity to ensure that it can hold at least the number of elements specified by
+   * the minimum capacity argument.
+   *
+   * @param minCapacity the desired minimum capacity
+   */
+  private void grow(int minCapacity) {
+    // overflow-conscious code
+    int oldCapacity = buf.length;
+    int newCapacity = oldCapacity << 1;
+    if (newCapacity - minCapacity < 0) {
+      newCapacity = minCapacity;
+    }
+    if (newCapacity - MAX_ARRAY_SIZE > 0) {
+      newCapacity = hugeCapacity(minCapacity);
+    }
+    buf = Arrays.copyOf(buf, newCapacity);
+  }
+
+  private static int hugeCapacity(int minCapacity) {
+    if (minCapacity < 0) {
+      throw new OutOfMemoryError();
+    }
+    return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
+  }
+
+  @Override
+  public void write(int b) {
+    throw new UnsupportedOperationException("expecting only write(byte[])");
+  }
+}
diff --git a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioBuffer.java b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioBuffer.java
index 737c7c828..e682f3501 100644
--- a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioBuffer.java
+++ b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioBuffer.java
@@ -5,10 +5,6 @@
  */
 package io.jooby.jstachio;
 
-import java.nio.charset.StandardCharsets;
-
-import io.jstach.jstachio.output.ByteBufferEncodedOutput;
-
 /**
  * To provide Rocker like buffer support
  *
@@ -16,9 +12,9 @@ import io.jstach.jstachio.output.ByteBufferEncodedOutput;
  */
 interface JStachioBuffer {
 
-  public ByteBufferEncodedOutput acquire();
+  public ByteBufferedOutputStream acquire();
 
-  public void release(ByteBufferEncodedOutput buffer);
+  public void release(ByteBufferedOutputStream buffer);
 
   static JStachioBuffer of(int bufferSize, boolean reuseBuffer) {
     if (reuseBuffer) {
@@ -31,31 +27,29 @@ interface JStachioBuffer {
 
 record NoReuseBuffer(int bufferSize) implements JStachioBuffer {
   @Override
-  public ByteBufferEncodedOutput acquire() {
-    return ByteBufferEncodedOutput.ofByteArray(StandardCharsets.UTF_8, bufferSize);
+  public ByteBufferedOutputStream acquire() {
+    return new ByteBufferedOutputStream(bufferSize);
   }
 
   @Override
-  public void release(ByteBufferEncodedOutput buffer) {}
+  public void release(ByteBufferedOutputStream buffer) {}
 }
 
 class ReuseBuffer implements JStachioBuffer {
-  private final ThreadLocal<ByteBufferEncodedOutput> localBuffer;
+  private final ThreadLocal<ByteBufferedOutputStream> localBuffer;
 
   public ReuseBuffer(int bufferSize) {
     super();
-    this.localBuffer =
-        ThreadLocal.withInitial(
-            () -> ByteBufferEncodedOutput.ofByteArray(StandardCharsets.UTF_8, bufferSize));
+    this.localBuffer = ThreadLocal.withInitial(() -> new ByteBufferedOutputStream(bufferSize));
   }
 
   @Override
-  public ByteBufferEncodedOutput acquire() {
+  public ByteBufferedOutputStream acquire() {
     return localBuffer.get();
   }
 
   @Override
-  public void release(ByteBufferEncodedOutput buffer) {
-    buffer.close();
+  public void release(ByteBufferedOutputStream buffer) {
+    buffer.reset();
   }
 }
diff --git a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioHandler.java b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioHandler.java
index f3af96d79..99758fedc 100644
--- a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioHandler.java
+++ b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioHandler.java
@@ -6,21 +6,18 @@
 package io.jooby.jstachio;
 
 import java.io.IOException;
-import java.util.function.BiFunction;
 
 import io.jooby.Context;
+import io.jooby.MediaType;
 import io.jooby.Route;
 import io.jooby.Route.Handler;
 import io.jstach.jstachio.JStachio;
-import io.jstach.jstachio.output.ByteBufferEncodedOutput;
+import io.jstach.jstachio.Template;
 
 class JStachioHandler extends JStachioRenderer<Context> implements Route.Filter {
 
-  public JStachioHandler(
-      JStachio jstachio,
-      JStachioBuffer buffer,
-      BiFunction<Context, String, String> contextFunction) {
-    super(jstachio, buffer, contextFunction);
+  public JStachioHandler(JStachio jstachio, JStachioBuffer buffer) {
+    super(jstachio, buffer);
   }
 
   @Override
@@ -36,9 +33,24 @@ class JStachioHandler extends JStachioRenderer<Context> implements Route.Filter
     };
   }
 
+  @SuppressWarnings("unchecked")
   @Override
-  Context extractOutput(Context ctx, ByteBufferEncodedOutput stream) throws IOException {
-    ctx.send(stream.asByteBuffer());
+  Context render(
+      Context ctx,
+      @SuppressWarnings("rawtypes") Template template,
+      Object model,
+      ByteBufferedOutputStream stream)
+      throws IOException {
+    ctx.setResponseType(MediaType.html);
+    template.write(model, stream);
+    /*
+     * Rocker used a byte buffer here BUT it just wraps the internal buffer in the stream
+     * instead of copying.
+     *
+     * Which is good for performance but bad if the ctx.send call is not blocking aka
+     * hand the buffer off to another thread.
+     */
+    ctx.send(stream.toBuffer());
     return ctx;
   }
 }
diff --git a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioMessageEncoder.java b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioMessageEncoder.java
index b06adc1e1..f1558cde2 100644
--- a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioMessageEncoder.java
+++ b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioMessageEncoder.java
@@ -6,20 +6,19 @@
 package io.jooby.jstachio;
 
 import java.io.IOException;
-import java.util.function.BiFunction;
 
 import io.jooby.Context;
 import io.jooby.MessageEncoder;
 import io.jstach.jstachio.JStachio;
-import io.jstach.jstachio.output.ByteBufferEncodedOutput;
+import io.jstach.jstachio.Template;
 
+/*
+ * Should this be public?
+ */
 class JStachioMessageEncoder extends JStachioRenderer<byte[]> implements MessageEncoder {
 
-  public JStachioMessageEncoder(
-      JStachio jstachio,
-      JStachioBuffer buffer,
-      BiFunction<Context, String, String> contextFunction) {
-    super(jstachio, buffer, contextFunction);
+  public JStachioMessageEncoder(JStachio jstachio, JStachioBuffer buffer) {
+    super(jstachio, buffer);
   }
 
   @Override
@@ -30,8 +29,15 @@ class JStachioMessageEncoder extends JStachioRenderer<byte[]> implements Message
     return null;
   }
 
+  @SuppressWarnings("unchecked")
   @Override
-  byte[] extractOutput(Context ctx, ByteBufferEncodedOutput stream) throws IOException {
+  byte[] render(
+      Context ctx,
+      @SuppressWarnings("rawtypes") Template template,
+      Object model,
+      ByteBufferedOutputStream stream)
+      throws IOException {
+    template.write(model, stream);
     return stream.toByteArray();
   }
 }
diff --git a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioModule.java b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioModule.java
index 8e20f0952..4fb1fdcc9 100644
--- a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioModule.java
+++ b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioModule.java
@@ -6,11 +6,9 @@
 package io.jooby.jstachio;
 
 import java.util.ServiceLoader;
-import java.util.function.BiFunction;
 
 import edu.umd.cs.findbugs.annotations.NonNull;
 import edu.umd.cs.findbugs.annotations.Nullable;
-import io.jooby.Context;
 import io.jooby.Extension;
 import io.jooby.Jooby;
 import io.jooby.ServiceRegistry;
@@ -36,7 +34,6 @@ public class JStachioModule implements Extension {
   private @Nullable JStachio jstachio;
   private int bufferSize = 8 * 1024;
   private boolean reuseBuffer;
-  private BiFunction<Context, String, String> contextFunction = (ctx, key) -> ctx.getAttribute(key);
 
   /**
    * Sets the jstachio to use instead of the default.
@@ -76,21 +73,6 @@ public class JStachioModule implements Extension {
     return this;
   }
 
-  /**
-   * JStachio will by default bind {@linkplain Context#getAttributes() Context attributes} to <code>
-   * &#64;context</code>. This configuration option allows fetching context keys from something
-   * else. <a
-   * href="https://jstach.io/jstachio/io.jstach.jstachio/io/jstach/jstachio/context/package-summary.html">
-   * See JStachio doc on context. </a>
-   *
-   * @param contextFunction
-   * @return This module.
-   */
-  public JStachioModule contextFunction(BiFunction<Context, String, String> contextFunction) {
-    this.contextFunction = contextFunction;
-    return this;
-  }
-
   /**
    * Installs JStachio into Jooby and provides the JStachio service to the {@link ServiceRegistry}.
    * {@inheritDoc}
@@ -116,8 +98,8 @@ public class JStachioModule implements Extension {
     }
     JStachioBuffer buffer = JStachioBuffer.of(bufferSize, reuseBuffer);
 
-    JStachioMessageEncoder encoder = new JStachioMessageEncoder(j, buffer, contextFunction);
-    JStachioResultHandler handler = new JStachioResultHandler(j, buffer, contextFunction);
+    JStachioMessageEncoder encoder = new JStachioMessageEncoder(j, buffer);
+    JStachioResultHandler handler = new JStachioResultHandler(j, buffer);
     application.encoder(encoder);
     application.resultHandler(handler);
   }
diff --git a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioRenderer.java b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioRenderer.java
index fb998a625..d876b9142 100644
--- a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioRenderer.java
+++ b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioRenderer.java
@@ -6,14 +6,11 @@
 package io.jooby.jstachio;
 
 import java.io.IOException;
-import java.util.function.BiFunction;
 
 import io.jooby.Context;
 import io.jooby.MediaType;
 import io.jstach.jstachio.JStachio;
-import io.jstach.jstachio.context.ContextJStachio;
-import io.jstach.jstachio.context.ContextNode;
-import io.jstach.jstachio.output.ByteBufferEncodedOutput;
+import io.jstach.jstachio.Template;
 
 /**
  * Shared logic between encoder and result handler
@@ -23,23 +20,20 @@ import io.jstach.jstachio.output.ByteBufferEncodedOutput;
  */
 abstract class JStachioRenderer<T> {
 
-  private final ContextJStachio jstachio;
+  private final JStachio jstachio;
   private final JStachioBuffer buffer;
-  private final BiFunction<Context, String, String> contextFunction;
 
-  public JStachioRenderer(
-      JStachio jstachio,
-      JStachioBuffer buffer,
-      BiFunction<Context, String, String> contextFunction) {
+  public JStachioRenderer(JStachio jstachio, JStachioBuffer buffer) {
     super();
-    this.jstachio = ContextJStachio.of(jstachio);
+    this.jstachio = jstachio;
     this.buffer = buffer;
-    this.contextFunction = contextFunction;
   }
 
   public T render(Context ctx, Object model) throws Exception {
     var stream = buffer.acquire();
     try {
+      @SuppressWarnings("rawtypes")
+      Template template = jstachio.findTemplate(model);
       /*
        * TODO we probably should resolve the correct media type here and more importantly charset
        * Or at least validate that it is text/html UTF-8.
@@ -49,15 +43,18 @@ abstract class JStachioRenderer<T> {
        * So for now we will as well.
        */
       ctx.setResponseType(MediaType.html);
-      ContextNode contextNode = ContextNode.of(s -> contextFunction.apply(ctx, s));
-      jstachio.write(model, contextNode, stream);
-      return extractOutput(ctx, stream);
+      return render(ctx, template, model, stream);
     } finally {
       buffer.release(stream);
     }
   }
 
-  abstract T extractOutput(Context ctx, ByteBufferEncodedOutput stream) throws IOException;
+  abstract T render(
+      Context ctx,
+      @SuppressWarnings("rawtypes") Template template,
+      Object model,
+      ByteBufferedOutputStream stream)
+      throws IOException;
 
   protected boolean supportsType(Class<?> modelClass) {
     return jstachio.supportsType(modelClass);
diff --git a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioResultHandler.java b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioResultHandler.java
index 71908ba5a..5af4e3aac 100644
--- a/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioResultHandler.java
+++ b/modules/jooby-jstachio/src/main/java/io/jooby/jstachio/JStachioResultHandler.java
@@ -6,9 +6,7 @@
 package io.jooby.jstachio;
 
 import java.lang.reflect.Type;
-import java.util.function.BiFunction;
 
-import io.jooby.Context;
 import io.jooby.Reified;
 import io.jooby.ResultHandler;
 import io.jooby.Route.Filter;
@@ -18,16 +16,11 @@ class JStachioResultHandler implements ResultHandler {
 
   private final JStachio jstachio;
   private final JStachioBuffer buffer;
-  private final BiFunction<Context, String, String> contextFunction;
 
-  public JStachioResultHandler(
-      JStachio jstachio,
-      JStachioBuffer buffer,
-      BiFunction<Context, String, String> contextFunction) {
+  public JStachioResultHandler(JStachio jstachio, JStachioBuffer buffer) {
     super();
     this.jstachio = jstachio;
     this.buffer = buffer;
-    this.contextFunction = contextFunction;
   }
 
   @Override
@@ -42,6 +35,6 @@ class JStachioResultHandler implements ResultHandler {
 
   @Override
   public Filter create() {
-    return new JStachioHandler(jstachio, buffer, contextFunction);
+    return new JStachioHandler(jstachio, buffer);
   }
 }
diff --git a/modules/jooby-jte/pom.xml b/modules/jooby-jte/pom.xml
index f7b1973e9..6bac36e38 100644
--- a/modules/jooby-jte/pom.xml
+++ b/modules/jooby-jte/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -23,7 +23,7 @@
     <dependency>
       <groupId>gg.jte</groupId>
       <artifactId>jte</artifactId>
-      <version>3.1.6</version>
+      <version>3.1.2</version>
     </dependency>
 
     <!-- Test dependencies -->
diff --git a/modules/jooby-jte/src/main/java/io/jooby/jte/JteTemplateEngine.java b/modules/jooby-jte/src/main/java/io/jooby/jte/JteTemplateEngine.java
index 1247187f4..33a5694d5 100644
--- a/modules/jooby-jte/src/main/java/io/jooby/jte/JteTemplateEngine.java
+++ b/modules/jooby-jte/src/main/java/io/jooby/jte/JteTemplateEngine.java
@@ -16,7 +16,7 @@ import io.jooby.Context;
 import io.jooby.ModelAndView;
 
 class JteTemplateEngine implements io.jooby.TemplateEngine {
-  private final TemplateEngine jte;
+  private TemplateEngine jte;
   private final List<String> extensions;
 
   public JteTemplateEngine(TemplateEngine jte) {
@@ -39,7 +39,7 @@ class JteTemplateEngine implements io.jooby.TemplateEngine {
     } else {
       model = new HashMap<>();
       model.putAll(attributes);
-      model.putAll(modelAndView.getModel());
+      model.putAll(model);
     }
     jte.render(modelAndView.getView(), model, output);
     return output.toString();
diff --git a/modules/jooby-jwt/pom.xml b/modules/jooby-jwt/pom.xml
index 613583024..a710125f6 100644
--- a/modules/jooby-jwt/pom.xml
+++ b/modules/jooby-jwt/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-kafka/pom.xml b/modules/jooby-kafka/pom.xml
index 19848a772..377645d45 100644
--- a/modules/jooby-kafka/pom.xml
+++ b/modules/jooby-kafka/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-kotlin/pom.xml b/modules/jooby-kotlin/pom.xml
index c64538c6a..78ce81665 100644
--- a/modules/jooby-kotlin/pom.xml
+++ b/modules/jooby-kotlin/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -25,7 +25,7 @@
       <plugin>
         <groupId>org.jetbrains.dokka</groupId>
         <artifactId>dokka-maven-plugin</artifactId>
-        <version>1.9.10</version>
+        <version>1.9.0</version>
         <configuration>
           <documentedVisibilities>
             <visibility>PUBLIC</visibility>
diff --git a/modules/jooby-log4j/pom.xml b/modules/jooby-log4j/pom.xml
index 13f1953aa..270a3e5e9 100644
--- a/modules/jooby-log4j/pom.xml
+++ b/modules/jooby-log4j/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-logback/pom.xml b/modules/jooby-logback/pom.xml
index b9d743a27..7606f5b12 100644
--- a/modules/jooby-logback/pom.xml
+++ b/modules/jooby-logback/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-maven-plugin/pom.xml b/modules/jooby-maven-plugin/pom.xml
index 150a7e3d3..339d757b5 100644
--- a/modules/jooby-maven-plugin/pom.xml
+++ b/modules/jooby-maven-plugin/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-metrics/pom.xml b/modules/jooby-metrics/pom.xml
index fcede30c9..497ee5a16 100644
--- a/modules/jooby-metrics/pom.xml
+++ b/modules/jooby-metrics/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-mutiny/pom.xml b/modules/jooby-mutiny/pom.xml
index 2a2dcb45e..fca7b9b78 100644
--- a/modules/jooby-mutiny/pom.xml
+++ b/modules/jooby-mutiny/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -27,7 +27,7 @@
     <dependency>
       <groupId>io.smallrye.reactive</groupId>
       <artifactId>mutiny</artifactId>
-      <version>2.5.3</version>
+      <version>2.5.1</version>
     </dependency>
 
     <!-- Test dependencies -->
diff --git a/modules/jooby-netty/pom.xml b/modules/jooby-netty/pom.xml
index f92d9ae96..d26a48f42 100644
--- a/modules/jooby-netty/pom.xml
+++ b/modules/jooby-netty/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -53,7 +53,7 @@
     <dependency>
       <groupId>io.netty.incubator</groupId>
       <artifactId>netty-incubator-transport-native-io_uring</artifactId>
-      <version>0.0.24.Final</version>
+      <version>0.0.23.Final</version>
       <optional>true</optional>
     </dependency>
 
diff --git a/modules/jooby-node/pom.xml b/modules/jooby-node/pom.xml
index 328dc8332..b9b6c792d 100644
--- a/modules/jooby-node/pom.xml
+++ b/modules/jooby-node/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-openapi/pom.xml b/modules/jooby-openapi/pom.xml
index df2967ba0..7459399a9 100644
--- a/modules/jooby-openapi/pom.xml
+++ b/modules/jooby-openapi/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -80,7 +80,7 @@
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
-      <version>3.14.0</version>
+      <version>3.13.0</version>
       <scope>test</scope>
     </dependency>
 
diff --git a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ASMType.java b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ASMType.java
index 70b898d0f..665101b87 100644
--- a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ASMType.java
+++ b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ASMType.java
@@ -53,7 +53,7 @@ public class ASMType {
     SignatureReader reader = new SignatureReader(signature);
     LinkedList<TypeName> stack = new LinkedList<>();
     SignatureVisitor visitor =
-        new SignatureVisitor(Opcodes.ASM9) {
+        new SignatureVisitor(Opcodes.ASM7) {
           @Override
           public void visitClassType(String name) {
             if (filter.test(name)) {
diff --git a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ParserContext.java b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ParserContext.java
index de1397bd6..e76e8a629 100644
--- a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ParserContext.java
+++ b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ParserContext.java
@@ -403,7 +403,7 @@ public class ParserContext {
   }
 
   public <T extends ClassVisitor> T createClassVisitor(Function<Integer, T> factory) {
-    return factory.apply(Opcodes.ASM9);
+    return factory.apply(Opcodes.ASM7);
   }
 
   public boolean isRouter(Type type) {
diff --git a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ResponseExt.java b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ResponseExt.java
index 6d9157afc..6a45d5623 100644
--- a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ResponseExt.java
+++ b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ResponseExt.java
@@ -5,7 +5,10 @@
  */
 package io.jooby.internal.openapi;
 
+import static java.util.stream.Collectors.toSet;
+
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
@@ -17,15 +20,17 @@ import io.swagger.v3.oas.models.responses.ApiResponse;
 
 public class ResponseExt extends ApiResponse {
   private static final Set<String> ASYNC_TYPES =
-      Set.of(
-          CompletionStage.class.getName(),
-          CompletableFuture.class.getName(),
-          "io.reactivex.Single",
-          "io.reactivex.Maybe",
-          "io.reactivex.Flowable",
-          "io.reactivex.Observable",
-          "reactor.core.publisher.Flux",
-          "reactor.core.publisher.Mono");
+      Arrays.asList(
+              CompletionStage.class.getName(),
+              CompletableFuture.class.getName(),
+              "io.reactivex.Single",
+              "io.reactivex.Maybe",
+              "io.reactivex.Flowable",
+              "io.reactivex.Observable",
+              "reactor.core.publisher.Flux",
+              "reactor.core.publisher.Mono")
+          .stream()
+          .collect(toSet());
 
   @JsonIgnore private List<String> javaTypes = new ArrayList<>();
 
@@ -89,7 +94,7 @@ public class ResponseExt extends ApiResponse {
 
   private String unwrapType(String javaType) {
     return ASYNC_TYPES.stream()
-        .filter(javaType::startsWith)
+        .filter(type -> javaType.startsWith(type))
         .findFirst()
         .map(
             type ->
diff --git a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ReturnTypeParser.java b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ReturnTypeParser.java
index 5b26f44ee..b0f063d7b 100644
--- a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ReturnTypeParser.java
+++ b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/ReturnTypeParser.java
@@ -5,15 +5,10 @@
  */
 package io.jooby.internal.openapi;
 
-import static java.util.Collections.singletonList;
-import static java.util.Optional.ofNullable;
-
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -48,30 +43,32 @@ public class ReturnTypeParser {
         && !TypeFactory.VOID.equals(returnType)
         && !TypeFactory.JOOBY.equals(returnType)) {
       if (node.signature == null) {
-        return singletonList(ASMType.parse(returnType.getDescriptor()));
+        return Collections.singletonList(ASMType.parse(returnType.getDescriptor()));
       } else {
         String desc = node.signature;
         int rparen = desc.indexOf(')');
         if (rparen > 0) {
           desc = desc.substring(rparen + 1);
         }
-        return singletonList(ASMType.parse(desc));
+        return Collections.singletonList(ASMType.parse(desc));
       }
     }
     return parseIgnoreSignature(ctx, node);
   }
 
   public static List<String> parseIgnoreSignature(ParserContext ctx, MethodNode node) {
-    return InsnSupport.next(node.instructions.getFirst())
-        .filter(
-            it ->
-                it.getOpcode() == Opcodes.ARETURN
-                    || it.getOpcode() == Opcodes.IRETURN
-                    || it.getOpcode() == Opcodes.RETURN)
-        .map(it -> handleReturnType(ctx, node, it))
-        .map(Object::toString)
-        .distinct()
-        .collect(Collectors.toList());
+    List<String> result =
+        InsnSupport.next(node.instructions.getFirst())
+            .filter(
+                it ->
+                    it.getOpcode() == Opcodes.ARETURN
+                        || it.getOpcode() == Opcodes.IRETURN
+                        || it.getOpcode() == Opcodes.RETURN)
+            .map(it -> handleReturnType(ctx, node, it))
+            .map(Object::toString)
+            .distinct()
+            .collect(Collectors.toList());
+    return result;
   }
 
   private static String handleReturnType(ParserContext ctx, MethodNode node, AbstractInsnNode it) {
@@ -117,7 +114,8 @@ public class ReturnTypeParser {
         continue;
       }
       /** return 1; return true; return new Foo(); */
-      if (i instanceof MethodInsnNode minnsn) {
+      if (i instanceof MethodInsnNode) {
+        MethodInsnNode minnsn = (MethodInsnNode) i;
         if (minnsn.name.equals("<init>")) {
           return Type.getObjectType(minnsn.owner).getClassName();
         } else {
@@ -125,8 +123,8 @@ public class ReturnTypeParser {
         }
       }
       /** return "String" | int | double */
-      if (i instanceof LdcInsnNode lin) {
-        Object cst = lin.cst;
+      if (i instanceof LdcInsnNode) {
+        Object cst = ((LdcInsnNode) i).cst;
         if (cst instanceof Type) {
           return ((Type) cst).getClassName();
         }
@@ -134,7 +132,8 @@ public class ReturnTypeParser {
       }
 
       /** return variable */
-      if (i instanceof VarInsnNode varInsn) {
+      if (i instanceof VarInsnNode) {
+        VarInsnNode varInsn = (VarInsnNode) i;
         String varType = localVariable(ctx, node, varInsn);
         // Is there local variable?
         if (varType != null) {
@@ -142,7 +141,8 @@ public class ReturnTypeParser {
         }
       }
       /** Invoke dynamic: */
-      if (i instanceof InvokeDynamicInsnNode invokeDynamic) {
+      if (i instanceof InvokeDynamicInsnNode) {
+        InvokeDynamicInsnNode invokeDynamic = (InvokeDynamicInsnNode) i;
         String handleDescriptor =
             Stream.of(invokeDynamic.bsmArgs)
                 .filter(Handle.class::isInstance)
@@ -168,72 +168,56 @@ public class ReturnTypeParser {
         // empty primitive array
         if (i instanceof IntInsnNode) {
           switch (((IntInsnNode) i).operand) {
-            case Opcodes.T_BOOLEAN -> {
+            case Opcodes.T_BOOLEAN:
               return boolean[].class.getName();
-            }
-            case Opcodes.T_CHAR -> {
+            case Opcodes.T_CHAR:
               return char[].class.getName();
-            }
-            case Opcodes.T_BYTE -> {
+            case Opcodes.T_BYTE:
               return byte[].class.getName();
-            }
-            case Opcodes.T_SHORT -> {
+            case Opcodes.T_SHORT:
               return short[].class.getName();
-            }
-            case Opcodes.T_INT -> {
+            case Opcodes.T_INT:
               return int[].class.getName();
-            }
-            case Opcodes.T_LONG -> {
+            case Opcodes.T_LONG:
               return long[].class.getName();
-            }
-            case Opcodes.T_FLOAT -> {
+            case Opcodes.T_FLOAT:
               return float[].class.getName();
-            }
-            case Opcodes.T_DOUBLE -> {
+            case Opcodes.T_DOUBLE:
               return double[].class.getName();
-            }
           }
         }
       }
       // empty array of objects
-      if (i.getOpcode() == Opcodes.ANEWARRAY && i instanceof TypeInsnNode typeInsn) {
+      if (i.getOpcode() == Opcodes.ANEWARRAY) {
+        TypeInsnNode typeInsn = (TypeInsnNode) i;
         return ASMType.parse("[L" + typeInsn.desc + ";");
       }
       // non empty array
       switch (i.getOpcode()) {
-        case Opcodes.BASTORE -> {
+        case Opcodes.BASTORE:
           return boolean[].class.getName();
-        }
-        case Opcodes.CASTORE -> {
+        case Opcodes.CASTORE:
           return char[].class.getName();
-        }
-        case Opcodes.SASTORE -> {
+        case Opcodes.SASTORE:
           return short[].class.getName();
-        }
-        case Opcodes.IASTORE -> {
+        case Opcodes.IASTORE:
           return int[].class.getName();
-        }
-        case Opcodes.LASTORE -> {
+        case Opcodes.LASTORE:
           return long[].class.getName();
-        }
-        case Opcodes.FASTORE -> {
+        case Opcodes.FASTORE:
           return float[].class.getName();
-        }
-        case Opcodes.DASTORE -> {
+        case Opcodes.DASTORE:
           return double[].class.getName();
-        }
-        case Opcodes.AASTORE -> {
+        case Opcodes.AASTORE:
           return InsnSupport.prev(i)
               .filter(e -> e.getOpcode() == Opcodes.ANEWARRAY)
               .findFirst()
-              .filter(e -> e instanceof TypeInsnNode)
               .map(
                   e -> {
                     TypeInsnNode typeInsn = (TypeInsnNode) e;
                     return ASMType.parse("[L" + typeInsn.desc + ";");
                   })
               .orElse(Object.class.getName());
-        }
       }
     }
 
@@ -257,18 +241,6 @@ public class ReturnTypeParser {
       return Object.class.getName();
     }
     Type returnType = Type.getReturnType(node.desc);
-    if (node.owner.equals("kotlin/collections/CollectionsKt")) {
-      // find previous typeInsns
-      return InsnSupport.prev(node)
-          .filter(TypeInsnNode.class::isInstance)
-          .map(TypeInsnNode.class::cast)
-          .findFirst()
-          .map(
-              it -> {
-                return returnType.getClassName() + "<" + it.desc.replace('/', '.') + ">";
-              })
-          .orElse(returnType.getClassName());
-    }
     // Since Kotlin 1.6+
     String methodName =
         node.name.startsWith("access$invoke$")
@@ -280,7 +252,7 @@ public class ReturnTypeParser {
         .findFirst()
         .map(
             m ->
-                ofNullable(m.signature)
+                Optional.ofNullable(m.signature)
                     .map(
                         s -> {
                           int pos = s.indexOf(')');
@@ -296,12 +268,13 @@ public class ReturnTypeParser {
     if (classNode == null) {
       return Collections.emptyList();
     }
-    List<MethodNode> result = new ArrayList<>(classNode.methods);
-    Stream.concat(
-            ofNullable(classNode.interfaces).stream().flatMap(Collection::stream),
-            ofNullable(classNode.superName).stream())
-        .filter(Objects::nonNull)
-        .forEach(parent -> result.addAll(classMethods(ctx, parent)));
+    List<MethodNode> result = new ArrayList<>();
+    result.addAll(classNode.methods);
+    if (classNode.interfaces != null) {
+      for (String anInterface : classNode.interfaces) {
+        result.addAll(classMethods(ctx, anInterface));
+      }
+    }
     return result;
   }
 
diff --git a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/RouteParser.java b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/RouteParser.java
index 048ff574e..65d38c77b 100644
--- a/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/RouteParser.java
+++ b/modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/RouteParser.java
@@ -804,14 +804,15 @@ public class RouteParser {
   }
 
   private MethodNode ktFunRef160(ParserContext ctx, MethodNode method) {
-    MethodInsnNode call =
+    AbstractInsnNode ref =
         InsnSupport.prev(method.instructions.getLast())
             .filter(MethodInsnNode.class::isInstance)
             .map(MethodInsnNode.class::cast)
             .filter(it -> Signature.create(it).matches(Context.class))
             .findFirst()
             .orElse(null);
-    if (call != null) {
+    if (ref != null) {
+      MethodInsnNode call = (MethodInsnNode) ref;
       ClassNode owner = ctx.classNodeOrNull(Type.getObjectType(call.owner));
       if (owner != null) {
         MethodNode methodRef =
diff --git a/modules/jooby-pac4j/pom.xml b/modules/jooby-pac4j/pom.xml
index f204d2fad..4e7e705e0 100644
--- a/modules/jooby-pac4j/pom.xml
+++ b/modules/jooby-pac4j/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-pebble/pom.xml b/modules/jooby-pebble/pom.xml
index c5f170552..880e087af 100644
--- a/modules/jooby-pebble/pom.xml
+++ b/modules/jooby-pebble/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-quartz/pom.xml b/modules/jooby-quartz/pom.xml
index 148459c1c..1bcd04b65 100644
--- a/modules/jooby-quartz/pom.xml
+++ b/modules/jooby-quartz/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-reactor/pom.xml b/modules/jooby-reactor/pom.xml
index 836cd50f7..8f84a3fcd 100644
--- a/modules/jooby-reactor/pom.xml
+++ b/modules/jooby-reactor/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-redis/pom.xml b/modules/jooby-redis/pom.xml
index daceb2b74..831081941 100644
--- a/modules/jooby-redis/pom.xml
+++ b/modules/jooby-redis/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -43,7 +43,7 @@
     <dependency>
       <groupId>io.lettuce</groupId>
       <artifactId>lettuce-core</artifactId>
-      <version>6.3.0.RELEASE</version>
+      <version>6.2.6.RELEASE</version>
     </dependency>
 
     <!-- Test dependencies -->
diff --git a/modules/jooby-redoc/pom.xml b/modules/jooby-redoc/pom.xml
index 2fa7bc09e..cb50d786a 100644
--- a/modules/jooby-redoc/pom.xml
+++ b/modules/jooby-redoc/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-rocker/pom.xml b/modules/jooby-rocker/pom.xml
index edc3c23c1..0ecfa3f81 100644
--- a/modules/jooby-rocker/pom.xml
+++ b/modules/jooby-rocker/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -33,7 +33,7 @@
     <dependency>
       <groupId>com.fizzed</groupId>
       <artifactId>rocker-compiler</artifactId>
-      <version>1.4.0</version>
+      <version>1.3.0</version>
       <scope>provided</scope>
     </dependency>
 
diff --git a/modules/jooby-run/pom.xml b/modules/jooby-run/pom.xml
index 6d9a549ad..e6692284b 100644
--- a/modules/jooby-run/pom.xml
+++ b/modules/jooby-run/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-rxjava3/pom.xml b/modules/jooby-rxjava3/pom.xml
index 1fe201a76..8c944276c 100644
--- a/modules/jooby-rxjava3/pom.xml
+++ b/modules/jooby-rxjava3/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-stork/pom.xml b/modules/jooby-stork/pom.xml
index dbc982acd..a47d2e90a 100644
--- a/modules/jooby-stork/pom.xml
+++ b/modules/jooby-stork/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <artifactId>jooby-stork</artifactId>
@@ -20,7 +20,7 @@
       <plugin>
         <groupId>io.repaint.maven</groupId>
         <artifactId>tiles-maven-plugin</artifactId>
-        <version>2.39</version>
+        <version>2.36</version>
         <extensions>true</extensions>
         <configuration>
           <filtering>true</filtering>
diff --git a/modules/jooby-swagger-ui/pom.xml b/modules/jooby-swagger-ui/pom.xml
index c51d217a6..ef3991525 100644
--- a/modules/jooby-swagger-ui/pom.xml
+++ b/modules/jooby-swagger-ui/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-thymeleaf/pom.xml b/modules/jooby-thymeleaf/pom.xml
index 90a9401aa..f87a636ad 100644
--- a/modules/jooby-thymeleaf/pom.xml
+++ b/modules/jooby-thymeleaf/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/jooby-undertow/pom.xml b/modules/jooby-undertow/pom.xml
index 8a588c942..313a930fe 100644
--- a/modules/jooby-undertow/pom.xml
+++ b/modules/jooby-undertow/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <properties>
@@ -28,7 +28,7 @@
       <!-- remove xnio once we upgrade to 2.2.18 +  There is a Invalida Path on Windows-->
       <groupId> org.jboss.xnio</groupId>
       <artifactId>xnio-api</artifactId>
-      <version>3.8.12.Final</version>
+      <version>3.8.11.Final</version>
     </dependency>
 
     <dependency>
diff --git a/modules/jooby-whoops/pom.xml b/modules/jooby-whoops/pom.xml
index 48bb54e6a..b4ea30629 100644
--- a/modules/jooby-whoops/pom.xml
+++ b/modules/jooby-whoops/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -36,7 +36,7 @@
     <dependency>
       <groupId>org.jsoup</groupId>
       <artifactId>jsoup</artifactId>
-      <version>1.17.1</version>
+      <version>1.16.1</version>
       <scope>test</scope>
     </dependency>
 
diff --git a/modules/jooby-yasson/pom.xml b/modules/jooby-yasson/pom.xml
index eff9bc9a7..c3f520ee9 100644
--- a/modules/jooby-yasson/pom.xml
+++ b/modules/jooby-yasson/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/modules/pom.xml b/modules/pom.xml
index ae36d4aaf..409227aeb 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>jooby-project</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <artifactId>modules</artifactId>
diff --git a/pom.xml b/pom.xml
index 5bb5c7ae3..c7cbcf42c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.jooby</groupId>
   <artifactId>jooby-project</artifactId>
-  <version>3.0.8-SNAPSHOT</version>
+  <version>3.0.7-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>jooby-project</name>
@@ -21,46 +21,48 @@
     <!-- Parser and Renderer -->
     <freemarker.version>2.3.32</freemarker.version>
     <handlebars.version>4.3.1</handlebars.version>
-    <jstachio.version>1.3.4</jstachio.version>
-    <pebble.version>3.2.2</pebble.version>
-    <jackson.version>2.16.1</jackson.version>
+    <jstachio.version>1.3.2</jstachio.version>
+    <pebble.version>3.2.1</pebble.version>
+    <jackson.version>2.15.2</jackson.version>
     <jackson-dataformat-yaml.version>${jackson.version}</jackson-dataformat-yaml.version>
     <jackson-databind.version>${jackson.version}</jackson-databind.version>
     <gson.version>2.10.1</gson.version>
-    <avaje-jsonb.version>1.9</avaje-jsonb.version>
+    <avaje-jsonb.version>1.8</avaje-jsonb.version>
     <jakarta.json.bind-api.version>3.0.0</jakarta.json.bind-api.version>
     <yasson.version>3.0.3</yasson.version>
-    <rocker.version>1.4.0</rocker.version>
+    <rocker.version>1.3.0</rocker.version>
     <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version>
 
     <!-- data -->
-    <HikariCP.version>5.1.0</HikariCP.version>
+    <HikariCP.version>5.0.1</HikariCP.version>
+    <mysql-connector-j.version>8.1.0</mysql-connector-j.version>
     <log4jdbc.version>1.2</log4jdbc.version>
-    <hibernate.version>6.4.1.Final</hibernate.version>
-    <ebean.version>13.25.2-jakarta</ebean.version>
-    <jdbi.version>3.42.0</jdbi.version>
-    <flyway.version>9.22.3</flyway.version>
-    <graphql-java.version>21.3</graphql-java.version>
-    <lettuce.version>6.3.0.RELEASE</lettuce.version>
+    <hibernate.version>6.3.1.Final</hibernate.version>
+    <ebean.version>13.23.0-jakarta</ebean.version>
+    <jdbi.version>3.41.3</jdbi.version>
+    <flyway.version>9.22.2</flyway.version>
+    <graphql-java.version>21.1</graphql-java.version>
+    <lettuce.version>6.2.6.RELEASE</lettuce.version>
     <commons-pool2.version>2.12.0</commons-pool2.version>
-    <kafka.version>3.6.1</kafka.version>
+    <kafka.version>3.6.0</kafka.version>
     <caffeine.version>3.1.8</caffeine.version>
 
-    <config.version>1.4.3</config.version>
+    <config.version>1.4.2</config.version>
 
     <!-- dependency injection -->
     <guice.version>7.0.0</guice.version>
 
     <!-- logging -->
-    <logback-classic.version>1.4.14</logback-classic.version>
-    <log4j.version>2.22.0</log4j.version>
-    <slf4j.version>2.0.10</slf4j.version>
+    <logback-classic.version>1.4.11</logback-classic.version>
+    <log4j.version>2.20.0</log4j.version>
+    <slf4j.version>2.0.9</slf4j.version>
 
     <!-- communication -->
     <commons-email.version>1.5</commons-email.version>
 
     <!-- util -->
-    <metrics.version>4.2.23</metrics.version>
+    <jfiglet.version>0.0.9</jfiglet.version>
+    <metrics.version>4.2.21</metrics.version>
 
     <!-- jboss modules -->
     <jboss-modules.version>2.1.2.Final</jboss-modules.version>
@@ -69,13 +71,13 @@
     <asm.version>9.6</asm.version>
 
     <!-- Server -->
-    <undertow.version>2.3.10.Final</undertow.version>
-    <jetty.version>11.0.19</jetty.version>
-    <netty.version>4.1.104.Final</netty.version>
+    <undertow.version>2.3.8.Final</undertow.version>
+    <jetty.version>11.0.15</jetty.version>
+    <netty.version>4.1.100.Final</netty.version>
 
     <!--OpenAPI-->
-    <swagger.version>2.2.20</swagger.version>
-    <swagger-parser.version>2.1.18</swagger-parser.version>
+    <swagger.version>2.2.17</swagger.version>
+    <swagger-parser.version>2.1.16</swagger-parser.version>
     <redoc.version>2.0.0-rc.20</redoc.version>
 
     <!-- SSL -->
@@ -83,34 +85,34 @@
 
     <!-- javax -->
     <jakarta.inject.version>2.0.1</jakarta.inject.version>
-    <spotbugs-annotations.version>4.8.1</spotbugs-annotations.version>
+    <spotbugs-annotations.version>4.8.0</spotbugs-annotations.version>
     <jakarta.ws.rs-api.version>3.1.0</jakarta.ws.rs-api.version>
 
     <!-- Misc -->
-    <okhttp.version>4.12.0</okhttp.version>
-    <jsonwebtoken.version>0.12.3</jsonwebtoken.version>
+    <okhttp.version>4.11.0</okhttp.version>
+    <jsonwebtoken.version>0.12.2</jsonwebtoken.version>
     <pac4j.version>5.7.0</pac4j.version>
     <quartz.version>2.3.2</quartz.version>
     <cron-utils.version>9.2.1</cron-utils.version>
     <bucket4j-core.version>7.6.0</bucket4j-core.version>
-    <aws-java-sdk.version>1.12.626</aws-java-sdk.version>
-    <camel.version>3.21.3</camel.version>
-    <frontend-plugin-core.version>1.15.0</frontend-plugin-core.version>
+    <aws-java-sdk.version>1.12.566</aws-java-sdk.version>
+    <camel.version>3.21.1</camel.version>
+    <frontend-plugin-core.version>1.14.0</frontend-plugin-core.version>
     <jasypt.version>1.9.3</jasypt.version>
 
-    <commons-io.version>2.15.1</commons-io.version>
+    <commons-io.version>2.14.0</commons-io.version>
 
     <!-- Kotlin -->
-    <kotlin.version>1.9.22</kotlin.version>
+    <kotlin.version>1.9.10</kotlin.version>
     <kotlinx-coroutines-core.version>1.7.3</kotlinx-coroutines-core.version>
     <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
 
     <!-- Test dependencies -->
-    <jacoco.version>0.8.11</jacoco.version>
-    <junit.version>5.10.1</junit.version>
-    <rest-assured.version>5.4.0</rest-assured.version>
-    <mockito.version>5.8.0</mockito.version>
-    <guava.version>33.0.0-jre</guava.version>
+    <jacoco.version>0.8.10</jacoco.version>
+    <junit.version>5.10.0</junit.version>
+    <rest-assured.version>5.3.2</rest-assured.version>
+    <mockito.version>5.6.0</mockito.version>
+    <guava.version>32.1.3-jre</guava.version>
 
     <auto-service.version>1.1.1</auto-service.version>
     <compile-testing.version>0.21.0</compile-testing.version>
@@ -126,34 +128,34 @@
     <maven-antrun-plugin.version>3.1.0</maven-antrun-plugin.version>
     <maven-archetype-plugin.version>3.2.0</maven-archetype-plugin.version>
     <maven-assembly-plugin.version>3.6.0</maven-assembly-plugin.version>
-    <maven-tiles-plugin.version>2.39</maven-tiles-plugin.version>
+    <maven-tiles-plugin.version>2.36</maven-tiles-plugin.version>
     <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
-    <maven-core.version>3.9.6</maven-core.version>
+    <maven-core.version>3.9.5</maven-core.version>
     <maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
     <maven-enforcer-plugin.version>3.4.1</maven-enforcer-plugin.version>
     <maven-gpg-plugin.version>3.1.0</maven-gpg-plugin.version>
     <maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
-    <maven-javadoc-plugin.version>3.6.3</maven-javadoc-plugin.version>
+    <maven-javadoc-plugin.version>3.6.0</maven-javadoc-plugin.version>
     <archetype-packaging.version>3.2.1</archetype-packaging.version>
-    <maven-plugin-annotations.version>3.10.2</maven-plugin-annotations.version>
-    <maven-plugin-api.version>3.9.6</maven-plugin-api.version>
-    <maven-plugin-plugin.version>3.10.2</maven-plugin-plugin.version>
+    <maven-plugin-annotations.version>3.9.0</maven-plugin-annotations.version>
+    <maven-plugin-api.version>3.9.4</maven-plugin-api.version>
+    <maven-plugin-plugin.version>3.9.0</maven-plugin-plugin.version>
     <maven-project.version>2.2.1</maven-project.version>
     <maven-resources-plugin.version>3.3.1</maven-resources-plugin.version>
     <maven-shade-plugin.version>3.5.1</maven-shade-plugin.version>
     <maven-site-plugin.version>3.8.2</maven-site-plugin.version>
     <maven-source-plugin.version>3.3.0</maven-source-plugin.version>
-    <maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
+    <maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
     <mojo-executor.version>2.3.1</mojo-executor.version>
     <nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
     <plexus-utils.version>4.0.0</plexus-utils.version>
     <stork-maven-plugin.version>3.1.3</stork-maven-plugin.version>
-    <versions-maven-plugin.version>2.16.2</versions-maven-plugin.version>
-    <exec-maven-plugin.version>3.1.1</exec-maven-plugin.version>
+    <versions-maven-plugin.version>2.16.1</versions-maven-plugin.version>
+    <exec-maven-plugin.version>3.1.0</exec-maven-plugin.version>
     <maven-dependency-plugin.version>3.1.2</maven-dependency-plugin.version>
-    <frontend-maven-plugin.version>1.15.0</frontend-maven-plugin.version>
+    <frontend-maven-plugin.version>1.14.0</frontend-maven-plugin.version>
     <node.version>v18.13.0</node.version>
-    <moditec.version>1.1.0</moditec.version>
+    <moditec.version>1.0.0.RC3</moditec.version>
 
     <!-- Jooby  -->
     <jooby.version>${project.version}</jooby.version>
@@ -166,7 +168,7 @@
     <!--  Javadoc is too strict in 17, don't fail on error -->
     <maven.javadoc.failOnError>false</maven.javadoc.failOnError>
     <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ssa</maven.build.timestamp.format>
-    <project.build.outputTimestamp>2024-01-04T15:44:48Z</project.build.outputTimestamp>
+    <project.build.outputTimestamp>2023-10-16T23:29:29Z</project.build.outputTimestamp>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <timestamp>${maven.build.timestamp}</timestamp>
 
@@ -861,6 +863,12 @@
         <version>${ebean.version}</version>
       </dependency>
 
+      <dependency>
+        <groupId>com.mysql</groupId>
+        <artifactId>mysql-connector-j</artifactId>
+        <version>${mysql-connector-j.version}</version>
+      </dependency>
+
       <!-- jdbi -->
       <dependency>
         <groupId>org.jdbi</groupId>
@@ -1470,7 +1478,7 @@
               <dependency>
                 <groupId>org.codehaus.groovy</groupId>
                 <artifactId>groovy-all</artifactId>
-                <version>3.0.20</version>
+                <version>3.0.19</version>
                 <type>pom</type>
                 <exclusions>
                   <exclusion>
@@ -1608,7 +1616,7 @@
           <plugin>
             <groupId>com.diffplug.spotless</groupId>
             <artifactId>spotless-maven-plugin</artifactId>
-            <version>2.41.1</version>
+            <version>2.40.0</version>
             <configuration>
               <upToDateChecking>
                 <enabled>true</enabled>
@@ -1725,7 +1733,7 @@
           <plugin>
             <groupId>org.codehaus.mojo</groupId>
             <artifactId>versions-maven-plugin</artifactId>
-            <version>2.16.2</version>
+            <version>2.16.1</version>
             <executions>
               <execution>
                 <goals>


Test patch:
diff --git a/docs/asciidoc/testing.adoc b/docs/asciidoc/testing.adoc
index f7c0e730f..2a0e1b774 100644
--- a/docs/asciidoc/testing.adoc
+++ b/docs/asciidoc/testing.adoc
@@ -39,7 +39,7 @@ class App: Kooby({
 [source,java,role="primary"]
 ----
 
-import io.jooby.MockRouter;
+import io.jooby.test.MockRouter;
 
 public class TestApp {
   
@@ -54,7 +54,7 @@ public class TestApp {
 .Kotlin
 [source,kotlin,role="secondary"]
 ----
-import io.jooby.MockRouter
+import io.jooby.test.MockRouter
 
 class TestApp {
   
diff --git a/modules/jooby-hikari/src/test/java/com/mysql/cj/jdbc/MysqlDataSource.java b/modules/jooby-hikari/src/test/java/com/mysql/cj/jdbc/MysqlDataSource.java
deleted file mode 100644
index d493ecdd8..000000000
--- a/modules/jooby-hikari/src/test/java/com/mysql/cj/jdbc/MysqlDataSource.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Jooby https://jooby.io
- * Apache License Version 2.0 https://jooby.io/LICENSE.txt
- * Copyright 2014 Edgar Espina
- */
-package com.mysql.cj.jdbc;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.logging.Logger;
-
-import javax.sql.DataSource;
-
-public class MysqlDataSource implements DataSource {
-  @Override
-  public Connection getConnection() throws SQLException {
-    return null;
-  }
-
-  @Override
-  public Connection getConnection(String username, String password) throws SQLException {
-    return null;
-  }
-
-  @Override
-  public PrintWriter getLogWriter() throws SQLException {
-    return null;
-  }
-
-  @Override
-  public void setLogWriter(PrintWriter out) throws SQLException {}
-
-  @Override
-  public void setLoginTimeout(int seconds) throws SQLException {}
-
-  @Override
-  public int getLoginTimeout() throws SQLException {
-    return 0;
-  }
-
-  @Override
-  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
-    return null;
-  }
-
-  @Override
-  public <T> T unwrap(Class<T> iface) throws SQLException {
-    return null;
-  }
-
-  @Override
-  public boolean isWrapperFor(Class<?> iface) throws SQLException {
-    return false;
-  }
-}
diff --git a/modules/jooby-openapi/src/test/kotlin/kt/i3217/App3217.kt b/modules/jooby-openapi/src/test/kotlin/kt/i3217/App3217.kt
deleted file mode 100644
index ded410722..000000000
--- a/modules/jooby-openapi/src/test/kotlin/kt/i3217/App3217.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Jooby https://jooby.io
- * Apache License Version 2.0 https://jooby.io/LICENSE.txt
- * Copyright 2014 Edgar Espina
- */
-package kt.i3217
-
-import io.jooby.annotation.GET
-import io.jooby.kt.Kooby
-
-class App3217 :
-  Kooby({
-    // mount the script router
-    mount(ScriptRouter3217())
-    // mount the mvc router
-    mvc(MvcRouter3217())
-  })
-
-// a router using script api
-class ScriptRouter3217 : Kooby({ get("/api-script/beans") { listOf(SomeBean3217("foo")) } })
-
-// a router using mvc api for comparison
-class MvcRouter3217 {
-
-  @GET("/api-mvc/beans") fun getBeans() = listOf(SomeBean3217("bar"))
-}
diff --git a/modules/jooby-openapi/src/test/kotlin/kt/i3217/Issue3217.kt b/modules/jooby-openapi/src/test/kotlin/kt/i3217/Issue3217.kt
deleted file mode 100644
index ebadd4875..000000000
--- a/modules/jooby-openapi/src/test/kotlin/kt/i3217/Issue3217.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Jooby https://jooby.io
- * Apache License Version 2.0 https://jooby.io/LICENSE.txt
- * Copyright 2014 Edgar Espina
- */
-package kt.i3217
-
-import io.jooby.openapi.OpenAPIResult
-import io.jooby.openapi.OpenAPITest
-import io.jooby.openapi.RouteIterator
-import org.junit.jupiter.api.Assertions.assertEquals
-
-class Issue3217 {
-
-  @OpenAPITest(value = App3217::class)
-  fun shouldFindBeanTypeOnKtCollections(iterator: RouteIterator) {
-    iterator
-      .next { route ->
-        assertEquals("java.util.List<kt.i3217.SomeBean3217>", route.defaultResponse.javaType)
-      }
-      .next { route ->
-        assertEquals("java.util.List<kt.i3217.SomeBean3217>", route.defaultResponse.javaType)
-      }
-      .verify()
-  }
-
-  @OpenAPITest(value = App3217::class)
-  fun shouldFindBeanTypeOnKtCollectionsAndRenderGoodYAML(result: OpenAPIResult) {
-    assertEquals(
-      "openapi: 3.0.1\n" +
-        "info:\n" +
-        "  title: 3217 API\n" +
-        "  description: 3217 API description\n" +
-        "  version: \"1.0\"\n" +
-        "paths:\n" +
-        "  /api-script/beans:\n" +
-        "    get:\n" +
-        "      operationId: getApiScriptBeans\n" +
-        "      responses:\n" +
-        "        \"200\":\n" +
-        "          description: Success\n" +
-        "          content:\n" +
-        "            application/json:\n" +
-        "              schema:\n" +
-        "                type: array\n" +
-        "                items:\n" +
-        "                  \$ref: '#/components/schemas/SomeBean3217'\n" +
-        "  /api-mvc/beans:\n" +
-        "    get:\n" +
-        "      operationId: getBeans\n" +
-        "      responses:\n" +
-        "        \"200\":\n" +
-        "          description: Success\n" +
-        "          content:\n" +
-        "            application/json:\n" +
-        "              schema:\n" +
-        "                type: array\n" +
-        "                items:\n" +
-        "                  \$ref: '#/components/schemas/SomeBean3217'\n" +
-        "components:\n" +
-        "  schemas:\n" +
-        "    SomeBean3217:\n" +
-        "      type: object\n" +
-        "      properties:\n" +
-        "        name:\n" +
-        "          type: string\n",
-      result.toYaml()
-    )
-  }
-}
diff --git a/modules/jooby-openapi/src/test/kotlin/kt/i3217/SomeBean3217.kt b/modules/jooby-openapi/src/test/kotlin/kt/i3217/SomeBean3217.kt
deleted file mode 100644
index 8e922fad9..000000000
--- a/modules/jooby-openapi/src/test/kotlin/kt/i3217/SomeBean3217.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Jooby https://jooby.io
- * Apache License Version 2.0 https://jooby.io/LICENSE.txt
- * Copyright 2014 Edgar Espina
- */
-package kt.i3217
-
-data class SomeBean3217(val name: String)
diff --git a/modules/jooby-test/pom.xml b/modules/jooby-test/pom.xml
index 326601be0..cf5a194b3 100644
--- a/modules/jooby-test/pom.xml
+++ b/modules/jooby-test/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>modules</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/tests/pom.xml b/tests/pom.xml
index 60f1aee7b..23508c0fd 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>io.jooby</groupId>
     <artifactId>jooby-project</artifactId>
-    <version>3.0.8-SNAPSHOT</version>
+    <version>3.0.7-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -192,7 +192,7 @@
     <dependency>
       <groupId>org.webjars.npm</groupId>
       <artifactId>vue</artifactId>
-      <version>3.3.11</version>
+      <version>3.3.4</version>
     </dependency>
 
     <dependency>
diff --git a/tests/src/test/java/io/jooby/i3267/Issue3267.java b/tests/src/test/java/io/jooby/i3267/Issue3267.java
deleted file mode 100644
index b848f073a..000000000
--- a/tests/src/test/java/io/jooby/i3267/Issue3267.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Jooby https://jooby.io
- * Apache License Version 2.0 https://jooby.io/LICENSE.txt
- * Copyright 2014 Edgar Espina
- */
-package io.jooby.i3267;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.function.Function;
-
-import io.jooby.MediaType;
-import io.jooby.handler.Asset;
-import io.jooby.handler.AssetHandler;
-import io.jooby.handler.AssetSource;
-import io.jooby.junit.ServerTest;
-import io.jooby.junit.ServerTestRunner;
-
-public class Issue3267 {
-
-  @ServerTest
-  public void shouldSupportCustomCharset(ServerTestRunner runner) {
-    runner
-        .define(
-            app -> {
-              var source = AssetSource.create(app.getClassLoader(), "/www");
-              app.assets("/3267/default/?*", new AssetHandler(source));
-
-              // GBK
-              var gbk = MediaType.valueOf("text/html;charset=GBK");
-              Function<Asset, MediaType> overrideCharset =
-                  asset -> {
-                    var defaultType = asset.getContentType();
-                    // Choose what is best for you
-                    if (defaultType.matches(gbk)) {
-                      return gbk;
-                    }
-                    return defaultType;
-                  };
-              app.assets(
-                  "/3267/gbk/?*", new AssetHandler(source).setMediaTypeResolver(overrideCharset));
-            })
-        .ready(
-            http -> {
-              http.get(
-                  "/3267/default",
-                  rsp -> {
-                    assertEquals("index.html", rsp.body().string().trim());
-                    assertEquals(
-                        "text/html;charset=utf-8",
-                        rsp.body().contentType().toString().toLowerCase());
-                  });
-              http.get(
-                  "/3267/gbk",
-                  rsp -> {
-                    assertEquals("index.html", rsp.body().string().trim());
-                    assertEquals(
-                        "text/html;charset=gbk", rsp.body().contentType().toString().toLowerCase());
-                  });
-            });
-  }
-}