Skip to content

Add enum and number values support to JsonKeysetCursorStrategy#1346

Closed
stupid58fly wants to merge 1 commit intospring-projects:mainfrom
stupid58fly:feature/add-enum-and-number-support-for-json-keyset-cursor-strategy
Closed

Add enum and number values support to JsonKeysetCursorStrategy#1346
stupid58fly wants to merge 1 commit intospring-projects:mainfrom
stupid58fly:feature/add-enum-and-number-support-for-json-keyset-cursor-strategy

Conversation

@stupid58fly
Copy link
Copy Markdown
Contributor

same issue as at #1327 for enum and numeric values exept integer and double

Signed-off-by: Ilya Bakaev <stupid58fly@gmail.com>
@bclozel
Copy link
Copy Markdown
Member

bclozel commented Oct 23, 2025

Hello @stupid58fly

We're considering both this issue and #1347.

Could you first elaborate a bit on the exact problem you're seeing? How do your entities/repositories/data fetchers look like in your code and what error are you hitting exactly? We don't need a complete analysis of the problem, but rather a short sample or anything that can help us better understand the use case would be welcome.

@bclozel bclozel added the status: waiting-for-feedback We need additional information before we can continue label Oct 23, 2025
@stupid58fly
Copy link
Copy Markdown
Contributor Author

Hello @stupid58fly

We're considering both this issue and #1347.

Could you first elaborate a bit on the exact problem you're seeing? How do your entities/repositories/data fetchers look like in your code and what error are you hitting exactly? We don't need a complete analysis of the problem, but rather a short sample or anything that can help us better understand the use case would be welcome.

i have

@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private BigDecimal cost;
}
public interface ProductRepository extends JpaRepository<Product, Long> {
    Window<Product> findByIdIsNotNull(ScrollPosition position, Sort sort, Limit limit);
}
@Controller
@RequiredArgsConstructor
public class ProductController {
    private final ProductRepository productRepository;

    @QueryMapping
    public Window<Product> products(ScrollSubrange scrollSubrange) {
        var position = scrollSubrange.position().orElseGet(ScrollPosition::keyset);
        var sort = Sort.by(Sort.Direction.ASC, "cost");
        var limit = scrollSubrange.count().stream().boxed().findFirst().map(Limit::of).orElseGet(Limit::unlimited);

        return productRepository.findByIdIsNotNull(position, sort, limit);
    }
}

when i try to fetch products without parameters, all is ok
but when i try to load products after keyset possition, i have following exception

query MyQuery {
  products (
    after: "S19bImphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVNYXAiLHsiaWQiOlsiamF2YS5sYW5nLkxvbmciLDIwXSwiY29zdCI6WyJqYXZhLm1hdGguQmlnRGVjaW1hbCIsMC4wMF19XQ=="
    first: 10
  ) {
    pageInfo {
      endCursor
      hasNextPage
      hasPreviousPage
      startCursor
    }
    edges {
      cursor
      node {
        cost
        id
        name
      }
    }
  }
}
2025-10-26T16:19:03.490+01:00 ERROR 9232 --- [nio-8080-exec-9] s.g.e.ExceptionResolversExceptionHandler : Unresolved IllegalArgumentException for executionId 44c28386-8a40-d677-dc47-466eda0a8ede

java.lang.IllegalArgumentException: Failed to parse cursor: K_["java.util.Collections$UnmodifiableMap",{"id":["java.lang.Long",20],"cost":["java.math.BigDecimal",0.00]}]
	at org.springframework.graphql.data.query.ScrollPositionCursorStrategy.fromCursor(ScrollPositionCursorStrategy.java:92) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.query.ScrollPositionCursorStrategy.fromCursor(ScrollPositionCursorStrategy.java:34) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.pagination.EncodingCursorStrategy.fromCursor(EncodingCursorStrategy.java:77) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.method.annotation.support.SubrangeMethodArgumentResolver.resolveArgument(SubrangeMethodArgumentResolver.java:66) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.method.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:83) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.method.annotation.support.DataFetcherHandlerMethodSupport.getMethodArgumentValues(DataFetcherHandlerMethodSupport.java:92) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.method.annotation.support.DataFetcherHandlerMethod.invoke(DataFetcherHandlerMethod.java:118) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.method.annotation.support.DataFetcherHandlerMethod.invoke(DataFetcherHandlerMethod.java:103) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.method.annotation.support.AnnotatedControllerConfigurer$SchemaMappingDataFetcher.get(AnnotatedControllerConfigurer.java:521) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.pagination.ConnectionFieldTypeVisitor$ConnectionDataFetcher.get(ConnectionFieldTypeVisitor.java:213) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.execution.ContextDataFetcherDecorator.lambda$get$0(ContextDataFetcherDecorator.java:92) ~[spring-graphql-1.4.2.jar:1.4.2]
