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

Reflection registration for getter / setter #19

Open
cmdjulian opened this issue May 31, 2024 · 3 comments
Open

Reflection registration for getter / setter #19

cmdjulian opened this issue May 31, 2024 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@cmdjulian
Copy link

Is your feature request related to a problem? Please describe.
Lets say I have the following Java class:

@ReflectionHint
public class RootFs {
   private final String type;
   private final List diffIds;

   public RootFs(String type, List diffIds) {
      this.type = type;
      this.diffIds = diffIds;
   }

   public String getType() {
      return this.type;
   }

   public List getDiffIds() {
      return this.diffIds;
   }
}

What actually gets generated is:

[{
  "name": "de.cmdjulian.kirc.spec.image.RootFs",
  "allDeclaredConstructors": true,
  "allDeclaredFields": true,
  "allDeclaredMethods": true
}]

On the runtime, this registers querying of all the different methods, but it does not register the getters nor the constructor. When I know try to serialize / deserialize such a class with Jackson, I get an error as nor the constructor, nor the getters are registered.

Describe the solution you'd like
I'm not 100% sure how to resolve this, but I think maybe having a boolean flag in the annotation includeAccessors and includeConstructors with a default true setting would be the way to go. Additionally the annotation could be allowed to be placed on methods and constructors to register the annotated element as well.

Describe alternatives you've considered

Additional context
Atm is quite impossible to use the lib with classes which do depend on getter / setter / constructor serialization like jackson does

@cmdjulian cmdjulian added the enhancement New feature or request label May 31, 2024
@cmdjulian
Copy link
Author

Okay seems like this was my bad. The problem seems to be the missing allDeclaredClasses property. From my feeling this should be included in the the ALL_DECLARED category.
Regardless, I would still vouch for having the ability to annotate constructor, field or method directly and register those

@GoodforGod
Copy link
Owner

Hi, I’ll check behavior, last time everything was working and I have working prototypes with such examples that were fine, will back when recheck Jackson behavior, maybe some changes in GraalVM

what GraalVM native image version/image you are using?

@cmdjulian
Copy link
Author

cmdjulian commented Jun 1, 2024

I use the newest GraalVM version for Java 21 and gradle native build tool 0.10.2.

I have the following Kotlin code:

@ReflectionHint
class Repository(@JsonValue private val value: String) : Comparable<Repository> {
    override fun compareTo(other: Repository): Int = value.compareTo(other.value)
    override fun equals(other: Any?): Boolean = other is Repository && other.value == value
    override fun hashCode(): Int = value.hashCode()
    override fun toString(): String = value

    companion object {
        @JvmStatic
        @JsonCreator
        fun of(repository: String) = Repository(repository)
    }
}

This translates to the following java code:

public final class Repository implements Comparable<Repository> {

    public static final Companion Companion = new Companion();

    @JsonValue
    private final String value;

    public Repository(String value) {
        this.value = value;
    }

    public int compareTo(Repository other) {
        return this.value.compareTo(other.value);
    }

    public boolean equals(Object other) {
        return other instanceof Repository && Objects.equals(((Repository) other).value, this.value);
    }

    public int hashCode() {
        return this.value.hashCode();
    }

    public String toString() {
        return this.value;
    }

    @JsonCreator
    public static Repository of(String repository) {
        return Companion.of(repository);
    }

    public static final class Companion {
        private Companion() {
        }

        @JsonCreator
        public Repository of(String repository) {
            return new Repository(repository);
        }
    }
}

As you can see Kotlin creates a inner static class. When looking at the generated reflection data from the tracing agent, the following is request during runtime:

[
  {
    "name": "de.cmdjulian.kirc.image.Repository",
    "allDeclaredFields": true,
    "queryAllDeclaredMethods": true,
    "queryAllDeclaredConstructors": true,
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": [
          "java.lang.String"
        ]
      }
    ]
  },
  {
    "name": "de.cmdjulian.kirc.image.Repository$Companion",
    "allDeclaredFields": true,
    "queryAllDeclaredMethods": true,
    "queryAllDeclaredConstructors": true,
    "methods": [
      {
        "name": "of",
        "parameterTypes": [
          "java.lang.String"
        ]
      }
    ]
  }
]

When I also annotate the companion object, everything works @ReflectionHint companion object { ... }

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

No branches or pull requests

2 participants