Skip to content

Commit cf005d9

Browse files
vaadin-botArtur-
andauthored
fix: set NullHandling to native when sorting (#2999) (CP: 24.6) (#3018)
fix: set NullHandling to native when sorting (#2999) Without this, I see an exception for all sort requests ``` Caused by: java.lang.UnsupportedOperationException: Applying Null Precedence using Criteria Queries is not yet supported. at org.springframework.data.jpa.repository.query.QueryUtils.toJpaOrder(QueryUtils.java:757) ~[spring-data-jpa-3.4.0.jar:3.4.0] at org.springframework.data.jpa.repository.query.QueryUtils.toOrders(QueryUtils.java:706) ~[spring-data-jpa-3.4.0.jar:3.4.0] at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:756) ~[spring-data-jpa-3.4.0.jar:3.4.0] at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:714) ~[spring-data-jpa-3.4.0.jar:3.4.0] at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:448) ~[spring-data-jpa-3.4.0.jar:3.4.0] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359) ~[spring-aop-6.2.0.jar:6.2.0] at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:515) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:284) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:752) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:174) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:149) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0] at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:69) ~[spring-data-commons-3.4.0.jar:3.4.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0] at org.springframewo ``` Related to spring-projects/spring-data-jpa#3529 Co-authored-by: Artur <[email protected]>
1 parent d2e84ca commit cf005d9

File tree

3 files changed

+44
-17
lines changed

3 files changed

+44
-17
lines changed

packages/ts/react-crud/src/data-provider.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { CountService, ListService } from './crud';
55
import type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion';
66
import type Sort from './types/com/vaadin/hilla/mappedtypes/Sort';
77
import Direction from './types/org/springframework/data/domain/Sort/Direction';
8+
import NullHandling from './types/org/springframework/data/domain/Sort/NullHandling';
89

910
type MaybeCountService<TItem> = Partial<CountService<TItem>>;
1011
type ListAndMaybeCountService<TItem> = ListService<TItem> & MaybeCountService<TItem>;
@@ -42,6 +43,7 @@ function createSort<TItem>(params: GridDataProviderParams<TItem>): Sort {
4243
property: order.path,
4344
direction: order.direction === 'asc' ? Direction.ASC : Direction.DESC,
4445
ignoreCase: false,
46+
nullHandling: NullHandling.NATIVE,
4547
})),
4648
};
4749
}

