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

Ignore super class methods / Classloader issue #1070

Open
cmelchior opened this Issue Jan 5, 2016 · 8 comments

Comments

Projects
None yet
8 participants
@cmelchior

cmelchior commented Jan 5, 2016

Use case: POJO that extends a 3rd party base class. The base class contains a method whose return type is not available to the ClassLoader.

This seems related to: https://github.com/FasterXML/jackson-databind/pull/785/files and #861

It doesn't look like it is possible to ignore methods/super class methods, only fields using the AnnotationIntrospector.

Example using Realm (https://github.com/realm/realm-java):

public class Foo extends RealmObject {
  private String bar;
  public void setBar(String bar) {
    this.bar = bar;
  }
  public String getBar() {
    return bar;
  }
}

The problematic method is asObservable() in RealmObject that returns an rx.Observable. RxJava is an optional dependency, so rx.Observable might not be available to the ClassLoader: https://github.com/realm/realm-java/blob/master/realm/realm-library/src/main/java/io/realm/RealmObject.java#L278-Lundefined

The stack trace from Jackson looks something like this:

java.lang.NoClassDefFoundError: rx.Observable
at libcore.reflect.InternalNames.getClass(InternalNames.java:55)
at java.lang.Class.getDexCacheType(Class.java:479)
at java.lang.reflect.ArtMethod.getDexCacheType(ArtMethod.java:191)
at java.lang.reflect.ArtMethod.getReturnType(ArtMethod.java:145)
at java.lang.reflect.Method.getReturnType(Method.java:184)
at java.lang.Class.getDeclaredMethods(Class.java:771)
at com.fasterxml.jackson.databind.introspect.AnnotatedClass._findClassMethods(AnnotatedClass.java:1046)
at com.fasterxml.jackson.databind.introspect.AnnotatedClass._addMemberMethods(AnnotatedClass.java:602)
at com.fasterxml.jackson.databind.introspect.AnnotatedClass.resolveMemberMethods(AnnotatedClass.java:431)
at com.fasterxml.jackson.databind.introspect.AnnotatedClass.memberMethods(AnnotatedClass.java:253)
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addMethods(POJOPropertiesCollector.java:477)
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:284)
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap(POJOPropertiesCollector.java:248)
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties(POJOPropertiesCollector.java:155)
at com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties(BasicBeanDescription.java:142)
at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties(BasicBeanDescription.java:217)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties(BasicDeserializerFactory.java:333)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:315)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:254)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:222)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:142)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:403)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:461)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3838)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3703)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2005)
at co.moonmonkeylabs.realmsearchview.example.MainActivity.loadBlogData(MainActivity.java:75)

Right now the only fix seems to be to create a dummy rx.Observable class that is empty, but maybe I am missing some configuration?

@cowtowncoder

This comment has been minimized.

Show comment
Hide comment
@cowtowncoder

cowtowncoder Jan 5, 2016

Member

The problem here is that the exception is thrown from very low level code, before actual annotation introspection occurs. So nothing in configuration would help, yet, as Jackson core is simply trying to make sense of methods and fields a Class has.

I wish I had good suggestions for how to tackle the issue. I guess fundamentally it might be possible to add some sort of extension to allow any processing of contents of specific types, similar to existing "ignorable types" (which is used to ignore properties of those types), but applied differently. Sort of like "ignorable parent types".

Other short-term work arounds would involve overriding methods in POJOPropertiesCollector (that is, sub-classing it, replacing with custom one), but since that is not designed as an extension point, I am not sure if that would work easily.

One other alternative would be to add generic MapperFeature for preventing inspection of parent types, at least for deserialization (for Serialization this would be unlikely to work well -- many JDK types have concrete type that only has a small subset of methods needed). But I am not sure whether it would work well in practice.
A combination of sorts would be to have an annotation that would indicate something like "Stop investigating parent types" on Class; or perhaps optionally even list parent types to ignore.
One challenge here is regarding access to annotation inspection; code that gets in trouble occurs before annotation inspection should occur (I think).

Member

cowtowncoder commented Jan 5, 2016

