jooby-project / jooby

The modular web framework for Java and Kotlin
https://jooby.io
Apache License 2.0
1.7k stars 199 forks source link

415 unsupported media type when using mount to add routes #3500

Closed mgeorge closed 4 weeks ago

mgeorge commented 1 month ago

This is a weird one that started happening since 3.0.8 onwards.

If I add a POST route that is declared in another router via a mount then I get a 415 error when POSTing a valid JSON payload.

If I add the same route directly to the server, I get the expected valid response.

Best demonstrated via the following MWE:

import io.jooby.Jooby;
import io.jooby.StatusCode;
import io.jooby.gson.GsonModule;

public class WidgetService extends Jooby {

    public WidgetService() {
        install(new GsonModule());

        post("/api/widgets1", ctx -> {
            Widget widget = ctx.body().to(Widget.class);
            System.out.println("Created " + widget);
            return ctx.send(StatusCode.CREATED);
        });

        mount(new WidgetRouter());

    }

    public static void main(String[] args) {
        new WidgetService().start();
    }

}

class WidgetRouter extends Jooby {

    public WidgetRouter() {

        post("/api/widgets2", ctx -> {
            Widget widget = ctx.body().to(Widget.class);
            System.out.println("Created " + widget);
            return ctx.send(StatusCode.CREATED);
        });

    }
}

Widget is just a POJO with a couple of string fields.

A POST containing valid JSON to /api/widgets1 works and returns the expected 201 response.

The same POST to /api/widgets2 throws a 415 unsupported media type with the following stack trace:

ERROR WidgetService - POST /api/widgets2 415 Unsupported Media Type
 io.jooby.exception.UnsupportedMediaType: application/json
    at io.jooby.MessageDecoder.lambda$static$0(MessageDecoder.java:24)
    at io.jooby.DefaultContext.decode(DefaultContext.java:420)
    at io.jooby.internal.netty.NettyBody.to(NettyBody.java:103)
    at io.jooby.Body.to(Body.java:100)
    at WidgetRouter.lambda$new$baa66101$1(WidgetService.java:32)
    at io.jooby.internal.handler.DefaultHandler.lambda$apply$e67b40fd$1(DefaultHandler.java:21)
    at io.jooby.Route$Filter$1.apply(Route.java:94)
    at io.jooby.internal.handler.WorkerHandler.lambda$apply$0(WorkerHandler.java:22)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:1583)

I'm using the following dependencies in my build.gradle:

dependencies {
    def joobyVer = '3.2.7';
    implementation group: 'io.jooby', name: 'jooby-netty', version: joobyVer;
    implementation group: 'io.jooby', name: 'jooby-gson', version: joobyVer;
    implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.5.6';
}

I've been messing around with this for a bit trying to work out why my service started breaking after I upgraded from 3.0.7 to 3.2.7, and as far as I can tell, it is the use of mount to add the route that leads to the 415 error.

I've tried Jackson instead of Gson, and get the same result.

As mentioned, versions prior to 3.0.8 don't seem to have this problem.

kliushnichenko commented 1 month ago

try to use install(WidgetRouter::new) instead of mount

mgeorge commented 1 month ago

Thanks - that did the trick.

Does that mean that mount is now deprecated? The documentation still shows it as the first option for composing routers:

https://jooby.io/#router-composing-mount

mgeorge commented 1 month ago

Also, sometimes you just need to call the constructor on the router in order to pass parameters. The mount method is the obvious way to do this.

edgar-espina-wpp commented 1 month ago

mount should work. There is a silly difference between them: mount fetch install only routes from app, while install copy services, routes, etc...

kliushnichenko commented 1 month ago

if so, that https://github.com/jooby-project/jooby/issues/3400 was the bug as well. And a fix (or at least a part of it) is here https://github.com/jooby-project/jooby/pull/3401/commits/7370e5a7add3229558faaac18dbe09e4fd886b63, can revive the PR

jknack commented 1 month ago

@kliushnichenko first of all apologies for missing the point when you raised the bug, but yea this is the same bug as #3400. Going to send PR and you can look if I'm still missing something

kliushnichenko commented 1 month ago

no worries, appreciate your support

mgeorge commented 3 weeks ago

Can confirm that this fixes my problem. Thanks for the good work.