Skip to content

Introduce first-class type-safe property path references at the core level#3409

Closed
mp911de wants to merge 2 commits intomainfrom
issue/3400
Closed

Introduce first-class type-safe property path references at the core level#3409
mp911de wants to merge 2 commits intomainfrom
issue/3400

Conversation

@mp911de
Copy link
Copy Markdown
Member

@mp911de mp911de commented Nov 17, 2025

We now support type-safe property paths and property references:

Java variants:

PropertyPath.from("name", Person.class) // existing String-based API
PropertyPath.of(Person::getName) // type-safe property reference expression

PropertyPath.from("address.country", Person.class) // existing nested path API
PropertyPath.of(Person::getAddress).then(Address::getCountry) // type-safe composed path expression


PropertyReference.of(Secret::getSecret)

Kotlin variants:

PropertyReference.of(Secret::secret)

PropertyPath.of(Person::address / Address::city)

allowing type-safe usage through e.g.:

Sort.by(Person::getFirstName, Person::getLastName)

Module adoption:

Copy link
Copy Markdown
Contributor

@schauder schauder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. I left a few nitpicks.

I didn't look into actually using it, since it seems Christoph already did that.
Let me know if I should take it for a spin as well.

This chapter covers the concept of property paths.
Property paths are a form of navigation through domain classes to apply certain aspects in the context of interacting with the model.
Application code provides property paths to data access components to express intents such as selection of properties within a query, forming predicates, or applying sorting.
A property path originates from its owning type and can consist of one to many segments.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"one to many segments"

I know, I lost the fight before, but I still find it really weird, that we don't have zero length paths, referring to the a aggregate root itself.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A zero-length-path that would describe its object root isn't a property path.

* This method returns a resolved {@link PropertyReference} by introspecting the given method reference.
*
* @param property the method reference to a Java beans property.
* @param <T> owning type.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we improve readability a little by using something more mnemonic than T? Or am I missing something?

O for Orgin or Owner.
R for Root
S for Source

Applies also for TypedPropertyPath

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T is a short variant for Type in alignment with Optional<T>, Function<T> and the like. O for the owner seems an okay match as well.

@Contract("_ -> new")
@CheckReturnValue
default <T> ExampleMatcher withIgnorePaths(TypedPropertyPath<T, ?>... ignoredPaths) {
return withIgnorePaths(Arrays.stream(ignoredPaths).map(TypedPropertyPath::of).map(TypedPropertyPath::toDotPath)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we mapping it explicitly to TypedPropertyPath? This happens already in the getSegment called inside toDotPath.

If this is for performance reasons (just guessing) we should add a comment to that effect .

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern appears a couple of times.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Initially, that was a fix for performance reasons. Default property path methods now handle of(this) themselves so the wrapping isn't necessary anymore.

*
* @author Mark Paluch
*/
class PropertyPathTck {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused by the name TCK. This seems more like a PropertyPathTestSupport.

From a TCK I would expect that it actually forces you to provide certain propertyPaths.
Maybe as a Map from a String representation to the representation under test and then run a bunch of tests against these, and failing when expected paths aren't in the provided Map.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TCK is an abbreviation for test compatibility kit.

We now support type-safe property paths and property references:

Java variants:

PropertyPath.from("name", Person.class) // existing String-based API
PropertyPath.of(Person::getName) // type-safe property reference expression

PropertyPath.from("address.country", Person.class) // existing nested path API
PropertyPath.of(Person::getAddress).then(Address::getCountry) // type-safe composed path expression

PropertyReference.of(Secret::getSecret)

Kotlin variants:

PropertyReference.of(Secret::secret)

PropertyPath.of(Person::address / Address::city)

allowing type-safe usage through e.g.:

Sort.by(Person::getFirstName, Person::getLastName)

Closes #3400
christophstrobl pushed a commit that referenced this pull request Jan 29, 2026
We now support type-safe property paths and property references:

Java variants:

PropertyPath.from("name", Person.class) // existing String-based API
PropertyPath.of(Person::getName) // type-safe property reference expression

PropertyPath.from("address.country", Person.class) // existing nested path API
PropertyPath.of(Person::getAddress).then(Address::getCountry) // type-safe composed path expression

PropertyReference.of(Secret::getSecret)

Kotlin variants:

PropertyReference.of(Secret::secret)

PropertyPath.of(Person::address / Address::city)

allowing type-safe usage through e.g.:

Sort.by(Person::getFirstName, Person::getLastName)

Closes: #3400
Original Pull Request: #3409
christophstrobl added a commit that referenced this pull request Jan 29, 2026
Original Pull Request: #3409
@christophstrobl christophstrobl deleted the issue/3400 branch January 29, 2026 08:36
mp911de added a commit that referenced this pull request Jan 29, 2026
We now properly implement resolution and delegation for raw paths not requiring TypedPropertyPath.of(…) usage at the call site.

See: #3400
Original Pull Request: #3409
mp911de added a commit that referenced this pull request Jan 29, 2026
We now properly implement resolution and delegation for raw paths not requiring TypedPropertyPath.of(…) usage at the call site.

See: #3400
Original Pull Request: #3409
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: enhancement A general enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce first-class type-safe property path references at the core level

4 participants