...
Caused by: org.springframework.core.codec.DecodingException: JSON decoding error: Could not resolve type id 'java.lang.Long' as a subtype of `java.lang.Object`: Configured `PolymorphicTypeValidator` (of type `com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator`) denied resolution
	at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:282) ~[spring-web-6.2.11.jar:6.2.11]
	at org.springframework.http.codec.json.AbstractJackson2Decoder.decode(AbstractJackson2Decoder.java:218) ~[spring-web-6.2.11.jar:6.2.11]
	at org.springframework.graphql.data.query.JsonKeysetCursorStrategy.fromCursor(JsonKeysetCursorStrategy.java:131) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.query.JsonKeysetCursorStrategy.fromCursor(JsonKeysetCursorStrategy.java:55) ~[spring-graphql-1.4.2.jar:1.4.2]
	at org.springframework.graphql.data.query.ScrollPositionCursorStrategy.fromCursor(ScrollPositionCursorStrategy.java:87) ~[spring-graphql-1.4.2.jar:1.4.2]
	... 81 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'java.lang.Long' as a subtype of `java.lang.Object`: Configured `PolymorphicTypeValidator` (of type `com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator`) denied resolution
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 66] (through reference chain: java.util.LinkedHashMap["id"])
	at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43) ~[jackson-databind-2.19.2.jar:2.19.2]
	at com.fasterxml.jackson.databind.DeserializationContext.invalidTypeIdException(DeserializationContext.java:2068) ~[jackson-databind-2.19.2.jar:2.19.2]
	at com.fasterxml.jackson.databind.DatabindContext._throwSubtypeClassNotAllowed(DatabindContext.java:302) ~[jackson-databind-2.19.2.jar:2.19.2]
	at com.fasterxml.jackson.databind.DatabindContext.resolveAndValidateSubType(DatabindContext.java:259) ~[jackson-databind-2.19.2.jar:2.19.2]
	at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver._typeFromId(ClassNameIdResolver.java:128) ~[jackson-databind-2.19.2.jar:2.19.2]
	at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:111) ~[jackson-databind-2.19.2.jar:2.19.2]
	at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:158) ~[jackson-databind-2.19.2.jar:2.19.2]
	at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:99) ~[jackson-databind-2.19.2.jar:2.19.2]

and this PR will fix the issue with deserialization for number (long, big decimal, etc) and enums

the issue #1347 is aimed for a more general fix, i.e. for @Embeddable, @Lob, etc

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Oct 26, 2025
@stupid58fly
Copy link
Copy Markdown
Contributor Author

Hi @bclozel,
Is any additional actions required from my side?

@bclozel bclozel self-assigned this Jan 8, 2026
@bclozel bclozel added type: enhancement A general enhancement in: data Issues related to working with data and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels Jan 8, 2026
@bclozel bclozel added this to the 2.0.2 milestone Jan 8, 2026
bclozel pushed a commit that referenced this pull request Jan 8, 2026
This commit adds JSON serialization support for Java Enums and Number
types in keyset cursors.

See gh-1346

Signed-off-by: Ilya Bakaev <stupid58fly@gmail.com>
@bclozel bclozel closed this in d37b2d6 Jan 8, 2026
@bclozel
Copy link
Copy Markdown
Member

bclozel commented Jan 8, 2026

Thanks for your contribution @stupid58fly , this is now merged in main and will be released this month.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: data Issues related to working with data type: enhancement A general enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants