3

Spring 5 comes with a reactive implementation for spring data mongo , before the i was able to extend my mongo repository with QuerydslPredicateExecutor

 @Repository
 public interface AccountRepo extends MongoRepository<Account,String> 
 ,QuerydslPredicateExecutor<Account>

if i try this

 @Repository
 public interface AccountRepo extends
 ReactiveMongoRepository<Account,String>,
 QuerydslPredicateExecutor<Account>

my application does not start it because :

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property exists found for type Account!

is there a way around this

here is the account class

package com.devop.models;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
@Data
public class Account {
@Id
String id;

String accountName;

String accountNumber;

String schemeCode;

String openDate;

String accountCategory;

String accountCurrency = "Naira";

String accountSecondaryCategory;

String receiveSmsAlert;

String recieveEmailAlert;

String cifId;

}

here is the interface AccountRepo

 package com.devop.mongoRepo;

 import com.devop.models.Account;
 import org.springframework.data.mongodb.repository.*;
 import org.springframework.data.mongodb.repository.support*;
 import org.springframework.data.querydsl.QuerydslPredicateExecutor;
 import org.springframework.stereotype.Repository;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;

 @Repository
 public interface AccountRepo extends 
 ReactiveMongoRepository<Account,String> 
 ,QuerydslPredicateExecutor<Account> {

Flux<Account> findAccountByAccountNameContains(String accountName);
Mono<Account> findAccountByAccountNumberEquals(String accountNumber);

}
6
  • share the Account class? Commented Sep 2, 2017 at 16:31
  • account class has been shared Commented Sep 2, 2017 at 18:45
  • Could you please share the entire interface AccountRepo ? Commented Sep 3, 2017 at 2:43
  • accountRepo has been shared Commented Sep 3, 2017 at 9:42
  • 1
    There's no Querydsl support for reactive MongoDB repositories yet. Commented Sep 8, 2017 at 6:55

2 Answers 2

1

You could use ReactiveQuerydslPredicateExecutor. See example for more information https://github.com/spring-projects/spring-data-examples/tree/master/mongodb/querydsl

Sign up to request clarification or add additional context in comments.

Comments

0

I found a workaround solution using a Custom ReactiveMongoRepositoryFactoryBean and ReactiveMongoRepositoryFactory, it could help someone else that is struggling with that

First you need to use repositoryFactoryBeanClass in the reactive annotation.

@EnableReactiveMongoRepositories(repositoryFactoryBeanClass = CustomReactiveMongoRepositoryFactoryBean.class)
@Configuration
public class ReactiveMongoDbHack {
}

CustomReactiveMongoRepositoryFactoryBean class

import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactoryBean;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

public class CustomReactiveMongoRepositoryFactoryBean extends ReactiveMongoRepositoryFactoryBean {
    public CustomReactiveMongoRepositoryFactoryBean(Class repositoryInterface) {
        super(repositoryInterface);
    }

    @Override
    protected RepositoryFactorySupport getFactoryInstance(ReactiveMongoOperations operations) {
        return new CustomReactiveMongoRepositoryFactory(operations);
    }
}

CustomReactiveMongoRepositoryFactory class

import static org.springframework.data.querydsl.QuerydslUtils.QUERY_DSL_PRESENT;

public class CustomReactiveMongoRepositoryFactory extends ReactiveMongoRepositoryFactory {

    private static MongoOperations operations;
    private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;

    public CustomReactiveMongoRepositoryFactory(ReactiveMongoOperations operations) {
    super(operations);
    this.mappingContext = operations.getConverter().getMappingContext();
    }

    //TODO Must set MongoOperations(MongoTemplate)
    public static void setOperations(MongoOperations operations) {
    CustomReactiveMongoRepositoryFactory.operations = operations;
    }

    @Override
    protected RepositoryComposition.RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {

    RepositoryComposition.RepositoryFragments fragments = RepositoryComposition.RepositoryFragments.empty();

    boolean isQueryDslRepository = QUERY_DSL_PRESENT
        && QuerydslPredicateExecutor.class.isAssignableFrom(metadata.getRepositoryInterface());

    if (isQueryDslRepository) {

        MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType(),
            metadata);

        fragments = fragments.append(RepositoryFragment.implemented(
            getTargetRepositoryViaReflection(QuerydslMongoPredicateExecutor.class, entityInformation, operations)));
    }

