Converter not being picked up despite having autoApply=true

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Converter not being picked up despite having autoApply=true

Andreas Joseph Krogh
Hi all.
 
I'm still juggeling with my EclipseLink test-project, https://github.com/andreak/hibernatetest, (on my quest for migrating away from Hibernate) and now I'm stuck with @Converter not being picked up. I'm having a Spring-wired environment (no persistence.xml etc.) and my @Converter class for converting joda-time's DateTime is not being picked up.
 
My converter looks like this:
@Converter(autoApply = true)
public class JodaDateTimeConverter implements AttributeConverter<DateTime, Timestamp> {

        @Override
        public Timestamp convertToDatabaseColumn(DateTime attribute) {
                if (attribute == null) {
                        return null;
                } else {
                        return new Timestamp(attribute.getMillis());
                }
        }

        @Override
        public DateTime convertToEntityAttribute(Timestamp dbData) {
                if (dbData == null) {
                        return null;
                } else {
                        return new DateTime(dbData.getTime());
                }
        }
}
 
Using DERBY as embedded DB, EclipseLink generates the following SQL:
[EL Fine]: sql: 2013-07-04 14:11:24.603--ServerSession(555941420)--Connection(1076476202)--Thread(Thread[main,5,main])--CREATE TABLE car (id BIGINT NOT NULL, created BLOB(2147483647) NOT NULL, model VARCHAR(255) NOT NULL, owner_name VARCHAR(255), data_id BIGINT, PRIMARY KEY (id))
 
Where "created" is of type org.joda.time.DateTime. As you can see EL creates a BLOB for that column, not Timestamp
 
In my real project I have a persistence-unit spread over lots of modules (maven) and have used Spring's "packagesToScan"-attribute of LocalContainerEntityManagerFactoryBean to locate all my entities and building up the PU, thus eliminating the need for maintaining persistence.xml/orm.xml.
<bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="packagesToScan" value="no.officenet.test"/>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <property name="jpaDialect" ref="jpaDialect"/>
        <property name="jpaProperties">
                <props>
                        <prop key="eclipselink.cache.shared.default">false</prop>
                        <prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
                </props>
        </property>
</bean>
I'd rather not have to maintain persistence.xml/orm.xml as it becomes a maintainence-nightmare when having lots modules.
 
