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

GuiceInjectableValues doesn't seem to work correctly #179

Open
plcarmel opened this issue May 26, 2022 · 2 comments
Open

GuiceInjectableValues doesn't seem to work correctly #179

plcarmel opened this issue May 26, 2022 · 2 comments
Labels

Comments

@plcarmel
Copy link

Looking at the code of GuiceInjectableValues, it seems unable to handle string values, which is what you get by default:

  @Override
  public Object findInjectableValue(
      Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance
  )
  {
    return injector.getInstance((Key<?>) valueId);
  }

We try to deserialize an object of class A:

package org.example;

import com.fasterxml.jackson.annotation.*;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

public class A
{
   private final String name;

   @Inject
   @JsonCreator
   A(@JacksonInject X x, @Assisted @JsonProperty("name") String name) {
       this.name = name;
   }

   public String getName() {
       return name;
   }
}

But valueId, in findInjectableValue, takes the name of the class, which is a string and cannot be converted to a Key, and we get an ClassCastException.

We ended-up creating our own InjectableValues subclass to handle this correctly:

package org.example;

import com.fasterxml.jackson.databind.*;
import com.google.inject.*;

public class WorkingGuiceInjectableValues extends InjectableValues
{
    private final Injector injector;

    public WorkingGuiceInjectableValues(Injector injector) {
        this.injector = injector;
    }

    public Object findInjectableValue(Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance) {
        try
        {
            return this.injector.getInstance(WorkingGuiceInjectableValues.class.getClassLoader().loadClass((String)valueId));
        }
        catch (ClassNotFoundException e)
        {
            throw new RuntimeException(e);
        }
    }
}

This is what the main of our small toy program looks like:

package org.example;

import java.io.*;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.module.guice.*;
import com.google.inject.Guice;

public class Main
{
    public static void main(String[] args) throws IOException
    {
        System.err.println("hello world");
        var objectMapper = new ObjectMapper();
        var injector = Guice.createInjector(new ObjectMapperModule(), new InjectionModule());
        var aFactory = injector.getInstance(AFactory.class);
        var a = aFactory.create("New instance of org.example.A !!!");
        System.err.println("a name: " + a.getName());
        var file = new File("a.json");
        objectMapper.writer().writeValue(file, a);
        var a2 = objectMapper.reader(new GuiceInjectableValues(injector)).readValue(file, A.class);
        System.err.println("a2 name: " + a2.getName());
    }
}

Version of guice: 5.1.0
Version of jackson-module-guice: 2.13.3

@plcarmel
Copy link
Author

Program is available on GitHub: https://github.com/plcarmel/jackson-test

@cowtowncoder
Copy link
Member

I don't know if the original author of this module is around any more, but if you were able to provide a PR against 2.14 I could merge improvements. I don't know how practical this would be wrt compatibility but if you think it is doable I always try to help get PRs merged.

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

No branches or pull requests

2 participants