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

ObjectMapper of @CustomSerialization has no effect #34934

Closed
geniusit opened this issue Jul 22, 2023 · 2 comments
Closed

ObjectMapper of @CustomSerialization has no effect #34934

geniusit opened this issue Jul 22, 2023 · 2 comments
Labels
area/rest kind/bug Something isn't working triage/invalid This doesn't seem right

Comments

@geniusit
Copy link

geniusit commented Jul 22, 2023

Describe the bug

I have a REST method with the @CustomSerialization annotation.
According to the documentation I have implemented the static class with the apply method. This method has an ObjectMapper as the first parameter.

The problem is the objectMapper has to be reinstanciate each time the method is called.

Concretely :

The addMixIn call has no effect.

return objectMapper.addMixIn(Buggy.class, NoTypes.class).writer();

I must do like this to customize the objectMapper :

return new ObjectMapper().addMixIn(Buggy.class, NoTypes.class).writer();

This is because somewhere else in the application I have this :

@Inject
    ObjectMapper mapper;

    public void buggyServiceMethod() {

        try {


            Map<String, Buggy> complexBuggyMap = new HashMap<>();
            complexBuggyMap.put("bug2", new SimpleBug("bug3"));
            Buggy complexBug = new ComplexBug(new SimpleBug("simple bug"), complexBuggyMap);

            //The bug is here! As soon as I use the injected mapper to write a !!ComplexBug!!, the @CustomSerialization requires to instanciate a new ObjectMapper(). There is absolutely NO PROBLEM if instead of writing a ComplexeBug I write a SimpleBug, and this is why this bug is really tricky!
            mapper.writeValueAsString(complexBug); //comment this line and the bug disappear
            //If here I instanciate the ObjectMapper the the @CustomSerialization will work perfectely! => new ObjectMapper().writeValueAsString(complexBug);
            //If I write a SimpleBug, the bug doesn't occur.
            //Like this :
            //mapper.writeValueAsString(new SimpleBug("bug1")); //you can uncomment this line and you will see there is no problem to use the method object mapper parameter of the apply method
            
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

The bug comes from my object model. I have an interface (Buggy) and two classes that implement it (SimpleBug and ComplexeBug)

There is no problem to use the objectMapper with the SimpleBug class. But if use the objectMapper with the ComplexeBug class then I need to reinstanciate the ObjectMapper each time for my MixIn to be applied

public static class MyBuggyClass implements BiFunction<ObjectMapper, Type, ObjectWriter> {

        @Override
        public ObjectWriter apply(ObjectMapper objectMapper, Type type) {

            //The addMinxIn as no effect because an object mapper has been used somewhere else in the application to write a !ComplexeBug! -> no problem with SimpleBug!
            return objectMapper.addMixIn(Buggy.class, NoTypes.class).writer();
            //To apply the MixIn I must do this :
            // return new ObjectMapper().addMixIn(Buggy.class, NoTypes.class).writer();
            // Why do I need to instanciate a new ObjectMapper() ???
        }
    }

Expected behavior

I don't have to reinstanciate the ObjectMapper class each time I want to use it.

The MixIn has been correctly applied.

{
    "bug2": {
        "simpleBug": {
            "name": "simple bug"
        },
        "bugs": {
            "bug2": {
                "name": "bug3"
            }
        },
        "name": "simple bug"
    },
    "bug1": {
        "name": "bug1"
    }
}

Actual behavior

The objectMapper parameter of the

 public ObjectWriter apply(ObjectMapper objectMapper, Type type)

seems to be corrupted or I don't know what's wrong with it.

As a result the MixIn has no effect. The "class" field should not be there

{
    "bug2": {
        "simpleBug": {
            "class": "serialization.SimpleBug",
            "name": "simple bug"
        },
        "bugs": {
            "bug2": {
                "class": "serialization.SimpleBug",
                "name": "bug3"
            }
        },
        "name": "simple bug"
    },
    "bug1": {
        "name": "bug1"
    }
}

I think the bug is tricky because of my object model. The SimpleBug class doesnt cause the bug. Only the ComplexeBug implementation. This is what I don t understand.

How to Reproduce?

bug.zip

Start the application :

1: mvn compile quarkus:dev -Dquarkus.http.port=8085
2: run that GET http method : http://localhost:8085/hello/bug

The response is buggy :

{
    "bug2": {
        "simpleBug": {
            "class": "serialization.SimpleBug",
            "name": "simple bug"
        },
        "bugs": {
            "bug2": {
                "class": "serialization.SimpleBug",
                "name": "bug3"
            }
        },
        "name": "simple bug"
    },
    "bug1": {
        "name": "bug1"
    }
}

There is 3 ways to get around the bug :

1 :
In BuggyService, replace the line 27 :

mapper.writeValueAsString(complexBug);

by

new ObjectMapper().writeValueAsString(complexBug);

2:
In BugResource line 46, replace the line

return objectMapper.addMixIn(Buggy.class, NoTypes.class).writer();

by

return new ObjectMapper().addMixIn(Buggy.class, NoTypes.class).writer();

3 :
In BuggyService, replace the line 27 :

mapper.writeValueAsString(complexBug);

by

objectMapper.writeValueAsString(new SimpleBug("bug"));

Then run the http GET request :

{
    "bug2": {
        "simpleBug": {
            "name": "simple bug"
        },
        "bugs": {
            "bug2": {
                "name": "bug3"
            }
        },
        "name": "simple bug"
    },
    "bug1": {
        "name": "bug1"
    }
}

The MixIn has been applied but none of these 3 workaround is acceptable.
The MixIn should be applied without the need to reinstanciate the ObjectMapper (1 and 2) and with both SimpleBug and ComplexeBug classes. (3)

Output of uname -a or ver

Windows 10

Output of java -version

openjdk version "17" 2021-09-14 OpenJDK Runtime Environment (build 17+35-2724) OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)

GraalVM version (if different from Java)

N/A

Quarkus version or git rev

3.2.1

Build tool (ie. output of mvnw --version or gradlew --version)

Maven home: C:\dev\apache-maven-3.8.2

Additional information

I use lombok. May be you will need to install the plugin if you use and IDE

@geniusit geniusit added the kind/bug Something isn't working label Jul 22, 2023
@quarkus-bot quarkus-bot bot added env/windows Impacts Windows machines triage/needs-triage labels Jul 22, 2023
@quarkus-bot
Copy link

quarkus-bot bot commented Jul 24, 2023

/cc @FroMage (resteasy-reactive), @Sgitario (resteasy-reactive), @stuartwdouglas (resteasy-reactive)

@geoand geoand added triage/needs-reproducer We are waiting for a reproducer. and removed env/windows Impacts Windows machines triage/needs-reproducer We are waiting for a reproducer. labels Jul 24, 2023
@geoand
Copy link
Contributor

geoand commented Jul 24, 2023

As is mentioned in the Javadoc of @CustomSerialization, you should never change the ObjectMapper in your BiFunction.

Your working example does

return new ObjectMapper().addMixIn(Buggy.class, NoTypes.class).writer();

while it's almost certainly best to do:

return objectMapper.copy().addMixIn(Buggy.class, NoTypes.class).writer();

@geoand geoand closed this as not planned Won't fix, can't repro, duplicate, stale Jul 24, 2023
@geoand geoand added the triage/invalid This doesn't seem right label Jul 24, 2023
geoand added a commit to geoand/quarkus that referenced this issue Jul 24, 2023
geoand added a commit to geoand/quarkus that referenced this issue Jul 24, 2023
geoand added a commit that referenced this issue Jul 24, 2023
Improve Javadoc of @CustomSerialization
gsmet pushed a commit to gsmet/quarkus that referenced this issue Jul 28, 2023
Relates to: quarkusio#34934

(cherry picked from commit b87954f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rest kind/bug Something isn't working triage/invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

2 participants