The problem here is that the exception is thrown from very low level code, before actual annotation introspection occurs. So nothing in configuration would help, yet, as Jackson core is simply trying to make sense of methods and fields a Class has.

I wish I had good suggestions for how to tackle the issue. I guess fundamentally it might be possible to add some sort of extension to allow any processing of contents of specific types, similar to existing "ignorable types" (which is used to ignore properties of those types), but applied differently. Sort of like "ignorable parent types".

Other short-term work arounds would involve overriding methods in POJOPropertiesCollector (that is, sub-classing it, replacing with custom one), but since that is not designed as an extension point, I am not sure if that would work easily.

One other alternative would be to add generic MapperFeature for preventing inspection of parent types, at least for deserialization (for Serialization this would be unlikely to work well -- many JDK types have concrete type that only has a small subset of methods needed). But I am not sure whether it would work well in practice.
A combination of sorts would be to have an annotation that would indicate something like "Stop investigating parent types" on Class; or perhaps optionally even list parent types to ignore.
One challenge here is regarding access to annotation inspection; code that gets in trouble occurs before annotation inspection should occur (I think).

@aldodevs

This comment has been minimized.

Show comment
Hide comment
@aldodevs

aldodevs commented Jun 7, 2016

+1

@BasanthVerma

This comment has been minimized.

Show comment
Hide comment
@BasanthVerma

BasanthVerma commented Dec 23, 2016

++

@AAverin

This comment has been minimized.

Show comment
Hide comment
@AAverin

AAverin Apr 4, 2017

Have the same exception happening only on Android 5.0.1/5.1.1.
Seems to be related to Jackson

AAverin commented Apr 4, 2017

Have the same exception happening only on Android 5.0.1/5.1.1.
Seems to be related to Jackson

@grennis

This comment has been minimized.

Show comment
Hide comment
@grennis

grennis Jun 13, 2017

Just defining a dummy class as recommended isn't enough anymore, now I also need the OnSubscribe interface like this:

package rx;

public class Observable {
    public interface OnSubscribe {
    }
}

This is making me very nervous, would love a proper fix.

grennis commented Jun 13, 2017

Just defining a dummy class as recommended isn't enough anymore, now I also need the OnSubscribe interface like this:

package rx;

public class Observable {
    public interface OnSubscribe {
    }
}

This is making me very nervous, would love a proper fix.

@GitHubMurt

This comment has been minimized.

Show comment
Hide comment
@GitHubMurt

GitHubMurt Jul 18, 2017

It happends me on Nougat and Marshmallow as well

GitHubMurt commented Jul 18, 2017

It happends me on Nougat and Marshmallow as well

@rogerioit

This comment has been minimized.

Show comment
Hide comment
@rogerioit

rogerioit Oct 9, 2017

Can someone take a look at this problem?!

It really bothers me to create an empty class and define an empty interface.

Thanks in advance.

rogerioit commented Oct 9, 2017

Can someone take a look at this problem?!

It really bothers me to create an empty class and define an empty interface.

Thanks in advance.

@cowtowncoder

This comment has been minimized.

Show comment
Hide comment
@cowtowncoder

cowtowncoder Oct 9, 2017

Member

@rogerioit Feel free to go ahead and figure out potential solution if you have itch here.

No one has proposed valid solution here yet, or, the usual starting point, unit test to reproduce the issue. Without one fixes are difficult to verify.
This is not a bug to fix, per se -- if system tries to load a class that refers to another class not found in classpath, it is quite natural that problems occur. It would be nice to have a way to handle this gracefully but it is not clear how this should be approached.
Asking for someone to solve this will not get you very far.

Member

cowtowncoder commented Oct 9, 2017

@rogerioit Feel free to go ahead and figure out potential solution if you have itch here.

No one has proposed valid solution here yet, or, the usual starting point, unit test to reproduce the issue. Without one fixes are difficult to verify.
This is not a bug to fix, per se -- if system tries to load a class that refers to another class not found in classpath, it is quite natural that problems occur. It would be nice to have a way to handle this gracefully but it is not clear how this should be approached.
Asking for someone to solve this will not get you very far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment