Search in sources :

Example 1 with FirestoreDataException

use of com.google.cloud.spring.data.firestore.FirestoreDataException in project spring-cloud-gcp by GoogleCloudPlatform.

the class PartTreeFirestoreQuery method validate.

private void validate() {
    List parts = this.tree.get().collect(Collectors.toList());
    if (parts.size() > 1 && parts.get(0) instanceof PartTree.OrPart) {
        throw new FirestoreDataException("Cloud Firestore doesn't support 'OR' (method name: " + this.getQueryMethod().getName() + ")");
    }
    List<String> unsupportedParts = this.tree.getParts().stream().filter(part -> !isSupportedPart(part.getType())).map(part -> part.getType().toString()).collect(Collectors.toList());
    if (!unsupportedParts.isEmpty()) {
        throw new FirestoreDataException("Unsupported predicate keywords: " + unsupportedParts + " in " + this.getQueryMethod().getName());
    }
}
Also used : GREATER_THAN(org.springframework.data.repository.query.parser.Part.Type.GREATER_THAN) Arrays(java.util.Arrays) MapBuilder(com.google.cloud.spring.core.util.MapBuilder) Order(org.springframework.data.domain.Sort.Order) FieldReference(com.google.firestore.v1.StructuredQuery.FieldReference) QueryMethod(org.springframework.data.repository.query.QueryMethod) LESS_THAN_EQUAL(org.springframework.data.repository.query.parser.Part.Type.LESS_THAN_EQUAL) Part(org.springframework.data.repository.query.parser.Part) FirestorePersistentEntity(com.google.cloud.spring.data.firestore.mapping.FirestorePersistentEntity) ArrayList(java.util.ArrayList) NOT_IN(org.springframework.data.repository.query.parser.Part.Type.NOT_IN) Value(com.google.firestore.v1.Value) NEGATING_SIMPLE_PROPERTY(org.springframework.data.repository.query.parser.Part.Type.NEGATING_SIMPLE_PROPERTY) Map(java.util.Map) NAME_FIELD(com.google.cloud.spring.data.firestore.FirestoreTemplate.NAME_FIELD) StreamSupport(java.util.stream.StreamSupport) Pageable(org.springframework.data.domain.Pageable) Sort(org.springframework.data.domain.Sort) Direction(org.springframework.data.domain.Sort.Direction) FirestoreClassMapper(com.google.cloud.spring.data.firestore.mapping.FirestoreClassMapper) FirestoreReactiveOperations(com.google.cloud.spring.data.firestore.FirestoreReactiveOperations) LESS_THAN(org.springframework.data.repository.query.parser.Part.Type.LESS_THAN) Int32Value(com.google.protobuf.Int32Value) ParametersParameterAccessor(org.springframework.data.repository.query.ParametersParameterAccessor) StructuredQuery(com.google.firestore.v1.StructuredQuery) Iterator(java.util.Iterator) FirestoreDataException(com.google.cloud.spring.data.firestore.FirestoreDataException) PartTree(org.springframework.data.repository.query.parser.PartTree) ParameterAccessor(org.springframework.data.repository.query.ParameterAccessor) SIMPLE_PROPERTY(org.springframework.data.repository.query.parser.Part.Type.SIMPLE_PROPERTY) Collectors(java.util.stream.Collectors) CONTAINING(org.springframework.data.repository.query.parser.Part.Type.CONTAINING) FirestorePersistentProperty(com.google.cloud.spring.data.firestore.mapping.FirestorePersistentProperty) List(java.util.List) IN(org.springframework.data.repository.query.parser.Part.Type.IN) FirestoreMappingContext(com.google.cloud.spring.data.firestore.mapping.FirestoreMappingContext) ReturnedType(org.springframework.data.repository.query.ReturnedType) GREATER_THAN_EQUAL(org.springframework.data.repository.query.parser.Part.Type.GREATER_THAN_EQUAL) PropertyPath(org.springframework.data.mapping.PropertyPath) RepositoryQuery(org.springframework.data.repository.query.RepositoryQuery) FirestoreDataException(com.google.cloud.spring.data.firestore.FirestoreDataException) ArrayList(java.util.ArrayList) List(java.util.List) PartTree(org.springframework.data.repository.query.parser.PartTree)

Example 2 with FirestoreDataException

use of com.google.cloud.spring.data.firestore.FirestoreDataException in project spring-cloud-gcp by GoogleCloudPlatform.

the class PartTreeFirestoreQuery method createBuilderWithFilter.

private StructuredQuery.Builder createBuilderWithFilter(Object[] parameters) {
    StructuredQuery.Builder builder = StructuredQuery.newBuilder();
    Iterator it = Arrays.asList(parameters).iterator();
    StructuredQuery.CompositeFilter.Builder compositeFilter = StructuredQuery.CompositeFilter.newBuilder();
    compositeFilter.setOp(StructuredQuery.CompositeFilter.Operator.AND);
    this.tree.getParts().forEach(part -> {
        StructuredQuery.FieldReference fieldReference = StructuredQuery.FieldReference.newBuilder().setFieldPath(buildName(part)).build();
        StructuredQuery.Filter.Builder filter = StructuredQuery.Filter.newBuilder();
        if (part.getType() == Part.Type.IS_NULL) {
            filter.getUnaryFilterBuilder().setField(fieldReference).setOp(StructuredQuery.UnaryFilter.Operator.IS_NULL);
        } else {
            if (!it.hasNext()) {
                throw new FirestoreDataException("Too few parameters are provided for query method: " + getQueryMethod().getName());
            }
            Object value = it.next();
            StructuredQuery.FieldFilter.Builder fieldFilterBuilder = filter.getFieldFilterBuilder().setField(fieldReference).setOp(getOperator(part, value));
            if (fieldReference.getFieldPath().equals(NAME_FIELD)) {
                // In Firestore, a field that is used as a document ID can only be of String type
                fieldFilterBuilder.setValue(Value.newBuilder().setReferenceValue(this.reactiveOperations.buildResourceName(persistentEntity, (String) value)));
            } else {
                fieldFilterBuilder.setValue(this.classMapper.toFirestoreValue(value));
            }
        }
        compositeFilter.addFilters(filter.build());
    });
    builder.setWhere(StructuredQuery.Filter.newBuilder().setCompositeFilter(compositeFilter.build()));
    return builder;
}
Also used : StructuredQuery(com.google.firestore.v1.StructuredQuery) Iterator(java.util.Iterator) FirestoreDataException(com.google.cloud.spring.data.firestore.FirestoreDataException) FieldReference(com.google.firestore.v1.StructuredQuery.FieldReference)

Example 3 with FirestoreDataException

use of com.google.cloud.spring.data.firestore.FirestoreDataException in project spring-cloud-gcp by GoogleCloudPlatform.

the class ReactiveFirestoreTransactionManagerTest method triggerRollbackCorrectly.

@Test
public void triggerRollbackCorrectly() {
    FirestoreTemplate template = getFirestoreTemplate();
    ReactiveFirestoreTransactionManager txManager = new ReactiveFirestoreTransactionManager(this.firestoreStub, this.parent, this.classMapper);
    TransactionalOperator operator = TransactionalOperator.create(txManager);
    template.findById(Mono.defer(() -> {
        throw new FirestoreDataException("BOOM!");
    }), FirestoreTemplateTests.TestEntity.class).as(operator::transactional).as(StepVerifier::create).expectError().verify();
    verify(this.firestoreStub, times(1)).beginTransaction(any(), any());
    verify(this.firestoreStub, times(0)).commit(any(), any());
    verify(this.firestoreStub, times(1)).rollback(any(), any());
}
Also used : TransactionalOperator(org.springframework.transaction.reactive.TransactionalOperator) FirestoreDataException(com.google.cloud.spring.data.firestore.FirestoreDataException) FirestoreTemplateTests(com.google.cloud.spring.data.firestore.FirestoreTemplateTests) StepVerifier(reactor.test.StepVerifier) FirestoreTemplate(com.google.cloud.spring.data.firestore.FirestoreTemplate) Test(org.junit.Test)

Example 4 with FirestoreDataException

use of com.google.cloud.spring.data.firestore.FirestoreDataException in project spring-cloud-gcp by GoogleCloudPlatform.

the class FirestoreIntegrationTests method transactionTest.

