Ok, code has a few problems.

First: method `constructFromCanonical()` really isn't meant to be
end-user functionality.
Maybe Javadocs should make this clear, but it is not something I was
planning to be used by anything but core Jackson functionality. I can
sort of see why it might seem useful, but there is one big problem
using it for persisting generic type...

The problem is this: all instances of generic types, at runtime, are
subject to type erasure.
So you will not be able to obtain any more information than actual
underlying `Class<?>`.
This being the case you might as well just access `class.getName()`
and use that.
This is different from programmatically constructed `JavaType`
instances which can and do retain generic type information; but this
comes from property type (and class super type) declarations.

So use of:

 JavaType type = typeFactory.constructType(list.getClass());

tends not to work as expected: none of generic types are preserved.

In this case it is also possible that canonical name handling isn't
working like it should (maybe worth filing a bug for), since it should
always be possible to read back canonical name you created.
However, I don't think it would work for your use case: it can not be
any better than simply serializing name of the `Class` you have, due
to type erasure.

Going back to persisting type externally: you should either serialize
simple class name (safest), or, if you absolutely need generic typing,
programmatically construct generic type using `TypeFactory`, and then
get canonical name.

I hope this helps,

-+ Tatu +-


On Tue, Jan 31, 2017 at 2:18 AM,  <thorben.lindha...@camunda.com> wrote:
> Hi,
>
> Jackson-databind version: 2.8.6
>
> I have a class that implements java.util.List with a compile-time defined
> generic type, e.g.
>
> public static class WrapperList implements List<Byte>
> {
>    // delegate to methods of a wrapped ArrayList
> }
>
> Now I want to use TypeFactory to create a canonical String representation of
> that type that I can persist and later use for (de-)serialization, e.g.
>
> WrapperList list = new WrapperList();
> list.add((byte) 10);
>
> ObjectMapper mapper = new ObjectMapper();
> TypeFactory typeFactory = mapper.getTypeFactory();
> JavaType type = typeFactory.constructType(list.getClass());
> String canonicalTypeName = type.toCanonical();
>
> This results in canonicalTypeName being
> org.camunda.bpm.Main$WrapperList<java.lang.Byte>. However, calling
>
> typeFactory.constructFromCanonical(canonicalTypeName);
>
> results in the following exception:
>
> Exception in thread "main" java.lang.IllegalArgumentException: Can not
> create TypeBindings for class org.camunda.bpm.Main$WrapperList with 1 type
> parameter: class expects 0
>     at
> com.fasterxml.jackson.databind.type.TypeBindings.create(TypeBindings.java:125)
>     at
> com.fasterxml.jackson.databind.type.TypeBindings.create(TypeBindings.java:95)
>     at
> com.fasterxml.jackson.databind.type.TypeBindings.create(TypeBindings.java:86)
>     at
> com.fasterxml.jackson.databind.type.TypeParser.parseType(TypeParser.java:54)
>     at
> com.fasterxml.jackson.databind.type.TypeParser.parse(TypeParser.java:33)
>     at
> com.fasterxml.jackson.databind.type.TypeFactory.constructFromCanonical(TypeFactory.java:544)
>     at com.example.Main.main(Main.java:42)
>
> Am I using the wrong method for creating the JavaType in this case?
>
> Cheers,
> Thorben
>
> PS: Here's the full code example for reference:
>
> package com.example;
>
> import java.io.IOException;
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.Iterator;
> import java.util.List;
> import java.util.ListIterator;
>
> import com.fasterxml.jackson.databind.JavaType;
> import com.fasterxml.jackson.databind.ObjectMapper;
> import com.fasterxml.jackson.databind.type.TypeFactory;
>
> public class Main {
>
>   public static void main(String[] args) throws IOException {
>     WrapperList list = new WrapperList();
>     list.add((byte) 10);
>
>     ObjectMapper mapper = new ObjectMapper();
>     TypeFactory typeFactory = mapper.getTypeFactory();
>     JavaType type = typeFactory.constructType(list.getClass());
>     System.out.println(type.toCanonical());
>
>     JavaType reconstructedType =
> typeFactory.constructFromCanonical(type.toCanonical());
>   }
>
>   public static class WrapperList implements List<Byte>
>   {
>     protected List<Byte> innerList = new ArrayList<Byte>();
>
>     public int size() {
>       return innerList.size();
>     }
>
>
>     public boolean isEmpty() {
>       return innerList.isEmpty();
>     }
>
>
>     public boolean contains(Object o) {
>       return innerList.contains(o);
>     }
>
>
>     public Iterator<Byte> iterator() {
>       return innerList.iterator();
>     }
>
>
>     public Object[] toArray() {
>       return innerList.toArray();
>     }
>
>
>     public <T> T[] toArray(T[] a) {
>       return innerList.toArray(a);
>     }
>
>
>     public boolean add(Byte e) {
>       return innerList.add(e);
>     }
>
>
>     public boolean remove(Object o) {
>       return innerList.remove(o);
>     }
>
>
>     public boolean containsAll(Collection<?> c) {
>       return innerList.containsAll(c);
>     }
>
>
>     public boolean addAll(Collection<? extends Byte> c) {
>       return innerList.addAll(c);
>     }
>
>
>     public boolean addAll(int index, Collection<? extends Byte> c) {
>       return innerList.addAll(index, c);
>     }
>
>
>     public boolean removeAll(Collection<?> c) {
>       return innerList.removeAll(c);
>     }
>
>
>     public boolean retainAll(Collection<?> c) {
>       return innerList.retainAll(c);
>     }
>
>
>     public void clear() {
>       innerList.clear();
>     }
>
>
>     public boolean equals(Object o) {
>       return innerList.equals(o);
>     }
>
>
>     public int hashCode() {
>       return innerList.hashCode();
>     }
>
>
>     public Byte get(int index) {
>       return innerList.get(index);
>     }
>
>
>     public Byte set(int index, Byte element) {
>       return innerList.set(index, element);
>     }
>
>
>     public void add(int index, Byte element) {
>       innerList.add(index, element);
>     }
>
>
>     public Byte remove(int index) {
>       return innerList.remove(index);
>     }
>
>     public int indexOf(Object o) {
>       return innerList.indexOf(o);
>     }
>
>
>     public int lastIndexOf(Object o) {
>       return innerList.lastIndexOf(o);
>     }
>
>
>     public ListIterator<Byte> listIterator() {
>       return innerList.listIterator();
>     }
>
>
>     public ListIterator<Byte> listIterator(int index) {
>       return innerList.listIterator(index);
>     }
>
>
>     public List<Byte> subList(int fromIndex, int toIndex) {
>       return innerList.subList(fromIndex, toIndex);
>     }
>   }
>
> }
>
> --
> 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+unsubscr...@googlegroups.com.
> To post to this group, send email to jackson-user@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
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+unsubscr...@googlegroups.com.
To post to this group, send email to jackson-user@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to