Compare commits

..

20 Commits

Author SHA1 Message Date
Spring Buildmaster
43d9f2f948 DATAMONGO-608 - Release version 1.1.2.RELEASE. 2013-02-08 03:50:29 -08:00
Oliver Gierke
fbb281959b DATAMONGO-608 - Upgraded to Spring Data Commons 1.4.1. 2013-02-08 12:20:54 +01:00
Oliver Gierke
c9ff78d17b DATACMNS-263 - Upgraded to Mongo Java Driver 2.9.3. 2013-02-08 12:19:43 +01:00
Oliver Gierke
b6f5614573 DATAMONGO-608 - Updated changelog. 2013-02-08 12:02:22 +01:00
Michal Vich
3c43a43206 DATAMONGO-81 - Added more unit tests for MongoExceptionTranslator. 2013-02-06 15:21:14 +01:00
Michal Vich
b2f82bb5bf DATAMONGO-568 - MongoTemplate.find(…) does not throw NullPointerException anymore.
Trigger findAll(…) if the Query object given to a find(…) method is null.
2013-02-06 15:20:57 +01:00
Oliver Gierke
38ccc59137 DATAMONGO-601 - Prevent password from being logged in case of an exception. 2013-01-29 16:47:22 +01:00
Oliver Gierke
cfa3e467d1 DATAMONGO-600 - Fixed parameter binding for derived queries on properties using polymorphism.
We need to retain the type in the serialized DBObject in case a derived query binds parameters for properties that use polymorphism as we serialize the object as nested document and this only matches in an all-or-nothing way. So if the type information is missing, we won't see any results.

So we now hand the TypeInformation of the property into the conversion logic and transparently skip the type information removal in case the types differ. Upgraded to Querydsl 2.8.2 as it fixes a bug regarding the APT processing which the test cases would stumble into otherwise.
2013-01-25 11:56:04 +01:00
Philipp Schneider
138a4942e9 DATAMONGO-583 - Using while (…) instead of for (…) for DBCursors to avoid memory leak.
Instead of iterating over the DBCursor using a for-loop we now use a while-loop to avoid the potential memory leak outlined in [0].

[0] https://jira.mongodb.org/browse/JAVA-664
2012-12-13 12:07:42 +05:30
Oliver Gierke
a110197b15 DATAMONGO-590 - Code cleanups in MongoTemplate and error handling APIs. 2012-12-13 12:07:33 +05:30
Oliver Gierke
0745fe1e25 DATAMONGO-588 - Version attribute now gets initialized on insert.
The version attribute of an entity has not been correctly initialized to 0 when inserting objects using MongoTemplate.insert(…). We now set it to 0 correctly.
2012-12-10 17:38:58 +09:00
Oliver Gierke
e16d6f4529 DATAMONGO-585 - Fix concurrency issue in database authentication.
So far the authentication of the database was synchronized *after* the check whether the database under consideration had already been authenticated. This can cause threads to concurrently try to authenticate the database which is rejected by the driver. Improved the synchronization block to include both the ….isAuthenticated() check as well as the authentication.
2012-12-03 11:48:04 +01:00
Oliver Gierke
fa1cc5011b DATAMONGO-580 - Improved BeanDefinitionParser for MappingMongoConverter. 2012-11-27 14:56:09 +01:00
Oliver Gierke
90d146235c DATAMONGO-578 - Fixed Maven version in parent pom.xml. 2012-11-23 19:19:26 +01:00
Oliver Gierke
23e1ebc000 DATAMONGO-576 - Configure java.util.logging to prevent verbose test logging.
Added Slf4j bridge and configured surefire to configure JUL accordingly.
2012-11-23 10:50:40 +01:00
Oliver Gierke
8850c2caf5 DATAMONGO-575 - Improved implementation of entity metadata lookup in MongoQueryMethod.
Got rid of obsolete EntityInformationCreator API and moved to a custom EntityMetadata extension instead.
2012-11-23 10:02:43 +01:00
Oliver Gierke
49d874d984 DATAMONGO-570 - Guard against null values in references.
QueryMapper does not try to convert null values into DBRef objects anymore but returns the plain null value as is.
2012-11-13 18:27:51 +01:00
Oliver Gierke
6fc1b7c1f0 DATAMONGO-573 - Moved to Logback for test logging. 2012-11-13 17:50:27 +01:00
Oliver Gierke
eb7c0fe1dd DATAMONGO-559 - Prepare 1.1.x branch.
Set version number to 1.1.2.BUILD-SNAPSHOT. Upgraded to Spring Data Commons 1.4.1.BUILD-SNAPSHOT.
2012-11-13 16:53:52 +01:00
Oliver Gierke
55dc16d8fa DATAMONGO-563 - Upgraded MongoDB Java driver to 2.9.2. 2012-10-24 22:43:45 +02:00
170 changed files with 3375 additions and 4413 deletions

133
README.md
View File

