7

I need to configure @TypeDefs for use custom @Type on package level. When I configured it following manner I am getting ClassNotFoundException. But when I put @TypeDefs on the class level it is working fine.

I have found similar kind of stackoverflow post but I haven't any idea to how to configure <resource package="com.foo.bar.thepackage"/> entry with my application-context.xml file.

According some post (as bellow), noted this a Spring related bug

I believe this is due to a bug in Spring, where it doesn't scan the annotations in package-info, but only those on classes annotated with @Entity, @Embeddable, or @MappedSuperclass. See https://jira.springsource.org/browse/SPR-8589. 

Can any one help me to resolve this issue. Thanks.

@TypeDefs declaration with package-info.java

@TypeDefs ({ @TypeDef( name="encryptedString", typeClass=EncryptedStringType.class, parameters={ @Parameter(name="encryptorRegisteredName", value="abcHibernateStringEncryptor") } ) }) package com.abc.core.model; import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDefs; import org.hibernate.annotations.Parameter; import org.jasypt.hibernate4.type.EncryptedStringType; 

application-context.xml

<!-- ############################### General Configurations #################################################### --> <!-- Enable annotation-driven configuration and auto-detection --> <context:annotation-config/> <!-- Enable Spring configuration-detection --> <context:spring-configured/> <!-- Scans the classpath of this application for @Components to deploy as beans --> <context:component-scan base-package="com.abc"/> <!-- Configure property placeholders for environment-specific properties customization --> <context:property-placeholder ignore-resource-not-found="true" location="classpath*:/project.properties"/> <!-- ############################### Persistence Related Configurations ######################################## --> <!-- JPA adapter --> <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> </bean> <!-- EntityManager factory --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" /> <property name="packagesToScan" value="com.abc.core.model" /> <property name="jpaProperties"> <props> <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> <prop key="hibernate.dialect">org.hibernate.dialect.PostgresPlusDialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">false</prop> <prop key="hibernate.use_sql_comments">false</prop> <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> <prop key="hibernate.connection.autocommit">false</prop> </props> </property> </bean> <!-- Transaction manager --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- JPA repositories --> <jpa:repositories base-package="com.abc" transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/> <!-- Use @Transactional annotation on methods --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <!-- ## JASYPT related configurations ## --> <!-- jasypt encryptor for string --> <bean id="abcStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"> <property name="algorithm"> <value>PBEWithMD5AndDES</value> </property> <property name="password"> <value>XXX</value> </property> </bean> <!-- hibernate encryptor for string --> <bean id="theHibernateStringEncryptor" class="org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor"> <property name="registeredName"> <value>abcHibernateStringEncryptor</value> </property> <property name="encryptor"> <ref bean="abcStringEncryptor" /> </property> </bean> 

Entity class with custom @Type mapping

package com.stee.rcm.core.model; @Entity @Table(name = "trail") public class Trail implements Serializable { @Id @GeneratedValue @Column(name = "ID") private Integer id; @Type(type="encryptedString") @Column(name = "DESCRIPTION") private String description; } 

Exception

Caused by: java.lang.ClassNotFoundException : encryptedString 
1
  • Anyone has a solution ? Commented Nov 10, 2017 at 13:40

1 Answer 1

1

I too faced same issue, It seems spring have some issue to scan TypeDef when they are at package-info.java class.

Declaring resource in the configuration is nothing but packagesToScan.You have already used in your configuration and even this does not help in scanning TypeDefs.

<resource package="com.foo.bar.thepackage"/> 

We can go with any of below approaches

  1. Declare TypeDef in each pojo classes(where ever userType/CustomType is used).
  2. Explicitly register CustomType to hibernate configuration.This can be done in two ways:
    1. Registering CustomType programmatic. configuration.registerTypeOverride(new EncryptedStringType(),new String[]{"encryptedString"});
    2. Declaring TypeDef in session factory bean configuration and extending local session factory bean.

Spring.xml :

<bean id="DateTypeSessionFactory" class="com.runtime.data.factory.TypeResolverSessionFactoryBean"> <property name="dataSource" ref="DateTypeDataSource"/> <property name="packagesToScan" value="com.p27.datetype"/> <property name="customTypes"> <array value-type="com.runtime.data.CustomType"> <ref bean="dateTimeCustomType"/> </array> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> ${DateType.dialect} </prop> <prop key="hibernate.show_sql"> false </prop> <prop key="hibernate.globally_quoted_identifiers"> false </prop> <prop key="hibernate.hbm2ddl.auto"> ${DateType.hbm2ddl} </prop> </props> </property> </bean> <bean id="persistentLocalDateTimeType" class="com.studio.common.data.type.WMPersistentLocalDateTime"/> <bean id="dateTimeCustomType" class="com.runtime.data.CustomType"> <property name="type" ref="persistentLocalDateTimeType"/> <property name="keys"> <list> <value>DateTime</value> <value>org.joda.time.LocalDateTime</value> </list> </property> </bean> public class CustomType { private UserType type; private String[] keys; //getters & setters } 

SessionFactoryBean :

public class TypeResolverSessionFactoryBean extends LocalSessionFactoryBean { private CustomType[] customTypes; @Override protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { if(customTypes != null) { registerCustomTypes(sfb); } return sfb.buildSessionFactory(); } protected void registerCustomTypes(LocalSessionFactoryBuilder sfb) { for (CustomType customType : customTypes) { sfb.registerTypeOverride(customType.getType(), customType.getKeys()); } } public void setCustomTypes(CustomType[] customTypes) { this.customTypes = customTypes; } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.