@Test
public void transactionTest() {
    User alice = new User("Alice", 29);
    User bob = new User("Bob", 60);
    User user = new User(null, 40);
    DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
    transactionDefinition.setReadOnly(false);
    TransactionalOperator operator = TransactionalOperator.create(this.txManager, transactionDefinition);
    reset(this.txManager);
    this.firestoreTemplate.save(alice).then(this.firestoreTemplate.save(bob)).then(this.firestoreTemplate.save(user)).as(operator::transactional).block();
    assertThat(this.firestoreTemplate.findAll(User.class).collectList().block()).containsExactlyInAnyOrder(bob, alice, user);
    verify(this.txManager, times(1)).commit(any());
    verify(this.txManager, times(0)).rollback(any());
    verify(this.txManager, times(1)).getReactiveTransaction(any());
    reset(this.txManager);
    // test rollback
    this.firestoreTemplate.saveAll(Mono.defer(() -> {
        throw new FirestoreDataException("BOOM!");
    })).then(this.firestoreTemplate.deleteAll(User.class)).as(operator::transactional).onErrorResume(throwable -> Mono.empty()).block();
    verify(this.txManager, times(0)).commit(any());
    verify(this.txManager, times(1)).rollback(any());
    verify(this.txManager, times(1)).getReactiveTransaction(any());
    assertThat(this.firestoreTemplate.count(User.class).block()).isEqualTo(3);
    this.firestoreTemplate.findAll(User.class).flatMap(a -> {
        a.setAge(a.getAge() - 1);
        return this.firestoreTemplate.save(a);
    }).as(operator::transactional).collectList().block();
    List<User> users = this.firestoreTemplate.findAll(User.class).collectList().block();
    assertThat(users).extracting("age").containsExactlyInAnyOrder(28, 59, 39);
    assertThat(users).extracting("name").doesNotContainNull();
    this.firestoreTemplate.deleteAll(User.class).as(operator::transactional).block();
    assertThat(this.firestoreTemplate.findAll(User.class).collectList().block()).isEmpty();
}
Also used : TransactionalOperator(org.springframework.transaction.reactive.TransactionalOperator) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) Assume.assumeThat(org.junit.Assume.assumeThat) StepVerifier(reactor.test.StepVerifier) BeforeClass(org.junit.BeforeClass) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) RunWith(org.junit.runner.RunWith) LoggerFactory(org.slf4j.LoggerFactory) Autowired(org.springframework.beans.factory.annotation.Autowired) Timestamp(com.google.cloud.Timestamp) FirestoreTemplate(com.google.cloud.spring.data.firestore.FirestoreTemplate) User(com.google.cloud.spring.data.firestore.entities.User) SpringRunner(org.springframework.test.context.junit4.SpringRunner) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) Before(org.junit.Before) FirestoreReactiveOperations(com.google.cloud.spring.data.firestore.FirestoreReactiveOperations) FirestoreDataException(com.google.cloud.spring.data.firestore.FirestoreDataException) TransactionalOperator(org.springframework.transaction.reactive.TransactionalOperator) Mockito.times(org.mockito.Mockito.times) Test(org.junit.Test) Mono(reactor.core.publisher.Mono) UUID(java.util.UUID) ReactiveFirestoreTransactionManager(com.google.cloud.spring.data.firestore.transaction.ReactiveFirestoreTransactionManager) Mockito.verify(org.mockito.Mockito.verify) StatusRuntimeException(io.grpc.StatusRuntimeException) Flux(reactor.core.publisher.Flux) Level(ch.qos.logback.classic.Level) PhoneNumber(com.google.cloud.spring.data.firestore.entities.PhoneNumber) List(java.util.List) ContextConfiguration(org.springframework.test.context.ContextConfiguration) Matchers.is(org.hamcrest.Matchers.is) Mockito.reset(org.mockito.Mockito.reset) User(com.google.cloud.spring.data.firestore.entities.User) DefaultTransactionDefinition(org.springframework.transaction.support.DefaultTransactionDefinition) FirestoreDataException(com.google.cloud.spring.data.firestore.FirestoreDataException) Test(org.junit.Test)

Aggregations

FirestoreDataException (com.google.cloud.spring.data.firestore.FirestoreDataException)4 FirestoreReactiveOperations (com.google.cloud.spring.data.firestore.FirestoreReactiveOperations)2 FirestoreTemplate (com.google.cloud.spring.data.firestore.FirestoreTemplate)2 StructuredQuery (com.google.firestore.v1.StructuredQuery)2 FieldReference (com.google.firestore.v1.StructuredQuery.FieldReference)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Test (org.junit.Test)2 TransactionalOperator (org.springframework.transaction.reactive.TransactionalOperator)2 StepVerifier (reactor.test.StepVerifier)2 Level (ch.qos.logback.classic.Level)1 Timestamp (com.google.cloud.Timestamp)1 MapBuilder (com.google.cloud.spring.core.util.MapBuilder)1 NAME_FIELD (com.google.cloud.spring.data.firestore.FirestoreTemplate.NAME_FIELD)1 FirestoreTemplateTests (com.google.cloud.spring.data.firestore.FirestoreTemplateTests)1 PhoneNumber (com.google.cloud.spring.data.firestore.entities.PhoneNumber)1 User (com.google.cloud.spring.data.firestore.entities.User)1 FirestoreClassMapper (com.google.cloud.spring.data.firestore.mapping.FirestoreClassMapper)1 FirestoreMappingContext (com.google.cloud.spring.data.firestore.mapping.FirestoreMappingContext)1 FirestorePersistentEntity (com.google.cloud.spring.data.firestore.mapping.FirestorePersistentEntity)1