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

Interface projection with native query not working for boolean (mysql) [DATACMNS-1695] #2290

Closed
spring-projects-issues opened this issue Apr 1, 2020 · 3 comments
Assignees
Labels
type: task

Comments

@spring-projects-issues
Copy link

spring-projects-issues commented Apr 1, 2020

Michal Ondrovic opened DATACMNS-1695 and commented

Simplified test case:

Projection interface:

public interface TestDto {
 Long getId();
 Boolean getTest();
}

Query with projection:

@Query(value = "select 1 id, true test", nativeQuery = true)
List<TestDto> test();

Boolean property "test" is not recognized as Boolean but as Byte. Calling getTest() throws this exception:

java.lang.IllegalArgumentException: Projection type must be an interface!

The projection is working if the boolean field is selected directly from a table, but not, when the field is "calculated".

More workarounds are possible, in my case change "Boolean getTest()" to "Byte getTest()" is the best


Affects: 2.2.6 (Moore SR6)

@mp911de mp911de transferred this issue from spring-projects/spring-data-commons Jan 26, 2021
@mp911de mp911de assigned mp911de and unassigned odrotbohm Jan 26, 2021
@mp911de
Copy link
Member

mp911de commented Feb 1, 2021

We should improve the error message to report the actual issue. We don't want to make any assumptions over Byte to Boolean conversion as one could use -1, 0, or 1 as true and we don't want to get into that business. Another approach to make it work, you could cast the value into a type that is reported by the driver to Java boolean (or one that can be safely converted to Boolean).

@mp911de
Copy link
Member

mp911de commented Feb 2, 2021

Stack trace:

java.lang.IllegalArgumentException: Projection type must be an interface!
	at org.springframework.util.Assert.isTrue(Assert.java:121) ~[spring-core-5.3.4-20210202.131018-48.jar:5.3.4-SNAPSHOT]
	at org.springframework.data.projection.ProxyProjectionFactory.createProjection(ProxyProjectionFactory.java:108) ~[spring-data-commons-2.5.0-20210202.135327-181.jar:2.5.0-SNAPSHOT]
	at org.springframework.data.projection.SpelAwareProxyProjectionFactory.createProjection(SpelAwareProxyProjectionFactory.java:45) ~[spring-data-commons-2.5.0-20210202.135327-181.jar:2.5.0-SNAPSHOT]
	at org.springframework.data.projection.ProjectingMethodInterceptor.getProjection(ProjectingMethodInterceptor.java:160) ~[spring-data-commons-2.5.0-20210202.135327-181.jar:2.5.0-SNAPSHOT]
	at org.springframework.data.projection.ProjectingMethodInterceptor.potentiallyConvertResult(ProjectingMethodInterceptor.java:108) ~[spring-data-commons-2.5.0-20210202.135327-181.jar:2.5.0-SNAPSHOT]
	at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:85) ~[spring-data-commons-2.5.0-20210202.135327-181.jar:2.5.0-SNAPSHOT]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.4-20210202.131018-48.jar:5.3.4-SNAPSHOT]
	at org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:253) ~[spring-data-commons-2.5.0-20210202.135327-181.jar:2.5.0-SNAPSHOT]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.4-20210202.131018-48.jar:5.3.4-SNAPSHOT]
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.5.0-20210202.135327-181.jar:2.5.0-SNAPSHOT]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.4-20210202.131018-48.jar:5.3.4-SNAPSHOT]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.4-20210202.131018-48.jar:5.3.4-SNAPSHOT]

The offending value is BigInteger. We could throw an exception that we cannot return the value or create a projection for the value %s of type %s that should be returned as %s.

@mp911de
Copy link
Member

mp911de commented Feb 2, 2021

Moving the issue back to Spring Data Commons as ProxyProjectionFactory comes from there.

@mp911de mp911de transferred this issue from spring-projects/spring-data-jpa Feb 2, 2021
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage label Feb 2, 2021
mp911de added a commit that referenced this issue Feb 2, 2021
…returned.

We now throw UnsupportedOperationException when a projected value cannot be returned because it cannot be brought into the target type, either via conversion or projection.

This exception improves the error message by avoiding throwing IllegalArgumentException: Projection type must be an interface from the last branch that falls back into projections.

Closes #2290.
@mp911de mp911de added type: task and removed status: waiting-for-triage labels Feb 2, 2021
christophstrobl pushed a commit that referenced this issue Feb 9, 2021
…returned.

We now throw UnsupportedOperationException when a projected value cannot be returned because it cannot be brought into the target type, either via conversion or projection.

This exception improves the error message by avoiding throwing IllegalArgumentException: Projection type must be an interface from the last branch that falls back into projections.

Closes #2290.
christophstrobl added a commit that referenced this issue Feb 9, 2021
Do not include the result value in the exception message to avoid data exposure.
Improve data flow to avoid superfluous null checks.

See #2290.
Original Pull Request: #2291.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: task
Projects
None yet
3 participants