Reputation: 34071
I have created a web app with Vert.x as the following:
class MainVerticle : AbstractVerticle() {
private fun apiResource(r: Router): Unit {
r.route("/api/*")
.subRouter(GenderApi(vertx).create())
.subRouter(InterestApi(vertx).create())
}
private fun rootResource(r: Router): Unit {
r.route("/").handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am healthy");
}
}
override fun start(startPromise: Promise<Void>) {
val server = vertx.createHttpServer()
val router = Router.router(vertx)
apiResource(router)
rootResource(router)
server.requestHandler(router).listen(8888) { http ->
if (http.succeeded()) {
startPromise.complete()
println("HTTP server started on port 8888")
} else {
startPromise.fail(http.cause());
}
}
}
}
class InterestApi(private val vertx: Vertx) {
private val router = Router.router(vertx)
init {
readAll()
}
private fun readAll(): Route =
router
.get("/interests")
.handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am genders path");
}
fun create(): Router = router
}
class GenderApi(private val vertx: Vertx) {
private val router = Router.router(vertx)
init {
readAll()
}
private fun readAll() : Route =
router
.get("/genders")
.handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am genders path");
}
fun create(): Router = router
}
and the compiler complains:
java.lang.IllegalStateException: Only one sub router per Route object is allowed.
at io.vertx.ext.web.impl.RouteImpl.subRouter(RouteImpl.java:161)
at io.databaker.MainVerticle.apiResource(MainVerticle.kt:15)
at io.databaker.MainVerticle.start(MainVerticle.kt:33)
at io.vertx.core.impl.DeploymentManager.lambda$doDeploy$5(DeploymentManager.java:196)
at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:96)
at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:59)
at io.vertx.core.impl.EventLoopContext.lambda$runOnContext$0(EventLoopContext.java:40)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
How to solve it?
Upvotes: 0
Views: 188
Reputation: 17711
There is a better way to achieve that functionality, though. Instead of using subRouter
, you can use mountSubRouter
:
class MainVerticle : AbstractVerticle() {
private fun apiResource(r: Router) {
r.mountSubRouter("/api/", GenderApi(vertx).create())
r.mountSubRouter("/api/", InterestApi(vertx).create())
}
private fun rootResource(r: Router): Unit {
r.route("/").handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am healthy");
}
}
override fun start(startPromise: Promise<Void>) {
val server = vertx.createHttpServer()
val router = Router.router(vertx)
apiResource(router)
rootResource(router)
server.requestHandler(router).listen(8888) { http ->
if (http.succeeded()) {
startPromise.complete()
println("HTTP server started on port 8888")
} else {
println(http.cause())
startPromise.fail(http.cause());
}
}
}
}
class InterestApi(vertx: Vertx) {
private val router = Router.router(vertx)
init {
readAll()
}
private fun readAll(): Route =
router
.get("/interests")
.handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am interests path");
}
fun create(): Router = router
}
class GenderApi(vertx: Vertx) {
private val router = Router.router(vertx)
init {
readAll()
}
private fun readAll(): Route =
router
.get("/genders")
.handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am genders path");
}
fun create(): Router = router
}
Note that when using mountSubRouter
, you don't need *
after /api/*
, and in fact, this will produce an error.
Upvotes: 0
Reputation: 17711
I think I misled you with my previous answer.
The correct syntax for Vertx 4 is:
class MainVerticle : AbstractVerticle() {
private fun apiResource(r: Router) {
r.route("/api/genders*")
.subRouter(GenderApi(vertx).create())
r.route("/api/interests*")
.subRouter(InterestApi(vertx).create())
}
private fun rootResource(r: Router): Unit {
r.route("/").handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am healthy");
}
}
override fun start(startPromise: Promise<Void>) {
val server = vertx.createHttpServer()
val router = Router.router(vertx)
apiResource(router)
rootResource(router)
server.requestHandler(router).listen(8888) { http ->
if (http.succeeded()) {
startPromise.complete()
println("HTTP server started on port 8888")
} else {
println(http.cause())
startPromise.fail(http.cause());
}
}
}
}
class InterestApi(vertx: Vertx) {
private val router = Router.router(vertx)
init {
readAll()
}
private fun readAll(): Route =
router
.get("/")
.handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am genders path");
}
fun create(): Router = router
}
class GenderApi(vertx: Vertx) {
private val router = Router.router(vertx)
init {
readAll()
}
private fun readAll(): Route =
router
.get("/")
.handler {
val res = it.response()
res.putHeader("content-type", "text/plain");
// Write to the response and end it
res.end("I am genders path");
}
fun create(): Router = router
}
Using sub routers in Vert.x makes sense if you plan to use Interests
as a resource.
Then you would have something like:
router.get(...)
router.post(...)
Upvotes: 2