packages/ts/react-crud/test/autogrid.spec.tsx

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Matcher from '../src/types/com/vaadin/hilla/crud/filter/PropertyStringFil
1717
import type PropertyStringFilter from '../src/types/com/vaadin/hilla/crud/filter/PropertyStringFilter.js';
1818
import type Sort from '../src/types/com/vaadin/hilla/mappedtypes/Sort.js';
1919
import Direction from '../src/types/org/springframework/data/domain/Sort/Direction.js';
20+
import NullHandling from '../src/types/org/springframework/data/domain/Sort/NullHandling.js';
2021
import type FilterUnion from '../types/com/vaadin/hilla/crud/filter/FilterUnion';
2122
import GridController from './GridController.js';
2223
import SelectController from './SelectController.js';
@@ -138,7 +139,11 @@ describe('@vaadin/hilla-react-crud', () => {
138139
const service = personService();
139140
const grid = await GridController.init(render(<TestAutoGridNoHeaderFilters service={service} />), user);
140141

141-
const expectedSort: Sort = { orders: [{ property: 'firstName', direction: Direction.ASC, ignoreCase: false }] };
142+
const expectedSort: Sort = {
143+
orders: [
144+
{ property: 'firstName', direction: Direction.ASC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
145+
],
146+
};
142147
expect(service.lastSort).to.deep.equal(expectedSort);
143148
await expect(grid.getSortOrder()).to.eventually.deep.equal([
144149
{ property: 'firstName', direction: Direction.ASC },
@@ -166,7 +171,9 @@ describe('@vaadin/hilla-react-crud', () => {
166171
await grid.sort('firstName', 'desc');
167172

168173
const expectedSort: Sort = {
169-
orders: [{ property: 'firstName', direction: Direction.DESC, ignoreCase: false }],
174+
orders: [
175+
{ property: 'firstName', direction: Direction.DESC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
176+
],
170177
};
171178
expect(service.lastSort).to.deep.equal(expectedSort);
172179
await expect(grid.getSortOrder()).to.eventually.deep.equal([
@@ -490,9 +497,12 @@ describe('@vaadin/hilla-react-crud', () => {
490497
});
491498

492499
it('sorts according to first column by default', async () => {
493-
expect(service.lastSort).to.deep.equal({
494-
orders: [{ property: 'firstName', direction: Direction.ASC, ignoreCase: false }],
495-
});
500+
const expectedSort = {
501+
orders: [
502+
{ property: 'firstName', direction: Direction.ASC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
503+
],
504+
};
505+
expect(service.lastSort).to.deep.equal(expectedSort);
496506

497507
await expect(grid.getSortOrder()).to.eventually.deep.equal([
498508
{ property: 'firstName', direction: Direction.ASC },
@@ -503,8 +513,8 @@ describe('@vaadin/hilla-react-crud', () => {
503513
await grid.sort('lastName', 'asc');
504514
expect(service.lastSort).to.deep.equal({
505515
orders: [
506-
{ property: 'firstName', direction: Direction.ASC, ignoreCase: false },
507-
{ property: 'lastName', direction: Direction.ASC, ignoreCase: false },
516+
{ property: 'firstName', direction: Direction.ASC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
517+
{ property: 'lastName', direction: Direction.ASC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
508518
],
509519
});
510520

@@ -516,8 +526,8 @@ describe('@vaadin/hilla-react-crud', () => {
516526
await grid.sort('lastName', 'desc');
517527
expect(service.lastSort).to.deep.equal({
518528
orders: [
519-
{ property: 'firstName', direction: Direction.ASC, ignoreCase: false },
520-
{ property: 'lastName', direction: Direction.DESC, ignoreCase: false },
529+
{ property: 'firstName', direction: Direction.ASC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
530+
{ property: 'lastName', direction: Direction.DESC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
521531
],
522532
});
523533

@@ -528,7 +538,9 @@ describe('@vaadin/hilla-react-crud', () => {
528538

529539
await grid.sort('lastName', null);
530540
expect(service.lastSort).to.deep.equal({
531-
orders: [{ property: 'firstName', direction: Direction.ASC, ignoreCase: false }],
541+
orders: [
542+
{ property: 'firstName', direction: Direction.ASC, ignoreCase: false, nullHandling: NullHandling.NATIVE },
543+
],
532544
});
533545

534546
await expect(grid.getSortOrder()).to.eventually.deep.equal([

packages/ts/react-crud/test/dataprovider.spec.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import type { GridDataProvider, GridSorterDefinition } from '@vaadin/react-compo
44
import sinon from 'sinon';
55
import sinonChai from 'sinon-chai';
66
import type { CountService, ListService } from '../crud.js';
7-
import { DataProvider } from '../src/data-provider.js';
87
import {
98
createDataProvider,
9+
DataProvider,
1010
FixedSizeDataProvider,
1111
InfiniteDataProvider,
1212
useDataProvider,
1313
type ItemCounts,
1414
} from '../src/data-provider.js';
15+
import NullHandling from '../src/types/org/springframework/data/domain/Sort/NullHandling.js';
1516
import type AndFilter from '../types/com/vaadin/hilla/crud/filter/AndFilter.js';
1617
import type FilterUnion from '../types/com/vaadin/hilla/crud/filter/FilterUnion.js';
1718
import Matcher from '../types/com/vaadin/hilla/crud/filter/PropertyStringFilter/Matcher.js';
@@ -203,11 +204,15 @@ describe('@hilla/react-crud', () => {
203204

204205
await grid.requestPage(0, [{ path: 'foo', direction: 'asc' }]);
205206
pageable = listSpy.lastCall.args[0];
206-
expect(pageable.sort).to.eql({ orders: [{ property: 'foo', direction: 'ASC', ignoreCase: false }] });
207+
expect(pageable.sort).to.eql({
208+
orders: [{ property: 'foo', direction: 'ASC', ignoreCase: false, nullHandling: NullHandling.NATIVE }],
209+
});
207210

208211
await grid.requestPage(0, [{ path: 'bar', direction: 'desc' }]);
209212
pageable = listSpy.lastCall.args[0];
210-
expect(pageable.sort).to.eql({ orders: [{ property: 'bar', direction: 'DESC', ignoreCase: false }] });
213+
expect(pageable.sort).to.eql({
214+
orders: [{ property: 'bar', direction: 'DESC', ignoreCase: false, nullHandling: NullHandling.NATIVE }],
215+
});
211216
});
212217

213218
it('utilizes count from listAndCountService and call it only once', async () => {
@@ -308,11 +313,15 @@ describe('@hilla/react-crud', () => {
308313

309314
await grid.requestPage(0, [{ path: 'foo', direction: 'asc' }]);
310315
pageable = listSpy.lastCall.args[0];
311-
expect(pageable.sort).to.eql({ orders: [{ property: 'foo', direction: 'ASC', ignoreCase: false }] });
316+
expect(pageable.sort).to.eql({
317+
orders: [{ property: 'foo', direction: 'ASC', ignoreCase: false, nullHandling: NullHandling.NATIVE }],
318+
});
312319

313320
await grid.requestPage(0, [{ path: 'bar', direction: 'desc' }]);
314321
pageable = listSpy.lastCall.args[0];
315-
expect(pageable.sort).to.eql({ orders: [{ property: 'bar', direction: 'DESC', ignoreCase: false }] });
322+
expect(pageable.sort).to.eql({
323+
orders: [{ property: 'bar', direction: 'DESC', ignoreCase: false, nullHandling: NullHandling.NATIVE }],
324+
});
316325
});
317326

318327
it('passes filter to service', async () => {
@@ -438,11 +447,15 @@ describe('@hilla/react-crud', () => {
438447

439448
await grid.requestPage(0, [{ path: 'foo', direction: 'asc' }]);
440449
pageable = listSpy.lastCall.args[0];
441-
expect(pageable.sort).to.eql({ orders: [{ property: 'foo', direction: 'ASC', ignoreCase: false }] });
450+
expect(pageable.sort).to.eql({
451+
orders: [{ property: 'foo', direction: 'ASC', ignoreCase: false, nullHandling: NullHandling.NATIVE }],
452+
});
442453

443454
await grid.requestPage(0, [{ path: 'bar', direction: 'desc' }]);
444455
pageable = listSpy.lastCall.args[0];
445-
expect(pageable.sort).to.eql({ orders: [{ property: 'bar', direction: 'DESC', ignoreCase: false }] });
456+
expect(pageable.sort).to.eql({
457+
orders: [{ property: 'bar', direction: 'DESC', ignoreCase: false, nullHandling: NullHandling.NATIVE }],
458+
});
446459
});
447460

448461
it('passes filter to service', async () => {

0 commit comments

Comments
 (0)