    return fragments;
    }

    private <T, ID> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
                                                                   @Nullable RepositoryMetadata metadata) {

    MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainClass);
    return MongoEntityInformationSupport.<T, ID> entityInformationFor(entity,
        metadata != null ? metadata.getIdType() : null);
    }

}

MongoEntityInformationSupport class copied from spring-data-mongodb

import org.springframework.data.domain.Persistable;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * Support class responsible for creating {@link MongoEntityInformation} instances for a given
 * {@link MongoPersistentEntity}.
 *
 * @author Christoph Strobl
 * @author Mark Paluch
 * @since 1.10
 */
final class MongoEntityInformationSupport {

    private MongoEntityInformationSupport() {}

    /**
     * Factory method for creating {@link MongoEntityInformation}.
     *
     * @param entity must not be {@literal null}.
     * @param idType can be {@literal null}.
     * @return never {@literal null}.
     */
    @SuppressWarnings("unchecked")
    static <T, ID> MongoEntityInformation<T, ID> entityInformationFor(MongoPersistentEntity<?> entity,
                                                                  @Nullable Class<?> idType) {

    Assert.notNull(entity, "Entity must not be null!");

    MappingMongoEntityInformation<T, ID> entityInformation = new MappingMongoEntityInformation<T, ID>(
        (MongoPersistentEntity<T>) entity, (Class<ID>) idType);

    return ClassUtils.isAssignable(Persistable.class, entity.getType())
        ? new PersistableMongoEntityInformation<>(entityInformation) : entityInformation;
    }
}

PersistableMongoEntityInformation class also copied from spring-data-mongodb

import lombok.NonNull;
import lombok.RequiredArgsConstructor;

import org.springframework.data.domain.Persistable;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;

/**
 * {@link MongoEntityInformation} implementation wrapping an existing {@link MongoEntityInformation} considering
 * {@link Persistable} types by delegating {@link #isNew(Object)} and {@link #getId(Object)} to the corresponding
 * {@link Persistable#isNew()} and {@link Persistable#getId()} implementations.
 *
 * @author Christoph Strobl
 * @author Oliver Gierke
 * @since 1.10
 */
@RequiredArgsConstructor
class PersistableMongoEntityInformation<T, ID> implements MongoEntityInformation<T, ID> {

    private final @NonNull MongoEntityInformation<T, ID> delegate;

    /*
     * (non-Javadoc)
     * @see org.springframework.data.mongodb.repository.MongoEntityInformation#getCollectionName()
     */
    @Override
    public String getCollectionName() {
    return delegate.getCollectionName();
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.mongodb.repository.MongoEntityInformation#getIdAttribute()
     */
    @Override
    public String getIdAttribute() {
    return delegate.getIdAttribute();
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.EntityInformation#isNew(java.lang.Object)
     */
    @Override
    @SuppressWarnings("unchecked")
    public boolean isNew(T t) {

    if (t instanceof Persistable) {
        return ((Persistable<ID>) t).isNew();
    }

    return delegate.isNew(t);
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
     */
    @Override
    @SuppressWarnings("unchecked")
    public ID getId(T t) {

    if (t instanceof Persistable) {
        return ((Persistable<ID>) t).getId();
    }

    return delegate.getId(t);
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.support.PersistentEntityInformation#getIdType()
     */
    @Override
    public Class<ID> getIdType() {
    return delegate.getIdType();
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.support.EntityMetadata#getJavaType()
     */
    @Override
    public Class<T> getJavaType() {
    return delegate.getJavaType();
    }
}

Then your Reactive Repository with Query DSL would work.

public interface AssetRepository extends ReactiveCrudRepository<Asset, String>, QuerydslPredicateExecutor<Asset> {
}

PS: It must need to set MongoOperations at CustomReactiveMongoRepositoryFactory.setOperations, what I did was to use the auto config classes(MongoAutoConfiguration and MongoDataAutoConfiguration) for Mongo then using @PostConstruct in a method to set it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.