Deserialize generated classes

393 views
Skip to first unread message

Marek Rogoziński

unread,
Nov 10, 2014, 5:44:23 PM11/10/14
to jackso...@googlegroups.com
Hello,

I am trying to derserialize to simple POJO. The interesting part is that the POJO class is generated with javassist. Everything works when I want to deserialize exactly the same type as
send to jackson.

The issue is when Jackson based on @JsonDeserialize(as=) tried to return implementation. For example:

mapper.reader().withType(cl).readValue(bytes);

(cl is a class generated by javassist implementing interfaces: User, Something and extends UserImpl)

 Jackson tries to return UserImpl and raise an error:

Failed to narrow type [simple type, class User#proxy1415658051724996000] with concrete-type annotation (value UserImpl), method 'User#proxy1415658051724996000': Class UserImpl is not assignable to User#proxy1415658051724996000

Exception comes from: com.fasterxml.jackson.databind.JavaType:

    protected void _assertSubclass(Class<?> subclass, Class<?> superClass) {

        if (!_class.isAssignableFrom(subclass)) {

            throw new IllegalArgumentException("Class "+subclass.getName()+" is not assignable to "+_class.getName());

        }

    }

And now the most interesting thing: In my code:

    UserImpl.class.isAssignableFrom(cl) returns true!

Maybe I did something wrong and the solution is obvious but I don't see it.

regards,

Marek

Tatu Saloranta

unread,
Nov 10, 2014, 6:12:14 PM11/10/14
to jackso...@googlegroups.com
That almost sounds as if a check was done in wrong order, i.e. arguments got mixed or something: error message differs from what you test slightly (assignable from vs to)

Would it be possible to write out a simple test case, where you just manually implement types, instead javassist?

-+ Tatu +-



--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Marek Rogoziński

unread,
Nov 10, 2014, 6:48:41 PM11/10/14
to jackso...@googlegroups.com
I will try but probably javassist is the key here. My code worked previously before the part with class generation was added. Anyway I will prepare simple test case for that.

Marek

Marek Rogoziński

unread,
Nov 10, 2014, 7:15:48 PM11/10/14
to jackso...@googlegroups.com
Hello,

Tatu, you have absolutely right with mixed arguments in my example. The issue is that isAssignableFrom() returns false even if object assignment is possible.


Btw dozer do something like that to detect proxies:

 public static final String CGLIB_ID = "$$EnhancerByCGLIB$$";
 public static final String JAVASSIST_ID = "$$_javassist";

  public static boolean isProxy(Class clazz) {
    //todo: implement a better way of determining this that is more generic
    return (clazz.getName().indexOf(MapperConstants.CGLIB_ID) >= 0 || clazz.getName().indexOf(MapperConstants.JAVASSIST_ID) >= 0);
  }

Not so pretty, but works (I hope)

Marek

Tatu Saloranta

unread,
Nov 10, 2014, 10:21:51 PM11/10/14
to jackso...@googlegroups.com
On Tue, Nov 11, 2014 at 12:15 AM, Marek Rogoziński <nneg...@gmail.com> wrote:
Hello,

Tatu, you have absolutely right with mixed arguments in my example. The issue is that isAssignableFrom() returns false even if object assignment is possible.

Ok.
 
Thanks.
 

Btw dozer do something like that to detect proxies:

 public static final String CGLIB_ID = "$$EnhancerByCGLIB$$";
 public static final String JAVASSIST_ID = "$$_javassist";

  public static boolean isProxy(Class clazz) {
    //todo: implement a better way of determining this that is more generic
    return (clazz.getName().indexOf(MapperConstants.CGLIB_ID) >= 0 || clazz.getName().indexOf(MapperConstants.JAVASSIST_ID) >= 0);
  }

Not so pretty, but works (I hope)

Jackson has some old checks for avoiding certain constructs, as well as proxy types. But the question there is what to do to make these constructs work...

-+ Tatu +-

Marek Rogoziński

unread,
Nov 11, 2014, 9:17:26 AM11/11/14
to jackso...@googlegroups.com
Do you think that modify com.fasterxml.jackson.databind.JavaType._assertSubclass()  and use  com.fasterxml.jackson.databind.util.ClassUtil.isProxyType(clazz) is a good solution? 
We could improve isProxyType to handle javassist and cglib (it checks only java and hibernate proxies now).

Marek

Tatu Saloranta

unread,
Nov 11, 2014, 12:36:22 PM11/11/14
to jackso...@googlegroups.com
On Tue, Nov 11, 2014 at 6:17 AM, Marek Rogoziński <nneg...@gmail.com> wrote:
Do you think that modify com.fasterxml.jackson.databind.JavaType._assertSubclass()

This is an important invariant, so unless there is a flaw in handling there, I don't know this could or should be changed.
 
 and use  com.fasterxml.jackson.databind.util.ClassUtil.isProxyType(clazz) is a good solution? 
We could improve isProxyType to handle javassist and cglib (it checks only java and hibernate proxies now).

If the problem is that Jackson should simply ignore fields with proxy types, this would definitely work.

But if the problem is handling of such properties, this wouldn't help a lot.

So I guess what I am saying is that it would be necessary to fully understand what is going on.

Reply all
Reply to author
Forward
0 new messages