Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deep Object format ignores values it can not convert #11331

Open
voronaam opened this issue Nov 8, 2024 · 2 comments
Open

Deep Object format ignores values it can not convert #11331

voronaam opened this issue Nov 8, 2024 · 2 comments

Comments

@voronaam
Copy link

voronaam commented Nov 8, 2024

Expected Behavior

When the user supplied value can not be converted to the desired type (e.g. UUID) an exception should be thrown.

Actual Behaviour

If the input invalid, the value is set to null (or default value for the type) as if there was no input at all.

Steps To Reproduce

  1. Sample controller to reproduce it with
package io.example;

import java.util.UUID;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.convert.format.Format;
import io.micronaut.http.annotation.*;
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.rules.SecurityRule;
import io.micronaut.serde.annotation.Serdeable;
import jakarta.validation.Valid;

@Controller("/test")
@Secured(SecurityRule.IS_ANONYMOUS)
public class TestController {

    @Get
    public String test(
        @QueryValue("filter") @Format("deep-object") @Valid RequestFilter requestFilter) {
            return "" + requestFilter.id;
    }

    @Serdeable
    @Introspected
    public static record RequestFilter (@Nullable UUID id) {};
}
  1. Execute request with a valid UUID all as expected:
curl 'http://localhost:8080/test?filter\[id\]=620a8db4-8890-4c14-b1f5-4ed2fac35e2c'
620a8db4-8890-4c14-b1f5-4ed2fac35e2c
  1. Execute request with an invalid UUID:
curl 'http://localhost:8080/test?filter\[id\]=blah'
null

I'd prefer a conversion error.

Note that the ConversionErrorException is thrown if the parameter was test(@QueryValue("id") UUID id) and user supplied an invalid value there.

Environment Information

  • Operating system: Linux
  • JDK: OpenJDK 21
$ java -version
java version "21.0.1" 2023-10-17
Java(TM) SE Runtime Environment Oracle GraalVM 21.0.1+12.1 (build 21.0.1+12-jvmci-23.1-b19)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 21.0.1+12.1 (build 21.0.1+12-jvmci-23.1-b19, mixed mode, sharing)

Example Application

No response

Version

4.6.3

@glorrian
Copy link
Contributor

glorrian commented Nov 9, 2024

why you cannot use simple conditional statement for null check and throw ex?
exception usually indicates a developer error at the code. here you have user error case so we don't have to throw an exception

@voronaam
Copy link
Author

voronaam commented Nov 9, 2024

why you cannot use simple conditional statement for null check and throw ex?

Because it is an optional parameter. Consider a classic example of a book store API where I'd have a method to list books /GET /books?[authorId={uuid}]. Since authorId is optional I will return all the books if it is null (missing). However, if user of the API asks for GET /books?authorId=620a8db4-8890-4c14-b1f5-4ed2fac35e2c I will return only books by this author. But if the user makes mistake and asks for GET /books?authorId=Tolkien I do not want to return all the books as if the authorId was legitimately null. I want to return an error to the user you must use id.

This works with Micronaut's top level @QueryValue parameters, but does not work for @Format("deep-object") @QueryValue.

This might also be the case for other @Format annotations - I have not checked. (The others are csv, ssv, pipes and multi). I am pretty sure multi works, but csv does not, but this bug is only about the deep-object format, as the current behavior makes the least sense there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants