ConstructorExpression with joined boolean parameter causes IllegalArgumentException #679

Closed
wrungel opened this Issue Mar 13, 2014 · 20 comments

Comments

Projects
None yet
4 participants
@wrungel

wrungel commented Mar 13, 2014

(Left-)Joining two entities with JPAQuery and using boolean property from the right joined entity causes IllegalArgumentException.

See test cases in https://github.com/wrungel/qdsl-bugs/tree/master/constructor-expression-boolean-bug
The following tests fails:

  • constructor_expression_with_joined_boolean_parameter()
  • nested_constructor_expression_with_joined_string_and_boolean_parameter()

Querydsl version: 3.3.1, 3.2.2
JPA Provider: Hibernate 4.2.8.Final, 4.1.5.Final
Database: h2, Oracle

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Mar 13, 2014

Member

Could you provide the full stacktrace?

Member

timowest commented Mar 13, 2014

Could you provide the full stacktrace?

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 13, 2014

Member

there is none, the JUnit runner catches the exception.

I think the argument count at construstor.newinstance() is mismatched, but I am not sure?

also, the exception has no stacktrace available, but I am looking into it.

Member

Shredder121 commented Mar 13, 2014

there is none, the JUnit runner catches the exception.

I think the argument count at construstor.newinstance() is mismatched, but I am not sure?

also, the exception has no stacktrace available, but I am looking into it.

@wrungel

This comment has been minimized.

Show comment
Hide comment
@wrungel

wrungel Mar 13, 2014

This is the output of the test method constructor_expression_with_joined_boolean_parameter:

10:24:22,195 DEBUG SQL:104 - insert into Video (id, book_id) values (null, ?)
10:24:22,364 DEBUG SQL:104 - select video0_.id as col_0_0_, book1_.good as col_1_0_ from Video video0_ left outer join Book book1_ on video0_.book_id=book1_.id

