Couchbase SpringData 4.1.1 and Boot 2.4 Query error

Hi All,
With springdata couchbase 4.1.1 and SpringBoot 2.4 along with couchbase 7 beta server below query annotated repository method is throwing error.
@Query(“SELECT COUNT(*) AS count FROM #{#n1ql.bucket} WHERE #{#n1ql.filter}”)
Long getProjectCountNickel();

It throws below error.
java.lang.NullPointerException: null
at org.springframework.data.couchbase.core.ReactiveFindByQueryOperationSupport$ReactiveFindByQuerySupport.lambda$null$1(ReactiveFindByQueryOperationSupport.java:100)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106)
at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250)

How ever "SELECT count(*) as count FROM test WHERE _class = “com.example.couchbase7upgrade.model.Project” query works fine in the consoleweb.

Please see whether its a bug

Thanks
Isuru

Same error happens when projections with Dtos are executed

@Query(“SELECT name,code FROM #{#n1ql.bucket} WHERE #{#n1ql.filter} AND name = $1 ORDER BY name DESC”)
List findByNameProjection(String name);

java.lang.NullPointerException: null
at org.springframework.data.couchbase.core.ReactiveFindByQueryOperationSupport$ReactiveFindByQuerySupport.lambda$null$1(ReactiveFindByQueryOperationSupport.java:100)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106)

Please check both .

@deniswsrosa / @mreiche can you assist ?

Give your query method a name beginning with “count” to indicate that it is a count() query.
The NPE occurs when spring-data-couchbase attempts to get the CAS from the query result.
Also - it’s safer to use #{#n1ql.selectEntity} instead of “SELECT …”

example from unit tests:
@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} #{#projectIds != null ? ‘AND iata IN $1’ : ‘’} "
+ " #{#planIds != null ? ‘AND icao IN $2’ : ‘’} #{#active != null ? ‘AND false = $3’ : ‘’} ")
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
Long countFancyExpression(@Param(“projectIds”) List projectIds, @Param(“planIds”) List planIds,
@Param(“active”) Boolean active);

@mreiche,
Yes you are right on count query it works after applying yoursuggestions.

How about projections it wont work by changing the query as you suggested. ??
@Query(“SELECT name,code FROM #{#n1ql.bucket} WHERE #{#n1ql.filter} AND name = $1 ORDER BY name DESC”)
List findByNameProjection(String name);
java.lang.NullPointerException: null
at org.springframework.data.couchbase.core.ReactiveFindByQueryOperationSupport$ReactiveFindByQuerySupport
Please clarify this one

Thanks
Isuru

The NPE occurs when spring-data-couchbase attempts to get the CAS from the query result.

It’s more-or-less the same issue.
The select needs to include __id and __cas.

SELECT META(#{n1ql.bucket}).id AS __id, META(#{n1ql.bucket}).cas AS __cas, name, code FROM …

There will be an easier way to do this in the future.

I tried the below but same error.

@Query(“SELECT META(#{#n1ql.bucket}).id AS __id, META(#{#n1ql.bucket}).cas AS __cas, name, code FROM #{#n1ql.bucket} WHERE #{#n1ql.filter} AND name = $1 ORDER BY name DESC”)
List findByNameProjection(String name);

I use the interface as per the spec for projection as below.
public interface ProjectDetailDto {
public String getCode();
public String getName();
}

Please check
Thanks
Isuru

They messed up something internally, you’ll get a nullpointer whenever you use “SELECT something” instead of #{#n1ql.selectEntity}. I’ve reported the same issue here

Spring boot 2.3 is also affected.

@TomLukman Thanks for your input.

@mreiche
In addition to the above I would like to draw your attention to the below scenario as well.

Lets say your entity A as below with a Field annotation
class A {
Field(“x”)
String y;
}
Then when I write a repository auto derived method as
public List findByY(String y)

Error is thrown at execution.Please see whether this is a bug or intended behaviour.

Thanks,
Isuru

What exception is thrown?
Please report issues here : https://github.com/spring-projects/spring-data-couchbase/issues

Lets say your entity A as below with a Field annotation
class A {
Field(“x”)
String y;
}
Then when I write a repository auto derived method as
public List findByY(String y)

Its returning empty results always.Isit the intended behaviour to have auto derived queries to work only when @Field(“tttt”) annotation is not present?

You are correct - this is broken right now. The property is saved as ‘x’ in couchbase, but the query is selecting on ‘y’.

Thanks @mreiche for creating the issue

@mreiche

I tested with SpringBoot 2.6.0-SNAPSHOT and couchbase 7 which is the most recent and there was springdatacouchbase 4.3.0-snapshot.jar.

Still The property is saved as ‘x’ in couchbase, but the query is selecting on ‘y’. issue exists.

May I know the springboot version if it is fixed or when it is fixed?

Still The property is saved as ‘x’ in couchbase, but the query is selecting on ‘y’. issue exists.

How are you determining it is selecting on ‘y’? Just because no result is being returned? Perhaps your find query method is not annotated with ScanConsistency(query=QueryScanConsistency.REQUEST_PLUS) ?

Fixed by DATACOUCH-1066 - Make QueryCriteria key a N1qlExpression. (#1082) · spring-projects/spring-data-couchbase@41ee1f9 · GitHub which is in

The tests for this are the following, middleName is

 @Field("nickname") private String middlename;
CouchbaseRepositoryQueryIntegrationTests
	@Test
	void annotatedFieldFind() {
		Person person = null;
		try {
			person = new Person(1, "first", "last");
			person.setMiddlename("Nick"); // middlename is stored as nickname
			personRepository.save(person);
			List<Person> persons2 = personRepository.findByMiddlename("Nick");
			assertEquals(1, persons2.size());
		} finally {
			personRepository.deleteById(person.getId().toString());
		}
	}
MappingCouchbaseConverterTests:
	@Test
	void createsQueryFieldAnnotationCorrectly() throws Exception {
		String input = "findByMiddlename";
		PartTree tree = new PartTree(input, Person.class);
		Method method = PersonRepository.class.getMethod(input, String.class);

		N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), "Oliver"), null, converter,
				bucketName);
		Query query = creator.createQuery();

		assertEquals(query.export(), " WHERE " + where(i("nickname")).is("Oliver").export());
	}

@mreiche
pubblic class Project {
@Id
private String _id;
private String name;
private String code;
@Field(“cost”)
private Long estimatedCost;

When I save the entity field is saved as cost.

But when I retrieve projectRepository.findById(id); extimatedCost field is NULL always.

This is with springdata couchbase 4.3.0-snapshot.jar.

Any explanation please? Is it because springboot '2.6.0-SNAPSHOT uses springdata couchbase 4.3.0-snapshot.jar.?Instead of 4 3 0 m1 or m2?

Ok - so this is different than
Still The property is saved as ‘x’ in couchbase, but the query is selecting on ‘y’. issue exists.
That was fixed in #1066 in N1qlQueryCreator. This is an issue with with the field not being deserialized. Can you please open an issue for that? There is an issue for queries, where the projection list contains the property getName() instead of getFieldName(), but that won’t manifest in KV (ById) queries.

Edit: I’ve created a new issue for n1ql queries. However, I cannot reproduce the issue with the KV api. fields renamed with Field(fieldName) annotation not deserialized in n1ql queries · Issue #1184 · spring-projects/spring-data-couchbase · GitHub

@mreiche
Yes it works fine with key value api.findById which uses keyvalue api works fine.But findAll which uses N1QL doesnot deserialize.Only N1QL doesnot deserialise properly.Issue 1184 covers that it seems.