@@ -29,13 +29,19 @@ For those in a hurry:
* Download the jar through Maven:
```xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.2.3.RELEASE</version>
</dependency>
```
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<repository>
<id>spring-maven-snapshot</id>
<snapshots><enabled>true</enabled></snapshots>
<name>Springframework Maven SNAPSHOT Repository</name>
<url>http://maven.springframework.org/snapshot</url>
</repository>
### MongoTemplate
MongoTemplate is the central support class for Mongo database operations. It provides
@@ -48,98 +54,93 @@ Future plans are to support optional logging and/or exception throwing based on
### Easy Data Repository generation
To simplify the creation of data repositories a generic `Repository` interface and default implementation is provided. Furthermore, Spring will automatically create a Repository implementation for you that adds implementations of finder methods you specify on an interface.
To simplify the creation of Data Repositories a generic Repository interface and default implementation is provided. Furthermore, Spring will automatically create a Repository implementation for you that adds implementations of finder methods you specify on an interface.
The Repository interface is
```java
public interface Repository<T, ID extends Serializable> {
public interface Repository<T, ID extends Serializable> {
T save(T entity);
T save(T entity);
List<T> save(Iterable<? extends T> entities);
List<T> save(Iterable<? extends T> entities);
T findById(ID id);
T findById(ID id);
boolean exists(ID id);
boolean exists(ID id);
List<T> findAll();
List<T> findAll();
Long count();
Long count();
void delete(T entity);
void delete(T entity);
void delete(Iterable<? extends T> entities);
void delete(Iterable<? extends T> entities);
void deleteAll();
}
```
void deleteAll();
}
The `MongoRepository` extends `Repository` and will in future add more Mongo specific methods.
The MongoRepository extends Repository and will in future add more Mongo specific methods.
```java
public interface MongoRepository<T, ID extends Serializable> extends Repository<T, ID> {
}
```
public interface MongoRepository<T, ID extends Serializable> extends
Repository<T, ID> {
}
`SimpleMongoRepository` is the out of the box implementation of the `MongoRepository` you can use for basid CRUD operations.
SimpleMongoRepository is the out of the box implementation of the MongoRepository you can use for basid CRUD operations.
To go beyond basic CRUD, extend the `MongoRepository` interface and supply your own finder methods that follow simple naming conventions such that they can be easily converted into queries.
To go beyond basic CRUD, extend the MongoRepository interface and supply your own finder methods that follow simple naming conventions such that they can be easily converted into queries.
For example, given a `Person` class with first and last name properties, a `PersonRepository` interface that can query for `Person` by last name and when the first name matches a regular expression is shown below
For example, given a Person class with first and last name properties, a PersonRepository interface that can query for Person by last name and when the first name matches a regular expression is shown below
```java
public interface PersonRepository extends MongoRepository<Person, Long> {
public interface PersonRepository extends MongoRepository<Person, Long> {
List<Person> findByLastname(String lastname);
List<Person> findByLastname(String lastname);
List<Person> findByFirstnameLike(String firstname);
}
```
List<Person> findByFirstnameLike(String firstname);
}
You can have Spring automatically create a proxy for the interface as shown below:
You can have Spring automatically generate the implemention as shown below
```xml
<bean id="template" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg>
<bean class="com.mongodb.Mongo">
<constructor-arg value="localhost" />
<constructor-arg value="27017" />
</bean>
</constructor-arg>
<constructor-arg value="database" />
<property name="defaultCollectionName" value="springdata" />
</bean>
<bean id="template" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg>
<bean class="com.mongodb.Mongo">
<constructor-arg value="localhost" />
<constructor-arg value="27017" />
</bean>
</constructor-arg>
<constructor-arg value="database" />
<property name="defaultCollectionName" value="springdata" />
</bean>
<mongo:repositories base-package="com.acme.repository" />
```
<bean class="org.springframework.data.document.mongodb.repository.MongoRepositoryFactoryBean">
<property name="template" ref="template" />
<property name="repositoryInterface" value="org.springframework.data.document.mongodb.repository.PersonRepository" />
</bean>
This will find the repository interface and register a proxy object in the container. You can use it as shown below:
This will register an object in the container named PersonRepository. You can use it as shown below
``java
@Service
public class MyService {
@Service
public class MyService {
@Autowired
private final PersonRepository repository;
@Autowired
PersonRepository repository;
public void doWork() {
repository.deleteAll();
public void doWork() {
Person person = new Person();
person.setFirstname("Oliver");
person.setLastname("Gierke");
person = repository.save(person);
repository.deleteAll();
List<Person> lastNameResults = repository.findByLastname("Gierke");
Person person = new Person();
person.setFirstname("Oliver");
person.setLastname("Gierke");
person = repository.save(person);
List<Person> firstNameResults = repository.findByFirstnameLike("Oli*");
List<Person> lastNameResults = repository.findByLastname("Gierke");
}
}
```
List<Person> firstNameResults = repository.findByFirstnameLike("Oli*");
}
}
Contributing to Spring Data

View File

@@ -73,7 +73,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
@@ -102,7 +102,7 @@
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
@@ -124,7 +124,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
@@ -135,9 +135,9 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
@@ -150,12 +150,12 @@
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
@@ -182,11 +182,11 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
@@ -237,7 +237,7 @@
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
@@ -251,12 +251,12 @@
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>

378
pom.xml
View File

@@ -1,99 +1,297 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-dist</artifactId>
<name>Spring Data MongoDB Distribution</name>
<description>Spring Data project for MongoDB</description>
<url>http://www.springsource.org/spring-data/mongodb</url>
<version>1.1.2.RELEASE</version>
<packaging>pom</packaging>
<modules>
<module>spring-data-mongodb</module>
<module>spring-data-mongodb-cross-store</module>
<module>spring-data-mongodb-log4j</module>
<module>spring-data-mongodb-parent</module>
</modules>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.2.5.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<developers>
<developer>
<id>trisberg</id>
<name>Thomas Risberg</name>
<email>trisberg at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles>
<role>Project Admin</role>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>mpollack</id>
<name>Mark Pollack</name>
<email>mpollack at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles>
<role>Project Admin</role>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>jbrisbin</id>
<name>Jon Brisbin</name>
<email>jbrisbin at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-6</timezone>
</developer>
</developers>
<name>Spring Data MongoDB</name>
<description>MongoDB support for Spring Data</description>
<url>http://www.springsource.org/spring-data/mongodb</url>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
<comments>
Copyright 2010 the original author or authors.
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>1.0.5.RELEASE</version>
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
</parent>
<modules>
<module>spring-data-mongodb</module>
<module>spring-data-mongodb-cross-store</module>
<module>spring-data-mongodb-log4j</module>
<module>spring-data-mongodb-distribution</module>
</modules>
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
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>1.5.3.RELEASE</springdata.commons>
<mongo>2.10.1</mongo>
</properties>
<developers>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Project Lean</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>trisberg</id>
<name>Thomas Risberg</name>
<email>trisberg at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>mpollack</id>
<name>Mark Pollack</name>
<email>mpollack at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>jbrisbin</id>
<name>Jon Brisbin</name>
<email>jbrisbin at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-6</timezone>
</developer>
</developers>
http://www.apache.org/licenses/LICENSE-2.0
<dependencies>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo}</version>
</dependency>
</dependencies>
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.
</comments>
</license>
</licenses>
<repositories>
<repository>
<id>spring-libs-release</id>
<url>http://repo.springsource.org/libs-release</url>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- dist.* properties are used by the antrun tasks below -->
<dist.id>spring-data-mongo</dist.id>
<dist.name>Spring Data Mongo</dist.name>
<dist.key>SDMONGO</dist.key>
<dist.version>${project.version}</dist.version>
<dist.releaseType>snapshot</dist.releaseType>
<dist.finalName>${dist.id}-${dist.version}</dist.finalName>
<dist.fileName>${dist.finalName}.zip</dist.fileName>
<dist.filePath>target/${dist.fileName}</dist.filePath>
<dist.bucketName>dist.springframework.org</dist.bucketName>
<!-- these properties should be in ~/.m2/settings.xml
<dist.accessKey>s3 access key</dist.accessKey>
<dist.secretKey>s3 secret key</dist.secretKey>
-->
</properties>
<build>
<extensions>
<extension>
<groupId>org.springframework.build.aws</groupId>
<artifactId>org.springframework.build.aws.maven</artifactId>
<version>3.1.0.RELEASE</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<!-- yes it really needs to be this (2.0.7) otherwise pdf generation from a clean build doesn't work -->
<version>2.0.7</version>
<executions>
<execution>
<goals>
<goal>generate-html</goal>
<goal>generate-pdf</goal>
</goals>
<phase>pre-site</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.docbook</groupId>
<artifactId>docbook-xml</artifactId>
<version>4.4</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<configuration>
<includes>index.xml</includes>
<xincludeSupported>true</xincludeSupported>
<foCustomization>${project.basedir}/src/docbkx/resources/xsl/fopdf.xsl</foCustomization>
<htmlStylesheet>css/html.css</htmlStylesheet>
<chunkedOutput>false</chunkedOutput>
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
<useExtensions>1</useExtensions>
<highlightSource>1</highlightSource>
<highlightDefaultLanguage />
<!-- callouts -->
<entities>
<entity>
<name>version</name>
<value>${project.version}</value>
</entity>
</entities>
<postProcess>
<copy todir="${project.basedir}/target/site/reference">
<fileset dir="${project.basedir}/target/docbkx">
<include name="**/*.html" />
<include name="**/*.pdf" />
</fileset>
</copy>
<copy todir="${project.basedir}/target/site/reference/html">
<fileset dir="${project.basedir}/src/docbkx/resources">
<include name="**/*.css" />
<include name="**/*.png" />
<include name="**/*.gif" />
<include name="**/*.jpg" />
</fileset>
</copy>
<copy todir="${project.basedir}/target/site/reference/html">
<fileset dir="${project.basedir}/src/docbkx/resources/images">
<include name="*.png" />
</fileset>
</copy>
<move file="${project.basedir}/target/site/reference/pdf/index.pdf" tofile="${project.basedir}/target/site/reference/pdf/spring-data-mongo-reference.pdf" failonerror="false" />
</postProcess>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version>
<configuration>
<aggregate>true</aggregate>
<breakiterator>true</breakiterator>
<header>Spring Data Document</header>
<source>1.5</source>
<quiet>true</quiet>
<javadocDirectory>${project.basedir}/src/main/javadoc</javadocDirectory>
<overview>${project.basedir}/src/main/javadoc/overview.html</overview>
<stylesheetfile>${project.basedir}/src/main/javadoc/spring-javadoc.css</stylesheetfile>
<!-- copies doc-files subdirectory which contains image resources -->
<docfilessubdirs>true</docfilessubdirs>
<links>
<link>http://static.springframework.org/spring/docs/3.0.x/javadoc-api</link>
<link>http://download.oracle.com/javase/1.5.0/docs/api</link>
<link>http://api.mongodb.org/java/2.3</link>
</links>
</configuration>
</plugin>
<plugin><!--
run `mvn package assembly:assembly` to trigger assembly creation.
see http://www.sonatype.com/books/mvnref-book/reference/assemblies-set-dist-assemblies.html -->
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<inherited>false</inherited>
<executions>
<execution>
<id>distribution</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/assembly/distribution.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>upload-dist</id>
<phase>deploy</phase>
<configuration>
<tasks>
<ant antfile="${basedir}/src/ant/upload-dist.xml">
<target name="upload-dist" />
</ant>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework.build</groupId>
<artifactId>org.springframework.build.aws.ant</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>net.java.dev.jets3t</groupId>
<artifactId>jets3t</artifactId>
<version>0.7.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
<!-- the name of this project is 'spring-data-mongo-dist';
make sure the zip file is just 'spring-data-mongo'. -->
<finalName>${dist.finalName}</finalName>
</build>
<pluginRepositories>
<!-- Necessary for the build extension -->
<pluginRepository>
<id>spring-plugins-release</id>
<url>http://repo.springsource.org/plugins-release</url>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<!-- see 'staging' profile for dry-run deployment settings -->
<downloadUrl>http://www.springsource.com/spring-data</downloadUrl>
<site>
<id>static.springframework.org</id>
<url>
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
</url>
</site>
<repository>
<id>spring-milestone</id>
<name>Spring Milestone Repository</name>
<url>s3://maven.springframework.org/milestone</url>
</repository>
<snapshotRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>s3://maven.springframework.org/snapshot</url>
</snapshotRepository>
</distributionManagement>
<scm>
<url>https://github.com/SpringSource/spring-data-mongodb</url>
</scm>
</project>

View File

@@ -1,145 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.1.2.RELEASE</version>
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb-cross-store</artifactId>
<name>Spring Data MongoDB Cross-store Persistence Support</name>
<dependencies>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.2.5.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb-cross-store</artifactId>
<name>Spring Data MongoDB - Cross-Store Persistence Support</name>
<properties>
<jpa>1.0.0.Final</jpa>
<hibernate>3.6.10.Final</hibernate>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version.range}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version.range}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${org.springframework.version.range}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version.range}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring}</version>
</dependency>
<!-- Spring Data -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons-core</artifactId>
<version>${data.commons.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
<!-- Spring Data -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.2.5.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<!-- JPA -->
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<!-- JPA -->
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>${jpa}</version>
</dependency>
<!-- For Tests -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.5.5-Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.2.GA</version>
<scope>test</scope>
</dependency>
<!-- For Tests -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.2.GA</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>${source.level}</source>
<target>${source.level}</target>
</configuration>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.2</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
<!-- <aspectLibrary>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons-aspects</artifactId>
</aspectLibrary> -->
</aspectLibraries>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011 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.
@@ -17,8 +17,8 @@ package org.springframework.data.mongodb.crossstore;
import javax.persistence.EntityManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
@@ -34,10 +34,6 @@ import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
/**
* @author Thomas Risberg
* @author Oliver Gierke
*/
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
private static final String ENTITY_CLASS = "_entity_class";
@@ -48,7 +44,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final Log log = LogFactory.getLog(getClass());
private MongoTemplate mongoTemplate;
@@ -62,10 +58,6 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
this.entityManagerFactory = entityManagerFactory;
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentState(java.lang.Class, java.lang.Object, org.springframework.data.crossstore.ChangeSet)
*/
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
throws DataAccessException, NotFoundException {
@@ -108,10 +100,6 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
*/
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
log.debug("getPersistentId called on " + entity);
if (entityManagerFactory == null) {
@@ -121,10 +109,6 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
return o;
}
/*
* (non-Javadoc)
* @see org.springframework.data.crossstore.ChangeSetPersister#persistState(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
*/
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
if (cs == null) {
log.debug("Flush: changeset was null, nothing to flush.");
@@ -185,13 +169,8 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
return 0L;
}
/**
* Returns the collection the given entity type shall be persisted to.
*
* @param entityClass must not be {@literal null}.
* @return
*/
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
return mongoTemplate.getCollectionName(entityClass);
return ClassUtils.getQualifiedName(entityClass);
}
}

View File

@@ -21,12 +21,13 @@ import javax.persistence.EntityManager;
import javax.persistence.Transient;
import javax.persistence.Entity;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.FieldSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.mongodb.crossstore.RelatedDocument;
import org.springframework.data.mongodb.crossstore.DocumentBacked;
import org.springframework.data.crossstore.ChangeSetBackedTransactionSynchronization;
@@ -43,7 +44,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
*/
public aspect MongoDocumentBacking {
private static final Logger LOGGER = LoggerFactory.getLogger(MongoDocumentBacking.class);
private static final Log LOGGER = LogFactory.getLog(MongoDocumentBacking.class);
// Aspect shared config
private ChangeSetPersister<Object> changeSetPersister;

View File

@@ -1,5 +0,0 @@
/**
* Infrastructure for Spring Data's MongoDB cross store support.
*/
package org.springframework.data.mongodb.crossstore;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011 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.
@@ -18,9 +18,7 @@ package org.springframework.data.mongodb.crossstore;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -28,6 +26,7 @@ import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.crossstore.test.Address;
import org.springframework.data.mongodb.crossstore.test.Person;
import org.springframework.data.mongodb.crossstore.test.Resume;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
@@ -36,76 +35,55 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
/**
* Integration tests for MongoDB cross-store persistence (mainly {@link MongoChangeSetPersister}).
*
* @author Thomas Risberg
* @author Oliver Gierke
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/META-INF/spring/applicationContext.xml")
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
public class CrossStoreMongoTests {
@Autowired
MongoTemplate mongoTemplate;
private MongoTemplate mongoTemplate;
@PersistenceContext
EntityManager entityManager;
private EntityManager entityManager;
@Autowired
PlatformTransactionManager transactionManager;
TransactionTemplate txTemplate;
private PlatformTransactionManager transactionManager;
@Before
public void setUp() {
txTemplate = new TransactionTemplate(transactionManager);
clearData(Person.class);
Address address = new Address(12, "MAin St.", "Boston", "MA", "02101");
Resume resume = new Resume();
resume.addEducation("Skanstulls High School, 1975");
resume.addEducation("Univ. of Stockholm, 1980");
resume.addJob("DiMark, DBA, 1990-2000");
resume.addJob("VMware, Developer, 2007-");
final Person person = new Person("Thomas", 20);
person.setAddress(address);
person.setResume(resume);
person.setId(1L);
txTemplate.execute(new TransactionCallback<Void>() {
public Void doInTransaction(TransactionStatus status) {
entityManager.persist(person);
return null;
}
});
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
@After
public void tearDown() {
txTemplate.execute(new TransactionCallback<Void>() {
public Void doInTransaction(TransactionStatus status) {
entityManager.remove(entityManager.find(Person.class, 1L));
return null;
}
});
}
private void clearData(Class<?> domainType) {
String collectionName = mongoTemplate.getCollectionName(domainType);
mongoTemplate.dropCollection(collectionName);
private void clearData(String collectionName) {
DBCollection col = this.mongoTemplate.getCollection(collectionName);
if (col != null) {
this.mongoTemplate.dropCollection(collectionName);
}
}
@Test
@Transactional
public void testReadJpaToMongoEntityRelationship() {
@Rollback(false)
public void testCreateJpaToMongoEntityRelationship() {
clearData(Person.class.getName());
Person p = new Person("Thomas", 20);
Address a = new Address(12, "MAin St.", "Boston", "MA", "02101");
p.setAddress(a);
Resume r = new Resume();
r.addEducation("Skanstulls High School, 1975");
r.addEducation("Univ. of Stockholm, 1980");
r.addJob("DiMark, DBA, 1990-2000");
r.addJob("VMware, Developer, 2007-");
p.setResume(r);
p.setId(1L);
entityManager.persist(p);
}
@Test
@Transactional
@Rollback(false)
public void testReadJpaToMongoEntityRelationship() {
Person found = entityManager.find(Person.class, 1L);
Assert.assertNotNull(found);
Assert.assertEquals(Long.valueOf(1), found.getId());
@@ -113,18 +91,15 @@ public class CrossStoreMongoTests {
Assert.assertEquals(Long.valueOf(1), found.getId());
Assert.assertNotNull(found.getResume());
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; " + "VMware, Developer, 2007-", found.getResume().getJobs());
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
found.setAge(44);
}
@Test
@Transactional
@Rollback(false)
public void testUpdatedJpaToMongoEntityRelationship() {
Person found = entityManager.find(Person.class, 1L);
found.setAge(44);
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
entityManager.merge(found);
Assert.assertNotNull(found);
Assert.assertEquals(Long.valueOf(1), found.getId());
Assert.assertNotNull(found);
@@ -136,19 +111,14 @@ public class CrossStoreMongoTests {
@Test
public void testMergeJpaEntityWithMongoDocument() {
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
final Person detached = entityManager.find(Person.class, 1L);
entityManager.detach(detached);
detached.getResume().addJob("TargetRx, Developer, 2000-2005");
Person merged = txTemplate.execute(new TransactionCallback<Person>() {
public Person doInTransaction(TransactionStatus status) {
Person result = entityManager.merge(detached);
entityManager.flush();
return result;
return entityManager.merge(detached);
}
});
Assert.assertTrue(detached.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
Assert.assertTrue(merged.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
final Person updated = entityManager.find(Person.class, 1L);
@@ -157,7 +127,7 @@ public class CrossStoreMongoTests {
@Test
public void testRemoveJpaEntityWithMongoDocument() {
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
txTemplate.execute(new TransactionCallback<Person>() {
public Person doInTransaction(TransactionStatus status) {
Person p2 = new Person("Thomas", 20);
@@ -184,10 +154,8 @@ public class CrossStoreMongoTests {
return null;
}
});
boolean weFound3 = false;
for (DBObject dbo : this.mongoTemplate.getCollection(mongoTemplate.getCollectionName(Person.class)).find()) {
for (DBObject dbo : this.mongoTemplate.getCollection(Person.class.getName()).find()) {
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
if (dbo.get("_entity_id").equals(3L)) {
weFound3 = true;

View File

@@ -1,18 +0,0 @@
Bundle-SymbolicName: org.springframework.data.mongodb.crossstore
Bundle-Name: Spring Data MongoDB Cross Store Support
Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Export-Template:
org.springframework.data.mongodb.crossstore.*;version="${project.version}"
Import-Template:
com.mongodb.*;version="0",
javax.persistence.*;version="${jpa:[=.=.=,+1.0.0)}",
org.aspectj.*;version="${aspectj:[1.0.0, 2.0.0)}",
org.bson.*;version="0",
org.slf4j.*;version="${slf4j:[=.=.=,+1.0.0)}",
org.springframework.*;version="${spring30:[=.=.=.=,+1.0.0)}",
org.springframework.data.*;version="${springdata.commons:[=.=.=.=,+1.0.0)}",
org.springframework.data.mongodb.*;version="${project.version:[=.=.=.=,+1.0.0)}",
org.w3c.dom.*;version="0"

View File

@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-mongodb-distribution</artifactId>
<packaging>pom</packaging>
<name>Spring Data MongoDB - Distribution</name>
<description>Distribution build for Spring Data MongoDB</description>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.2.5.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.root>${basedir}/..</project.root>
<dist.key>SDMONGO</dist.key>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -32,7 +32,7 @@ An example log entry might look like:
{
"_id" : ObjectId("4d89341a8ef397e06940d5cd"),
"applicationId" : "my.application",
"name" : "org.springframework.data.mongodb.log4j.MongoLog4jAppenderIntegrationTests",
"name" : "org.springframework.data.mongodb.log4j.AppenderTest",
"level" : "DEBUG",
"timestamp" : ISODate("2011-03-23T16:53:46.778Z"),
"properties" : {

View File

@@ -1,30 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.2.5.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.1.2.RELEASE</version>
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb-log4j</artifactId>
<name>Spring Data MongoDB Log4J Appender</name>
<artifactId>spring-data-mongodb-log4j</artifactId>
<name>Spring Data MongoDB - Log4J Appender</name>
<properties>
<log4j.version>1.2.16</log4j.version>
</properties>
<properties>
<log4j>1.2.16</log4j>
</properties>
<dependencies>
<dependencies>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo.version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright (c) 2011 by the original author(s).
*
* 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
* 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,
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.log4j;
import java.net.UnknownHostException;
@@ -20,207 +21,188 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Map;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.WriteConcern;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.MDC;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.WriteConcern;
/**
* Log4j appender writing log entries into a MongoDB instance.
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MongoLog4jAppender extends AppenderSkeleton {
public static final String LEVEL = "level";
public static final String NAME = "name";
public static final String APP_ID = "applicationId";
public static final String TIMESTAMP = "timestamp";
public static final String PROPERTIES = "properties";
public static final String TRACEBACK = "traceback";
public static final String MESSAGE = "message";
public static final String YEAR = "year";
public static final String MONTH = "month";
public static final String DAY = "day";
public static final String HOUR = "hour";
public static final String LEVEL = "level";
public static final String NAME = "name";
public static final String APP_ID = "applicationId";
public static final String TIMESTAMP = "timestamp";
public static final String PROPERTIES = "properties";
public static final String TRACEBACK = "traceback";
public static final String MESSAGE = "message";
public static final String YEAR = "year";
public static final String MONTH = "month";
public static final String DAY = "day";
public static final String HOUR = "hour";
protected String host = "localhost";
protected int port = 27017;
protected String database = "logs";
protected String collectionPattern = "%c";
protected PatternLayout collectionLayout = new PatternLayout(collectionPattern);
protected String applicationId = System.getProperty("APPLICATION_ID", null);
protected WriteConcern warnOrHigherWriteConcern = WriteConcern.SAFE;
protected WriteConcern infoOrLowerWriteConcern = WriteConcern.NORMAL;
protected Mongo mongo;
protected DB db;
protected String host = "localhost";
protected int port = 27017;
protected String database = "logs";
protected String collectionPattern = "%c";
protected PatternLayout collectionLayout = new PatternLayout(collectionPattern);
protected String applicationId = System.getProperty("APPLICATION_ID", null);
protected WriteConcern warnOrHigherWriteConcern = WriteConcern.SAFE;
protected WriteConcern infoOrLowerWriteConcern = WriteConcern.NORMAL;
protected Mongo mongo;
protected DB db;
public MongoLog4jAppender() {
}
public MongoLog4jAppender() {
}
public MongoLog4jAppender(boolean isActive) {
super(isActive);
}
public MongoLog4jAppender(boolean isActive) {
super(isActive);
}
public String getHost() {
return host;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public void setPort(int port) {
this.port = port;
}
public String getDatabase() {
return database;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getCollectionPattern() {
return collectionPattern;
}
public String getCollectionPattern() {
return collectionPattern;
}
public void setCollectionPattern(String collectionPattern) {
this.collectionPattern = collectionPattern;
this.collectionLayout = new PatternLayout(collectionPattern);
}
public void setCollectionPattern(String collectionPattern) {
this.collectionPattern = collectionPattern;
this.collectionLayout = new PatternLayout(collectionPattern);
}
public String getApplicationId() {
return applicationId;
}
public String getApplicationId() {
return applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
public void setWarnOrHigherWriteConcern(String wc) {
this.warnOrHigherWriteConcern = WriteConcern.valueOf(wc);
}
public void setWarnOrHigherWriteConcern(String wc) {
this.warnOrHigherWriteConcern = WriteConcern.valueOf(wc);
}
public String getWarnOrHigherWriteConcern() {
return warnOrHigherWriteConcern.toString();
}
public String getWarnOrHigherWriteConcern() {
return warnOrHigherWriteConcern.toString();
}
public String getInfoOrLowerWriteConcern() {
return infoOrLowerWriteConcern.toString();
}
public String getInfoOrLowerWriteConcern() {
return infoOrLowerWriteConcern.toString();
}
public void setInfoOrLowerWriteConcern(String wc) {
this.infoOrLowerWriteConcern = WriteConcern.valueOf(wc);
}
public void setInfoOrLowerWriteConcern(String wc) {
this.infoOrLowerWriteConcern = WriteConcern.valueOf(wc);
}
protected void connectToMongo() throws UnknownHostException {
this.mongo = new Mongo(host, port);
this.db = mongo.getDB(database);
}
protected void connectToMongo() throws UnknownHostException {
this.mongo = new Mongo(host, port);
this.db = mongo.getDB(database);
}
/*
* (non-Javadoc)
* @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent)
*/
@Override
@SuppressWarnings({ "unchecked" })
protected void append(final LoggingEvent event) {
if (null == db) {
try {
connectToMongo();
} catch (UnknownHostException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@SuppressWarnings({"unchecked"})
@Override
protected void append(final LoggingEvent event) {
if (null == db) {
try {
connectToMongo();
} catch (UnknownHostException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
BasicDBObject dbo = new BasicDBObject();
if (null != applicationId) {
dbo.put(APP_ID, applicationId);
MDC.put(APP_ID, applicationId);
}
dbo.put(NAME, event.getLogger().getName());
dbo.put(LEVEL, event.getLevel().toString());
Calendar tstamp = Calendar.getInstance();
tstamp.setTimeInMillis(event.getTimeStamp());
dbo.put(TIMESTAMP, tstamp.getTime());
BasicDBObject dbo = new BasicDBObject();
if (null != applicationId) {
dbo.put(APP_ID, applicationId);
MDC.put(APP_ID, applicationId);
}
dbo.put(NAME, event.getLogger().getName());
dbo.put(LEVEL, event.getLevel().toString());
Calendar tstamp = Calendar.getInstance();
tstamp.setTimeInMillis(event.getTimeStamp());
dbo.put(TIMESTAMP, tstamp.getTime());
// Copy properties into document
Map<Object, Object> props = event.getProperties();
if (null != props && props.size() > 0) {
BasicDBObject propsDbo = new BasicDBObject();
for (Map.Entry<Object, Object> entry : props.entrySet()) {
propsDbo.put(entry.getKey().toString(), entry.getValue().toString());
}
dbo.put(PROPERTIES, propsDbo);
}
// Copy properties into document
Map<Object, Object> props = event.getProperties();
if (null != props && props.size() > 0) {
BasicDBObject propsDbo = new BasicDBObject();
for (Map.Entry<Object, Object> entry : props.entrySet()) {
propsDbo.put(entry.getKey().toString(), entry.getValue().toString());
}
dbo.put(PROPERTIES, propsDbo);
}
// Copy traceback info (if there is any) into the document
String[] traceback = event.getThrowableStrRep();
if (null != traceback && traceback.length > 0) {
BasicDBList tbDbo = new BasicDBList();
tbDbo.addAll(Arrays.asList(traceback));
dbo.put(TRACEBACK, tbDbo);
}
// Copy traceback info (if there is any) into the document
String[] traceback = event.getThrowableStrRep();
if (null != traceback && traceback.length > 0) {
BasicDBList tbDbo = new BasicDBList();
tbDbo.addAll(Arrays.asList(traceback));
dbo.put(TRACEBACK, tbDbo);
}
// Put the rendered message into the document
dbo.put(MESSAGE, event.getRenderedMessage());
// Put the rendered message into the document
dbo.put(MESSAGE, event.getRenderedMessage());
// Insert the document
Calendar now = Calendar.getInstance();
MDC.put(YEAR, now.get(Calendar.YEAR));
MDC.put(MONTH, String.format("%1$02d", now.get(Calendar.MONTH) + 1));
MDC.put(DAY, String.format("%1$02d", now.get(Calendar.DAY_OF_MONTH)));
MDC.put(HOUR, String.format("%1$02d", now.get(Calendar.HOUR_OF_DAY)));
// Insert the document
Calendar now = Calendar.getInstance();
MDC.put(YEAR, now.get(Calendar.YEAR));
MDC.put(MONTH, String.format("%1$02d", now.get(Calendar.MONTH) + 1));
MDC.put(DAY, String.format("%1$02d", now.get(Calendar.DAY_OF_MONTH)));
MDC.put(HOUR, String.format("%1$02d", now.get(Calendar.HOUR_OF_DAY)));
String coll = collectionLayout.format(event);
String coll = collectionLayout.format(event);
MDC.remove(YEAR);
MDC.remove(MONTH);
MDC.remove(DAY);
MDC.remove(HOUR);
if (null != applicationId) {
MDC.remove(APP_ID);
}
MDC.remove(YEAR);
MDC.remove(MONTH);
MDC.remove(DAY);
MDC.remove(HOUR);
if (null != applicationId) {
MDC.remove(APP_ID);
}
WriteConcern wc;
if (event.getLevel().isGreaterOrEqual(Level.WARN)) {
wc = warnOrHigherWriteConcern;
} else {
wc = infoOrLowerWriteConcern;
}
db.getCollection(coll).insert(dbo, wc);
}
WriteConcern wc;
if (event.getLevel().isGreaterOrEqual(Level.WARN)) {
wc = warnOrHigherWriteConcern;
} else {
wc = infoOrLowerWriteConcern;
}
db.getCollection(coll).insert(dbo, wc);
}
/*
* (non-Javadoc)
* @see org.apache.log4j.AppenderSkeleton#close()
*/
public void close() {
public void close() {
mongo.close();
}
if (mongo != null) {
mongo.close();
}
}
/*
* (non-Javadoc)
* @see org.apache.log4j.AppenderSkeleton#requiresLayout()
*/
public boolean requiresLayout() {
return true;
}
public boolean requiresLayout() {
return true;
}
}

View File

@@ -1,5 +0,0 @@
/**
* Infrastructure for to use MongoDB as a logging sink.
*/
package org.springframework.data.mongodb.log4j;

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2011 by the original author(s).
*
* 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.mongodb.log4j;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.net.UnknownHostException;
import java.util.Calendar;
import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.junit.Before;
import org.junit.Test;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class AppenderTest {
private static final String NAME = AppenderTest.class.getName();
private Logger log = Logger.getLogger(NAME);
private Mongo mongo;
private DB db;
private String collection;
@Before
public void setup() {
try {
mongo = new Mongo("localhost", 27017);
db = mongo.getDB("logs");
Calendar now = Calendar.getInstance();
collection = String.valueOf(now.get(Calendar.YEAR)) + String.format("%1$02d", now.get(Calendar.MONTH) + 1);
db.getCollection(collection).drop();
} catch (UnknownHostException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Test
public void testLogging() {
log.debug("DEBUG message");
log.info("INFO message");
log.warn("WARN message");
log.error("ERROR message");
DBCursor msgs = db.getCollection(collection).find();
assertThat(msgs.count(), is(4));
}
@Test
public void testProperties() {
MDC.put("property", "one");
log.debug("DEBUG message");
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright 2011-2013 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.mongodb.log4j;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.Calendar;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
/**
* Integration tests for {@link MongoLog4jAppender}.
*
* @author Jon Brisbin
* @author Oliver Gierke
*/
public class MongoLog4jAppenderIntegrationTests {
static final String NAME = MongoLog4jAppenderIntegrationTests.class.getName();
Logger log = Logger.getLogger(NAME);
Mongo mongo;
DB db;
String collection;
@Before
public void setUp() throws Exception {
mongo = new Mongo("localhost", 27017);
db = mongo.getDB("logs");
Calendar now = Calendar.getInstance();
collection = String.valueOf(now.get(Calendar.YEAR)) + String.format("%1$02d", now.get(Calendar.MONTH) + 1);
db.getCollection(collection).drop();
}
@Test
public void testLogging() {
log.debug("DEBUG message");
log.info("INFO message");
log.warn("WARN message");
log.error("ERROR message");
DBCursor msgs = db.getCollection(collection).find();
assertThat(msgs.count(), is(4));
}
@Test
public void testProperties() {
MDC.put("property", "one");
log.debug("DEBUG message");
}
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright 2013 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.mongodb.log4j;
import org.junit.Test;
/**
* Unit tests for {@link MongoLog4jAppender}.
*
* @author Oliver Gierke
*/
public class MongoLog4jAppenderUnitTests {
/**
* @see DATAMONGO-641
*/
@Test
public void closesWithoutMongoInstancePresent() {
new MongoLog4jAppender().close();
}
}

View File

@@ -10,4 +10,11 @@ log4j.appender.stdout.collectionPattern = %X{year}%X{month}
log4j.appender.stdout.applicationId = my.application
log4j.appender.stdout.warnOrHigherWriteConcern = FSYNC_SAFE
log4j.category.org.springframework.data.mongodb=DEBUG
log4j.category.org.apache.activemq=ERROR
log4j.category.org.springframework.batch=DEBUG
log4j.category.org.springframework.data.document.mongodb=DEBUG
log4j.category.org.springframework.transaction=INFO
log4j.category.org.hibernate.SQL=DEBUG
# for debugging datasource initialization
# log4j.category.test.jdbc=DEBUG

View File

@@ -5,5 +5,6 @@ Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Import-Template:
com.mongodb.*;version="${mongo:[=.=,+1.0.0)}",
org.apache.log4j.*;version="${log4j:[=.=.=,+1.0.0)}"
com.mongodb.*;version="${mongo.version:[=.=,+1.0.0)}",
org.apache.log4j.*;version="[1.2.15, 2.0.0)",
org.apache.log4j.spi.*;version="[1.2.15, 2.0.0)"

View File

@@ -0,0 +1,356 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<name>Spring Data MongoDB Parent</name>
<description>Spring Data project for MongoDB</description>
<url>http://www.springsource.org/spring-data/mongodb</url>
<version>1.1.2.RELEASE</version>
<packaging>pom</packaging>
<developers>
<developer>
<id>trisberg</id>
<name>Thomas Risberg</name>
<email>trisberg at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles>
<role>Project Admin</role>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>mpollack</id>
<name>Mark Pollack</name>
<email>mpollack at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles>
<role>Project Admin</role>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>jbrisbin</id>
<name>Jon Brisbin</name>
<email>jbrisbin at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-6</timezone>
</developer>
</developers>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
<comments>
Copyright 2010 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.
</comments>
</license>
</licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- versions for commonly-used dependencies -->
<mongo.version>2.9.3</mongo.version>
<junit.version>4.10</junit.version>
<logback.version>1.0.6</logback.version>
<org.mockito.version>1.9.0</org.mockito.version>
<org.slf4j.version>1.6.1</org.slf4j.version>
<org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version>
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
<org.springframework.version.range>3.1.2.RELEASE</org.springframework.version.range>
<data.commons.version>1.4.1.RELEASE</data.commons.version>
<aspectj.version>1.6.11.RELEASE</aspectj.version>
<bundlor.failOnWarnings>true</bundlor.failOnWarnings>
</properties>
<distributionManagement>
<!-- see 'staging' profile for dry-run deployment settings -->
<downloadUrl>http://www.springsource.com/download/community
</downloadUrl>
<site>
<id>static.springframework.org</id>
<url>
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
</url>
</site>
<repository>
<id>spring-milestone</id>
<name>Spring Milestone Repository</name>
<url>s3://maven.springframework.org/milestone</url>
</repository>
<snapshotRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>s3://maven.springframework.org/snapshot</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<!-- Test dependencies -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${org.mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>1.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${org.slf4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version.range}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<!--
available only in the springframework maven repository. see
<repositories> section below
-->
<groupId>org.springframework.build.aws</groupId>
<artifactId>org.springframework.build.aws.maven</artifactId>
<version>3.1.0.RELEASE</version>
</extension>
</extensions>
<resources>
<resource>
<directory>${project.basedir}/src/main/java</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/java</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
<compilerArgument>-Xlint:-path</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>false</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<useDefaultManifestFile>true</useDefaultManifestFile>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<useFile>false</useFile>
<includes>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/PerformanceTests.java</exclude>
</excludes>
<junitArtifactName>junit:junit-dep</junitArtifactName>
<systemPropertyVariables>
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<!--
configures the springsource bundlor plugin, which generates
OSGI-compatible MANIFEST.MF files during the 'compile' phase of
the maven build. this plugin is declared within the
pluginManagement section because not every module that inherits
from this pom needs bundlor's services, e.g.:
spring-integration-samples and all its children. for this reason,
all modules that wish to use bundlor must declare it explicitly.
it is not necessary to specify the <version> or <configuration>
sections, but groupId and artifactId are required. see
http://static.springsource.org/s2-bundlor/1.0.x/user-guide/html/ch04s03.html
for more info
-->
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
<version>1.0.0.RELEASE</version>
<configuration>
<failOnWarnings>${bundlor.failOnWarnings}</failOnWarnings>
</configuration>
<executions>
<execution>
<id>bundlor</id>
<goals>
<goal>bundlor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<pluginRepositories>
<pluginRepository>
<id>spring-plugins-release</id>
<url>http://repo.springsource.org/plugins-release</url>
</pluginRepository>
<pluginRepository>
<id>querydsl</id>
<url>http://source.mysema.com/maven2/releases</url>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<id>spring-libs-snapshot</id>
<url>http://repo.springsource.org/libs-snapshot</url>
</repository>
</repositories>
<reporting>
<plugins>
<plugin>
<!--
significantly speeds up the 'Dependencies' report during site
creation see
http://old.nabble.com/Skipping-dependency-report-during-Maven2-site-generation-td20116761.html
-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.1</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>
</plugin>
</plugins>
</reporting>
<scm>
<url>https://github.com/SpringSource/spring-data-mongodb</url>
</scm>
</project>

View File

@@ -1,80 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-mongodb</artifactId>
<name>Spring Data MongoDB - Core</name>
<description>MongoDB support for Spring Data</description>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.2.5.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
<version>1.1.2.RELEASE</version>
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb</artifactId>
<name>Spring Data MongoDB</name>
<properties>
<validation>1.0.0.GA</validation>
<querydsl.version>2.8.2</querydsl.version>
<cdi.version>1.0</cdi.version>
<validation.version>1.0.0.GA</validation.version>
<webbeans.version>1.1.3</webbeans.version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring}</version>
<version>${org.springframework.version.range}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring}</version>
<version>${org.springframework.version.range}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring}</version>
<version>${org.springframework.version.range}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring}</version>
<version>${org.springframework.version.range}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring}</version>
<version>${org.springframework.version.range}</version>
</dependency>
<!-- Spring Data -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${springdata.commons}</version>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons-core</artifactId>
<version>${data.commons.version}</version>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo.version}</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-mongodb</artifactId>
<version>${querydsl}</version>
<version>${querydsl.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
@@ -86,7 +84,7 @@
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>${cdi}</version>
<version>${cdi.version}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
@@ -94,14 +92,14 @@
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>${cdi}</version>
<version>${cdi.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans.test</groupId>
<artifactId>cditest-owb</artifactId>
<version>${webbeans}</version>
<version>${webbeans.version}</version>
<scope>test</scope>
</dependency>
@@ -116,7 +114,7 @@
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${validation}</version>
<version>${validation.version}</version>
<optional>true</optional>
</dependency>
@@ -126,18 +124,39 @@
<version>4.2.0.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>performance-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8</version>
<configuration>
<includes>
<include>**/PerformanceTests.java</include>
</includes>
<excludes>
<exclude>none</exclude>
</excludes>
<junitArtifactName>junit:junit-dep</junitArtifactName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
@@ -147,7 +166,7 @@
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl}</version>
<version>${querydsl.version}</version>
</dependency>
</dependencies>
<executions>
@@ -163,25 +182,7 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<useFile>false</useFile>
<includes>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/PerformanceTests.java</exclude>
</excludes>
<systemPropertyVariables>
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,72 +0,0 @@
/*
* Copyright 2013 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.mongodb;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.mongodb.core.MongoActionOperation;
import org.springframework.util.Assert;
import com.mongodb.WriteResult;
/**
* Mongo-specific {@link DataIntegrityViolationException}.
*
* @author Oliver Gierke
*/
public class MongoDataIntegrityViolationException extends DataIntegrityViolationException {
private static final long serialVersionUID = -186980521176764046L;
private final WriteResult writeResult;
private final MongoActionOperation actionOperation;
/**
* Creates a new {@link MongoDataIntegrityViolationException} using the given message and {@link WriteResult}.
*
* @param message the exception message
* @param writeResult the {@link WriteResult} that causes the exception, must not be {@literal null}.
* @param actionOperation the {@link MongoActionOperation} that caused the exception, must not be {@literal null}.
*/
public MongoDataIntegrityViolationException(String message, WriteResult writeResult,
MongoActionOperation actionOperation) {
super(message);
Assert.notNull(writeResult, "WriteResult must not be null!");
Assert.notNull(actionOperation, "MongoActionOperation must not be null!");
this.writeResult = writeResult;
this.actionOperation = actionOperation;
}
/**
* Returns the {@link WriteResult} that caused the exception.
*
* @return the writeResult
*/
public WriteResult getWriteResult() {
return writeResult;
}
/**
* Returns the {@link MongoActionOperation} in which the current exception occured.
*
* @return the actionOperation
*/
public MongoActionOperation getActionOperation() {
return actionOperation;
}
}

View File

@@ -27,15 +27,12 @@ import org.springframework.core.convert.converter.Converter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.support.CachingIsNewStrategyFactory;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -134,21 +131,11 @@ public abstract class AbstractMongoConfiguration {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.initialize();
return mappingContext;
}
/**
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
*
* @return
* @throws ClassNotFoundException
*/
@Bean
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(mongoMappingContext()));
}
/**
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and

View File

@@ -50,7 +50,6 @@ import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.config.BeanComponentDefinitionBuilder;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
@@ -91,8 +90,6 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, id);
createIsNewStrategyFactoryBeanDefinition(ctxRef, parserContext, element);
// Need a reference to a Mongo instance
String dbFactoryRef = element.getAttribute("db-factory-ref");
if (!StringUtils.hasText(dbFactoryRef)) {
@@ -118,7 +115,6 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
indexHelperBuilder.addConstructorArgReference(ctxRef);
indexHelperBuilder.addConstructorArgReference(dbFactoryRef);
indexHelperBuilder.addDependsOn(ctxRef);
parserContext.registerBeanComponent(new BeanComponentDefinition(indexHelperBuilder.getBeanDefinition(),
INDEX_HELPER));
@@ -249,7 +245,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
return null;
}
private static Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
public static Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
String basePackage = element.getAttribute(BASE_PACKAGE);
@@ -288,19 +284,6 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
return null;
}
public static String createIsNewStrategyFactoryBeanDefinition(String mappingContextRef, ParserContext context,
Element element) {
BeanDefinitionBuilder mappingContextStrategyFactoryBuilder = BeanDefinitionBuilder
.rootBeanDefinition(MappingContextIsNewStrategyFactory.class);
mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
context.registerBeanComponent(builder.getComponent(mappingContextStrategyFactoryBuilder, IS_NEW_STRATEGY_FACTORY));
return IS_NEW_STRATEGY_FACTORY;
}
/**
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
*

View File

@@ -1,80 +0,0 @@
/*
* Copyright 2012 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.mongodb.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.config.IsNewAwareAuditingHandlerBeanDefinitionParser;
import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener;
import org.w3c.dom.Element;
/**
* {@link BeanDefinitionParser} to register a {@link AuditingEventListener} to transparently set auditing information on
* an entity.
*
* @author Oliver Gierke
*/
public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
*/
@Override
protected Class<?> getBeanClass(Element element) {
return AuditingEventListener.class;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#shouldGenerateId()
*/
@Override
protected boolean shouldGenerateId() {
return true;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
*/
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
BeanDefinitionRegistry registry = parserContext.getRegistry();
if (!registry.containsBeanDefinition(BeanNames.IS_NEW_STRATEGY_FACTORY)) {
String mappingContextName = BeanNames.MAPPING_CONTEXT;
if (!registry.containsBeanDefinition(BeanNames.MAPPING_CONTEXT)) {
mappingContextName = MappingMongoConverterParser.potentiallyCreateMappingContext(element, parserContext, null,
BeanNames.DEFAULT_CONVERTER_BEAN_NAME);
}
MappingMongoConverterParser.createIsNewStrategyFactoryBeanDefinition(mappingContextName, parserContext, element);
}
BeanDefinitionParser parser = new IsNewAwareAuditingHandlerBeanDefinitionParser(BeanNames.IS_NEW_STRATEGY_FACTORY);
BeanDefinition handlerBeanDefinition = parser.parse(element, parserContext);
builder.addConstructorArgValue(handlerBeanDefinition);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2012 the original author or authors.
* Copyright 2011 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.
@@ -21,16 +21,17 @@ import org.springframework.data.repository.config.RepositoryBeanDefinitionParser
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB configuration.
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB based repositories.
*
* @author Oliver Gierke
*/
public class MongoNamespaceHandler extends NamespaceHandlerSupport {
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
* (non-Javadoc)
*
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
public void init() {
RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension();
@@ -41,6 +42,5 @@ public class MongoNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("mongo", new MongoParser());
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
registerBeanDefinitionParser("jmx", new MongoJmxParser());
registerBeanDefinitionParser("auditing", new MongoAuditingBeanDefinitionParser());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011 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.
@@ -31,7 +31,6 @@ import com.mongodb.ServerAddress;
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
@@ -44,11 +43,6 @@ public class ServerAddressPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String replicaSetString) {
if (!StringUtils.hasText(replicaSetString)) {
setValue(null);
return;
}
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
Set<ServerAddress> serverAddresses = new HashSet<ServerAddress>(replicaSetStringArray.length);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2011 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.
@@ -26,13 +26,14 @@ import com.mongodb.DB;
import com.mongodb.Mongo;
/**
* Helper class featuring helper methods for internal MongoDb classes. Mainly intended for internal use within the
* framework.
* Helper class featuring helper methods for internal MongoDb classes.
* <p/>
* <p>
* Mainly intended for internal use within the framework.
*
* @author Thomas Risberg
* @author Graeme Rocher
* @author Oliver Gierke
* @author Randy Watler
* @since 1.0
*/
public abstract class MongoDbUtils {
@@ -111,8 +112,8 @@ public abstract class MongoDbUtils {
String password = credentials.hasPassword() ? credentials.getPassword() : null;
if (!db.authenticate(username, password == null ? null : password.toCharArray())) {
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName + "], "
+ credentials.toString(), databaseName, credentials);
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
+ "], username = [" + username + "], password = [ -not-shown- ]", databaseName, credentials);
}
}
}
@@ -130,11 +131,8 @@ public abstract class MongoDbUtils {
holderToUse.addDB(databaseName, db);
}
// synchronize holder only if not yet synchronized
if (!holderToUse.isSynchronizedWithTransaction()) {
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
holderToUse.setSynchronizedWithTransaction(true);
}
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != dbHolder) {
TransactionSynchronizationManager.bindResource(mongo, holderToUse);

View File

@@ -15,9 +15,7 @@
*/
package org.springframework.data.mongodb.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.DisposableBean;
@@ -26,7 +24,6 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
import org.springframework.util.StringUtils;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;
@@ -39,7 +36,6 @@ import com.mongodb.WriteConcern;
* @author Thomas Risberg
* @author Graeme Rocher
* @author Oliver Gierke
* @author Thomas Darimont
* @since 1.0
*/
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, DisposableBean,
@@ -61,38 +57,11 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, D
}
public void setReplicaSetSeeds(ServerAddress[] replicaSetSeeds) {
this.replicaSetSeeds = filterNonNullElementsAsList(replicaSetSeeds);
this.replicaSetSeeds = Arrays.asList(replicaSetSeeds);
}
/**
* @deprecated use {@link #setReplicaSetSeeds(ServerAddress[])} instead
*
* @param replicaPair
*/
@Deprecated
public void setReplicaPair(ServerAddress[] replicaPair) {
this.replicaPair = filterNonNullElementsAsList(replicaPair);
}
/**
* @param elements the elements to filter <T>
* @return a new unmodifiable {@link List#} from the given elements without nulls
*/
private <T> List<T> filterNonNullElementsAsList(T[] elements) {
if (elements == null) {
return Collections.emptyList();
}
List<T> candidateElements = new ArrayList<T>();
for (T element : elements) {
if (element != null) {
candidateElements.add(element);
}
}
return Collections.unmodifiableList(candidateElements);
this.replicaPair = Arrays.asList(replicaPair);
}
public void setHost(String host) {
@@ -157,15 +126,15 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, D
mongoOptions = new MongoOptions();
}
if (!isNullOrEmpty(replicaPair)) {
if (replicaPair != null) {
if (replicaPair.size() < 2) {
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
}
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
} else if (!isNullOrEmpty(replicaSetSeeds)) {
} else if (replicaSetSeeds != null) {
mongo = new Mongo(replicaSetSeeds, mongoOptions);
} else {
String mongoHost = StringUtils.hasText(host) ? host : defaultOptions.getHost();
String mongoHost = host != null ? host : defaultOptions.getHost();
mongo = port != null ? new Mongo(new ServerAddress(mongoHost, port), mongoOptions) : new Mongo(mongoHost,
mongoOptions);
}
@@ -177,10 +146,6 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, D
this.mongo = mongo;
}
private boolean isNullOrEmpty(Collection<?> elements) {
return elements == null || elements.isEmpty();
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.DisposableBean#destroy()

View File

@@ -247,7 +247,7 @@ public interface MongoOperations {
* Query for a list of objects of type T from the collection used by the entity class.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
@@ -261,7 +261,7 @@ public interface MongoOperations {
* Query for a list of objects of type T from the specified collection.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
@@ -382,7 +382,7 @@ public interface MongoOperations {
* specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
@@ -399,7 +399,7 @@ public interface MongoOperations {
* type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
@@ -417,7 +417,7 @@ public interface MongoOperations {
* Map the results of an ad-hoc query on the collection for the entity class to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
@@ -433,7 +433,7 @@ public interface MongoOperations {
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
@@ -501,7 +501,7 @@ public interface MongoOperations {
* type. The first document that matches the query is returned and also removed from the collection in the database.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
@@ -555,7 +555,7 @@ public interface MongoOperations {
* Insert the object into the specified collection.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
@@ -593,7 +593,7 @@ public interface MongoOperations {
* object is not already present, that is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
@@ -610,7 +610,7 @@ public interface MongoOperations {
* is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of MappingMongoConverter will be used.
* configured otherwise, an instance of SimpleMongoConverter will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
@@ -734,4 +734,4 @@ public interface MongoOperations {
* @return
*/
MongoConverter getConverter();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2012 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.
@@ -44,6 +44,7 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.authentication.UserCredentials;
@@ -52,7 +53,6 @@ import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.MongoDataIntegrityViolationException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
@@ -534,26 +534,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
mongoConverter, entityClass), near.getMetric());
List<GeoResult<T>> result = new ArrayList<GeoResult<T>>(results.size());
int index = 0;
int elementsToSkip = near.getSkip() != null ? near.getSkip() : 0;
for (Object element : results) {
/*
* As MongoDB currently (2.4.4) doesn't support the skipping of elements in near queries
* we skip the elements ourselves to avoid at least the document 2 object mapping overhead.
*
* @see https://jira.mongodb.org/browse/SERVER-3925
*/
if (index >= elementsToSkip) {
result.add(callback.doWith((DBObject) element));
}
index++;
}
if (elementsToSkip > 0) {
// as we skipped some elements we have to calculate the averageDistance ourselves:
return new GeoResults<T>(result, near.getMetric());
result.add(callback.doWith((DBObject) element));
}
DBObject stats = (DBObject) commandResult.get("stats");
@@ -684,9 +666,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(entity.getClass());
if (mongoPersistentEntity != null && mongoPersistentEntity.hasVersionProperty()) {
BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(entity,
this.mongoConverter.getConversionService());
if (mongoPersistentEntity == null || mongoPersistentEntity.hasVersionProperty()) {
BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(entity, null);
wrapper.setProperty(mongoPersistentEntity.getVersionProperty(), 0);
}
}
@@ -789,7 +770,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
// Fresh instance -> initialize version property
if (version == null) {
doInsert(collectionName, objectToSave, this.mongoConverter);
beanWrapper.setProperty(versionProperty, 0);
doSave(collectionName, objectToSave, this.mongoConverter);
} else {
assertUpdateableIdIfNotSet(objectToSave);
@@ -810,11 +792,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject));
Update update = Update.fromDBObject(dbObject, ID_FIELD);
doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
updateFirst(query, update, objectToSave.getClass());
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject));
}
}
@SuppressWarnings("unchecked")
protected <T> void doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
assertUpdateableIdIfNotSet(objectToSave);
@@ -827,7 +810,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
writer.write(objectToSave, dbDoc);
} else {
try {
dbDoc = (DBObject) JSON.parse((String) objectToSave);
objectToSave = (T) JSON.parse((String) objectToSave);
} catch (JSONParseException e) {
throw new MappingException("Could not parse given String to save into a JSON document!", e);
}
@@ -958,7 +941,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
if (entity != null && entity.hasVersionProperty() && !multi) {
if (writeResult.getN() == 0) {
throw new OptimisticLockingFailureException("Optimistic lock exception on saving entity: "
+ updateObj.toMap().toString() + " to collection " + collectionName);
+ updateObj.toMap().toString());
}
}
@@ -998,12 +981,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
Assert.notNull(object);
Class<?> objectType = object.getClass();
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(objectType);
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
MongoPersistentProperty idProp = entity == null ? null : entity.getIdProperty();
if (idProp == null) {
throw new MappingException("No id property found for object of type " + objectType);
throw new MappingException("No id property found for object of type " + entity.getType().getName());
}
ConversionService service = mongoConverter.getConversionService();
@@ -1324,8 +1306,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
/**
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type. The object is
* converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless configured
* otherwise, an instance of MappingMongoConverter will be used. The query document is specified as a standard
* DBObject and so is the fields specification. Can be overridden by subclasses.
* otherwise, an instance of SimpleMongoConverter will be used. The query document is specified as a standard DBObject
* and so is the fields specification. Can be overridden by subclasses.
*
* @param collectionName name of the collection to retrieve the objects from
* @param query the query document that specifies the criteria used to find a record
@@ -1426,15 +1408,19 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), entity);
DBObject updateObj = update.getUpdateObject();
for (String key : updateObj.keySet()) {
updateObj.put(key, mongoConverter.convertToMongoType(updateObj.get(key)));
}
DBObject mappedQuery = mapper.getMappedObject(query, entity);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findAndModify using query: " + mappedQuery + " fields: " + fields + " sort: " + sort
+ " for class: " + entityClass + " and update: " + mappedUpdate + " in collection: " + collectionName);
+ " for class: " + entityClass + " and update: " + updateObj + " in collection: " + collectionName);
}
return executeFindOneInternal(new FindAndModifyCallback(mappedQuery, fields, sort, mappedUpdate, options),
return executeFindOneInternal(new FindAndModifyCallback(mappedQuery, fields, sort, updateObj, options),
new ReadDbObjectCallback<T>(readerToUse, entityClass), collectionName);
}
@@ -1661,7 +1647,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
}
if (writeResultChecking == WriteResultChecking.EXCEPTION) {
throw new MongoDataIntegrityViolationException(message, writeResult, operation);
throw new DataIntegrityViolationException(message);
} else {
LOGGER.error(message);
return;

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright (c) 2011 by the original author(s).
*
* 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
* 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,
@@ -17,11 +17,9 @@ package org.springframework.data.mongodb.core.convert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
@@ -33,7 +31,6 @@ import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.convert.JodaTimeConverters;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.mapping.model.SimpleTypeHolder;
@@ -65,7 +62,6 @@ public class CustomConversions {
private final Set<ConvertiblePair> writingPairs;
private final Set<Class<?>> customSimpleTypes;
private final SimpleTypeHolder simpleTypeHolder;
private final Map<Class<?>, HashMap<Class<?>, CacheValue>> cache;
private final List<Object> converters;
@@ -88,7 +84,6 @@ public class CustomConversions {
this.readingPairs = new HashSet<ConvertiblePair>();
this.writingPairs = new HashSet<ConvertiblePair>();
this.customSimpleTypes = new HashSet<Class<?>>();
this.cache = new HashMap<Class<?>, HashMap<Class<?>, CacheValue>>();
this.converters = new ArrayList<Object>();
this.converters.add(CustomToStringConverter.INSTANCE);
@@ -98,7 +93,6 @@ public class CustomConversions {
this.converters.add(StringToBigIntegerConverter.INSTANCE);
this.converters.add(URLToStringConverter.INSTANCE);
this.converters.add(StringToURLConverter.INSTANCE);
this.converters.addAll(JodaTimeConverters.getConvertersToRegister());
this.converters.addAll(converters);
for (Object c : this.converters) {
@@ -272,11 +266,9 @@ public class CustomConversions {
* @return
*/
public boolean hasCustomReadTarget(Class<?> source, Class<?> expectedTargetType) {
Assert.notNull(source);
Assert.notNull(expectedTargetType);
return getCustomReadTarget(source, expectedTargetType) != null;
return getCustomTarget(source, expectedTargetType, readingPairs) != null;
}
/**
@@ -305,32 +297,8 @@ public class CustomConversions {
return null;
}
private Class<?> getCustomReadTarget(Class<?> source, Class<?> expectedTargetType) {
Class<?> type = expectedTargetType == null ? PlaceholderType.class : expectedTargetType;
Map<Class<?>, CacheValue> map;
CacheValue toReturn;
if ((map = cache.get(source)) == null || (toReturn = map.get(type)) == null) {
Class<?> target = getCustomTarget(source, type, readingPairs);
if (cache.get(source) == null) {
cache.put(source, new HashMap<Class<?>, CacheValue>());
}
Map<Class<?>, CacheValue> value = cache.get(source);
toReturn = target == null ? CacheValue.NULL : new CacheValue(target);
value.put(type, toReturn);
}
return toReturn.clazz;
}
@WritingConverter
private enum CustomToStringConverter implements GenericConverter {
INSTANCE;
public Set<ConvertiblePair> getConvertibleTypes() {
@@ -343,30 +311,4 @@ public class CustomConversions {
return source.toString();
}
}
/**
* Placeholder type to allow registering not-found values in the converter cache.
*
* @author Patryk Wasik
* @author Oliver Gierke
*/
private static class PlaceholderType {
}
/**
* Wrapper to safely store {@literal null} values in the type cache.
*
* @author Patryk Wasik
* @author Oliver Gierke
*/
private static class CacheValue {
public static final CacheValue NULL = new CacheValue(null);
private final Class<?> clazz;
public CacheValue(Class<?> clazz) {
this.clazz = clazz;
}
}
}

View File

@@ -31,13 +31,11 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper;
@@ -48,7 +46,6 @@ import org.springframework.data.mapping.model.PersistentEntityParameterValueProv
import org.springframework.data.mapping.model.PropertyValueProvider;
import org.springframework.data.mapping.model.SpELContext;
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
@@ -218,9 +215,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator, parent);
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
entity, provider, parent);
parameterProvider.setSpELEvaluator(evaluator);
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider,
parent);
return parameterProvider;
}
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo, Object parent) {
@@ -238,7 +235,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
if (!dbo.containsField(prop.getFieldName()) || entity.isConstructorArgument(prop)) {
boolean isConstructorProperty = entity.isConstructorArgument(prop);
boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
if (!hasValueForProperty || isConstructorProperty) {
return;
}
@@ -829,7 +829,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return conversionService.convert(obj, target);
}
if (conversions.isSimpleType(obj.getClass())) {
if (null != obj && conversions.isSimpleType(obj.getClass())) {
// Doesn't need conversion
return getPotentiallyConvertedSimpleWrite(obj);
}
@@ -942,6 +942,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* (non-Javadoc)
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
*/
@SuppressWarnings("unchecked")
public <T> T getPropertyValue(MongoPersistentProperty property) {
String expression = property.getSpelExpression();
@@ -951,60 +952,20 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return null;
}
return readValue(value, property.getTypeInformation(), parent);
}
}
TypeInformation<?> type = property.getTypeInformation();
Class<?> rawType = type.getType();
/**
* Extension of {@link SpELExpressionParameterValueProvider} to recursively trigger value conversion on the raw
* resolved SpEL value.
*
* @author Oliver Gierke
*/
private class ConverterAwareSpELExpressionParameterValueProvider extends
SpELExpressionParameterValueProvider<MongoPersistentProperty> {
private final Object parent;
/**
* Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider}.
*
* @param evaluator must not be {@literal null}.
* @param conversionService must not be {@literal null}.
* @param delegate must not be {@literal null}.
*/
public ConverterAwareSpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator,
ConversionService conversionService, ParameterValueProvider<MongoPersistentProperty> delegate, Object parent) {
super(evaluator, conversionService, delegate);
this.parent = parent;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.SpELExpressionParameterValueProvider#potentiallyConvertSpelValue(java.lang.Object, org.springframework.data.mapping.PreferredConstructor.Parameter)
*/
@Override
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, MongoPersistentProperty> parameter) {
return readValue(object, parameter.getType(), parent);
}
}
@SuppressWarnings("unchecked")
private <T> T readValue(Object value, TypeInformation<?> type, Object parent) {
Class<?> rawType = type.getType();
if (conversions.hasCustomReadTarget(value.getClass(), rawType)) {
return (T) conversionService.convert(value, rawType);
} else if (value instanceof DBRef) {
return (T) (rawType.equals(DBRef.class) ? value : read(type, ((DBRef) value).fetch(), parent));
} else if (value instanceof BasicDBList) {
return (T) readCollectionOrArray(type, (BasicDBList) value, parent);
} else if (value instanceof DBObject) {
return (T) read(type, (DBObject) value, parent);
} else {
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
if (conversions.hasCustomReadTarget(value.getClass(), rawType)) {
return (T) conversionService.convert(value, rawType);
} else if (value instanceof DBRef) {
return (T) (rawType.equals(DBRef.class) ? value : read(type, ((DBRef) value).fetch(), parent));
} else if (value instanceof BasicDBList) {
return (T) readCollectionOrArray(type, (BasicDBList) value, parent);
} else if (value instanceof DBObject) {
return (T) read(type, (DBObject) value, parent);
} else {
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2012 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.
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.core.convert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.bson.types.ObjectId;
import org.springframework.core.convert.ConversionException;
@@ -42,7 +41,6 @@ import com.mongodb.DBRef;
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Patryk Wasik
*/
public class QueryMapper {
@@ -85,22 +83,11 @@ public class QueryMapper {
for (String key : query.keySet()) {
if (Keyword.isKeyword(key)) {
result.putAll(getMappedKeyword(new Keyword(query, key), entity));
continue;
}
MongoPersistentProperty targetProperty = getTargetProperty(key, entity);
String newKey = determineKey(key, entity);
Object value = query.get(key);
Field field = entity == null ? new Field(key) : new MetadataBackedField(key, entity, mappingContext);
Object rawValue = query.get(key);
String newKey = field.getMappedKey();
if (Keyword.isKeyword(rawValue) && !field.isIdField()) {
Keyword keyword = new Keyword((DBObject) rawValue);
result.put(newKey, getMappedKeyword(field, keyword));
} else {
result.put(newKey, getMappedValue(field, query.get(key)));
}
result.put(newKey, getMappedValue(value, targetProperty, newKey));
}
return result;
@@ -116,14 +103,13 @@ public class QueryMapper {
private DBObject getMappedKeyword(Keyword query, MongoPersistentEntity<?> entity) {
// $or/$nor
if (query.key.matches(N_OR_PATTERN) || query.value instanceof Iterable) {
if (query.key.matches(N_OR_PATTERN)) {
Iterable<?> conditions = (Iterable<?>) query.value;
BasicDBList newConditions = new BasicDBList();
for (Object condition : conditions) {
newConditions.add(condition instanceof DBObject ? getMappedObject((DBObject) condition, entity)
: convertSimpleOrDBObject(condition, entity));
newConditions.add(getMappedObject((DBObject) condition, entity));
}
return new BasicDBObject(query.key, newConditions);
@@ -135,34 +121,38 @@ public class QueryMapper {
/**
* Returns the mapped keyword considered defining a criteria for the given property.
*
* @param property
* @param keyword
* @param property
* @return
*/
private DBObject getMappedKeyword(Field property, Keyword keyword) {
public DBObject getMappedKeyword(Keyword keyword, MongoPersistentProperty property) {
boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists();
Object value = needsAssociationConversion ? convertAssociation(keyword.value, property.getProperty())
: getMappedValue(property.with(keyword.key), keyword.value);
if (property.isAssociation()) {
convertAssociation(keyword.value, property);
}
return new BasicDBObject(keyword.key, value);
return new BasicDBObject(keyword.key, getMappedValue(keyword.value, property, keyword.key));
}
/**
* Returns the mapped value for the given source object assuming it's a value for the given
* {@link MongoPersistentProperty}.
*
* @param value the source object to be mapped
* @param source the source object to be mapped
* @param property the property the value is a value for
* @param newKey the key the value will be bound to eventually
* @return
*/
private Object getMappedValue(Field documentField, Object value) {
private Object getMappedValue(Object source, MongoPersistentProperty property, String newKey) {
if (documentField.isIdField()) {
if (property == null) {
return convertSimpleOrDBObject(source, null);
}
if (value instanceof DBObject) {
DBObject valueDbo = (DBObject) value;
if (property.isIdProperty() || "_id".equals(newKey)) {
if (source instanceof DBObject) {
DBObject valueDbo = (DBObject) source;
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
List<Object> ids = new ArrayList<Object>();
@@ -173,25 +163,63 @@ public class QueryMapper {
} else if (valueDbo.containsField("$ne")) {
valueDbo.put("$ne", convertId(valueDbo.get("$ne")));
} else {
return getMappedObject((DBObject) value, null);
return getMappedObject((DBObject) source, null);
}
return valueDbo;
} else {
return convertId(value);
return convertId(source);
}
}
if (Keyword.isKeyword(value)) {
return getMappedKeyword(new Keyword((DBObject) value), null);
if (property.isAssociation()) {
return Keyword.isKeyword(source) ? getMappedKeyword(new Keyword(source), property) : convertAssociation(source,
property);
}
if (documentField.isAssociation()) {
return convertAssociation(value, documentField.getProperty());
return convertSimpleOrDBObject(source, mappingContext.getPersistentEntity(property));
}
private MongoPersistentProperty getTargetProperty(String key, MongoPersistentEntity<?> entity) {
if (isIdKey(key, entity)) {
return entity.getIdProperty();
}
return convertSimpleOrDBObject(value, documentField.getPropertyEntity());
PersistentPropertyPath<MongoPersistentProperty> path = getPath(key, entity);
return path == null ? null : path.getLeafProperty();
}
private PersistentPropertyPath<MongoPersistentProperty> getPath(String key, MongoPersistentEntity<?> entity) {
if (entity == null) {
return null;
}
try {
PropertyPath path = PropertyPath.from(key, entity.getTypeInformation());
return mappingContext.getPersistentPropertyPath(path);
} catch (PropertyReferenceException e) {
return null;
}
}
/**
* Returns the translated key assuming the given one is a propert (path) reference.
*
* @param key the source key
* @param entity the base entity
* @return the translated key
*/
private String determineKey(String key, MongoPersistentEntity<?> entity) {
if (entity == null && DEFAULT_ID_NAMES.contains(key)) {
return "_id";
}
PersistentPropertyPath<MongoPersistentProperty> path = getPath(key, entity);
return path == null ? key : path.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE);
}
/**
@@ -215,7 +243,7 @@ public class QueryMapper {
}
/**
* Converts the given source assuming it's actually an association to another object.
* Converts the given source assuming it's actually an association to anoter object.
*
* @param source
* @param property
@@ -235,17 +263,29 @@ public class QueryMapper {
return result;
}
if (property.isMap()) {
BasicDBObject result = new BasicDBObject();
DBObject dbObject = (DBObject) source;
for (String key : dbObject.keySet()) {
Object o = dbObject.get(key);
result.put(key, o instanceof DBRef ? o : converter.toDBRef(o, property));
}
return result;
return source == null || source instanceof DBRef ? source : converter.toDBRef(source, property);
}
/**
* Returns whether the given key will be considered an id key.
*
* @param key
* @param entity
* @return
*/
private boolean isIdKey(String key, MongoPersistentEntity<?> entity) {
if (entity == null) {
return false;
}
return source == null || source instanceof DBRef ? source : converter.toDBRef(source, property);
MongoPersistentProperty idProperty = entity.getIdProperty();
if (idProperty != null) {
return idProperty.getName().equals(key) || idProperty.getFieldName().equals(key);
}
return DEFAULT_ID_NAMES.contains(key);
}
/**
@@ -275,27 +315,16 @@ public class QueryMapper {
String key;
Object value;
public Keyword(DBObject source, String key) {
this.key = key;
this.value = source.get(key);
}
Keyword(Object source) {
public Keyword(DBObject dbObject) {
Assert.isInstanceOf(DBObject.class, source);
Set<String> keys = dbObject.keySet();
Assert.isTrue(keys.size() == 1, "Can only use a single value DBObject!");
DBObject value = (DBObject) source;
this.key = keys.iterator().next();
this.value = dbObject.get(key);
}
Assert.isTrue(value.keySet().size() == 1, "Keyword must have a single key only!");
/**
* Returns whether the current keyword is the {@code $exists} keyword.
*
* @return
*/
public boolean isExists() {
return "$exists".equalsIgnoreCase(key);
this.key = value.keySet().iterator().next();
this.value = value.get(key);
}
/**
@@ -305,11 +334,7 @@ public class QueryMapper {
* @param value
* @return
*/
public static boolean isKeyword(Object value) {
if (value instanceof String) {
return ((String) value).startsWith("$");
}
static boolean isKeyword(Object value) {
if (!(value instanceof DBObject)) {
return false;
@@ -319,192 +344,4 @@ public class QueryMapper {
return dbObject.keySet().size() == 1 && dbObject.keySet().iterator().next().startsWith("$");
}
}
/**
* Value object to represent a field and its meta-information.
*
* @author Oliver Gierke
*/
private static class Field {
private static final String ID_KEY = "_id";
protected final String name;
/**
* Creates a new {@link Field} without meta-information but the given name.
*
* @param name must not be {@literal null} or empty.
*/
public Field(String name) {
Assert.hasText(name, "Name must not be null!");
this.name = name;
}
/**
* Returns a new {@link Field} with the given name.
*
* @param name must not be {@literal null} or empty.
* @return
*/
public Field with(String name) {
return new Field(name);
}
/**
* Returns whether the current field is the id field.
*
* @return
*/
public boolean isIdField() {
return ID_KEY.equals(name);
}
/**
* Returns the underlying {@link MongoPersistentProperty} backing the field.
*
* @return
*/
public MongoPersistentProperty getProperty() {
return null;
}
/**
* Returns the {@link MongoPersistentEntity} that field is conatined in.
*
* @return
*/
public MongoPersistentEntity<?> getPropertyEntity() {
return null;
}
/**
* Returns whether the field represents an association.
*
* @return
*/
public boolean isAssociation() {
return false;
}
/**
* Returns the key to be used in the mapped document eventually.
*
* @return
*/
public String getMappedKey() {
return isIdField() ? ID_KEY : name;
}
}
/**
* Extension of {@link Field} to be backed with mapping metadata.
*
* @author Oliver Gierke
*/
private static class MetadataBackedField extends Field {
private final MongoPersistentEntity<?> entity;
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
private final MongoPersistentProperty property;
/**
* Creates a new {@link MetadataBackedField} with the given name, {@link MongoPersistentEntity} and
* {@link MappingContext}.
*
* @param name must not be {@literal null} or empty.
* @param entity must not be {@literal null}.
* @param context must not be {@literal null}.
*/
public MetadataBackedField(String name, MongoPersistentEntity<?> entity,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context) {
super(name);
Assert.notNull(entity, "MongoPersistentEntity must not be null!");
this.entity = entity;
this.mappingContext = context;
PersistentPropertyPath<MongoPersistentProperty> path = getPath(name);
this.property = path == null ? null : path.getLeafProperty();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#with(java.lang.String)
*/
@Override
public MetadataBackedField with(String name) {
return new MetadataBackedField(name, entity, mappingContext);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#isIdKey()
*/
@Override
public boolean isIdField() {
MongoPersistentProperty idProperty = entity.getIdProperty();
if (idProperty != null) {
return idProperty.getName().equals(name) || idProperty.getFieldName().equals(name);
}
return DEFAULT_ID_NAMES.contains(name);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getProperty()
*/
@Override
public MongoPersistentProperty getProperty() {
return property;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getEntity()
*/
@Override
public MongoPersistentEntity<?> getPropertyEntity() {
MongoPersistentProperty property = getProperty();
return property == null ? null : mappingContext.getPersistentEntity(property);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#isAssociation()
*/
@Override
public boolean isAssociation() {
MongoPersistentProperty property = getProperty();
return property == null ? false : property.isAssociation();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getTargetKey()
*/
@Override
public String getMappedKey() {
PersistentPropertyPath<MongoPersistentProperty> path = getPath(name);
return path == null ? name : path.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE);
}
private PersistentPropertyPath<MongoPersistentProperty> getPath(String name) {
try {
PropertyPath path = PropertyPath.from(name, entity.getTypeInformation());
return mappingContext.getPersistentPropertyPath(path);
} catch (PropertyReferenceException e) {
return null;
}
}
}
}

View File

@@ -1,5 +0,0 @@
/**
* Spring Data MongoDB specific converter infrastructure.
*/
package org.springframework.data.mongodb.core.convert;

View File

@@ -1,43 +0,0 @@
/*
* Copyright 2013 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.mongodb.core.geo;
/**
* Value object to create custom {@link Metric}s on the fly.
*
* @author Oliver Gierke
*/
public class CustomMetric implements Metric {
private final double multiplier;
/**
* Creates a custom {@link Metric} using the given multiplier.
*
* @param multiplier
*/
public CustomMetric(double multiplier) {
this.multiplier = multiplier;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Metric#getMultiplier()
*/
public double getMultiplier() {
return multiplier;
}
}

View File

@@ -131,7 +131,7 @@ public class GeoResults<T> implements Iterable<GeoResult<T>> {
private static Distance calculateAverageDistance(List<? extends GeoResult<?>> results, Metric metric) {
if (results.isEmpty()) {
return new Distance(0, metric);
return new Distance(0, null);
}
double averageDistance = 0;

View File

@@ -1,5 +0,0 @@
/**
* Support for MongoDB geo-spatial queries.
*/
package org.springframework.data.mongodb.core.geo;

View File

@@ -1,5 +0,0 @@
/**
* Support for MongoDB document indexing.
*/
package org.springframework.data.mongodb.core.index;

View File

@@ -23,6 +23,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.MongoCollectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
@@ -37,6 +38,7 @@ import org.springframework.util.StringUtils;
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Patryk Wasik
*/
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
MongoPersistentEntity<T>, ApplicationContextAware {
@@ -45,6 +47,8 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
private final SpelExpressionParser parser;
private final StandardEvaluationContext context;
private MongoPersistentProperty versionProperty;
/**
* Creates a new {@link BasicMongoPersistentEntity} with the given {@link TypeInformation}. Will default the
* collection name to the entities simple type name.
@@ -69,6 +73,27 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.MutablePersistentEntity#addPersistentProperty(P)
*/
@Override
public void addPersistentProperty(MongoPersistentProperty 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()));
}
this.versionProperty = property;
}
super.addPersistentProperty(property);
}
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -85,10 +110,27 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getCollection()
*/
public String getCollection() {
Expression expression = parser.parseExpression(collection, ParserContext.TEMPLATE_EXPRESSION);
return expression.getValue(context, String.class);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getVersionProperty()
*/
public MongoPersistentProperty getVersionProperty() {
return versionProperty;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#hasVersionProperty()
*/
public boolean hasVersionProperty() {
return getVersionProperty() != null;
}
/**
* {@link Comparator} implementation inspecting the {@link MongoPersistentProperty}'s order.
*

View File

@@ -153,6 +153,14 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
return getField().getAnnotation(DBRef.class);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isVersionProperty()
*/
public boolean isVersionProperty() {
return getField().isAnnotationPresent(Version.class);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()

View File

@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.AbstractMap;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
@@ -52,7 +51,7 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
*/
@Override
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
return !MongoSimpleTypes.HOLDER.isSimpleType(type.getType()) && !AbstractMap.class.isAssignableFrom(type.getType());
return !MongoSimpleTypes.HOLDER.isSimpleType(type.getType());
}
/*

View File

@@ -21,6 +21,7 @@ import org.springframework.data.mapping.PersistentEntity;
* MongoDB specific {@link PersistentEntity} abstraction.
*
* @author Oliver Gierke
* @author Patryk Wasik
*/
public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersistentProperty> {
@@ -30,4 +31,19 @@ public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersi
* @return
*/
String getCollection();
/**
* Returns the {@link MongoPersistentProperty} that represents the version attribute of an entity. Will not be
* {@literal null} if {@link #hasVersionProperty()}.
*
* @return
*/
MongoPersistentProperty getVersionProperty();
/**
* Returns whether the entity has a property representing the version of the entity.
*
* @return
*/
boolean hasVersionProperty();
}

View File

@@ -56,6 +56,13 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
*/
DBRef getDBRef();
/**
* Returns whether the property is representing the version attribute of an entity.
*
* @return
*/
boolean isVersionProperty();
/**
* Simple {@link Converter} implementation to transform a {@link MongoPersistentProperty} into its field name.
*

View File

@@ -27,13 +27,10 @@ import java.lang.annotation.Target;
*
* @since 1.4
* @author Patryk Wasik
* @deprecated use {@link org.springframework.data.annotation.Version} instead.
*/
@Deprecated
@Documented
@Target({ FIELD })
@Retention(RUNTIME)
@org.springframework.data.annotation.Version
public @interface Version {
}

View File

@@ -1,53 +0,0 @@
/*
* Copyright 2012 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.mongodb.core.mapping.event;
import org.springframework.context.ApplicationListener;
import org.springframework.data.auditing.AuditingHandler;
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
/**
* Event listener to populate auditing related fields on an entity about to be saved.
*
* @author Oliver Gierke
*/
public class AuditingEventListener implements ApplicationListener<BeforeConvertEvent<Object>> {
private final IsNewAwareAuditingHandler<Object> auditingHandler;
/**
* Creates a new {@link AuditingEventListener} using the given {@link MappingContext} and {@link AuditingHandler}.
*
* @param auditingHandler must not be {@literal null}.
*/
public AuditingEventListener(IsNewAwareAuditingHandler<Object> auditingHandler) {
Assert.notNull(auditingHandler, "IsNewAwareAuditingHandler must not be null!");
this.auditingHandler = auditingHandler;
}
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(BeforeConvertEvent<Object> event) {
Object entity = event.getSource();
auditingHandler.markAudited(entity);
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2012 the original author or authors.
* Copyright (c) 2011 by the original author(s).
*
* 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
* 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,
@@ -13,17 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.mapping.event;
/**
* Event being thrown before a domain object is converted to be persisted.
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class BeforeConvertEvent<T> extends MongoMappingEvent<T> {
private static final long serialVersionUID = 252614269008845243L;
private static final long serialVersionUID = 1L;
public BeforeConvertEvent(T source) {
super(source, null);

View File

@@ -1,5 +0,0 @@
/**
* Mapping event callback infrastructure for the MongoDB document-to-object mapping subsystem.
*/
package org.springframework.data.mongodb.core.mapping.event;

View File

@@ -1,5 +0,0 @@
/**
* Infrastructure for the MongoDB document-to-object mapping subsystem.
*/
package org.springframework.data.mongodb.core.mapping;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2012 the original author or authors.
* Copyright 2010-2011 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.
@@ -16,42 +16,30 @@
package org.springframework.data.mongodb.core.mapreduce;
/**
* Value object to encapsulate results of a map-reduce count.
*
* @author Mark Pollack
* @author Oliver Gierke
*/
public class MapReduceCounts {
public static MapReduceCounts NONE = new MapReduceCounts(-1, -1, -1);
private final long inputCount;
private final long emitCount;
private final long outputCount;
/**
* Creates a new {@link MapReduceCounts} using the given input count, emit count, and output count.
*
* @param inputCount
* @param emitCount
* @param outputCount
*/
public MapReduceCounts(long inputCount, long emitCount, long outputCount) {
private final int inputCount;
private final int emitCount;
private final int outputCount;
public MapReduceCounts(int inputCount, int emitCount, int outputCount) {
super();
this.inputCount = inputCount;
this.emitCount = emitCount;
this.outputCount = outputCount;
}
public long getInputCount() {
public int getInputCount() {
return inputCount;
}
public long getEmitCount() {
public int getEmitCount() {
return emitCount;
}
public long getOutputCount() {
public int getOutputCount() {
return outputCount;
}
@@ -71,15 +59,12 @@ public class MapReduceCounts {
*/
@Override
public int hashCode() {
final int prime = 31;
long result = 1;
int result = 1;
result = prime * result + emitCount;
result = prime * result + inputCount;
result = prime * result + outputCount;
return Long.valueOf(result).intValue();
return result;
}
/*

View File

@@ -118,14 +118,15 @@ public class MapReduceResults<T> implements Iterable<T> {
DBObject counts = (DBObject) rawResults.get("counts");
if (counts == null) {
return MapReduceCounts.NONE;
return new MapReduceCounts(-1, -1, -1);
}
if (counts.get("input") != null && counts.get("emit") != null && counts.get("output") != null) {
return new MapReduceCounts(getAsLong(counts, "input"), getAsLong(counts, "emit"), getAsLong(counts, "output"));
return new MapReduceCounts((Integer) counts.get("input"), (Integer) counts.get("emit"),
(Integer) counts.get("output"));
}
return MapReduceCounts.NONE;
return new MapReduceCounts(-1, -1, -1);
}
/**

View File

@@ -1,5 +0,0 @@
/**
* Support for MongoDB map-reduce operations.
*/
package org.springframework.data.mongodb.core.mapreduce;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2011 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.
@@ -39,10 +39,6 @@ import com.mongodb.DBObject;
/**
* Central class for creating queries. It follows a fluent API style so that you can easily chain together multiple
* criteria. Static import of the 'Criteria.where' method will improve readability.
*
* @author Thomas Risberg
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class Criteria implements CriteriaDefinition {
@@ -400,54 +396,34 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates an 'or' criteria using the $or operator for all of the provided criteria
* <p>
* Note that mongodb doesn't support an $or operator to be wrapped in a $not operator.
* <p>
*
* @throws IllegalArgumentException if {@link #orOperator(Criteria...)} follows a not() call directly.
* @param criteria
*/
public Criteria orOperator(Criteria... criteria) {
BasicDBList bsonList = createCriteriaList(criteria);
return registerCriteriaChainElement(new Criteria("$or").is(bsonList));
criteriaChain.add(new Criteria("$or").is(bsonList));
return this;
}
/**
* Creates a 'nor' criteria using the $nor operator for all of the provided criteria.
* <p>
* Note that mongodb doesn't support an $nor operator to be wrapped in a $not operator.
* <p>
* Creates a 'nor' criteria using the $nor operator for all of the provided criteria
*
* @throws IllegalArgumentException if {@link #norOperator(Criteria...)} follows a not() call directly.
* @param criteria
*/
public Criteria norOperator(Criteria... criteria) {
BasicDBList bsonList = createCriteriaList(criteria);
return registerCriteriaChainElement(new Criteria("$nor").is(bsonList));
criteriaChain.add(new Criteria("$nor").is(bsonList));
return this;
}
/**
* Creates an 'and' criteria using the $and operator for all of the provided criteria.
* <p>
* Note that mongodb doesn't support an $and operator to be wrapped in a $not operator.
* <p>
* Creates an 'and' criteria using the $and operator for all of the provided criteria
*
* @throws IllegalArgumentException if {@link #andOperator(Criteria...)} follows a not() call directly.
* @param criteria
*/
public Criteria andOperator(Criteria... criteria) {
BasicDBList bsonList = createCriteriaList(criteria);
return registerCriteriaChainElement(new Criteria("$and").is(bsonList));
}
private Criteria registerCriteriaChainElement(Criteria criteria) {
if (lastOperatorWasNot()) {
throw new IllegalArgumentException("operator $not is not allowed around criteria chain element: "
+ criteria.getCriteriaObject());
} else {
criteriaChain.add(criteria);
}
criteriaChain.add(new Criteria("$and").is(bsonList));
return this;
}
@@ -492,7 +468,6 @@ public class Criteria implements CriteriaDefinition {
}
}
}
DBObject queryCriteria = new BasicDBObject();
if (isValue != NOT_SET) {
queryCriteria.put(this.key, this.isValue);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2011 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.
@@ -18,15 +18,14 @@ package org.springframework.data.mongodb.core.query;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.ObjectUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
public class Field {
private final Map<String, Integer> criteria = new HashMap<String, Integer>();
private final Map<String, Object> slices = new HashMap<String, Object>();
private Map<String, Integer> criteria = new HashMap<String, Integer>();
private Map<String, Object> slices = new HashMap<String, Object>();
public Field include(String key) {
criteria.put(key, Integer.valueOf(1));
@@ -51,54 +50,11 @@ public class Field {
public DBObject getFieldsObject() {
DBObject dbo = new BasicDBObject();
for (String k : criteria.keySet()) {
dbo.put(k, criteria.get(k));
dbo.put(k, (criteria.get(k)));
}
for (String k : slices.keySet()) {
dbo.put(k, new BasicDBObject("$slice", slices.get(k)));
dbo.put(k, new BasicDBObject("$slice", (slices.get(k))));
}
return dbo;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof Field)) {
return false;
}
Field that = (Field) object;
if (!this.criteria.equals(that.criteria)) {
return false;
}
if (!this.slices.equals(that.slices)) {
return false;
}
return true;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * ObjectUtils.nullSafeHashCode(this.criteria);
result += 31 * ObjectUtils.nullSafeHashCode(this.slices);
return result;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011 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.
@@ -15,8 +15,6 @@
*/
package org.springframework.data.mongodb.core.query;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.geo.CustomMetric;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.Metric;
import org.springframework.data.mongodb.core.geo.Metrics;
@@ -30,17 +28,13 @@ import com.mongodb.DBObject;
* Builder class to build near-queries.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class NearQuery {
private final Point point;
private final DBObject criteria;
private Query query;
private Distance maxDistance;
private Double maxDistance;
private Metric metric;
private boolean spherical;
private Integer num;
private Integer skip;
/**
* Creates a new {@link NearQuery}.
@@ -51,11 +45,13 @@ public class NearQuery {
Assert.notNull(point);
this.point = point;
this.spherical = false;
this.criteria = new BasicDBObject();
this.criteria.put("near", point.asList());
this.metric = metric;
if (metric != null) {
in(metric);
spherical(true);
distanceMultiplier(metric);
}
}
@@ -109,135 +105,83 @@ public class NearQuery {
}
/**
* Returns the {@link Metric} underlying the actual query. If no metric was set explicitly {@link Metrics#NEUTRAL}
* will be returned.
* Returns the {@link Metric} underlying the actual query.
*
* @return will never be {@literal null}.
* @return
*/
public Metric getMetric() {
return metric == null ? Metrics.NEUTRAL : metric;
return metric;
}
/**
* Configures the maximum number of results to return.
* Configures the number of results to return.
*
* @param num
* @return
*/
public NearQuery num(int num) {
this.num = num;
this.criteria.put("num", num);
return this;
}
/**
* Configures the number of results to skip.
*
* @param skip
* @return
*/
public NearQuery skip(int skip) {
this.skip = skip;
return this;
}
/**
* Configures the {@link Pageable} to use.
*
* @param pageable
* @return
*/
public NearQuery with(Pageable pageable) {
this.num = pageable.getOffset() + pageable.getPageSize();
this.skip = pageable.getOffset();
return this;
}
/**
* Sets the max distance results shall have from the configured origin. If a {@link Metric} was set before the given
* value will be interpreted as being a value in that metric. E.g.
*
* <pre>
* NearQuery query = near(10.0, 20.0, Metrics.KILOMETERS).maxDistance(150);
* </pre>
*
* Will set the maximum distance to 150 kilometers.
* Sets the max distance results shall have from the configured origin. Will normalize the given value using a
* potentially already configured {@link Metric}.
*
* @param maxDistance
* @return
*/
public NearQuery maxDistance(double maxDistance) {
return maxDistance(new Distance(maxDistance, getMetric()));
this.maxDistance = getNormalizedDistance(maxDistance, this.metric);
return this;
}
/**
* Sets the maximum distance supplied in a given metric. Will normalize the distance but not reconfigure the query's
* result {@link Metric} if one was configured before.
* {@link Metric}.
*
* @param maxDistance
* @param metric must not be {@literal null}.
* @return
*/
public NearQuery maxDistance(double maxDistance, Metric metric) {
Assert.notNull(metric);
return maxDistance(new Distance(maxDistance, metric));
this.spherical(true);
return maxDistance(getNormalizedDistance(maxDistance, metric));
}
/**
* Sets the maximum distance to the given {@link Distance}. Will set the returned {@link Metric} to be the one of the
* given {@link Distance} if no {@link Metric} was set before.
* Sets the maximum distance to the given {@link Distance}.
*
* @param distance must not be {@literal null}.
* @param distance
* @return
*/
public NearQuery maxDistance(Distance distance) {
Assert.notNull(distance);
if (distance.getMetric() != Metrics.NEUTRAL) {
this.spherical(true);
}
if (this.metric == null) {
in(distance.getMetric());
}
this.maxDistance = distance;
return this;
return maxDistance(distance.getValue(), distance.getMetric());
}
/**
* Returns the maximum {@link Distance}.
*
* @return
*/
public Distance getMaxDistance() {
return this.maxDistance;
}
/**
* Configures a {@link CustomMetric} with the given multiplier.
* Configures a distance multiplier the resulting distances get applied.
*
* @param distanceMultiplier
* @return
*/
public NearQuery distanceMultiplier(double distanceMultiplier) {
this.metric = new CustomMetric(distanceMultiplier);
this.criteria.put("distanceMultiplier", distanceMultiplier);
return this;
}
/**
* Configures the distance multiplier to the multiplier of the given {@link Metric}.
* Configures the distance multiplier to the multiplier of the given {@link Metric}. Does <em>not</em> recalculate the
* {@link #maxDistance(double)}.
*
* @deprecated use {@link #in(Metric)} instead.
* @param metric must not be {@literal null}.
* @return
*/
@Deprecated
public NearQuery distanceMultiplier(Metric metric) {
Assert.notNull(metric);
return in(metric);
return distanceMultiplier(metric.getMultiplier());
}
/**
@@ -247,19 +191,10 @@ public class NearQuery {
* @return
*/
public NearQuery spherical(boolean spherical) {
this.spherical = spherical;
this.criteria.put("spherical", spherical);
return this;
}
/**
* Returns whether spharical values will be returned.
*
* @return
*/
public boolean isSpherical() {
return this.spherical;
}
/**
* Will cause the results' distances being returned in kilometers. Sets {@link #distanceMultiplier(double)} and
* {@link #spherical(boolean)} accordingly.
@@ -280,18 +215,6 @@ public class NearQuery {
return adaptMetric(Metrics.MILES);
}
/**
* Will cause the results' distances being returned in the given metric. Sets {@link #distanceMultiplier(double)}
* accordingly as well as {@link #spherical(boolean)} if the given {@link Metric} is not {@link Metrics#NEUTRAL}.
*
* @param metric the metric the results shall be returned in. Uses {@link Metrics#NEUTRAL} if {@literal null} is
* passed.
* @return
*/
public NearQuery in(Metric metric) {
return adaptMetric(metric == null ? Metrics.NEUTRAL : metric);
}
/**
* Configures the given {@link Metric} to be used as base on for this query and recalculate the maximum distance if no
* metric was set before.
@@ -300,12 +223,12 @@ public class NearQuery {
*/
private NearQuery adaptMetric(Metric metric) {
if (metric != Metrics.NEUTRAL) {
spherical(true);
if (this.metric == null && maxDistance != null) {
maxDistance(this.maxDistance, metric);
}
this.metric = metric;
return this;
spherical(true);
return distanceMultiplier(metric);
}
/**
@@ -316,18 +239,9 @@ public class NearQuery {
*/
public NearQuery query(Query query) {
this.query = query;
this.skip = query.getSkip();
this.num = query.getLimit();
return this;
}
/**
* @return the number of elements to skip.
*/
public Integer getSkip() {
return skip;
}
/**
* Returns the {@link DBObject} built by the {@link NearQuery}.
*
@@ -335,27 +249,18 @@ public class NearQuery {
*/
public DBObject toDBObject() {
BasicDBObject dbObject = new BasicDBObject();
BasicDBObject dbObject = new BasicDBObject(criteria.toMap());
if (query != null) {
dbObject.put("query", query.getQueryObject());
}
if (maxDistance != null) {
dbObject.put("maxDistance", this.maxDistance.getNormalizedValue());
dbObject.put("maxDistance", maxDistance);
}
if (metric != null) {
dbObject.put("distanceMultiplier", metric.getMultiplier());
}
if (num != null) {
dbObject.put("num", num);
}
dbObject.put("near", point.asList());
dbObject.put("spherical", spherical);
return dbObject;
}
private double getNormalizedDistance(double distance, Metric metric) {
return metric == null ? distance : distance / metric.getMultiplier();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2012 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.
@@ -46,33 +46,22 @@ public class Query {
private String hint;
/**
* Static factory method to create a {@link Query} using the provided {@link Criteria}.
* Static factory method to create a Query using the provided criteria
*
* @param criteria must not be {@literal null}.
* @param critera
* @return
*/
public static Query query(Criteria criteria) {
return new Query(criteria);
public static Query query(Criteria critera) {
return new Query(critera);
}
public Query() {
}
/**
* Creates a new {@link Query} using the given {@link Criteria}.
*
* @param criteria must not be {@literal null}.
*/
public Query(Criteria criteria) {
addCriteria(criteria);
}
/**
* Adds the given {@link Criteria} to the current {@link Query}.
*
* @param criteria must not be {@literal null}.
* @return
*/
public Query addCriteria(Criteria criteria) {
CriteriaDefinition existing = this.criteria.get(criteria.getKey());
String key = criteria.getKey();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2012 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.
@@ -52,10 +52,7 @@ public class Update {
/**
* Creates an {@link Update} instance from the given {@link DBObject}. Allows to explicitly exlude fields from making
* it into the created {@link Update} object. Note, that this will set attributes directly and <em>not</em> use
* {@literal $set}. This means fields not given in the {@link DBObject} will be nulled when executing the update. To
* create an only-updating {@link Update} instance of a {@link DBObject}, call {@link #set(String, Object)} for each
* value in it.
* it into the created {@link Update} object.
*
* @param object the source {@link DBObject} to create the update from.
* @param exclude the fields to exclude.
@@ -72,7 +69,7 @@ public class Update {
continue;
}
update.modifierOps.put(key, object.get(key));
update.set(key, object.get(key));
}
return update;
@@ -163,7 +160,7 @@ public class Update {
* @return
*/
public Update pop(String key, Position pos) {
addMultiFieldOperation("$pop", key, pos == Position.FIRST ? -1 : 1);
addMultiFieldOperation("$pop", key, (pos == Position.FIRST ? -1 : 1));
return this;
}
@@ -217,23 +214,22 @@ public class Update {
return dbo;
}
@SuppressWarnings("unchecked")
protected void addMultiFieldOperation(String operator, String key, Object value) {
Object existingValue = this.modifierOps.get(operator);
DBObject keyValueMap;
LinkedHashMap<String, Object> keyValueMap;
if (existingValue == null) {
keyValueMap = new BasicDBObject();
keyValueMap = new LinkedHashMap<String, Object>();
this.modifierOps.put(operator, keyValueMap);
} else {
if (existingValue instanceof BasicDBObject) {
keyValueMap = (BasicDBObject) existingValue;
if (existingValue instanceof LinkedHashMap) {
keyValueMap = (LinkedHashMap<String, Object>) existingValue;
} else {
throw new InvalidDataAccessApiUsageException("Modifier Operations should be a LinkedHashMap but was "
+ existingValue.getClass());
}
}
keyValueMap.put(key, value);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2012 the original author or authors.
* Copyright 2011 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.
@@ -30,7 +30,6 @@ import com.mongodb.gridfs.GridFSFile;
* Collection of operations to store and read files from MongoDB GridFS.
*
* @author Oliver Gierke
* @author Philipp Schneider
*/
public interface GridFsOperations extends ResourcePatternResolver {
@@ -43,60 +42,27 @@ public interface GridFsOperations extends ResourcePatternResolver {
*/
GridFSFile store(InputStream content, String filename);
/**
* Stores the given content into a file with the given name and content type.
*
* @param content must not be {@literal null}.
* @param filename must not be {@literal null} or empty.
* @param contentType can be {@literal null}.
* @return the {@link GridFSFile} just created
*/
GridFSFile store(InputStream content, String filename, String contentType);
/**
* Stores the given content into a file with the given name using the given metadata. The metadata object will be
* marshalled before writing.
*
* @param content must not be {@literal null}.
* @param filename must not be {@literal null} or empty.
* @param metadata can be {@literal null}.
* @param metadata
* @return the {@link GridFSFile} just created
*/
GridFSFile store(InputStream content, String filename, Object metadata);
/**
* Stores the given content into a file with the given name and content type using the given metadata. The metadata
* object will be marshalled before writing.
*
* @param content must not be {@literal null}.
* @param filename must not be {@literal null} or empty.
* @param contentType can be {@literal null}.
* @param metadata can be {@literal null}
* @return the {@link GridFSFile} just created
*/
GridFSFile store(InputStream content, String filename, String contentType, Object metadata);
/**
* Stores the given content into a file with the given name using the given metadata.
*
* @param content must not be {@literal null}.
* @param filename must not be {@literal null} or empty.
* @param metadata can be {@literal null}.
* @param metadata must not be {@literal null}.
* @return the {@link GridFSFile} just created
*/
GridFSFile store(InputStream content, String filename, DBObject metadata);
/**
* Stores the given content into a file with the given name and content type using the given metadata.
*
* @param content must not be {@literal null}.
* @param filename must not be {@literal null} or empty.
* @param contentType can be {@literal null}.
* @param metadata can be {@literal null}.
* @return the {@link GridFSFile} just created
*/
GridFSFile store(InputStream content, String filename, String contentType, DBObject metadata);
/**
* Returns all files matching the given query. Note, that currently {@link Sort} criterias defined at the
* {@link Query} will not be regarded as MongoDB does not support ordering for GridFS file access.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2012 the original author or authors.
* Copyright 2011 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.
@@ -42,7 +42,6 @@ import com.mongodb.gridfs.GridFSInputFile;
* {@link GridFsOperations} implementation to store content into MongoDB GridFS.
*
* @author Oliver Gierke
* @author Philipp Schneider
*/
public class GridFsTemplate implements GridFsOperations, ResourcePatternResolver {
@@ -88,37 +87,15 @@ public class GridFsTemplate implements GridFsOperations, ResourcePatternResolver
return store(content, filename, (Object) null);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.String)
*/
public GridFSFile store(InputStream content, String filename, String contentType) {
return store(content, filename, contentType, (Object) null);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.Object)
*/
public GridFSFile store(InputStream content, String filename, Object metadata) {
return store(content, filename, null, metadata);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, java.lang.String, java.lang.Object)
*/
public GridFSFile store(InputStream content, String filename, String contentType, Object metadata) {
DBObject dbObject = null;
if (metadata != null) {
dbObject = new BasicDBObject();
converter.write(metadata, dbObject);
}
return store(content, filename, contentType, dbObject);
DBObject dbObject = new BasicDBObject();
converter.write(metadata, dbObject);
return store(content, filename, dbObject);
}
/*
@@ -126,30 +103,16 @@ public class GridFsTemplate implements GridFsOperations, ResourcePatternResolver
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, com.mongodb.DBObject)
*/
public GridFSFile store(InputStream content, String filename, DBObject metadata) {
return this.store(content, filename, null, metadata);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.gridfs.GridFsOperations#store(java.io.InputStream, java.lang.String, com.mongodb.DBObject)
*/
public GridFSFile store(InputStream content, String filename, String contentType, DBObject metadata) {
Assert.notNull(content);
Assert.hasText(filename);
Assert.notNull(metadata);
GridFSInputFile file = getGridFs().createFile(content);
file.setFilename(filename);
if (metadata != null) {
file.setMetaData(metadata);
}
if (contentType != null) {
file.setContentType(contentType);
}
file.setMetaData(metadata);
file.save();
return file;
}

View File

@@ -1,5 +0,0 @@
/**
* Support for MongoDB GridFS feature.
*/
package org.springframework.data.mongodb.gridfs;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2011 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.
@@ -15,20 +15,19 @@
*/
package org.springframework.data.mongodb.monitor;
import java.net.InetAddress;
import java.net.UnknownHostException;
import com.mongodb.Mongo;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.support.MetricType;
import com.mongodb.Mongo;
/**
* Expose basic server information via JMX
*
* @author Mark Pollack
* @author Thomas Darimont
*/
@ManagedResource(description = "Server Information")
public class ServerInfo extends AbstractMonitor {
@@ -37,20 +36,9 @@ public class ServerInfo extends AbstractMonitor {
this.mongo = mongo;
}
/**
* Returns the hostname of the used server reported by mongo.
*
* @return the reported hostname can also be an IP address.
* @throws UnknownHostException
*/
@ManagedOperation(description = "Server host name")
public String getHostName() throws UnknownHostException {
/*
* UnknownHostException is not necessary anymore, but clients could have
* called this method in a try..catch(UnknownHostException) already
*/
return getServerStatus().getServerUsed().getHost();
return InetAddress.getLocalHost().getHostName();
}
@ManagedMetric(displayName = "Uptime Estimate")

View File

@@ -1,5 +0,0 @@
/**
* Spring Data's MongoDB abstraction.
*/
package org.springframework.data.mongodb;

View File

@@ -1,5 +0,0 @@
/**
* CDI support for MongoDB specific repository implementation.
*/
package org.springframework.data.mongodb.repository.cdi;

View File

@@ -1,5 +0,0 @@
/**
* Support infrastructure for the configuration of MongoDB specific repositories.
*/
package org.springframework.data.mongodb.repository.config;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2012 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.
@@ -36,7 +36,6 @@ import org.springframework.util.Assert;
* Base class for {@link RepositoryQuery} implementations for Mongo.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public abstract class AbstractMongoQuery implements RepositoryQuery {
@@ -255,12 +254,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
Distance maxDistance = accessor.getMaxDistance();
if (maxDistance != null) {
nearQuery.maxDistance(maxDistance).in(maxDistance.getMetric());
}
Pageable pageable = accessor.getPageable();
if (pageable != null) {
nearQuery.with(pageable);
nearQuery.maxDistance(maxDistance);
}
MongoEntityMetadata<?> metadata = method.getEntityInformation();
@@ -270,13 +264,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
private boolean isListOfGeoResult() {
TypeInformation<?> returnType = method.getReturnType();
if (!returnType.getType().equals(List.class)) {
return false;
}
TypeInformation<?> componentType = returnType.getComponentType();
return componentType == null ? false : GeoResult.class.equals(componentType.getType());
return returnType.getType().equals(List.class) && GeoResult.class.equals(returnType.getComponentType());
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2012 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.
@@ -268,16 +268,15 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
private String toLikeRegex(String source, Type type) {
switch (type) {
case STARTING_WITH:
source = "^" + source;
break;
case ENDING_WITH:
source = source + "$";
break;
case CONTAINING:
source = "*" + source + "*";
break;
default:
case STARTING_WITH:
source = source + "*";
break;
case ENDING_WITH:
source = "*" + source;
break;
case CONTAINING:
source = "*" + source + "*";
break;
}
return source.replaceAll("\\*", ".*");

View File

@@ -1,5 +0,0 @@
/**
* Query derivation mechanism for MongoDB specific repositories.
*/
package org.springframework.data.mongodb.repository.query;

View File

@@ -16,7 +16,6 @@
package org.springframework.data.mongodb.repository.support;
import java.io.Serializable;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
@@ -58,8 +57,7 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends A
this.customCollectionName = customCollectionName;
}
/*
* (non-Javadoc)
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getId(java.lang.Object)
*/
@SuppressWarnings("unchecked")
@@ -67,10 +65,6 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends A
MongoPersistentProperty idProperty = entityMetadata.getIdProperty();
if (idProperty == null) {
return null;
}
try {
return (ID) BeanWrapper.create(entity, null).getProperty(idProperty);
} catch (Exception e) {

View File

@@ -41,8 +41,8 @@ public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
* @param operations the operations to set
*/
public void setMongoOperations(MongoOperations operations) {
this.operations = operations;
setMappingContext(operations.getConverter().getMappingContext());
}
/**

View File

@@ -1,5 +0,0 @@
/**
* Support infrastructure for query derivation of MongoDB specific repositories.
*/
package org.springframework.data.mongodb.repository.support;

View File

@@ -1,4 +1,3 @@
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd
http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd
http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd

View File

@@ -11,7 +11,8 @@
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:import namespace="http://www.springframework.org/schema/context" />
<xsd:import namespace="http://www.springframework.org/schema/context"
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" />
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository-1.0.xsd" />

View File

@@ -11,7 +11,8 @@
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:import namespace="http://www.springframework.org/schema/context" />
<xsd:import namespace="http://www.springframework.org/schema/context"
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" />
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />

View File

@@ -1,482 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.springframework.org/schema/data/mongo"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:repository="http://www.springframework.org/schema/data/repository"
targetNamespace="http://www.springframework.org/schema/data/mongo"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:import namespace="http://www.springframework.org/schema/context" />
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />
<xsd:element name="mongo" type="mongoType">
<xsd:annotation>
<xsd:documentation source="org.springframework.data.mongodb.core.core.MongoFactoryBean"><![CDATA[
Defines a Mongo instance used for accessing MongoDB'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.mongodb.Mongo"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="db-factory">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines a MongoDbFactory for connecting to a specific database
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the mongo definition (by default "mongoDbFactory").]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The reference to a Mongo instance. If not configured a default com.mongodb.Mongo instance will be created.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="dbname" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the database to connect to. Default is 'db'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="port" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The port to connect to MongoDB server. Default is 27017
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="host" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The host to connect to a MongoDB server. Default is localhost
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="username" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The username to use when connecting to a MongoDB server.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="password" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The password to use when connecting to a MongoDB server.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="uri" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Mongo URI string.]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="write-concern">
<xsd:annotation>
<xsd:documentation>
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:attributeGroup name="mongo-repository-attributes">
<xsd:attribute name="mongo-template-ref" type="mongoTemplateRef" default="mongoTemplate">
<xsd:annotation>
<xsd:documentation>
The reference to a MongoTemplate. Will default to 'mongoTemplate'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="create-query-indexes" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation>
Enables creation of indexes for queries that get derived from the method name
and thus reference domain class properties. Defaults to false.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:attributeGroup>
<xsd:element name="repositories">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="repository:repositories">
<xsd:attributeGroup ref="mongo-repository-attributes"/>
<xsd:attributeGroup ref="repository:repository-attributes"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="mapping-converter">
<xsd:annotation>
<xsd:documentation><![CDATA[Defines a MongoConverter for getting rich mapping functionality.]]></xsd:documentation>
<xsd:appinfo>
<tool:exports type="org.springframework.data.mongodb.core.convert.MappingMongoConverter" />
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="custom-converters" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
Top-level element that contains one or more custom converters to be used for mapping
domain objects to and from Mongo's DBObject]]>
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="converter" type="customConverterType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="base-package" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the MappingMongoConverter instance (by default "mappingConverter").]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="base-package" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The base package in which to scan for entities annotated with @Document
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="db-factory-ref" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>
The reference to a DbFactory.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to type="org.springframework.data.mongodb.MongoDbFactory" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
<xsd:annotation>
<xsd:documentation>
The reference to a Mongo. Will default to 'mongo'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mapping-context-ref" type="mappingContextRef" use="optional">
<xsd:annotation>
<xsd:documentation source="org.springframework.data.mapping.model.MappingContext">
The reference to a MappingContext. Will default to 'mappingContext'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mongo-template-ref" type="mongoTemplateRef" use="optional">
<xsd:annotation>
<xsd:documentation source="org.springframework.data.mongodb.core.core.MongoTemplate">
The reference to a MongoTemplate. Will default to 'mongoTemplate'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="disable-validation" use="optional">
<xsd:annotation>
<xsd:documentation source="org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener">
Disables JSR-303 validation on MongoDB documents before they are saved. By default it is set to false.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="jmx">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines a JMX Model MBeans for monitoring a MongoDB server'.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the Mongo object that determines what server to monitor. (by default "mongo").]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="auditing">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="org.springframework.data.mongodb.core.mapping.event.AuditingEventListener" />
<tool:exports type="org.springframework.data.auditing.IsNewAwareAuditingHandler" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:attributeGroup ref="repository:auditing-attributes" />
<xsd:attribute name="mapping-context-ref" type="mappingContextRef" />
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="mappingContextRef">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to type="org.springframework.data.mapping.model.MappingContext"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="mongoTemplateRef">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to type="org.springframework.data.mongodb.core.core.MongoTemplate"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="mongoRef">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:assignable-to type="org.springframework.data.mongodb.core.core.MongoFactoryBean"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="writeConcernEnumeration">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="NONE" />
<xsd:enumeration value="NORMAL" />
<xsd:enumeration value="SAFE" />
<xsd:enumeration value="FSYNC_SAFE" />
<xsd:enumeration value="REPLICAS_SAFE" />
<xsd:enumeration value="JOURNAL_SAFE" />
<xsd:enumeration value="MAJORITY" />
</xsd:restriction>
</xsd:simpleType>
<!-- MLP
<xsd:attributeGroup name="writeConcern">
<xsd:attribute name="write-concern">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="NONE" />
<xsd:enumeration value="NORMAL" />
<xsd:enumeration value="SAFE" />
<xsd:enumeration value="FSYNC_SAFE" />
<xsd:enumeration value="REPLICA_SAFE" />
<xsd:enumeration value="JOURNAL_SAFE" />
<xsd:enumeration value="MAJORITY" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
-->
<xsd:complexType name="mongoType">
<xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:element name="options" type="optionsType">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Mongo driver options
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.mongodb.MongoOptions"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="write-concern">
<xsd:annotation>
<xsd:documentation>
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<!-- MLP
<xsd:attributeGroup ref="writeConcern" />
-->
<xsd:attribute name="id" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the mongo definition (by default "mongo").]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="port" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The port to connect to MongoDB server. Default is 27017
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="host" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The host to connect to a MongoDB server. Default is localhost
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="replica-set" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The comma delimited list of host:port entries to use for replica set/pairs.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="optionsType">
<xsd:attribute name="connections-per-host" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The number of connections allowed per host. Will block if run out. Default is 10. System property MONGO.POOLSIZE can override
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="threads-allowed-to-block-for-connection-multiplier" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The multiplier for connectionsPerHost for # of threads that can block. Default is 5.
If connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5,
then 50 threads can block more than that and an exception will be thrown.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-wait-time" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The max wait time of a blocking thread for a connection. Default is 12000 ms (2 minutes)
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="connect-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The connect timeout in milliseconds. 0 is default and infinite.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="socket-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The socket timeout. 0 is default and infinite.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="socket-keep-alive" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-connect-retry" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
This controls whether or not on a connect, the system retries automatically. Default is false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-auto-connect-retry-time" type="xsd:long">
<xsd:annotation>
<xsd:documentation><![CDATA[
The maximum amount of time in millisecons to spend retrying to open connection to the same server. Default is 0, which means to use the default 15s if autoConnectRetry is on.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="write-number" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
This specifies the number of servers to wait for on the write operation, and exception raising behavior. The 'w' option to the getlasterror command. Defaults to 0.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="write-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
This controls timeout for write operations in milliseconds. The 'wtimeout' option to the getlasterror command. Defaults to 0 (indefinite). Greater than zero is number of milliseconds to wait.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="write-fsync" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="slave-ok" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
This controls if the driver is allowed to read from secondaries or slaves. Defaults to false.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:group name="beanElementGroup">
<xsd:choice>
<xsd:element ref="beans:bean"/>
<xsd:element ref="beans:ref"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="customConverterType">
<xsd:annotation>
<xsd:documentation><![CDATA[
Element defining a custom converterr.
]]></xsd:documentation>
</xsd:annotation>
<xsd:group ref="beanElementGroup" minOccurs="0" maxOccurs="1"/>
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A reference to a custom converter.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>

View File

@@ -19,13 +19,8 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.Mongo;
@@ -68,17 +63,6 @@ public class AbstractMongoConfigurationUnitTests {
assertScanningDisabled(" ");
}
@Test
public void lifecycleCallbacksAreInvokedInAppropriateOrder() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class);
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
BasicMongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(Entity.class);
StandardEvaluationContext spElContext = (StandardEvaluationContext) ReflectionTestUtils.getField(entity, "context");
assertThat(spElContext.getBeanResolver(), is(notNullValue()));
}
private static void assertScanningDisabled(final String value) throws ClassNotFoundException {
AbstractMongoConfiguration configuration = new SampleMongoConfiguration() {

View File

@@ -1,68 +0,0 @@
/*
* Copyright 2012 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.mongodb.config;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.joda.time.DateTime;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
/**
* Integration test for the auditing support.
*
* @author Oliver Gierke
*/
public class AuditingIntegrationTests {
@Test
public void enablesAuditingAndSetsPropertiesAccordingly() {
ApplicationContext context = new ClassPathXmlApplicationContext("auditing.xml", getClass());
Entity entity = new Entity();
BeforeConvertEvent<Entity> event = new BeforeConvertEvent<Entity>(entity);
context.publishEvent(event);
assertThat(entity.created, is(notNullValue()));
assertThat(entity.modified, is(entity.created));
entity.id = 1L;
event = new BeforeConvertEvent<Entity>(entity);
context.publishEvent(event);
assertThat(entity.created, is(notNullValue()));
assertThat(entity.modified, is(not(entity.created)));
}
class Entity {
@CreatedDate
DateTime created;
@LastModifiedDate
DateTime modified;
@Id
Long id;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012 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.
@@ -31,7 +31,6 @@ import com.mongodb.ServerAddress;
* Unit tests for {@link ServerAddressPropertyEditor}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class ServerAddressPropertyEditorUnitTests {
@@ -71,16 +70,6 @@ public class ServerAddressPropertyEditorUnitTests {
assertSingleAddressOfLocalhost(editor.getValue());
}
/**
* @see DATAMONGO-693
*/
@Test
public void interpretEmptyStringAsNull() {
editor.setAsText("");
assertNull(editor.getValue());
}
private static void assertSingleAddressOfLocalhost(Object result) throws UnknownHostException {
assertThat(result, is(instanceOf(ServerAddress[].class)));

View File

@@ -27,7 +27,7 @@ import com.mongodb.WriteConcern;
*
* @author Oliver Gierke
*/
public class StringToWriteConcernConverterUnitTests {
public class StringToWriteConcernConverterUnitTest {
StringToWriteConcernConverter converter = new StringToWriteConcernConverter();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012 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.
@@ -20,8 +20,6 @@ import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -30,9 +28,7 @@ import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionSynchronizationUtils;
import com.mongodb.DB;
import com.mongodb.Mongo;
@@ -41,12 +37,12 @@ import com.mongodb.Mongo;
* Unit tests for {@link MongoDbUtils}.
*
* @author Oliver Gierke
* @author Randy Watler
*/
@RunWith(MockitoJUnitRunner.class)
public class MongoDbUtilsUnitTests {
@Mock Mongo mongo;
@Mock
Mongo mongo;
@Before
public void setUp() throws Exception {
@@ -85,94 +81,4 @@ public class MongoDbUtilsUnitTests {
assertThat(first, is(notNullValue()));
assertThat(MongoDbUtils.getDB(mongo, "first"), is(sameInstance(first)));
}
/**
* @see DATAMONGO-737
*/
@Test
public void handlesTransactionSynchronizationLifecycle() {
// ensure transaction synchronization manager has no registered
// transaction synchronizations or bound resources at start of test
assertThat(TransactionSynchronizationManager.getSynchronizations().isEmpty(), is(true));
assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty(), is(true));
// access database for one mongo instance, (registers transaction
// synchronization and binds transaction resource)
MongoDbUtils.getDB(mongo, "first");
// ensure transaction synchronization manager has registered
// transaction synchronizations and bound resources
assertThat(TransactionSynchronizationManager.getSynchronizations().isEmpty(), is(false));
assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty(), is(false));
// simulate transaction completion, (unbinds transaction resource)
try {
simulateTransactionCompletion();
} catch (Exception e) {
fail("Unexpected exception thrown during transaction completion: " + e);
}
// ensure transaction synchronization manager has no bound resources
// at end of test
assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty(), is(true));
}
/**
* @see DATAMONGO-737
*/
@Test
public void handlesTransactionSynchronizationsLifecycle() {
// ensure transaction synchronization manager has no registered
// transaction synchronizations or bound resources at start of test
assertThat(TransactionSynchronizationManager.getSynchronizations().isEmpty(), is(true));
assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty(), is(true));
// access multiple databases for one mongo instance, (registers
// transaction synchronizations and binds transaction resources)
MongoDbUtils.getDB(mongo, "first");
MongoDbUtils.getDB(mongo, "second");
// ensure transaction synchronization manager has registered
// transaction synchronizations and bound resources
assertThat(TransactionSynchronizationManager.getSynchronizations().isEmpty(), is(false));
assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty(), is(false));
// simulate transaction completion, (unbinds transaction resources)
try {
simulateTransactionCompletion();
} catch (Exception e) {
fail("Unexpected exception thrown during transaction completion: " + e);
}
// ensure transaction synchronization manager has no bound
// transaction resources at end of test
assertThat(TransactionSynchronizationManager.getResourceMap().isEmpty(), is(true));
}
/**
* Simulate transaction rollback/commit completion protocol on managed transaction synchronizations which will unbind
* managed transaction resources. Does not swallow exceptions for testing purposes.
*
* @see TransactionSynchronizationUtils#triggerBeforeCompletion()
* @see TransactionSynchronizationUtils#triggerAfterCompletion(int)
*/
private void simulateTransactionCompletion() {
// triggerBeforeCompletion() implementation without swallowed exceptions
List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
for (TransactionSynchronization synchronization : synchronizations) {
synchronization.beforeCompletion();
}
// triggerAfterCompletion() implementation without swallowed exceptions
List<TransactionSynchronization> remainingSynchronizations = TransactionSynchronizationManager
.getSynchronizations();
if (remainingSynchronizations != null) {
for (TransactionSynchronization remainingSynchronization : remainingSynchronizations) {
remainingSynchronization.afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012 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.
@@ -21,21 +21,17 @@ import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.data.mongodb.config.ServerAddressPropertyEditor;
import org.springframework.data.mongodb.config.WriteConcernPropertyEditor;
import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.Mongo;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
/**
* Integration tests for {@link MongoFactoryBean}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class MongoFactoryBeanIntegrationTests {
public class MongoFactoryBeanIntegrationTest {
/**
* @see DATAMONGO-408
@@ -53,22 +49,4 @@ public class MongoFactoryBeanIntegrationTests {
MongoFactoryBean bean = factory.getBean("&factory", MongoFactoryBean.class);
assertThat(ReflectionTestUtils.getField(bean, "writeConcern"), is((Object) WriteConcern.SAFE));
}
/**
* @see DATAMONGO-693
*/
@Test
public void createMongoInstanceWithHostAndEmptyReplicaSets() {
RootBeanDefinition definition = new RootBeanDefinition(MongoFactoryBean.class);
definition.getPropertyValues().addPropertyValue("host", "localhost");
definition.getPropertyValues().addPropertyValue("replicaPair", "");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerCustomEditor(ServerAddress.class, ServerAddressPropertyEditor.class);
factory.registerBeanDefinition("factory", definition);
Mongo mongo = factory.getBean(Mongo.class);
assertNotNull(mongo);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2012 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.
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import static org.springframework.data.mongodb.core.query.Update.*;
@@ -31,7 +30,6 @@ import java.util.List;
import java.util.Map;
import org.bson.types.ObjectId;
import org.hamcrest.CoreMatchers;
import org.joda.time.DateTime;
import org.junit.After;
import org.junit.Assert;
@@ -44,15 +42,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.annotation.Version;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import org.springframework.data.mongodb.MongoDataIntegrityViolationException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
@@ -60,7 +55,6 @@ import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.Index.Duplicates;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
@@ -88,18 +82,20 @@ import com.mongodb.WriteResult;
* @author Thomas Risberg
* @author Amol Nayak
* @author Patryk Wasik
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class MongoTemplateTests {
@Autowired MongoTemplate template;
@Autowired MongoDbFactory factory;
@Autowired
MongoTemplate template;
@Autowired
MongoDbFactory factory;
MongoTemplate mappingTemplate;
@Rule public ExpectedException thrown = ExpectedException.none();
@Rule
public ExpectedException thrown = ExpectedException.none();
@Autowired
@SuppressWarnings("unchecked")
@@ -149,10 +145,7 @@ public class MongoTemplateTests {
template.dropCollection(TestClass.class);
template.dropCollection(Sample.class);
template.dropCollection(MyPerson.class);
template.dropCollection(TypeWithFieldAnnotation.class);
template.dropCollection(TypeWithDate.class);
template.dropCollection("collection");
template.dropCollection("personX");
}
@Test
@@ -279,8 +272,7 @@ public class MongoTemplateTests {
} catch (DataIntegrityViolationException e) {
assertThat(
e.getMessage(),
CoreMatchers
.startsWith("Insert list failed: E11000 duplicate key error index: database.person.$_id_ dup key: { : ObjectId"));
startsWith("Insert list failed: E11000 duplicate key error index: database.person.$_id_ dup key: { : ObjectId"));
}
}
@@ -773,7 +765,8 @@ public class MongoTemplateTests {
Query q3 = new Query(Criteria.where("age").in(l1, l2));
template.find(q3, PersonWithIdPropertyOfTypeObjectId.class);
Assert.fail("Should have trown an InvalidDocumentStoreApiUsageException");
} catch (InvalidMongoDbApiUsageException e) {}
} catch (InvalidMongoDbApiUsageException e) {
}
}
@Test
@@ -956,7 +949,6 @@ public class MongoTemplateTests {
}
@Test
@SuppressWarnings("deprecation")
public void testUsingReadPreference() throws Exception {
this.template.execute("readPref", new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
@@ -1326,18 +1318,6 @@ public class MongoTemplateTests {
template.save(person);
}
/**
* @see DATAMONGO-617
*/
@Test
public void doesNotFailOnVersionInitForUnversionedEntity() {
DBObject dbObject = new BasicDBObject();
dbObject.put("firstName", "Oliver");
template.insert(dbObject, template.determineCollectionName(PersonWithVersionPropertyOfTypeInteger.class));
}
/**
* @see DATAMONGO-539
*/
@@ -1475,199 +1455,6 @@ public class MongoTemplateTests {
assertThat(template.find(null, PersonWithIdPropertyOfTypeObjectId.class), is(result));
}
/**
* @see DATAMONGO-620
*/
@Test
public void versionsObjectIntoDedicatedCollection() {
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
person.firstName = "Dave";
template.save(person, "personX");
assertThat(person.version, is(0));
template.save(person, "personX");
assertThat(person.version, is(1));
}
/**
* @see DATAMONGO-621
*/
@Test
public void correctlySetsLongVersionProperty() {
PersonWithVersionPropertyOfTypeLong person = new PersonWithVersionPropertyOfTypeLong();
person.firstName = "Dave";
template.save(person);
assertThat(person.version, is(0L));
}
/**
* @see DATAMONGO-622
*/
@Test(expected = DuplicateKeyException.class)
public void preventsDuplicateInsert() {
template.setWriteConcern(WriteConcern.SAFE);
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
person.firstName = "Dave";
template.save(person);
assertThat(person.version, is(0));
person.version = null;
template.save(person);
}
/**
* @see DATAMONGO-629
*/
@Test
public void countAndFindWithoutTypeInformation() {
Person person = new Person();
template.save(person);
Query query = query(where("_id").is(person.getId()));
String collectionName = template.getCollectionName(Person.class);
assertThat(template.find(query, HashMap.class, collectionName), hasSize(1));
assertThat(template.count(query, collectionName), is(1L));
}
/**
* @see DATAMONGO-571
*/
@Test
public void nullsPropertiesForVersionObjectUpdates() {
VersionedPerson person = new VersionedPerson();
person.firstname = "Dave";
person.lastname = "Matthews";
template.save(person);
assertThat(person.id, is(notNullValue()));
person.lastname = null;
template.save(person);
person = template.findOne(query(where("id").is(person.id)), VersionedPerson.class);
assertThat(person.lastname, is(nullValue()));
}
/**
* @see DATAMONGO-571
*/
@Test
public void nullsValuesForUpdatesOfUnversionedEntity() {
Person person = new Person("Dave");
template.save(person);
person.setFirstName(null);
template.save(person);
person = template.findOne(query(where("id").is(person.getId())), Person.class);
assertThat(person.getFirstName(), is(nullValue()));
}
/**
* @see DATAMONGO-651
*/
@Test
public void throwsMongoSpecificExceptionForDataIntegrityViolations() {
WriteResult result = mock(WriteResult.class);
when(result.getError()).thenReturn("ERROR");
MongoActionOperation operation = MongoActionOperation.INSERT;
MongoTemplate mongoTemplate = new MongoTemplate(factory);
mongoTemplate.setWriteResultChecking(WriteResultChecking.EXCEPTION);
try {
mongoTemplate.handleAnyWriteResultErrors(result, null, operation);
fail("Expected MonogoDataIntegrityViolationException!");
} catch (MongoDataIntegrityViolationException o_O) {
assertThat(o_O.getActionOperation(), is(operation));
assertThat(o_O.getWriteResult(), is(result));
}
}
/**
* @see DATAMONGO-679
*/
@Test
public void savesJsonStringCorrectly() {
DBObject dbObject = new BasicDBObject().append("first", "first").append("second", "second");
template.save(dbObject.toString(), "collection");
List<DBObject> result = template.findAll(DBObject.class, "collection");
assertThat(result.size(), is(1));
assertThat(result.get(0).containsField("first"), is(true));
}
/**
* @see DATAMONGO-675
*/
@Test
public void updateConsidersMappingAnnotations() {
TypeWithFieldAnnotation entity = new TypeWithFieldAnnotation();
entity.emailAddress = "old";
template.save(entity);
Query query = query(where("_id").is(entity.id));
Update update = Update.update("emailAddress", "new");
FindAndModifyOptions options = new FindAndModifyOptions().returnNew(true);
TypeWithFieldAnnotation result = template.findAndModify(query, update, options, TypeWithFieldAnnotation.class);
assertThat(result.emailAddress, is("new"));
}
/**
* @see DATAMONGO-671
*/
@Test
public void findsEntityByDateReference() {
TypeWithDate entity = new TypeWithDate();
entity.date = new Date(System.currentTimeMillis() - 10);
template.save(entity);
Query query = query(where("date").lt(new Date()));
List<TypeWithDate> result = template.find(query, TypeWithDate.class);
assertThat(result, hasSize(1));
assertThat(result.get(0).date, is(notNullValue()));
}
/**
* @see DATAMONGO-540
*/
@Test
public void findOneAfterUpsertForNonExistingObjectReturnsTheInsertedObject() {
String idValue = "4711";
Query query = new Query(Criteria.where("id").is(idValue));
String fieldValue = "bubu";
Update update = Update.update("field", fieldValue);
template.upsert(query, update, Sample.class);
Sample result = template.findOne(query, Sample.class);
assertThat(result, is(notNullValue()));
assertThat(result.field, is(fieldValue));
assertThat(result.id, is(idValue));
}
static class MyId {
String first;
@@ -1676,12 +1463,14 @@ public class MongoTemplateTests {
static class TypeWithMyId {
@Id MyId id;
@Id
MyId id;
}
public static class Sample {
@Id String id;
@Id
String id;
String field;
}
@@ -1735,22 +1524,4 @@ public class MongoTemplateTests {
String state;
String city;
}
static class VersionedPerson {
@Version Long version;
String id, firstname, lastname;
}
static class TypeWithFieldAnnotation {
@Id ObjectId id;
@Field("email") String emailAddress;
}
static class TypeWithDate {
@Id String id;
Date date;
}
}

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.data.mongodb.core;
import org.springframework.data.annotation.Version;
import org.springframework.data.mongodb.core.mapping.Version;
public class PersonWithVersionPropertyOfTypeInteger {

View File

@@ -1,34 +0,0 @@
/*
* Copyright 2012 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.mongodb.core;
import org.springframework.data.annotation.Version;
public class PersonWithVersionPropertyOfTypeLong {
String id;
String firstName;
int age;
@Version
Long version;
@Override
public String toString() {
return "PersonWithVersionPropertyOfTypeInteger [id=" + id + ", firstName=" + firstName + ", age=" + age
+ ", version=" + version + "]";
}
}

View File

@@ -0,0 +1,64 @@
package org.springframework.data.mongodb.core;
public class SomeEnumTest {
public enum StringEnum {
ONE, TWO, FIVE;
}
public enum NumberEnum {
ONE(1), TWO(2), FIVE(5);
private int value;
public int value() {
return value;
}
NumberEnum(int value) {
this.value = value;
}
}
private StringEnum stringEnum;
private NumberEnum numberEnum;
private String id;
private String name;
public StringEnum getStringEnum() {
return stringEnum;
}
public void setStringEnum(StringEnum stringEnum) {
this.stringEnum = stringEnum;
}
public NumberEnum getNumberEnum() {
return numberEnum;
}
public void setNumberEnum(NumberEnum numberEnum) {
this.numberEnum = numberEnum;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2012 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.
@@ -45,6 +45,7 @@ import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
@@ -53,7 +54,6 @@ import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.MappingInstantiationException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
@@ -65,7 +65,6 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import com.mongodb.util.JSON;
/**
* Unit tests for {@link MappingMongoConverter}.
@@ -87,7 +86,7 @@ public class MappingMongoConverterUnitTests {
mappingContext = new MongoMappingContext();
mappingContext.setApplicationContext(context);
mappingContext.afterPropertiesSet();
mappingContext.onApplicationEvent(new ContextRefreshedEvent(context));
converter = new MappingMongoConverter(factory, mappingContext);
converter.afterPropertiesSet();
@@ -111,7 +110,15 @@ public class MappingMongoConverterUnitTests {
@Test
public void convertsJodaTimeTypesCorrectly() {
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(new LocalDateToDateConverter());
converters.add(new DateToLocalDateConverter());
CustomConversions conversions = new CustomConversions(converters);
mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
converter = new MappingMongoConverter(factory, mappingContext);
converter.setCustomConversions(conversions);
converter.afterPropertiesSet();
Person person = new Person();
@@ -129,7 +136,15 @@ public class MappingMongoConverterUnitTests {
@Test
public void convertsCustomTypeOnConvertToMongoType() {
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(new LocalDateToDateConverter());
converters.add(new DateToLocalDateConverter());
CustomConversions conversions = new CustomConversions(converters);
mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
converter = new MappingMongoConverter(factory, mappingContext);
converter.setCustomConversions(conversions);
converter.afterPropertiesSet();
LocalDate date = new LocalDate();
@@ -1308,18 +1323,6 @@ public class MappingMongoConverterUnitTests {
converter.write(wrapper, dbObject);
}
/**
* @see DATAMONGO-592
*/
@Test
public void recursivelyConvertsSpELReadValue() {
DBObject input = (DBObject) JSON
.parse("{ \"_id\" : { \"$oid\" : \"50ca271c4566a2b08f2d667a\" }, \"_class\" : \"com.recorder.TestRecorder2$ObjectContainer\", \"property\" : { \"property\" : 100 } }");
converter.read(ObjectContainer.class, input);
}
static class GenericType<T> {
T content;
}
@@ -1513,38 +1516,6 @@ public class MappingMongoConverterUnitTests {
Throwable throwable;
}
@Document
static class PrimitiveContainer {
@Field("property")
private final int m_property;
@PersistenceConstructor
public PrimitiveContainer(@Value("#root.property") int a_property) {
m_property = a_property;
}
public int property() {
return m_property;
}
}
@Document
static class ObjectContainer {
@Field("property")
private final PrimitiveContainer m_property;
@PersistenceConstructor
public ObjectContainer(@Value("#root.property") PrimitiveContainer a_property) {
m_property = a_property;
}
public PrimitiveContainer property() {
return m_property;
}
}
private class LocalDateToDateConverter implements Converter<LocalDate, Date> {
public Date convert(LocalDate source) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2012 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.
@@ -25,7 +25,6 @@ import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.bson.types.ObjectId;
import org.junit.Before;
@@ -37,7 +36,6 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.DBObjectUtils;
import org.springframework.data.mongodb.core.Person;
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
@@ -55,7 +53,6 @@ import com.mongodb.QueryBuilder;
* Unit tests for {@link QueryMapper}.
*
* @author Oliver Gierke
* @author Patryk Wasik
*/
@RunWith(MockitoJUnitRunner.class)
public class QueryMapperUnitTests {
@@ -64,7 +61,8 @@ public class QueryMapperUnitTests {
MongoMappingContext context;
MappingMongoConverter converter;
@Mock MongoDbFactory factory;
@Mock
MongoDbFactory factory;
@Before
public void setUp() {
@@ -334,11 +332,7 @@ public class QueryMapperUnitTests {
DBObject result = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDBRef.class));
DBObject reference = DBObjectUtils.getAsDBObject(result, "reference");
BasicDBList inClause = getAsDBList(reference, "$in");
assertThat(inClause, hasSize(2));
assertThat(inClause.get(0), is(instanceOf(com.mongodb.DBRef.class)));
assertThat(inClause.get(1), is(instanceOf(com.mongodb.DBRef.class)));
assertThat(reference.containsField("$in"), is(true));
}
/**
@@ -353,91 +347,6 @@ public class QueryMapperUnitTests {
assertThat(object.get("reference"), is(nullValue()));
}
/**
* @see DATAMONGO-629
*/
@Test
public void doesNotMapIdIfNoEntityMetadataAvailable() {
String id = new ObjectId().toString();
Query query = query(where("id").is(id));
DBObject object = mapper.getMappedObject(query.getQueryObject(), null);
assertThat(object.containsField("id"), is(true));
assertThat(object.get("id"), is((Object) id));
assertThat(object.containsField("_id"), is(false));
}
/**
* @see DATAMONGO-677
*/
@Test
public void handleMapWithDBRefCorrectly() {
DBObject mapDbObject = new BasicDBObject();
mapDbObject.put("test", new com.mongodb.DBRef(null, "test", "test"));
DBObject dbObject = new BasicDBObject();
dbObject.put("mapWithDBRef", mapDbObject);
DBObject mapped = mapper.getMappedObject(dbObject, context.getPersistentEntity(WithMapDBRef.class));
assertThat(mapped.containsField("mapWithDBRef"), is(true));
assertThat(mapped.get("mapWithDBRef"), instanceOf(BasicDBObject.class));
assertThat(((BasicDBObject) mapped.get("mapWithDBRef")).containsField("test"), is(true));
assertThat(((BasicDBObject) mapped.get("mapWithDBRef")).get("test"), instanceOf(com.mongodb.DBRef.class));
}
@Test
public void convertsUnderscoreIdValueWithoutMetadata() {
DBObject dbObject = new BasicDBObject().append("_id", new ObjectId().toString());
DBObject mapped = mapper.getMappedObject(dbObject, null);
assertThat(mapped.containsField("_id"), is(true));
assertThat(mapped.get("_id"), is(instanceOf(ObjectId.class)));
}
/**
* @see DATAMONGO-705
*/
@Test
public void convertsDBRefWithExistsQuery() {
Query query = query(where("reference").exists(false));
BasicMongoPersistentEntity<?> entity = context.getPersistentEntity(WithDBRef.class);
DBObject mappedObject = mapper.getMappedObject(query.getQueryObject(), entity);
DBObject reference = getAsDBObject(mappedObject, "reference");
assertThat(reference.containsField("$exists"), is(true));
assertThat(reference.get("$exists"), is((Object) false));
}
/**
* @see DATAMONGO-706
*/
@Test
public void convertsNestedDBRefsCorrectly() {
Reference reference = new Reference();
reference.id = 5L;
Query query = query(where("someString").is("foo").andOperator(where("reference").in(reference)));
BasicMongoPersistentEntity<?> entity = context.getPersistentEntity(WithDBRef.class);
DBObject mappedObject = mapper.getMappedObject(query.getQueryObject(), entity);
assertThat(mappedObject.get("someString"), is((Object) "foo"));
BasicDBList andClause = getAsDBList(mappedObject, "$and");
assertThat(andClause, hasSize(1));
BasicDBList inClause = getAsDBList(getAsDBObject(getAsDBObject(andClause, 0), "reference"), "$in");
assertThat(inClause, hasSize(1));
assertThat(inClause.get(0), is(instanceOf(com.mongodb.DBRef.class)));
}
class IdWrapper {
Object id;
}
@@ -450,12 +359,14 @@ public class QueryMapperUnitTests {
class Sample {
@Id private String foo;
@Id
private String foo;
}
class BigIntegerId {
@Id private BigInteger id;
@Id
private BigInteger id;
}
enum Enum {
@@ -469,13 +380,14 @@ public class QueryMapperUnitTests {
class CustomizedField {
@Field("foo") CustomizedField field;
@Field("foo")
CustomizedField field;
}
class WithDBRef {
String someString;
@DBRef Reference reference;
@DBRef
Reference reference;
}
class Reference {
@@ -487,9 +399,4 @@ public class QueryMapperUnitTests {
WithDBRef withDbRef;
}
class WithMapDBRef {
@DBRef Map<String, Sample> mapWithDBRef;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2011 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.
@@ -115,12 +115,10 @@ public class GeoSpatialTests {
@Test
public void geoNear() {
NearQuery geoNear = NearQuery.near(-73, 40, Metrics.KILOMETERS).num(10).maxDistance(150);
GeoResults<Venue> geoNearResult = template.geoNear(geoNear, Venue.class);
GeoResults<Venue> result = template.geoNear(geoNear, Venue.class);
assertThat(result.getContent().size(), is(not(0)));
assertThat(result.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
assertThat(geoNearResult.getContent().size(), is(not(0)));
}
@Test

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright (c) 2011 by the original author(s).
*
* 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
* 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,
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.mapping;
import static org.hamcrest.Matchers.*;
@@ -36,15 +37,14 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.MongoCollectionUtils;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoDbUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Order;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.DB;
import com.mongodb.DBCollection;
@@ -53,8 +53,7 @@ import com.mongodb.Mongo;
import com.mongodb.MongoException;
/**
* @author Jon Brisbin
* @author Oliver Gierke
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MappingTests {
@@ -79,7 +78,7 @@ public class MappingTests {
ApplicationContext applicationContext;
Mongo mongo;
MongoTemplate template;
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
MongoMappingContext mappingContext;
@Before
public void setUp() throws Exception {
@@ -90,7 +89,7 @@ public class MappingTests {
}
applicationContext = new ClassPathXmlApplicationContext("/mapping.xml");
template = applicationContext.getBean(MongoTemplate.class);
mappingContext = template.getConverter().getMappingContext();
mappingContext = (MongoMappingContext) ReflectionTestUtils.getField(template, "mappingContext");
}
@Test
@@ -465,7 +464,7 @@ public class MappingTests {
template.insert(p4);
Query q = query(where("id").in("1", "2"));
q.with(new Sort(Direction.ASC, "id"));
q.sort().on("id", Order.ASCENDING);
List<PersonPojoStringId> people = template.find(q, PersonPojoStringId.class);
assertEquals(2, people.size());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 by the original author(s).
* Copyright (c) 2011 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.mapping;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.AbstractMap;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Map;
@@ -28,7 +29,9 @@ import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.context.AbstractMappingContext;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.util.ReflectionUtils;
import com.mongodb.DBRef;
@@ -66,14 +69,15 @@ public class MongoMappingContextUnitTests {
assertThat(context.getPersistentEntity(DBRef.class), is(nullValue()));
}
/**
* @see DATAMONGO-638
*/
@Test
public void doesNotCreatePersistentEntityForAbstractMap() {
public void populatesAbstractMappingContextsApplicationCorrectly() {
MongoMappingContext context = new MongoMappingContext();
assertThat(context.getPersistentEntity(AbstractMap.class), is(nullValue()));
context.setApplicationContext(applicationContext);
Field field = ReflectionUtils.findField(AbstractMappingContext.class, "applicationContext");
ReflectionUtils.makeAccessible(field);
assertThat(ReflectionUtils.getField(field, context), is(notNullValue()));
}
class ClassWithMultipleIdProperties {

View File

@@ -1,89 +0,0 @@
/*
* Copyright 2012 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.mongodb.core.mapping.event;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.annotation.Id;
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.support.IsNewStrategyFactory;
/**
* Unit tests for {@link AuditingEventListener}.
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class AuditingEventListenerUnitTests {
IsNewAwareAuditingHandler<Object> handler;
IsNewStrategyFactory factory;
AuditingEventListener listener;
@Before
public void setUp() {
MongoMappingContext mappingContext = new MongoMappingContext();
factory = new MappingContextIsNewStrategyFactory(mappingContext);
handler = spy(new IsNewAwareAuditingHandler<Object>(factory));
doNothing().when(handler).markCreated(Mockito.any(Object.class));
doNothing().when(handler).markModified(Mockito.any(Object.class));
listener = new AuditingEventListener(handler);
}
@Test(expected = IllegalArgumentException.class)
public void rejectsNullAuditingHandler() {
new AuditingEventListener(null);
}
@Test
public void triggersCreationMarkForObjectWithEmptyId() {
Sample sample = new Sample();
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample));
verify(handler, times(1)).markCreated(sample);
verify(handler, times(0)).markModified(any(Sample.class));
}
@Test
public void triggersModificationMarkForObjectWithSetId() {
Sample sample = new Sample();
sample.id = "id";
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample));
verify(handler, times(0)).markCreated(any(Sample.class));
verify(handler, times(1)).markModified(sample);
}
static class Sample {
@Id
String id;
}
}

View File

@@ -36,7 +36,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ValidatingMongoEventListenerTests {
public class ValidatingMongoEventListenerTest {
@Autowired
MongoTemplate mongoTemplate;

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2012 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.mongodb.core.mapreduce;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Unit tests for {@link MapReduceCounts}.
*
* @author Oliver Gierke
*/
public class MapReduceCountsUnitTests {
/**
* @see DATACMNS-378
*/
@Test
public void equalsForSameNumberValues() {
MapReduceCounts left = new MapReduceCounts(1L, 1L, 1L);
MapReduceCounts right = new MapReduceCounts(1L, 1L, 1L);
assertThat(left, is(right));
assertThat(right, is(left));
assertThat(left.hashCode(), is(right.hashCode()));
}
/**
* @see DATACMNS-378
*/
@Test
public void notEqualForDifferentNumberValues() {
MapReduceCounts left = new MapReduceCounts(1L, 1L, 1L);
MapReduceCounts right = new MapReduceCounts(1L, 2L, 1L);
assertThat(left, is(not(right)));
assertThat(right, is(not(left)));
assertThat(left.hashCode(), is(not(right.hashCode())));
}
}

View File

@@ -69,18 +69,4 @@ public class MapReduceResultsUnitTests {
DBObject source = new BasicDBObject("timing", inner);
new MapReduceResults<Object>(Collections.emptyList(), source);
}
/**
* @see DATAMONGO-378
*/
@Test
public void handlesLongResultsForCounts() {
DBObject inner = new BasicDBObject("input", 1L);
inner.put("emit", 1L);
inner.put("output", 1);
DBObject source = new BasicDBObject("counts", inner);
new MapReduceResults<Object>(Collections.emptyList(), source);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2011 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.
@@ -24,10 +24,6 @@ import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class CriteriaTests {
@Test
@@ -72,50 +68,4 @@ public class CriteriaTests {
assertThat(left, is(not(right)));
assertThat(right, is(not(left)));
}
/**
* @see DATAMONGO-507
*/
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenTryingToNegateAndOperation() {
new Criteria() //
.not() //
.andOperator(Criteria.where("delete").is(true).and("_id").is(42)); //
}
/**
* @see DATAMONGO-507
*/
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenTryingToNegateOrOperation() {
new Criteria() //
.not() //
.orOperator(Criteria.where("delete").is(true).and("_id").is(42)); //
}
/**
* @see DATAMONGO-507
*/
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenTryingToNegateNorOperation() {
new Criteria() //
.not() //
.norOperator(Criteria.where("delete").is(true).and("_id").is(42)); //
}
/**
* @see DATAMONGO-507
*/
@Test
public void shouldNegateFollowingSimpleExpression() {
Criteria c = Criteria.where("age").not().gt(18).and("status").is("student");
DBObject co = c.getCriteriaObject();
assertThat(co, is(notNullValue()));
assertThat(co.toString(), is("{ \"age\" : { \"$not\" : { \"$gt\" : 18}} , \"status\" : \"student\"}"));
}
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright 2013 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.mongodb.core.query;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Unit tests for {@link Field}.
*
* @author Oliver Gierke
*/
public class FieldUnitTests {
@Test
public void sameObjectSetupCreatesEqualField() {
Field left = new Field().include("foo");
Field right = new Field().include("foo");
assertThat(left, is(right));
assertThat(right, is(left));
}
@Test
public void differentObjectSetupCreatesEqualField() {
Field left = new Field().include("foo");
Field right = new Field().include("bar");
assertThat(left, is(not(right)));
assertThat(right, is(not(left)));
}
}

View File

@@ -1,41 +1,17 @@
/*
* Copyright 2011-2013 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.mongodb.core.query;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.Metric;
import org.springframework.data.mongodb.core.geo.Metrics;
import org.springframework.data.mongodb.core.geo.Point;
/**
* Unit tests for {@link NearQuery}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class NearQueryUnitTests {
private static final Distance ONE_FIFTY_KILOMETERS = new Distance(150, Metrics.KILOMETERS);
@Test(expected = IllegalArgumentException.class)
public void rejectsNullPoint() {
NearQuery.near(null);
@@ -46,9 +22,9 @@ public class NearQueryUnitTests {
NearQuery query = NearQuery.near(2.5, 2.5, Metrics.KILOMETERS).maxDistance(150);
assertThat(query.getMaxDistance(), is(ONE_FIFTY_KILOMETERS));
assertThat(query.getMetric(), is((Metric) Metrics.KILOMETERS));
assertThat(query.isSpherical(), is(true));
assertThat((Double) query.toDBObject().get("maxDistance"), is(0.02351783914331097));
assertThat((Boolean) query.toDBObject().get("spherical"), is(true));
assertThat((Double) query.toDBObject().get("distanceMultiplier"), is(Metrics.KILOMETERS.getMultiplier()));
}
@Test
@@ -56,71 +32,13 @@ public class NearQueryUnitTests {
NearQuery query = NearQuery.near(2.5, 2.5, Metrics.KILOMETERS).maxDistance(150);
assertThat((Double) query.toDBObject().get("maxDistance"), is(0.02351783914331097));
assertThat((Double) query.toDBObject().get("distanceMultiplier"), is(Metrics.KILOMETERS.getMultiplier()));
query.inMiles();
assertThat(query.getMetric(), is((Metric) Metrics.MILES));
}
assertThat((Double) query.toDBObject().get("distanceMultiplier"), is(Metrics.MILES.getMultiplier()));
@Test
public void configuresResultMetricCorrectly() {
NearQuery query = NearQuery.near(2.5, 2.1);
assertThat(query.getMetric(), is((Metric) Metrics.NEUTRAL));
query = query.maxDistance(ONE_FIFTY_KILOMETERS);
assertThat(query.getMetric(), is((Metric) Metrics.KILOMETERS));
assertThat(query.getMaxDistance(), is(ONE_FIFTY_KILOMETERS));
assertThat(query.isSpherical(), is(true));
query = query.in(Metrics.MILES);
assertThat(query.getMetric(), is((Metric) Metrics.MILES));
assertThat(query.getMaxDistance(), is(ONE_FIFTY_KILOMETERS));
assertThat(query.isSpherical(), is(true));
query = query.maxDistance(new Distance(200, Metrics.KILOMETERS));
assertThat(query.getMetric(), is((Metric) Metrics.MILES));
}
/**
* @see DATAMONGO-445
*/
@Test
public void shouldTakeSkipAndLimitSettingsFromGivenPageable() {
Pageable pageable = new PageRequest(3, 5);
NearQuery query = NearQuery.near(new Point(1, 1)).with(pageable);
assertThat(query.getSkip(), is(pageable.getPageNumber() * pageable.getPageSize()));
assertThat((Integer) query.toDBObject().get("num"), is((pageable.getPageNumber() + 1) * pageable.getPageSize()));
}
/**
* @see DATAMONGO-445
*/
@Test
public void shouldTakeSkipAndLimitSettingsFromGivenQuery() {
int limit = 10;
int skip = 5;
NearQuery query = NearQuery.near(new Point(1, 1)).query(
Query.query(Criteria.where("foo").is("bar")).limit(limit).skip(skip));
assertThat(query.getSkip(), is(skip));
assertThat((Integer) query.toDBObject().get("num"), is(limit));
}
/**
* @see DATAMONGO-445
*/
@Test
public void shouldTakeSkipAndLimitSettingsFromPageableEvenIfItWasSpecifiedOnQuery() {
int limit = 10;
int skip = 5;
Pageable pageable = new PageRequest(3, 5);
NearQuery query = NearQuery.near(new Point(1, 1))
.query(Query.query(Criteria.where("foo").is("bar")).limit(limit).skip(skip)).with(pageable);
assertThat(query.getSkip(), is(pageable.getPageNumber() * pageable.getPageSize()));
assertThat((Integer) query.toDBObject().get("num"), is((pageable.getPageNumber() + 1) * pageable.getPageSize()));
NearQuery.near(2.5, 2.5).maxDistance(150).inKilometers();
assertThat((Double) query.toDBObject().get("maxDistance"), is(0.02351783914331097));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2012 the original author or authors.
* Copyright 2011 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.
@@ -41,7 +41,6 @@ import com.mongodb.gridfs.GridFSFile;
* Integration tests for {@link GridFsTemplate}.
*
* @author Oliver Gierke
* @author Philipp Schneider
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:gridfs/gridfs.xml")
@@ -78,19 +77,6 @@ public class GridFsTemplateIIntegrationTests {
assertSame(result.get(0), reference);
}
/**
* @see DATAMONGO-503
*/
@Test
public void storesContentType() throws IOException {
GridFSFile reference = operations.store(resource.getInputStream(), "foo2.xml", "application/xml");
List<GridFSDBFile> result = operations.find(query(whereContentType().is("application/xml")));
assertThat(result.size(), is(1));
assertSame(result.get(0), reference);
}
@Test
public void marshalsComplexMetadata() throws IOException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2011 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.
@@ -15,32 +15,28 @@
*/
package org.springframework.data.mongodb.monitor;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.net.UnknownHostException;
import com.mongodb.Mongo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.monitor.OperationCounters;
import org.springframework.data.mongodb.monitor.ServerInfo;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.Mongo;
/**
* This test class assumes that you are already running the MongoDB server.
*
* @author Mark Pollack
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
@ContextConfiguration
public class MongoMonitorIntegrationTests {
@Autowired Mongo mongo;
@Autowired
Mongo mongo;
@Test
public void serverInfo() {
@@ -49,29 +45,9 @@ public class MongoMonitorIntegrationTests {
Assert.isTrue(StringUtils.hasText("1."));
}
/**
* @throws UnknownHostException
* @see DATAMONGO-685
*/
@Test
public void getHostNameShouldReturnServerNameReportedByMongo() throws UnknownHostException {
ServerInfo serverInfo = new ServerInfo(mongo);
String hostName = null;
try {
hostName = serverInfo.getHostName();
} catch (UnknownHostException e) {
throw e;
}
assertThat(hostName, is(notNullValue()));
assertThat(hostName, is("127.0.0.1"));
}
@Test
public void operationCounters() {
OperationCounters operationCounters = new OperationCounters(mongo);
operationCounters.getInsertCount();
}
}
}

View File

@@ -18,16 +18,12 @@ package org.springframework.data.mongodb.performance;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.regex.Pattern;
@@ -39,15 +35,12 @@ import org.springframework.core.Constants;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
@@ -67,40 +60,29 @@ import com.mongodb.WriteConcern;
public class PerformanceTests {
private static final String DATABASE_NAME = "performance";
private static final int NUMBER_OF_PERSONS = 300;
private static final int ITERATIONS = 50;
private static final int NUMBER_OF_PERSONS = 30000;
private static final StopWatch watch = new StopWatch();
private static final Collection<String> IGNORED_WRITE_CONCERNS = Arrays.asList("MAJORITY", "REPLICAS_SAFE",
"FSYNC_SAFE", "FSYNCED", "JOURNAL_SAFE", "JOURNALED", "REPLICA_ACKNOWLEDGED");
"FSYNC_SAFE", "JOURNAL_SAFE");
private static final int COLLECTION_SIZE = 1024 * 1024 * 256; // 256 MB
private static final Collection<String> COLLECTION_NAMES = Arrays.asList("template", "driver", "person");
Mongo mongo;
MongoTemplate operations;
PersonRepository repository;
MongoConverter converter;
@Before
public void setUp() throws Exception {
this.mongo = new Mongo();
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(this.mongo, DATABASE_NAME);
MongoMappingContext context = new MongoMappingContext();
context.setInitialEntitySet(Collections.singleton(Person.class));
context.afterPropertiesSet();
this.converter = new MappingMongoConverter(mongoDbFactory, context);
this.operations = new MongoTemplate(new SimpleMongoDbFactory(this.mongo, DATABASE_NAME), converter);
this.operations = new MongoTemplate(new SimpleMongoDbFactory(this.mongo, DATABASE_NAME));
MongoRepositoryFactoryBean<PersonRepository, Person, ObjectId> factory = new MongoRepositoryFactoryBean<PersonRepository, Person, ObjectId>();
factory.setMongoOperations(operations);
factory.setRepositoryInterface(PersonRepository.class);
factory.afterPropertiesSet();
this.repository = factory.getObject();
repository = factory.getObject();
}
@Test
@@ -108,137 +90,69 @@ public class PerformanceTests {
executeWithWriteConcerns(new WriteConcernCallback() {
public void doWithWriteConcern(String constantName, WriteConcern concern) {
writeHeadline("WriteConcern: " + constantName);
System.out.println(String.format("Writing %s objects using plain driver took %sms", NUMBER_OF_PERSONS,
writingObjectsUsingPlainDriver(NUMBER_OF_PERSONS)));
System.out.println(String.format("Writing %s objects using template took %sms", NUMBER_OF_PERSONS,
writingObjectsUsingMongoTemplate(NUMBER_OF_PERSONS)));
System.out.println(String.format("Writing %s objects using repository took %sms", NUMBER_OF_PERSONS,
writingObjectsUsingRepositories(NUMBER_OF_PERSONS)));
writingObjectsUsingPlainDriver("Writing %s objects using plain driver");
writingObjectsUsingMongoTemplate("Writing %s objects using template");
writingObjectsUsingRepositories("Writing %s objects using repository");
writeFooter();
}
});
}
@Test
public void plainConversion() throws InterruptedException {
Statistics statistics = new Statistics("Plain conversion of " + NUMBER_OF_PERSONS * 100
+ " persons - After %s iterations");
List<DBObject> dbObjects = getPersonDBObjects(NUMBER_OF_PERSONS * 100);
for (int i = 0; i < ITERATIONS; i++) {
statistics.registerTime(Api.DIRECT, Mode.READ, convertDirectly(dbObjects));
statistics.registerTime(Api.CONVERTER, Mode.READ, convertUsingConverter(dbObjects));
}
statistics.printResults(ITERATIONS);
}
private long convertDirectly(final List<DBObject> dbObjects) {
executeWatched(new WatchCallback<List<Person>>() {
@Override
public List<Person> doInWatch() {
List<Person> persons = new ArrayList<PerformanceTests.Person>();
for (DBObject dbObject : dbObjects) {
persons.add(Person.from(dbObject));
}
return persons;
}
});
return watch.getLastTaskTimeMillis();
}
private long convertUsingConverter(final List<DBObject> dbObjects) {
executeWatched(new WatchCallback<List<Person>>() {
@Override
public List<Person> doInWatch() {
List<Person> persons = new ArrayList<PerformanceTests.Person>();
for (DBObject dbObject : dbObjects) {
persons.add(converter.read(Person.class, dbObject));
}
return persons;
}
});
return watch.getLastTaskTimeMillis();
}
@Test
public void writeAndRead() throws Exception {
public void writeAndRead() {
mongo.setWriteConcern(WriteConcern.SAFE);
readsAndWrites(NUMBER_OF_PERSONS, ITERATIONS);
}
private void readsAndWrites(int numberOfPersons, int iterations) {
Statistics statistics = new Statistics("Reading " + numberOfPersons + " - After %s iterations");
for (int i = 0; i < iterations; i++) {
for (int i = 3; i > 0; i--) {
setupCollections();
statistics.registerTime(Api.DRIVER, Mode.WRITE, writingObjectsUsingPlainDriver(numberOfPersons));
statistics.registerTime(Api.TEMPLATE, Mode.WRITE, writingObjectsUsingMongoTemplate(numberOfPersons));
statistics.registerTime(Api.REPOSITORY, Mode.WRITE, writingObjectsUsingRepositories(numberOfPersons));
writeHeadline("Plain driver");
writingObjectsUsingPlainDriver("Writing %s objects using plain driver");
readingUsingPlainDriver("Reading all objects using plain driver");
queryUsingPlainDriver("Executing query using plain driver");
writeFooter();
statistics.registerTime(Api.DRIVER, Mode.READ, readingUsingPlainDriver());
statistics.registerTime(Api.TEMPLATE, Mode.READ, readingUsingTemplate());
statistics.registerTime(Api.REPOSITORY, Mode.READ, readingUsingRepository());
writeHeadline("Template");
writingObjectsUsingMongoTemplate("Writing %s objects using template");
readingUsingTemplate("Reading all objects using template");
queryUsingTemplate("Executing query using template");
writeFooter();
statistics.registerTime(Api.DRIVER, Mode.QUERY, queryUsingPlainDriver());
statistics.registerTime(Api.TEMPLATE, Mode.QUERY, queryUsingTemplate());
statistics.registerTime(Api.REPOSITORY, Mode.QUERY, queryUsingRepository());
writeHeadline("Repositories");
writingObjectsUsingRepositories("Writing %s objects using repository");
readingUsingRepository("Reading all objects using repository");
queryUsingRepository("Executing query using repository");
writeFooter();
if (i > 0 && i % (iterations / 10) == 0) {
statistics.printResults(i);
}
writeFooter();
}
statistics.printResults(iterations);
}
private void writeHeadline(String headline) {
System.out.println(headline);
System.out.println(createUnderline(headline));
System.out.println("---------------------------------".substring(0, headline.length()));
}
private void writeFooter() {
System.out.println();
}
private long queryUsingTemplate() {
executeWatched(new WatchCallback<List<Person>>() {
private void queryUsingTemplate(String template) {
executeWatchedWithTimeAndResultSize(template, new WatchCallback<List<Person>>() {
public List<Person> doInWatch() {
Query query = query(where("addresses.zipCode").regex(".*1.*"));
return operations.find(query, Person.class, "template");
}
});
return watch.getLastTaskTimeMillis();
}
private long queryUsingRepository() {
executeWatched(new WatchCallback<List<Person>>() {
private void queryUsingRepository(String template) {
executeWatchedWithTimeAndResultSize(template, new WatchCallback<List<Person>>() {
public List<Person> doInWatch() {
return repository.findByAddressesZipCodeContaining("1");
}
});
return watch.getLastTaskTimeMillis();
}
private void executeWithWriteConcerns(WriteConcernCallback callback) {
@@ -267,7 +181,7 @@ public class PerformanceTests {
for (String collectionName : COLLECTION_NAMES) {
DBCollection collection = db.getCollection(collectionName);
collection.drop();
collection.getDB().command(getCreateCollectionCommand(collectionName));
db.command(getCreateCollectionCommand(collectionName));
collection.ensureIndex(new BasicDBObject("firstname", -1));
collection.ensureIndex(new BasicDBObject("lastname", -1));
}
@@ -281,42 +195,38 @@ public class PerformanceTests {
return dbObject;
}
private long writingObjectsUsingPlainDriver(int numberOfPersons) {
private void writingObjectsUsingPlainDriver(String template) {
final DBCollection collection = mongo.getDB(DATABASE_NAME).getCollection("driver");
final List<Person> persons = getPersonObjects(numberOfPersons);
final List<DBObject> persons = getPersonDBObjects();
executeWatched(new WatchCallback<Void>() {
executeWatchedWithTime(template, new WatchCallback<Void>() {
public Void doInWatch() {
for (Person person : persons) {
collection.save(person.toDBObject());
for (DBObject person : persons) {
collection.save(person);
}
return null;
}
});
return watch.getLastTaskTimeMillis();
}
private long writingObjectsUsingRepositories(int numberOfPersons) {
private void writingObjectsUsingRepositories(String template) {
final List<Person> persons = getPersonObjects(numberOfPersons);
final List<Person> persons = getPersonObjects();
executeWatched(new WatchCallback<Void>() {
executeWatchedWithTime(template, new WatchCallback<Void>() {
public Void doInWatch() {
repository.save(persons);
return null;
}
});
return watch.getLastTaskTimeMillis();
}
private long writingObjectsUsingMongoTemplate(int numberOfPersons) {
private void writingObjectsUsingMongoTemplate(String template) {
final List<Person> persons = getPersonObjects(numberOfPersons);
final List<Person> persons = getPersonObjects();
executeWatched(new WatchCallback<Void>() {
executeWatchedWithTime(template, new WatchCallback<Void>() {
public Void doInWatch() {
for (Person person : persons) {
operations.save(person, "template");
@@ -324,95 +234,82 @@ public class PerformanceTests {
return null;
}
});
return watch.getLastTaskTimeMillis();
}
private long readingUsingPlainDriver() {
private void readingUsingPlainDriver(String template) {
executeWatched(new WatchCallback<List<Person>>() {
final DBCollection collection = mongo.getDB(DATABASE_NAME).getCollection("driver");
executeWatchedWithTimeAndResultSize(String.format(template, NUMBER_OF_PERSONS), new WatchCallback<List<Person>>() {
public List<Person> doInWatch() {
return toPersons(mongo.getDB(DATABASE_NAME).getCollection("driver").find());
return toPersons(collection.find());
}
});
return watch.getLastTaskTimeMillis();
}
private long readingUsingTemplate() {
executeWatched(new WatchCallback<List<Person>>() {
private void readingUsingTemplate(String template) {
executeWatchedWithTimeAndResultSize(String.format(template, NUMBER_OF_PERSONS), new WatchCallback<List<Person>>() {
public List<Person> doInWatch() {
return operations.findAll(Person.class, "template");
}
});
return watch.getLastTaskTimeMillis();
}
private long readingUsingRepository() {
executeWatched(new WatchCallback<List<Person>>() {
private void readingUsingRepository(String template) {
executeWatchedWithTimeAndResultSize(String.format(template, NUMBER_OF_PERSONS), new WatchCallback<List<Person>>() {
public List<Person> doInWatch() {
return repository.findAll();
}
});
return watch.getLastTaskTimeMillis();
}
private long queryUsingPlainDriver() {
private void queryUsingPlainDriver(String template) {
executeWatched(new WatchCallback<List<Person>>() {
final DBCollection collection = mongo.getDB(DATABASE_NAME).getCollection("driver");
executeWatchedWithTimeAndResultSize(template, new WatchCallback<List<Person>>() {
public List<Person> doInWatch() {
DBCollection collection = mongo.getDB(DATABASE_NAME).getCollection("driver");
DBObject regex = new BasicDBObject("$regex", Pattern.compile(".*1.*"));
DBObject query = new BasicDBObject("addresses.zipCode", regex);
return toPersons(collection.find(query));
}
});
return watch.getLastTaskTimeMillis();
}
private List<Person> getPersonObjects(int numberOfPersons) {
private List<DBObject> getPersonDBObjects() {
List<Person> result = new ArrayList<Person>();
List<DBObject> result = new ArrayList<DBObject>(NUMBER_OF_PERSONS);
for (int i = 0; i < numberOfPersons; i++) {
List<Address> addresses = new ArrayList<Address>();
for (int a = 0; a < 5; a++) {
addresses.add(new Address("zip" + a, "city" + a));
}
Person person = new Person("Firstname" + i, "Lastname" + i, addresses);
for (int o = 0; o < 10; o++) {
person.orders.add(new Order(LineItem.generate()));
}
result.add(person);
for (Person person : getPersonObjects()) {
result.add(person.toDBObject());
}
return result;
}
private List<DBObject> getPersonDBObjects(int numberOfPersons) {
private List<Person> getPersonObjects() {
List<DBObject> dbObjects = new ArrayList<DBObject>(numberOfPersons);
List<Person> result = new ArrayList<Person>(NUMBER_OF_PERSONS);
for (Person person : getPersonObjects(numberOfPersons)) {
dbObjects.add(person.toDBObject());
watch.start("Created " + NUMBER_OF_PERSONS + " Persons");
for (int i = 0; i < NUMBER_OF_PERSONS; i++) {
Address address = new Address("zip" + i, "city" + i);
Person person = new Person("Firstname" + i, "Lastname" + i, Arrays.asList(address));
person.orders.add(new Order(LineItem.generate()));
person.orders.add(new Order(LineItem.generate()));
result.add(person);
}
return dbObjects;
watch.stop();
return result;
}
private <T> T executeWatched(WatchCallback<T> callback) {
private <T> T executeWatched(String template, WatchCallback<T> callback) {
watch.start();
watch.start(String.format(template, NUMBER_OF_PERSONS));
try {
return callback.doInWatch();
@@ -421,6 +318,28 @@ public class PerformanceTests {
}
}
private <T> void executeWatchedWithTime(String template, WatchCallback<?> callback) {
executeWatched(template, callback);
printStatistics(null);
}
private <T> void executeWatchedWithTimeAndResultSize(String template, WatchCallback<List<T>> callback) {
printStatistics(executeWatched(template, callback));
}
private void printStatistics(Collection<?> result) {
long time = watch.getLastTaskTimeMillis();
StringBuilder builder = new StringBuilder(watch.getLastTaskName());
if (result != null) {
builder.append(" returned ").append(result.size()).append(" results and");
}
builder.append(" took ").append(time).append(" milliseconds");
System.out.println(builder);
}
private static List<Person> toPersons(DBCursor cursor) {
List<Person> persons = new ArrayList<Person>();
@@ -435,9 +354,10 @@ public class PerformanceTests {
static class Person {
ObjectId id;
String firstname, lastname;
List<Address> addresses;
Set<Order> orders;
@Indexed
final String firstname, lastname;
final List<Address> addresses;
final Set<Order> orders;
public Person(String firstname, String lastname, List<Address> addresses) {
this.firstname = firstname;
@@ -659,253 +579,11 @@ public class PerformanceTests {
DBObject toDBObject();
}
private static BasicDBList writeAll(Collection<? extends Convertible> convertibles) {
BasicDBList result = new BasicDBList();
private static List<DBObject> writeAll(Collection<? extends Convertible> convertibles) {
List<DBObject> result = new ArrayList<DBObject>();
for (Convertible convertible : convertibles) {
result.add(convertible.toDBObject());
}
return result;
}
static enum Api {
DRIVER, TEMPLATE, REPOSITORY, DIRECT, CONVERTER;
}
static enum Mode {
WRITE, READ, QUERY;
}
private static class Statistics {
private final String headline;
private final Map<Mode, ModeTimes> times;
public Statistics(String headline) {
this.headline = headline;
this.times = new HashMap<Mode, ModeTimes>();
for (Mode mode : Mode.values()) {
times.put(mode, new ModeTimes(mode));
}
}
public void registerTime(Api api, Mode mode, double time) {
times.get(mode).add(api, time);
}
public void printResults(int iterations) {
String title = String.format(headline, iterations);
System.out.println(title);
System.out.println(createUnderline(title));
StringBuilder builder = new StringBuilder();
for (Mode mode : Mode.values()) {
String print = times.get(mode).print();
if (!print.isEmpty()) {
builder.append(print).append('\n');
}
}
System.out.println(builder.toString());
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(times.size());
for (ModeTimes times : this.times.values()) {
builder.append(times.toString());
}
return builder.toString();
}
}
private static String createUnderline(String input) {
StringBuilder builder = new StringBuilder(input.length());
for (int i = 0; i < input.length(); i++) {
builder.append("-");
}
return builder.toString();
}
static class ApiTimes {
private static final String TIME_TEMPLATE = "%s %s time -\tAverage: %sms%s,%sMedian: %sms%s";
private static final DecimalFormat TIME_FORMAT;
private static final DecimalFormat DEVIATION_FORMAT;
static {
TIME_FORMAT = new DecimalFormat("0.00");
DEVIATION_FORMAT = new DecimalFormat("0.00");
DEVIATION_FORMAT.setPositivePrefix("+");
}
private final Api api;
private final Mode mode;
private final List<Double> times;
public ApiTimes(Api api, Mode mode) {
this.api = api;
this.mode = mode;
this.times = new ArrayList<Double>();
}
public void add(double time) {
this.times.add(time);
}
public boolean hasTimes() {
return !times.isEmpty();
}
public double getAverage() {
double result = 0;
for (Double time : times) {
result += time;
}
return result == 0.0 ? 0.0 : result / times.size();
}
public double getMedian() {
if (times.isEmpty()) {
return 0.0;
}
ArrayList<Double> list = new ArrayList<Double>(times);
Collections.sort(list);
int size = list.size();
if (size % 2 == 0) {
return (list.get(size / 2 - 1) + list.get(size / 2)) / 2;
} else {
return list.get(size / 2);
}
}
private double getDeviationFrom(double otherAverage) {
double average = getAverage();
return average * 100 / otherAverage - 100;
}
private double getMediaDeviationFrom(double otherMedian) {
double median = getMedian();
return median * 100 / otherMedian - 100;
}
public String print() {
if (times.isEmpty()) {
return "";
}
return basicPrint("", "\t\t", "") + '\n';
}
private String basicPrint(String extension, String middle, String foo) {
return String.format(TIME_TEMPLATE, api, mode, TIME_FORMAT.format(getAverage()), extension, middle,
TIME_FORMAT.format(getMedian()), foo);
}
public String print(double referenceAverage, double referenceMedian) {
if (times.isEmpty()) {
return "";
}
return basicPrint(String.format(" %s%%", DEVIATION_FORMAT.format(getDeviationFrom(referenceAverage))), "\t",
String.format(" %s%%", DEVIATION_FORMAT.format(getMediaDeviationFrom(referenceMedian)))) + '\n';
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return times.isEmpty() ? "" : String.format("%s, %s: %s", api, mode,
StringUtils.collectionToCommaDelimitedString(times)) + '\n';
}
}
static class ModeTimes {
private final Map<Api, ApiTimes> times;
public ModeTimes(Mode mode) {
this.times = new HashMap<Api, ApiTimes>();
for (Api api : Api.values()) {
this.times.put(api, new ApiTimes(api, mode));
}
}
public void add(Api api, double time) {
times.get(api).add(time);
}
@SuppressWarnings("null")
public String print() {
if (times.isEmpty()) {
return "";
}
Double previousTime = null;
Double previousMedian = null;
StringBuilder builder = new StringBuilder();
for (Api api : Api.values()) {
ApiTimes apiTimes = times.get(api);
if (!apiTimes.hasTimes()) {
continue;
}
if (previousTime == null) {
builder.append(apiTimes.print());
previousTime = apiTimes.getAverage();
previousMedian = apiTimes.getMedian();
} else {
builder.append(apiTimes.print(previousTime, previousMedian));
}
}
return builder.toString();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder(times.size());
for (ApiTimes times : this.times.values()) {
builder.append(times.toString());
}
return builder.toString();
}
}
}

View File

@@ -38,7 +38,6 @@ import org.springframework.data.mongodb.core.geo.Circle;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.GeoPage;
import org.springframework.data.mongodb.core.geo.GeoResults;
import org.springframework.data.mongodb.core.geo.Metric;
import org.springframework.data.mongodb.core.geo.Metrics;
import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.data.mongodb.core.geo.Polygon;
@@ -53,9 +52,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
public abstract class AbstractPersonRepositoryIntegrationTests {
@Autowired protected PersonRepository repository;
@Autowired
protected PersonRepository repository;
@Autowired MongoOperations operations;
@Autowired
MongoOperations operations;
Person dave, oliver, carter, boyd, stefan, leroi, alicia;
QPerson person;
@@ -400,9 +401,6 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
Metrics.KILOMETERS), new PageRequest(0, 20));
assertThat(results.getContent().isEmpty(), is(false));
// DATAMONGO-607
assertThat(results.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
}
/**
@@ -544,116 +542,4 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(result, hasSize(1));
assertThat(result, hasItem(dave));
}
/**
* @see DATAMONGO-701
*/
@Test
public void executesDerivedStartsWithQueryCorrectly() {
List<Person> result = repository.findByLastnameStartsWith("Matt");
assertThat(result, hasSize(2));
assertThat(result, hasItems(dave, oliver));
}
/**
* @see DATAMONGO-701
*/
@Test
public void executesDerivedEndsWithQueryCorrectly() {
List<Person> result = repository.findByLastnameEndsWith("thews");
assertThat(result, hasSize(2));
assertThat(result, hasItems(dave, oliver));
}
/**
* @see DATAMONGO-445
*/
@Test
public void executesGeoPageQueryForWithPageRequestForPageInBetween() {
Point farAway = new Point(-73.9, 40.7);
Point here = new Point(-73.99, 40.73);
dave.setLocation(farAway);
oliver.setLocation(here);
carter.setLocation(here);
boyd.setLocation(here);
leroi.setLocation(here);
repository.save(Arrays.asList(dave, oliver, carter, boyd, leroi));
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
Metrics.KILOMETERS), new PageRequest(1, 2));
assertThat(results.getContent().isEmpty(), is(false));
assertThat(results.getNumberOfElements(), is(2));
assertThat(results.isFirstPage(), is(false));
assertThat(results.isLastPage(), is(false));
assertThat(results.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
assertThat(results.getAverageDistance().getNormalizedValue(), is(0.0));
}
/**
* @see DATAMONGO-445
*/
@Test
public void executesGeoPageQueryForWithPageRequestForPageAtTheEnd() {
Point point = new Point(-73.99171, 40.738868);
dave.setLocation(point);
oliver.setLocation(point);
carter.setLocation(point);
repository.save(Arrays.asList(dave, oliver, carter));
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
Metrics.KILOMETERS), new PageRequest(1, 2));
assertThat(results.getContent().isEmpty(), is(false));
assertThat(results.getNumberOfElements(), is(1));
assertThat(results.isFirstPage(), is(false));
assertThat(results.isLastPage(), is(true));
assertThat(results.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
}
/**
* @see DATAMONGO-445
*/
@Test
public void executesGeoPageQueryForWithPageRequestForJustOneElement() {
Point point = new Point(-73.99171, 40.738868);
dave.setLocation(point);
repository.save(dave);
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
Metrics.KILOMETERS), new PageRequest(0, 2));
assertThat(results.getContent().isEmpty(), is(false));
assertThat(results.getNumberOfElements(), is(1));
assertThat(results.isFirstPage(), is(true));
assertThat(results.isLastPage(), is(true));
assertThat(results.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
}
/**
* @see DATAMONGO-445
*/
@Test
public void executesGeoPageQueryForWithPageRequestForJustOneElementEmptyPage() {
dave.setLocation(new Point(-73.99171, 40.738868));
repository.save(dave);
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
Metrics.KILOMETERS), new PageRequest(1, 2));
assertThat(results.getContent().isEmpty(), is(true));
assertThat(results.getNumberOfElements(), is(0));
assertThat(results.isFirstPage(), is(false));
assertThat(results.isLastPage(), is(true));
assertThat(results.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
}
}

Some files were not shown because too many files have changed in this diff Show More