Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PropertyAccessingMethodInterceptor fails with IllegalStateException when target method is bridged #3215

Closed
sivaprasadreddy opened this issue Dec 1, 2024 · 2 comments
Assignees
Labels
type: bug A general bug

Comments

@sivaprasadreddy
Copy link

I have used Spring Data JPA DTO interface-based projection many times and it worked just fine.
But yesterday I came across an interesting issue that is happening only under certain specific combination such as follows:

I have a BaseEntity as follows:

@MappedSuperclass
class BaseEntity {
    @Column(name = "created_at")
    protected LocalDateTime createdAt;

    @PrePersist
    void prePersist() {
        createdAt = LocalDateTime.now();
    }
    //setter & getter
}

I have a JPA entity Post extending BaseEntity class as follows:

@Entity
@Table(name = "posts")
public class Post extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "title", nullable = false, length = 150)
    private String title;

    @Column(name = "slug", nullable = false, unique = true)
    private String slug;

    @Column(name = "content", nullable = false)
    private String content;

    //setters & getters
}

I have created a Interface Projections as follows:

public interface PostProjection {
    Long getId();
    String getTitle();
    String getSlug();
    String getContent();
    LocalDateTime getCreatedAt();
}

Now I have PostRepository as follows:

public interface PostRepository extends JpaRepository<Post, Long> {
    List<PostProjection> findAllBy();

    @Query("from Post")
    List<PostProjection> findAllPosts();
}

The problem: When I get List<PostProjection> by calling postRepository.findAllBy(), everything is working fine. But when I get List<PostProjection> by calling postRepository.findAllPosts() and then try to access postProjection.getCreatedAt() method then it is throwing the following Exception:

**java.lang.IllegalStateException: Invoked method is not a property accessor**
	at org.springframework.data.projection.PropertyAccessingMethodInterceptor.invoke(PropertyAccessingMethodInterceptor.java:66) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:71) ~[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.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:243) ~[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.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223) ~[spring-aop-6.2.0.jar:6.2.0]
	at jdk.proxy2/jdk.proxy2.$Proxy123.getCreatedAt(Unknown Source) ~[na:na]

Observations:

  • This Exception is occurring only when I access methods from super class(BaseEntity)
  • This Exception is occurring only when I use @Query("...")

Here is a minimal reproducer: https://github.com/siva-attic/spring-data-jpa-projection-issue

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Dec 1, 2024
@mp911de
Copy link
Member

mp911de commented Dec 2, 2024

This is an interesting effect of mixed visibilities. BaseEntity is package-protected, Post is public. When we look up the target method (method with arguments on the target type Post), we get returned Post.getCreatedAt().

Looking at the byte code, the compiler generates a bridge synthetic method to invoke its parent's getCreatedAt() method.

Interestingly, if we align visibilities (all public or all package-private), the target method resolves to BaseEntity.getCreatedAt() as the compiler no longer generates a bridge synthetic method.

I think we could filter synthetic methods if we walk the inheritance tree to mitigate the issue.

@mp911de mp911de added type: bug A general bug for: team-attention An issue we need to discuss as a team to make progress status: waiting-for-triage An issue we've not yet triaged and removed status: waiting-for-triage An issue we've not yet triaged labels Dec 2, 2024
@quaff
Copy link
Contributor

quaff commented Dec 2, 2024

Duplicate of #3159

@mp911de mp911de changed the title Spring Data JPA DTO Projection is failing only when using a MappedSuperClass with custom finder using @Query PropertyAccessingMethodInterceptor fails with IllegalStateException when target method is bridged Dec 2, 2024
@mp911de mp911de self-assigned this Dec 2, 2024
@mp911de mp911de removed status: waiting-for-triage An issue we've not yet triaged for: team-attention An issue we need to discuss as a team to make progress labels Dec 2, 2024
@mp911de mp911de added this to the 3.3.7 (2024.0.7) milestone Dec 2, 2024
@mp911de mp911de transferred this issue from spring-projects/spring-data-jpa Dec 2, 2024
mp911de added a commit that referenced this issue Dec 2, 2024
…a bridge method.

We now skip synthetic bridge methods when resolving a PropertyDescriptor from a called interface method on the target type and resolve the bridged method.

Closes #3215
@mp911de mp911de closed this as completed in b2c3623 Dec 2, 2024
mp911de added a commit that referenced this issue Dec 2, 2024
…a bridge method.

We now skip synthetic bridge methods when resolving a PropertyDescriptor from a called interface method on the target type and resolve the bridged method.

Closes #3215
mp911de added a commit that referenced this issue Dec 2, 2024
Fix ticket reference.

See #3215
mp911de added a commit that referenced this issue Dec 2, 2024
Fix ticket reference.

See #3215
mp911de added a commit that referenced this issue Dec 2, 2024
Fix ticket reference.

See #3215
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants