diff --git a/pom.xml b/pom.xml
index bd1ae1c9..f52e39cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
3.1.2.RELEASE
1.7.1
2.6
- 0.20.2
+ 0.20.4
4.2.2
1.4.0.RELEASE
2.1
diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Version.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Version.java
new file mode 100644
index 00000000..d31297d0
--- /dev/null
+++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Version.java
@@ -0,0 +1,10 @@
+package org.springframework.data.elasticsearch.annotations;
+
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Documented
+public @interface Version {
+}
diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java
index 8f26ff48..b1e41af7 100644
--- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java
+++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java
@@ -216,8 +216,12 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
private IndexRequestBuilder prepareIndex(IndexQuery query){
try {
ElasticsearchPersistentEntity persistentEntity = getPersistentEntityFor(query.getObject().getClass());
- return client.prepareIndex(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId())
+ IndexRequestBuilder indexRequestBuilder = client.prepareIndex(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId())
.setSource(objectMapper.writeValueAsString(query.getObject()));
+ if(query.getVersion() != null){
+ indexRequestBuilder.setVersion(query.getVersion());
+ }
+ return indexRequestBuilder;
} catch (IOException e) {
throw new ElasticsearchException("failed to index the document [id: " + query.getId() +"]",e);
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java
index 9bac38e2..1bc7aaf8 100644
--- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java
+++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java
@@ -21,5 +21,5 @@ public interface ElasticsearchPersistentEntity extends PersistentEntity {
INSTANCE;
diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java
index 82d8c182..5b96e51d 100644
--- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java
+++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java
@@ -22,6 +22,7 @@ import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.mapping.model.BasicPersistentEntity;
+import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;
@@ -41,6 +42,7 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit
private final StandardEvaluationContext context;
private String indexName;
private String indexType;
+ private ElasticsearchPersistentProperty versionProperty;
public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation) {
super(typeInformation);
@@ -70,4 +72,23 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit
public String getIndexType() {
return indexType;
}
+
+ @Override
+ public ElasticsearchPersistentProperty getVersionProperty() {
+ return this.versionProperty;
+ }
+
+ @Override
+ public void addPersistentProperty(ElasticsearchPersistentProperty property) {
+ super.addPersistentProperty(property);
+ if(property.isVersionProperty()){
+ if (this.versionProperty != null) {
+ throw new MappingException(String.format(
+ "Attempt to add version property %s but already have property %s registered "
+ + "as version. Check your mapping configuration!", property.getField(), versionProperty.getField()));
+ }
+ Assert.isTrue(property.getType() == Long.class, "Version property should be Long");
+ this.versionProperty = property;
+ }
+ }
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java
index 87073ee7..65e3fc5b 100644
--- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java
+++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java
@@ -15,6 +15,7 @@
*/
package org.springframework.data.elasticsearch.core.mapping;
+import org.springframework.data.elasticsearch.annotations.Version;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
@@ -55,7 +56,12 @@ public class SimpleElasticsearchPersistentProperty extends AnnotationBasedPersis
return super.isIdProperty() || SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName());
}
- @Override
+ @Override
+ public boolean isVersionProperty(){
+ return field.isAnnotationPresent(Version.class);
+ }
+
+ @Override
protected Association createAssociation() {
return null;
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java
index e6092366..ca84865f 100644
--- a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java
+++ b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java
@@ -5,6 +5,7 @@ public class IndexQuery{
private String id;
private Object object;
+ private Long version;
public String getId() {
return id;
@@ -21,4 +22,12 @@ public class IndexQuery{
public void setObject(Object object) {
this.object = object;
}
+
+ public Long getVersion() {
+ return version;
+ }
+
+ public void setVersion(Long version) {
+ this.version = version;
+ }
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java
index 5f8518b4..80a3e6b9 100644
--- a/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java
+++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/ElasticsearchEntityInformation.java
@@ -28,5 +28,6 @@ public interface ElasticsearchEntityInformation exte
String getIdAttribute();
String getIndexName();
String getType();
-
+ String getVersionAttribute();
+ Long getVersion(T entity);
}
diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java
index 2fbaa756..0f612a97 100644
--- a/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java
+++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/MappingElasticsearchEntityInformation.java
@@ -15,6 +15,8 @@
*/
package org.springframework.data.elasticsearch.repository.support;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.model.BeanWrapper;
@@ -32,6 +34,7 @@ import java.io.Serializable;
public class MappingElasticsearchEntityInformation extends AbstractEntityInformation
implements ElasticsearchEntityInformation {
+ private static final Logger logger = LoggerFactory.getLogger(MappingElasticsearchEntityInformation.class);
private final ElasticsearchPersistentEntity entityMetadata;
private final String indexName;
private final String type;
@@ -79,4 +82,24 @@ public class MappingElasticsearchEntityInformation e
public String getType() {
return type != null? type : entityMetadata.getIndexType();
}
+
+ @Override
+ public String getVersionAttribute() {
+ return entityMetadata.getVersionProperty().getFieldName();
+ }
+
+ @Override
+ public Long getVersion(T entity) {
+ ElasticsearchPersistentProperty versionProperty = entityMetadata.getIdProperty();
+ try {
+ if(versionProperty != null){
+ return (Long) BeanWrapper.create(entity, null).getProperty(versionProperty);
+ }
+ } catch (Exception e) {
+ logger.debug("failed to retrieve version", e);
+ }
+ return null;
+ }
}
+
+
diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java
index b3eb2a27..ebe84b9a 100644
--- a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java
+++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java
@@ -212,6 +212,7 @@ public class SimpleElasticsearchRepository implements ElasticsearchRepository
IndexQuery query = new IndexQuery();
query.setObject(entity);
query.setId(extractIdFromBean(entity));
+ query.setVersion(extractVersionFromBean(entity));
return query;
}
@@ -266,4 +267,11 @@ public class SimpleElasticsearchRepository implements ElasticsearchRepository
return null;
}
+ private Long extractVersionFromBean(T entity){
+ if (entityInformation != null) {
+ return entityInformation.getVersion(entity);
+ }
+ return null;
+ }
+
}
diff --git a/src/test/java/org/springframework/data/elasticsearch/Author.java b/src/test/java/org/springframework/data/elasticsearch/Author.java
index fc3b66d7..28c267e9 100644
--- a/src/test/java/org/springframework/data/elasticsearch/Author.java
+++ b/src/test/java/org/springframework/data/elasticsearch/Author.java
@@ -1,16 +1,9 @@
package org.springframework.data.elasticsearch;
public class Author {
- private String name;
- private String id;
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
+ private String id;
+ private String name;
public String getId() {
return id;
@@ -19,4 +12,12 @@ public class Author {
public void setId(String id) {
this.id = id;
}
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
}
diff --git a/src/test/java/org/springframework/data/elasticsearch/Book.java b/src/test/java/org/springframework/data/elasticsearch/Book.java
index eb4b2871..9f2e6e1a 100644
--- a/src/test/java/org/springframework/data/elasticsearch/Book.java
+++ b/src/test/java/org/springframework/data/elasticsearch/Book.java
@@ -4,9 +4,10 @@ import org.springframework.data.elasticsearch.annotations.Document;
@Document(indexName = "book",type = "book")
public class Book {
- private String id;
- private String name;
- private Author author;
+
+ private String id;
+ private String name;
+ private Author author;
public String getId() {
return id;
diff --git a/src/test/java/org/springframework/data/elasticsearch/SampleEntity.java b/src/test/java/org/springframework/data/elasticsearch/SampleEntity.java
index 1b8cdcce..3a556591 100644
--- a/src/test/java/org/springframework/data/elasticsearch/SampleEntity.java
+++ b/src/test/java/org/springframework/data/elasticsearch/SampleEntity.java
@@ -4,6 +4,7 @@ import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
+import org.springframework.data.elasticsearch.annotations.Version;
@Document(indexName = "test-index", type = "test-type")
public class SampleEntity {
@@ -14,6 +15,8 @@ public class SampleEntity {
private String message;
private int rate;
private boolean available;
+ @Version
+ private Long version;
public String getId() {
return id;
@@ -55,6 +58,14 @@ public class SampleEntity {
this.available = available;
}
+ public Long getVersion() {
+ return version;
+ }
+
+ public void setVersion(Long version) {
+ this.version = version;
+ }
+
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SampleEntity)) {
@@ -67,6 +78,9 @@ public class SampleEntity {
return new EqualsBuilder().append(this.id, rhs.id)
.append(this.type, rhs.type)
.append(this.message, rhs.message)
+ .append(this.rate,rhs.rate)
+ .append(this.available,rhs.available)
+ .append(this.version,rhs.version)
.isEquals();
}
@@ -76,6 +90,9 @@ public class SampleEntity {
.append(id)
.append(type)
.append(message)
+ .append(rate)
+ .append(available)
+ .append(version)
.toHashCode();
}
}
diff --git a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTest.java b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTest.java
new file mode 100644
index 00000000..a7dbd12a
--- /dev/null
+++ b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntityTest.java
@@ -0,0 +1,90 @@
+package org.springframework.data.elasticsearch.core.mapping;
+
+import org.junit.Test;
+import org.springframework.data.elasticsearch.annotations.Version;
+import org.springframework.data.mapping.model.MappingException;
+import org.springframework.data.mapping.model.SimpleTypeHolder;
+import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.TypeInformation;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+
+public class SimpleElasticsearchPersistentEntityTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionGivenVersionPropertyIsNotLong() throws NoSuchFieldException, IntrospectionException {
+ //given
+ TypeInformation typeInformation = ClassTypeInformation.from(EntityWithWrongVersionType.class);
+ SimpleElasticsearchPersistentProperty persistentProperty =
+ new SimpleElasticsearchPersistentProperty(EntityWithWrongVersionType.class.getDeclaredField("version"),
+ new PropertyDescriptor("version", EntityWithWrongVersionType.class),
+ new SimpleElasticsearchPersistentEntity(typeInformation),
+ new SimpleTypeHolder());
+
+ //when
+ new SimpleElasticsearchPersistentEntity(typeInformation).addPersistentProperty(persistentProperty);
+ }
+
+
+ @Test(expected = MappingException.class)
+ public void shouldThrowExceptionGivenMultipleVersionPropertiesArePresent() throws NoSuchFieldException, IntrospectionException {
+ //given
+ TypeInformation typeInformation = ClassTypeInformation.from(EntityWithMultipleVersionField.class);
+ SimpleElasticsearchPersistentProperty persistentProperty1 =
+ new SimpleElasticsearchPersistentProperty(EntityWithMultipleVersionField.class.getDeclaredField("version1"),
+ new PropertyDescriptor("version1", EntityWithMultipleVersionField.class),
+ new SimpleElasticsearchPersistentEntity(typeInformation),
+ new SimpleTypeHolder());
+
+ SimpleElasticsearchPersistentProperty persistentProperty2 =
+ new SimpleElasticsearchPersistentProperty(EntityWithMultipleVersionField.class.getDeclaredField("version2"),
+ new PropertyDescriptor("version2", EntityWithMultipleVersionField.class),
+ new SimpleElasticsearchPersistentEntity(typeInformation),
+ new SimpleTypeHolder());
+
+ SimpleElasticsearchPersistentEntity simpleElasticsearchPersistentEntity = new SimpleElasticsearchPersistentEntity(typeInformation);
+ simpleElasticsearchPersistentEntity.addPersistentProperty(persistentProperty1);
+ //when
+ simpleElasticsearchPersistentEntity.addPersistentProperty(persistentProperty2);
+ }
+
+
+ private class EntityWithWrongVersionType {
+ @Version
+ private String version;
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+
+ private class EntityWithMultipleVersionField{
+
+ @Version
+ private Long version1;
+ @Version
+ private Long version2;
+
+ public Long getVersion1() {
+ return version1;
+ }
+
+ public void setVersion1(Long version1) {
+ this.version1 = version1;
+ }
+
+ public Long getVersion2() {
+ return version2;
+ }
+
+ public void setVersion2(Long version2) {
+ this.version2 = version2;
+ }
+ }
+
+}
diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/RepositoryTest.java b/src/test/java/org/springframework/data/elasticsearch/repositories/RepositoryTest.java
index 097359e0..42d37e04 100644
--- a/src/test/java/org/springframework/data/elasticsearch/repositories/RepositoryTest.java
+++ b/src/test/java/org/springframework/data/elasticsearch/repositories/RepositoryTest.java
@@ -27,7 +27,6 @@ public class RepositoryTest {
@Resource
private SampleElasticsearchRepository repository;
-
@Test
public void shouldDoBulkIndexDocument(){
//given
@@ -148,7 +147,7 @@ public class RepositoryTest {
@Test
@Ignore
- public void testFindAllByIdQuery(){
+ public void shouldFindAllByIdQuery(){
//todo : find solution for findAll(Iterable ids)
//given
String documentId = randomNumeric(5);
@@ -171,31 +170,27 @@ public class RepositoryTest {
}
@Test
- public void testSaveIterableEntities(){
- //given
-
+ public void shouldSaveIterableEntities(){
+ //given
String documentId = randomNumeric(5);
- SampleEntity sampleEntity = new SampleEntity();
- sampleEntity.setId(documentId);
- sampleEntity.setMessage("hello world.");
+ SampleEntity sampleEntity1 = new SampleEntity();
+ sampleEntity1.setId(documentId);
+ sampleEntity1.setMessage("hello world.");
String documentId2 = randomNumeric(5);
SampleEntity sampleEntity2 = new SampleEntity();
sampleEntity2.setId(documentId2);
sampleEntity2.setMessage("hello world.");
-
- Iterable sampleEntities = Arrays.asList(sampleEntity,sampleEntity2);
-
+ Iterable sampleEntities = Arrays.asList(sampleEntity1,sampleEntity2);
//when
repository.save(sampleEntities);
-
//then
Page entities = repository.search(fieldQuery("id", documentId), new PageRequest(0, 50));
assertNotNull(entities);
}
@Test
- public void testDocumentExistById(){
+ public void shouldReturnTrueGivenDocumentWithIdExists(){
//given
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntity();
@@ -211,7 +206,7 @@ public class RepositoryTest {
}
@Test
- public void testSearchForGivenSearchQuery(){
+ public void shouldReturnResultsForGivenSearchQuery(){
//given
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntity();
@@ -227,7 +222,7 @@ public class RepositoryTest {
}
@Test
- public void testDeleteAll(){
+ public void shouldDeleteAll(){
//when
repository.deleteAll();
//then
@@ -238,7 +233,7 @@ public class RepositoryTest {
}
@Test
- public void testDeleteByEntity(){
+ public void shouldDeleteEntity(){
//given
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntity();
@@ -255,28 +250,30 @@ public class RepositoryTest {
}
@Test
- public void testSearchForReturnIterableEntities(){
+ public void shouldReturnIterableEntities(){
//given
String documentId = randomNumeric(5);
- SampleEntity sampleEntity = new SampleEntity();
- sampleEntity.setId(documentId);
- sampleEntity.setMessage("hello world.");
- repository.save(sampleEntity);
+ SampleEntity sampleEntity1 = new SampleEntity();
+ sampleEntity1.setId(documentId);
+ sampleEntity1.setMessage("hello world.");
+ sampleEntity1.setVersion(System.currentTimeMillis());
+ repository.save(sampleEntity1);
String documentId2 = randomNumeric(5);
SampleEntity sampleEntity2 = new SampleEntity();
sampleEntity2.setId(documentId2);
sampleEntity2.setMessage("hello world.");
+ sampleEntity2.setVersion(System.currentTimeMillis());
repository.save(sampleEntity2);
//when
Iterable sampleEntities=repository.search(fieldQuery("id",documentId));
- //then
+ //then
assertNotNull("sample entities cant be null..", sampleEntities);
}
@Test
- public void testDeleteIterableEntities(){
+ public void shouldDeleteIterableEntities(){
//given
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntity();
@@ -291,10 +288,8 @@ public class RepositoryTest {
repository.save(sampleEntity);
Iterable sampleEntities = Arrays.asList(sampleEntity,sampleEntity2);
-
//when
repository.delete(sampleEntities);
-
//then
Page entities = repository.search(fieldQuery("id", documentId), new PageRequest(0,50));
assertThat(entities.getTotalElements(),equalTo(0L));
@@ -303,11 +298,12 @@ public class RepositoryTest {
}
@Test
- public void testIndexEntity(){
+ public void shouldIndexEntity(){
//given
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(documentId);
+ sampleEntity.setVersion(System.currentTimeMillis());
sampleEntity.setMessage("some message");
//when
repository.index(sampleEntity);
@@ -318,7 +314,7 @@ public class RepositoryTest {
@Test
@Ignore("By default, the search request will fail if there is no mapping associated with a field. The ignore_unmapped option allows to ignore fields that have no mapping and not sort by them")
- public void testFindBySort(){
+ public void shouldSortByGivenField(){
//todo
//given
String documentId = randomNumeric(5);
@@ -332,12 +328,9 @@ public class RepositoryTest {
sampleEntity2.setId(documentId2);
sampleEntity2.setMessage("B.hello world.");
repository.save(sampleEntity2);
-
//when
Iterable sampleEntities=repository.findAll(new Sort(new Sort.Order(Sort.Direction.ASC,"message")));
-
//then
assertThat(sampleEntities,is(notNullValue()));
}
-
}