diff --git a/pom.xml b/pom.xml
index 2bd2fcf18..bd4b95e11 100644
--- a/pom.xml
+++ b/pom.xml
@@ -137,6 +137,13 @@
true
+
+ org.threeten
+ threetenbp
+ ${threetenbp}
+ true
+
+
diff --git a/src/main/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConverters.java b/src/main/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConverters.java
new file mode 100644
index 000000000..4c73340d6
--- /dev/null
+++ b/src/main/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConverters.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jpa.domain.support;
+
+import java.util.Date;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+
+import org.springframework.data.convert.Jsr310BackPortConverters.DateToInstantConverter;
+import org.springframework.data.convert.Jsr310BackPortConverters.DateToLocalDateConverter;
+import org.springframework.data.convert.Jsr310BackPortConverters.DateToLocalDateTimeConverter;
+import org.springframework.data.convert.Jsr310BackPortConverters.DateToLocalTimeConverter;
+import org.springframework.data.convert.Jsr310BackPortConverters.InstantToDateConverter;
+import org.springframework.data.convert.Jsr310BackPortConverters.LocalDateTimeToDateConverter;
+import org.springframework.data.convert.Jsr310BackPortConverters.LocalDateToDateConverter;
+import org.springframework.data.convert.Jsr310BackPortConverters.LocalTimeToDateConverter;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.threeten.bp.Instant;
+import org.threeten.bp.LocalDate;
+import org.threeten.bp.LocalDateTime;
+import org.threeten.bp.LocalTime;
+
+/**
+ * JPA 2.1 converters to turn ThreeTen back port types into legacy {@link Date}s. To activate these converters make sure
+ * your persistence provider detects them by including this class in the list of mapped classes. In Spring environments,
+ * you can simply register the package of this class (i.e. {@code org.springframework.data.jpa.domain.support}) as
+ * package to be scanned on e.g. the {@link LocalContainerEntityManagerFactoryBean}.
+ *
+ * @author Oliver Gierke
+ * @see http://www.threeten.org/threetenbp
+ */
+public class Jsr310BackPortJpaConverters {
+
+ @Converter(autoApply = true)
+ public static class LocalDateConverter implements AttributeConverter {
+
+ @Override
+ public Date convertToDatabaseColumn(LocalDate date) {
+ return LocalDateToDateConverter.INSTANCE.convert(date);
+ }
+
+ @Override
+ public LocalDate convertToEntityAttribute(Date date) {
+ return DateToLocalDateConverter.INSTANCE.convert(date);
+ }
+ }
+
+ @Converter(autoApply = true)
+ public static class LocalTimeConverter implements AttributeConverter {
+
+ @Override
+ public Date convertToDatabaseColumn(LocalTime time) {
+ return LocalTimeToDateConverter.INSTANCE.convert(time);
+ }
+
+ @Override
+ public LocalTime convertToEntityAttribute(Date date) {
+ return DateToLocalTimeConverter.INSTANCE.convert(date);
+ }
+ }
+
+ @Converter(autoApply = true)
+ public static class LocalDateTimeConverter implements AttributeConverter {
+
+ @Override
+ public Date convertToDatabaseColumn(LocalDateTime date) {
+ return LocalDateTimeToDateConverter.INSTANCE.convert(date);
+ }
+
+ @Override
+ public LocalDateTime convertToEntityAttribute(Date date) {
+ return DateToLocalDateTimeConverter.INSTANCE.convert(date);
+ }
+ }
+
+ @Converter(autoApply = true)
+ public static class InstantConverter implements AttributeConverter {
+
+ @Override
+ public Date convertToDatabaseColumn(Instant instant) {
+ return InstantToDateConverter.INSTANCE.convert(instant);
+ }
+
+ @Override
+ public Instant convertToEntityAttribute(Date date) {
+ return DateToInstantConverter.INSTANCE.convert(date);
+ }
+ }
+}
diff --git a/src/test/java/org/springframework/data/jpa/domain/support/AbstractAttributeConverterIntegrationTests.java b/src/test/java/org/springframework/data/jpa/domain/support/AbstractAttributeConverterIntegrationTests.java
new file mode 100644
index 000000000..b0be657a3
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/domain/support/AbstractAttributeConverterIntegrationTests.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jpa.domain.support;
+
+import javax.persistence.AttributeConverter;
+import javax.sql.DataSource;
+
+import org.junit.runner.RunWith;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jpa.domain.sample.User;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
+import org.springframework.orm.jpa.vendor.Database;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Base class for integration tests for JPA 2.1 {@link AttributeConverter} integration.
+ *
+ * @author Oliver Gierke
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+@Transactional
+public abstract class AbstractAttributeConverterIntegrationTests {
+
+ @Configuration
+ static class Config {
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+
+ AbstractJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ vendorAdapter.setDatabase(Database.HSQL);
+ vendorAdapter.setGenerateDdl(true);
+
+ LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
+ factory.setDataSource(dataSource());
+ factory.setPackagesToScan(getClass().getPackage().getName(), User.class.getPackage().getName());
+ factory.setJpaVendorAdapter(vendorAdapter);
+
+ return factory;
+ }
+
+ public @Bean PlatformTransactionManager transactionManager() {
+ return new JpaTransactionManager();
+ }
+
+ public @Bean DataSource dataSource() {
+ return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build();
+ }
+ }
+}
diff --git a/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java b/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java
index 9d4fe31fc..32c695c42 100644
--- a/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java
+++ b/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java
@@ -35,4 +35,9 @@ public class DateTimeSample {
LocalDate localDate;
LocalTime localTime;
LocalDateTime localDateTime;
+
+ org.threeten.bp.Instant bpInstant;
+ org.threeten.bp.LocalDate bpLocalDate;
+ org.threeten.bp.LocalTime bpLocalTime;
+ org.threeten.bp.LocalDateTime bpLocalDateTime;
}
diff --git a/src/test/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConvertersIntegrationTests.java b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConvertersIntegrationTests.java
new file mode 100644
index 000000000..96a1ab537
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConvertersIntegrationTests.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jpa.domain.support;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+import static org.springframework.data.jpa.support.EntityManagerTestUtils.*;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.junit.Test;
+import org.threeten.bp.Instant;
+import org.threeten.bp.LocalDate;
+import org.threeten.bp.LocalDateTime;
+import org.threeten.bp.LocalTime;
+
+/**
+ * Integration tests for {@link Jsr310BackPortJpaConverters}.
+ *
+ * @author Oliver Gierke
+ */
+public class Jsr310BackPortJpaConvertersIntegrationTests extends AbstractAttributeConverterIntegrationTests {
+
+ @PersistenceContext EntityManager em;
+
+ /**
+ * @see DATAJPA-650
+ */
+ @Test
+ public void usesJsr310BackPortJpaConverters() {
+
+ assumeTrue(currentEntityManagerIsAJpa21EntityManager(em));
+
+ DateTimeSample sample = new DateTimeSample();
+
+ sample.bpInstant = Instant.now();
+ sample.bpLocalDate = LocalDate.now();
+ sample.bpLocalTime = LocalTime.now();
+ sample.bpLocalDateTime = LocalDateTime.now();
+
+ em.persist(sample);
+ em.clear();
+
+ DateTimeSample result = em.find(DateTimeSample.class, sample.id);
+
+ assertThat(result, is(notNullValue()));
+ assertThat(result.bpInstant, is(sample.bpInstant));
+ assertThat(result.bpLocalDate, is(sample.bpLocalDate));
+ assertThat(result.bpLocalTime, is(sample.bpLocalTime));
+ assertThat(result.bpLocalDateTime, is(sample.bpLocalDateTime));
+ }
+}
diff --git a/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java
index 462ca2266..1982a4e97 100644
--- a/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java
+++ b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java
@@ -27,61 +27,15 @@ import java.time.LocalTime;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
-import javax.sql.DataSource;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.data.jpa.domain.sample.User;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
-import org.springframework.orm.jpa.JpaTransactionManager;
-import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
-import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
-import org.springframework.orm.jpa.vendor.Database;
-import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.annotation.Transactional;
/**
* Integration tests for {@link Jsr310JpaConverters}.
*
* @author Oliver Gierke
*/
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration
-@Transactional
-public class Jsr310JpaConvertersIntegrationTests {
-
- @Configuration
- static class Config {
-
- @Bean
- public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
-
- AbstractJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
- vendorAdapter.setDatabase(Database.HSQL);
- vendorAdapter.setGenerateDdl(true);
-
- LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
- factory.setDataSource(dataSource());
- factory.setPackagesToScan(getClass().getPackage().getName(), User.class.getPackage().getName());
- factory.setJpaVendorAdapter(vendorAdapter);
-
- return factory;
- }
-
- public @Bean PlatformTransactionManager transactionManager() {
- return new JpaTransactionManager();
- }
-
- public @Bean DataSource dataSource() {
- return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build();
- }
- }
+public class Jsr310JpaConvertersIntegrationTests extends AbstractAttributeConverterIntegrationTests {
@PersistenceContext EntityManager em;
diff --git a/template.mf b/template.mf
index 95ee501d7..d7fa9eb82 100644
--- a/template.mf
+++ b/template.mf
@@ -21,6 +21,7 @@ Import-Template:
org.springframework.*;version="${spring:[=.=.=.=,+1.1.0)}",
org.springframework.beans.factory.aspectj;version="${spring:[=.=.=.=,+1.1.0)}";resolution:=optional,
org.springframework.data.*;version="${springdata.commons:[=.=.=.=,+1.0.0)}",
+ org.threeten.bp.*;version="${threetenbp:[=.=.=,+1.0.0)}";resolution:=optional,
org.w3c.*;version="0.0.0"
Import-Package: org.aspectj.lang;version="${aspectj:[=.=.=,+1.0.0)}";resolution:=optional,
org.aspectj.runtime.reflect;version="${aspectj:[=.=.=,+1.0.0)}";resolution:=optional,