Possible Bug: Creating a findOne method with custom query

Hi There,

I’ve the following entity defined:

@Data
@Document
public class ApplicationEntity {
    @Id
    private String applicationId;

    @Field
    private String userId;

    @Field
    private String name;

    @Field
    private boolean active = true;

    @CreatedDate
    private ZonedDateTime createdAt;

    @LastModifiedDate
    private ZonedDateTime lastModifiedAt;

    @Version
    private long docVersion;
}

Then I have the following repository definition for this entity:

@Repository
public interface ApplicationRepository extends BaseRepository<ApplicationEntity, String> {
    @Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND active = true")
    Page<ApplicationEntity> findByUserId(String userId, Pageable pageable);

    @Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND active = true")
    ApplicationEntity findOne(String applicationId);

    default ApplicationEntity findOneByUserIdAndApplicationId(final String userId, final String applicationId) {
        val applicationEntity = findOne(applicationId);

        if (applicationEntity == null || !applicationEntity.getUserId().equalsIgnoreCase(userId)) {
            throw new RuntimeException("Application doesn't exist!");
        }

        return applicationEntity;
    }
}

Retrieving applications via these repository methods are just fine. However if I try to update an entity using these methods, it fails with CASMismatchException. If I remove findOne method, update works just fine. My update method is like below:

    @Override
    public void disableApplication(final String userId, final String applicationId) {
        final ApplicationEntity applicationEntity = repository.findOneByUserIdAndApplicationId(userId, applicationId);

        applicationEntity.setActive(false);

        repository.save(applicationEntity);
    }

Am I missing something?

Update: I’m running my application with Spring Boot 1.5.1 (+ Spring Data Couchbase) against Couchbase 4.5.0-2601 Community Edition (build-2601) running on top of Docker.

Hi @alperkanat,

I see val in your code. Is it lombok local variable? Does it work if you don’t use it?

@subhashni Yes it’s a lombok local variable. Basically it replaces val’s with final and type. It doesn’t change anything at all.

Looks like this is related to Couchbase’s ID management. findOne seems to have a unique case which is handled differently than the rest of the queries. No matter what I wrote (into custom query) I couldn’t make it query against the ID of the document. My trials include the following:

@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND _ID = $0 AND active = true")
ApplicationEntity findOne(String applicationId);
@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND meta().id = $0 AND active = true")
ApplicationEntity findOne(String applicationId);

Unfortunetely the above queries doesn’t work.

Yes, findOne is a default method provided by Spring repository http://docs.spring.io/spring-data/data-commons/docs/current/api/org/springframework/data/repository/CrudRepository.html#findOne-ID so they don’t get resolved as custom queries. You should use a different method name for the SpEL based query.