I have also tried this with PostgreSQL as DB creating the column manually and then EL complains with:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Error converting parameter 0
Error Code: 0
Call: INSERT INTO car (created, model, owner_name, data_id, id) VALUES (?, ?, ?, ?, ?)
    bind => [[B@5c787c2d, Vamonda!, null, 36, 211]
Query: InsertObjectQuery(no.officenet.test.hibernatetest.model.Car@5eb9ec47)
 
Any help is most welcome, thanks.
 
--
Andreas Joseph Krogh <[hidden email]>      mob: +47 909 56 963
Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no
Public key: http://home.officenet.no/~andreak/public_key.asc

_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Converter not being picked up despite having autoApply=true

Guy Pelletier
Hi Andreas,

Not knowing the full details of the spring package scan tool, I suspect the @Converter class is not being returned from this scan and would explain why it is not being applied by EclipseLink.

Perhaps you could try including a persistence.xml file as a test and make sure the converter is listed there.

<class>JodaDateTimeConverter</class>


Also, if you have debugging capabilities, you could try looking at initPersistenceUnitClasses from org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor. That is where the @Converter would be picked up if found.

Cheers,
Guy

On 04/07/2013 8:21 AM, Andreas Joseph Krogh wrote:
Hi all.
 
I'm still juggeling with my EclipseLink test-project, https://github.com/andreak/hibernatetest, (on my quest for migrating away from Hibernate) and now I'm stuck with @Converter not being picked up. I'm having a Spring-wired environment (no persistence.xml etc.) and my @Converter class for converting joda-time's DateTime is not being picked up.
 
My converter looks like this:
@Converter(autoApply = true)
public class JodaDateTimeConverter implements AttributeConverter<DateTime, Timestamp> {

        @Override
        public Timestamp convertToDatabaseColumn(DateTime attribute) {
                if (attribute == null) {
                        return null;
                } else {
                        return new Timestamp(attribute.getMillis());
                }
        }

        @Override
        public DateTime convertToEntityAttribute(Timestamp dbData) {
                if (dbData == null) {
                        return null;
                } else {
                        return new DateTime(dbData.getTime());
                }
        }
}
 
Using DERBY as embedded DB, EclipseLink generates the following SQL:
[EL Fine]: sql: 2013-07-04 14:11:24.603--ServerSession(555941420)--Connection(1076476202)--Thread(Thread[main,5,main])--CREATE TABLE car (id BIGINT NOT NULL, created BLOB(2147483647) NOT NULL, model VARCHAR(255) NOT NULL, owner_name VARCHAR(255), data_id BIGINT, PRIMARY KEY (id))
 
Where "created" is of type org.joda.time.DateTime. As you can see EL creates a BLOB for that column, not Timestamp
 
In my real project I have a persistence-unit spread over lots of modules (maven) and have used Spring's "packagesToScan"-attribute of LocalContainerEntityManagerFactoryBean to locate all my entities and building up the PU, thus eliminating the need for maintaining persistence.xml/orm.xml.
<bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="packagesToScan" value="no.officenet.test"/>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <property name="jpaDialect" ref="jpaDialect"/>
        <property name="jpaProperties">
                <props>
                        <prop key="eclipselink.cache.shared.default">false</prop>
                        <prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
                </props>
        </property>
</bean>
I'd rather not have to maintain persistence.xml/orm.xml as it becomes a maintainence-nightmare when having lots modules.
 
I have also tried this with PostgreSQL as DB creating the column manually and then EL complains with:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Error converting parameter 0
Error Code: 0
Call: INSERT INTO car (created, model, owner_name, data_id, id) VALUES (?, ?, ?, ?, ?)
    bind => [[B@5c787c2d, Vamonda!, null, 36, 211]
Query: InsertObjectQuery(no.officenet.test.hibernatetest.model.Car@5eb9ec47)
 
Any help is most welcome, thanks.
 
--
Andreas Joseph Krogh [hidden email]      mob: +47 909 56 963
Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no
Public key: http://home.officenet.no/~andreak/public_key.asc


_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users

--

Oracle
Guy Pelletier

ORACLE Canada, 45 O'Connor Street Suite 400 Ottawa, Ontario Canada K1P 1A4

Green
            Oracle Oracle is committed to developing practices and products that help protect the environment


_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Converter not being picked up despite having autoApply=true

Andreas Joseph Krogh
På torsdag 04. juli 2013 kl. 15:26:23, skrev Guy Pelletier <[hidden email]>:
Hi Andreas,

Not knowing the full details of the spring package scan tool, I suspect the @Converter class is not being returned from this scan and would explain why it is not being applied by EclipseLink.

Perhaps you could try including a persistence.xml file as a test and make sure the converter is listed there.

<class>JodaDateTimeConverter</class>


Also, if you have debugging capabilities, you could try looking at initPersistenceUnitClasses from org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor. That is where the @Converter would be picked up if found.
 
Adding the following persistence.xml makes it work, both ddl-creation and inserting/retrieving:
 
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.1">
        <persistence-unit name="default">
                <class>no.officenet.test.hibernatetest.infrastructure.jpa.JodaDateTimeConverter</class>
        </persistence-unit>
</persistence>
 
So it seems it's Spring's package-scanning tool which needs to be updated to also add @Converter classes?
 
--
Andreas Joseph Krogh <[hidden email]>      mob: +47 909 56 963
Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no
Public key: http://home.officenet.no/~andreak/public_key.asc
 

_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Converter not being picked up despite having autoApply=true

Andreas Joseph Krogh
På torsdag 04. juli 2013 kl. 16:12:17, skrev Andreas Joseph Krogh <[hidden email]>:
På torsdag 04. juli 2013 kl. 15:26:23, skrev Guy Pelletier <[hidden email]>:
Hi Andreas,

Not knowing the full details of the spring package scan tool, I suspect the @Converter class is not being returned from this scan and would explain why it is not being applied by EclipseLink.

Perhaps you could try including a persistence.xml file as a test and make sure the converter is listed there.

<class>JodaDateTimeConverter</class>


Also, if you have debugging capabilities, you could try looking at initPersistenceUnitClasses from org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor. That is where the @Converter would be picked up if found.
 
Adding the following persistence.xml makes it work, both ddl-creation and inserting/retrieving:
 
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.1">
        <persistence-unit name="default">
                <class>no.officenet.test.hibernatetest.infrastructure.jpa.JodaDateTimeConverter</class>
        </persistence-unit>
</persistence>
 
So it seems it's Spring's package-scanning tool which needs to be updated to also add @Converter classes?
 
I added a custom PersistenceUnitPostProcessor to add @Converter classes:
public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {

        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AnnotationTypeFilter(Converter.class));

        for (BeanDefinition definition : provider.findCandidateComponents(basePackage)) {

                LOG.debug("Registering classpath-scanned entity %s in persistence unit info!", definition.getBeanClassName());
                pui.addManagedClassName(definition.getBeanClassName());
        }

}
It now works very well.
 
Thanks for all the help!
 
--
Andreas Joseph Krogh <[hidden email]>      mob: +47 909 56 963
Senior Software Developer / CTO - OfficeNet AS - http://www.officenet.no
Public key: http://home.officenet.no/~andreak/public_key.asc
 

_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users