java.lang.IllegalArgumentException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysema.query.types.ConstructorExpression.newInstance(ConstructorExpression.java:173)
    at com.mysema.query.jpa.FactoryExpressionTransformer.transformTuple(FactoryExpressionTransformer.java:50)
    at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:95)
    at org.hibernate.loader.hql.QueryLoader.getResultList(QueryLoader.java:463)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2364)
    at org.hibernate.loader.Loader.list(Loader.java:2359)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:495)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:357)
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1194)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:268)
    at com.mysema.query.jpa.impl.AbstractJPAQuery.getResultList(AbstractJPAQuery.java:196)
    at com.mysema.query.jpa.impl.AbstractJPAQuery.list(AbstractJPAQuery.java:244)
    at frol.querydsl.ConstructorExpressionWithJoinedBooleanTest.constructor_expression_with_joined_boolean_parameter(ConstructorExpressionWithJoinedBooleanTest.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

wrungel commented Mar 13, 2014

This is the output of the test method constructor_expression_with_joined_boolean_parameter:

10:24:22,195 DEBUG SQL:104 - insert into Video (id, book_id) values (null, ?)
10:24:22,364 DEBUG SQL:104 - select video0_.id as col_0_0_, book1_.good as col_1_0_ from Video video0_ left outer join Book book1_ on video0_.book_id=book1_.id

java.lang.IllegalArgumentException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysema.query.types.ConstructorExpression.newInstance(ConstructorExpression.java:173)
    at com.mysema.query.jpa.FactoryExpressionTransformer.transformTuple(FactoryExpressionTransformer.java:50)
    at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:95)
    at org.hibernate.loader.hql.QueryLoader.getResultList(QueryLoader.java:463)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2364)
    at org.hibernate.loader.Loader.list(Loader.java:2359)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:495)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:357)
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1194)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:268)
    at com.mysema.query.jpa.impl.AbstractJPAQuery.getResultList(AbstractJPAQuery.java:196)
    at com.mysema.query.jpa.impl.AbstractJPAQuery.list(AbstractJPAQuery.java:244)
    at frol.querydsl.ConstructorExpressionWithJoinedBooleanTest.constructor_expression_with_joined_boolean_parameter(ConstructorExpressionWithJoinedBooleanTest.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 13, 2014

Member

the book.good argument is null. with a book entity attached to the video it is resolved.

@wrungel can you confirm this? ( see my pull request (edit, my fork)

Member

Shredder121 commented Mar 13, 2014

the book.good argument is null. with a book entity attached to the video it is resolved.

@wrungel can you confirm this? ( see my pull request (edit, my fork)

@wrungel

This comment has been minimized.

Show comment
Hide comment
@wrungel

wrungel Mar 13, 2014

@Shredder121 The argument count is OK. The problem is the type of the argument. It fails if the type is boolean and it comes from the right table,

wrungel commented Mar 13, 2014

@Shredder121 The argument count is OK. The problem is the type of the argument. It fails if the type is boolean and it comes from the right table,

@wrungel

This comment has been minimized.

Show comment
Hide comment
@wrungel

wrungel Mar 13, 2014

@Shredder121 I confirm, that attaching a book to the videoresolves the problem.
I added a new test method for this case: book_attached_to_video_and_constructor_expr_with_joined_boolean_param, see:
https://github.com/wrungel/qdsl-bugs/blob/master/constructor-expression-boolean-bug/src/test/java/frol/querydsl/ConstructorExpressionWithJoinedBooleanTest.java

wrungel commented Mar 13, 2014

@Shredder121 I confirm, that attaching a book to the videoresolves the problem.
I added a new test method for this case: book_attached_to_video_and_constructor_expr_with_joined_boolean_param, see:
https://github.com/wrungel/qdsl-bugs/blob/master/constructor-expression-boolean-bug/src/test/java/frol/querydsl/ConstructorExpressionWithJoinedBooleanTest.java

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 13, 2014

Member

According to the javadoc:
http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)

in the exceptions list it explicitly mentions if unwrapping of a primitive argument fails it throws an illegalargumentexception.
this is true with null values.
how should we overcome this?

Member

Shredder121 commented Mar 13, 2014

According to the javadoc:
http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)

in the exceptions list it explicitly mentions if unwrapping of a primitive argument fails it throws an illegalargumentexception.
this is true with null values.
how should we overcome this?

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Mar 13, 2014

Member

@wrungel @Shredder121 Maybe for the constructor invocation an array with default parameters for primitive arguments could be merged into the array for the call. Do you have better ideas?

Member

timowest commented Mar 13, 2014

@wrungel @Shredder121 Maybe for the constructor invocation an array with default parameters for primitive arguments could be merged into the array for the call. Do you have better ideas?

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 13, 2014

Member

what default parameters were you thinking of?

Member

Shredder121 commented Mar 13, 2014

what default parameters were you thinking of?

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Mar 13, 2014

Member

Zero values for numbers and false for boolean
On 13 Mar 2014 17:05, "Ruben Dijkstra" notifications@github.com wrote:

what default parameters were you thinking of?

Reply to this email directly or view it on GitHubhttps://github.com/mysema/querydsl/issues/679#issuecomment-37543545
.

Member

timowest commented Mar 13, 2014

Zero values for numbers and false for boolean
On 13 Mar 2014 17:05, "Ruben Dijkstra" notifications@github.com wrote:

what default parameters were you thinking of?

Reply to this email directly or view it on GitHubhttps://github.com/mysema/querydsl/issues/679#issuecomment-37543545
.

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 13, 2014

Member

What about String literals? Are they affected?(just wondering)

(edit: nevermind the complex objects, they initially are a collection of primitives.
but don't you think that there should be a null placeholder?
nested objects that are created with data that is not quite right might be strange.)

Member

Shredder121 commented Mar 13, 2014

What about String literals? Are they affected?(just wondering)

(edit: nevermind the complex objects, they initially are a collection of primitives.
but don't you think that there should be a null placeholder?
nested objects that are created with data that is not quite right might be strange.)

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Mar 13, 2014

Member

What about String literals? Are they affected?(just wondering)

String literals are not primitives, so no problem with them.

(edit: nevermind the complex objects, they initially are a collection of primitives. but don't you think that there should be a null placeholder? nested objects that are created with data that is not quite right might be strange.)

That is a good question. Maybe for both bean population and constructor invocation there could be variants that return null if all the arguments are null?

Member

timowest commented Mar 13, 2014

What about String literals? Are they affected?(just wondering)

String literals are not primitives, so no problem with them.

(edit: nevermind the complex objects, they initially are a collection of primitives. but don't you think that there should be a null placeholder? nested objects that are created with data that is not quite right might be strange.)

That is a good question. Maybe for both bean population and constructor invocation there could be variants that return null if all the arguments are null?

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 13, 2014

Member

the only thing I can think of right now is one constructor that is null-aware and accepts a map of member names mapped to the value.
but that doesn't sound pretty.

Member

Shredder121 commented Mar 13, 2014

the only thing I can think of right now is one constructor that is null-aware and accepts a map of member names mapped to the value.
but that doesn't sound pretty.

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 15, 2014

Member

what if the codegen module uses the boxed version of the primitives?

Member

Shredder121 commented Mar 15, 2014

what if the codegen module uses the boxed version of the primitives?

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Mar 15, 2014

Member

The codegen module will always use the boxed version of the primitives, the types are taken via reflection from the constructor.

Member

timowest commented Mar 15, 2014

The codegen module will always use the boxed version of the primitives, the types are taken via reflection from the constructor.

@timowest timowest added fixed and removed fixed labels Mar 20, 2014

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Mar 20, 2014

Member

@wrungel or @Shredder121 would you be interested to provide a pull request? The change would be local to ConstructorExpression.

Member

timowest commented Mar 20, 2014

@wrungel or @Shredder121 would you be interested to provide a pull request? The change would be local to ConstructorExpression.

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 20, 2014

Member

yes, I'll at least look into it

Member

Shredder121 commented Mar 20, 2014

yes, I'll at least look into it

@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 20, 2014

Member

#681 I submitted a pull request, I'll hear from you considering feedback or tweaking.

I might have some ideas for smoothening the primitive type capturing (at creation time of the constructorexpression), but this should work for now, I think?
Let me know your opinion.

Member

Shredder121 commented Mar 20, 2014

#681 I submitted a pull request, I'll hear from you considering feedback or tweaking.

I might have some ideas for smoothening the primitive type capturing (at creation time of the constructorexpression), but this should work for now, I think?
Let me know your opinion.

@timowest timowest added this to the 3.3.4 milestone May 2, 2014

@timowest timowest added the fixed label May 10, 2014

@timowest timowest modified the milestone: 3.3.4 May 10, 2014

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest May 20, 2014

Member

Released in 3.3.4

Member

timowest commented May 20, 2014

Released in 3.3.4

@timowest timowest closed this May 20, 2014

@axelosorio

This comment has been minimized.

Show comment
Hide comment
@axelosorio

axelosorio Sep 14, 2017

I have similar problem when I was working in a Join with no values in the other table to join. The problem in hibernate is that it causes illegalArgumentException and tupleTransform problem in the join.
The thing was that in my constructor of the entity I have a type as double and it must be Double.
BAD CODE:

public DetalleFacturaEmbarqueEB(Integer idDetalleFacturaEmbarque,
									Integer idFacturaEmbarque,
									double descuento
				  					){

GOOD CODE

public DetalleFacturaEmbarqueEB(Integer idDetalleFacturaEmbarque,
									Integer idFacturaEmbarque,
									Double descuento
				  					){

As you see "descuento" was as double and not as Double.
It works for me, I hope it helps someone else.

I have similar problem when I was working in a Join with no values in the other table to join. The problem in hibernate is that it causes illegalArgumentException and tupleTransform problem in the join.
The thing was that in my constructor of the entity I have a type as double and it must be Double.
BAD CODE:

public DetalleFacturaEmbarqueEB(Integer idDetalleFacturaEmbarque,
									Integer idFacturaEmbarque,
									double descuento
				  					){

GOOD CODE

public DetalleFacturaEmbarqueEB(Integer idDetalleFacturaEmbarque,
									Integer idFacturaEmbarque,
									Double descuento
				  					){

As you see "descuento" was as double and not as Double.
It works for me, I hope it helps someone else.

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