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

Parent class generic collection field not working #124

Closed
GoodforGod opened this issue Jan 28, 2022 · 5 comments
Closed

Parent class generic collection field not working #124

GoodforGod opened this issue Jan 28, 2022 · 5 comments
Assignees
Labels
type: bug Something isn't working

Comments

@GoodforGod
Copy link

Expected Behavior

When we have class that is like:

class Sup<T> {
    public List<T> value;
}

And its child extends such class:

class Sub extends Sup<String> {
}

Expecting serialization works properly, not 100% sure that you will support such case, but looks like legit one (this is expected to any Collection like, Collection, Set, List interfaces)

I see that it could be like and work successfully:

class Sub extends Sup<List<String>> {
}

But some times that's not the case in some DTOs behavior/design

Actual Behaviour

Tests from above fails with:

example/Sub.java:14: error: cannot find symbol
    public List<T> value;
           ^
  symbol:   class List
  location: class example.Sup<T>
java.lang.RuntimeException: example/Sub.java:14: error: cannot find symbol
    public List<T> value;
           ^
  symbol:   class List
  location: class example.Sup<T>
	at io.micronaut.annotation.processing.test.JavaParser.generate(JavaParser.java:275)
	at io.micronaut.annotation.processing.test.JavaParser.generate(JavaParser.java:230)
	at io.micronaut.annotation.processing.test.AbstractTypeElementSpec.buildContext(AbstractTypeElementSpec.groovy:213)
	at io.micronaut.serde.jackson.JsonCompileSpec.buildContext(JsonCompileSpec.groovy:107)
	at io.micronaut.serde.jackson.object.ObjectSerdeSpec.generic collection member supertype(ObjectSerdeSpec.groovy:2186)

Steps To Reproduce

Here is test that reproduces this issue as analog to (

void 'generic supertype'() {
given:
def compiled = buildContext('example.Sub', '''
package example;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.serde.annotation.Serdeable;
@Serdeable
class Sub extends Sup<String> {
}
@Serdeable
@Introspected(accessKind = Introspected.AccessKind.FIELD)
class Sup<T> {
public T value;
}
''')
expect:
jsonMapper.readValue('{"value":"bar"}', typeUnderTest).value == 'bar'
}
)

    void 'generic collection member supertype'() {
        given:
        def compiled = buildContext('example.Sub', '''
package example;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.serde.annotation.Serdeable;

@Serdeable
class Sub extends Sup<String> {
}

@Serdeable
@Introspected(accessKind = Introspected.AccessKind.FIELD)
class Sup<T> {
    public List<T> value;
}
''')

        expect:
        jsonMapper.readValue('{"value":"bar"}', typeUnderTest).value == 'bar'
    }

Environment Information

Just cloned repo, added this test and run

Example Application

No response

Version

3.3.0

@GoodforGod
Copy link
Author

I'll try to dig and fing the issue, but thats difficult to navigate in processors looking at project first time, so this may took some time for me

@graemerocher graemerocher self-assigned this Jan 31, 2022
@graemerocher graemerocher added the type: bug Something isn't working label Jan 31, 2022
@graemerocher
Copy link
Contributor

Don't worry will take a look, thanks for the good report

graemerocher added a commit that referenced this issue Jan 31, 2022
@graemerocher
Copy link
Contributor

Hmm I added a test and it passed #127

Can you provide a sample project?

@GoodforGod
Copy link
Author

GoodforGod commented Jan 31, 2022

Hello, yes my bad, I didn't properly checked test myself, thought the problem is just with List/Collection parent types, case is a bit complex, thats when the generic type is complex itself, here some tests below that represent my situation

In my project I had the same case, when parent have List type and the T type is actually some other DTO class, hope this tests below illustrates the issue I faced. I checked tests below they fail.
Im my app I was using Micronaut Client and Controller and similar DTO setup, can't find exact code

May be tests are inaccurate or I did something wrong actually

    void 'generic complex collection member supertype serialize'() {
        given:
        def compiled = buildContext('example.Sub', '''
package example;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.serde.annotation.Serdeable;
import java.util.List;

@Serdeable
class Typo {
    public String name;
}

@Serdeable
class Sub extends Sup<Typo> {
}

@Serdeable
@Introspected(accessKind = Introspected.AccessKind.FIELD)
class Sup<T> {
    public List<T> value;
}
''')

        def baseClass = compiled.classLoader.loadClass('example.Sub')
        def a = newInstance(compiled, 'example.Sub')
        def typo = newInstance(compiled, 'example.Typo')
        typo.name = "Bob"
        a.value = Arrays.asList(typo);

        expect:
        serializeToString(jsonMapper, a, baseClass) == '{"value":[{"name":"Bob"}]}'
    }

    void 'generic complex collection member supertype deserialize'() {
        given:
        def compiled = buildContext('example.Sub', '''
package example;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.serde.annotation.Serdeable;
import java.util.List;

@Serdeable
class Typo {
    public String name;
}

@Serdeable
class Sub extends Sup<Typo> {
}

@Serdeable
@Introspected(accessKind = Introspected.AccessKind.FIELD)
class Sup<T> {
    public List<T> value;
}
''')

        expect:
        def baseClass = compiled.classLoader.loadClass('example.Sub')
        deserializeFromString(jsonMapper, baseClass, '{"value":[{"name":"Bob"}]}').value.get(0).name == 'Bob'
    }

graemerocher added a commit that referenced this issue Feb 24, 2022
graemerocher added a commit that referenced this issue Feb 24, 2022
@graemerocher
Copy link
Contributor

Issue was unrelated to generics, you were missing the access kind field declaration for child classes ccf5385

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants