2
votes

I'm using hibernate-core 5.1.0 and I've implemented a converter that builds out a HashMap for a field. The issue is that hibernate is failing while building the sessionFactory. It's throwing a "Unable to instantiate AttributeConverter" and I've appended the entire trace.

The interesting part is that this exception goes away if I create a class that extends HashMap<String,String> and use that class in the converter (and the Hibernate entity class). It appears as if the converting type shouldnt use generics.

Are there other alternatives to solving this issue?

My Converter:

 @Converter(autoApply=true)
    public class JsonKeyValueConverter implements 
               AttributeConverter<HashMap<String, String>, String> // DOESNT work
              //AttributeConverter<ClassExtendingHashMap, String> // works
    {

        public String convertToDatabaseColumn(HashMap<String, String> arg0) {
            if ( arg0 == null ) {
                return null;
            }

            return DBUtility.GSON.toJson(arg0);
        }

        public KeyValueData convertToEntityAttribute(String arg0) {
            arg0 = StringUtils.isBlank(arg0) ? null : arg0;

            return (KeyValueData) DBUtility.GSON.fromJson(arg0, HashMap.class );
        }
    }

java.lang.IllegalStateException: Unable to instantiate AttributeConverter [org.labs.collab.repo.entity.conversion.JsonKeyValueConverter at org.hibernate.cfg.AbstractPropertyHolder.resolveAttributeConverterDefinition(AbstractPropertyHolder.java:98) at org.hibernate.cfg.annotations.PropertyBinder.makePropertyAndValue(PropertyBinder.java:195) at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:216) at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2238) at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:963) at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:796) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3788) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3742) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844) Caused by: org.hibernate.AnnotationException: Unable to create AttributeConverter instance at org.hibernate.cfg.AbstractPropertyHolder.makeAttributeConverterDefinition(AbstractPropertyHolder.java:132) at org.hibernate.cfg.AbstractPropertyHolder.resolveAttributeConverterDefinition(AbstractPropertyHolder.java:95) ... 27 more Caused by: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class at org.hibernate.cfg.AttributeConverterDefinition.(AttributeConverterDefinition.java:67) at org.hibernate.cfg.AbstractPropertyHolder.makeAttributeConverterDefinition(AbstractPropertyHolder.java:129) ... 28 more

Thanks!

1

1 Answers

2
votes

You are right, unfortunately, AttributeConverter doesn't work with parametric types(generics) so the easiest way is to use:

@Converter(autoApply=true)
public class JsonKeyValueConverter implements 
           AttributeConverter<HashMap, String> {

it allows you to use HashMap<String, String> directly inside your overridden methods.