From dev-return-26114-archive-asf-public=cust-asf.ponee.io@openjpa.apache.org Wed Apr 10 08:24:02 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id 0E69C180626 for ; Wed, 10 Apr 2019 10:24:01 +0200 (CEST) Received: (qmail 86650 invoked by uid 500); 10 Apr 2019 08:24:00 -0000 Mailing-List: contact dev-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list dev@openjpa.apache.org Received: (qmail 86639 invoked by uid 99); 10 Apr 2019 08:24:00 -0000 Received: from mailrelay1-us-west.apache.org (HELO mailrelay1-us-west.apache.org) (209.188.14.139) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 10 Apr 2019 08:24:00 +0000 Received: from jira-lw-us.apache.org (unknown [207.244.88.139]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 7117EE0782 for ; Wed, 10 Apr 2019 08:24:00 +0000 (UTC) Received: from jira-lw-us.apache.org (localhost [127.0.0.1]) by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id 2555E24595 for ; Wed, 10 Apr 2019 08:24:00 +0000 (UTC) Date: Wed, 10 Apr 2019 08:24:00 +0000 (UTC) From: "Michael Wiles (JIRA)" To: dev@openjpa.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Created] (OPENJPA-2785) Queries invoked by Spring data that have parameters fail MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 Michael Wiles created OPENJPA-2785: -------------------------------------- Summary: Queries invoked by Spring data that have parameters f= ail Key: OPENJPA-2785 URL: https://issues.apache.org/jira/browse/OPENJPA-2785 Project: OpenJPA Issue Type: Bug Components: criteria Affects Versions: 3.1.0 Reporter: Michael Wiles When you invoke a query provided/built by spring data this fails. Only affects version 3.1.0 =C2=A0 See=C2=A0[https://github.com/michaelwiles/openjpa-spring-data-bug]=C2=A0for= demo project. Here is the stack trace: org.springframework.dao.InvalidDataAccessApiUsageException: Cannot execute = query; declared parameters "ParameterExpression" were not given val= ues. You must supply a value for each of the following parameters, in the g= iven order: [ParameterExpression]; nested exception is org.apach= e.openjpa.persistence.ArgumentException: Cannot execute query; declared par= ameters "ParameterExpression" were not given values. You must suppl= y a value for each of the following parameters, in the given order: [Parame= terExpression] at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessE= xceptionIfPossible(EntityManagerFactoryUtils.java:373) at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossi= ble(DefaultJpaDialect.java:127) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateE= xceptionIfPossible(AbstractEntityManagerFactoryBean.java:527) at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.t= ranslateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(Da= taAccessUtils.java:242) at org.springframework.dao.support.PersistenceExceptionTranslationIntercep= tor.invoke(PersistenceExceptionTranslationInterceptor.java:153) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Re= flectiveMethodInvocation.java:186) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostP= rocessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMet= adataPostProcessor.java:138) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Re= flectiveMethodInvocation.java:186) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(= ExposeInvocationInterceptor.java:93) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Re= flectiveMethodInvocation.java:186) at org.springframework.data.repository.core.support.SurroundingTransaction= DetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterc= eptor.java:61) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Re= flectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicA= opProxy.java:212) at com.sun.proxy.$Proxy64.findByName(Unknown Source) at com.afrozaar.bug.openjpa.OpenjpaSpringDataJpaApplicationTests.MemberByN= ame(OpenjpaSpringDataJpaApplicationTests.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.ja= va:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccesso= rImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMe= thod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCalla= ble.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMeth= od.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMetho= d.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecuti= onCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestExecutio= nCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodC= allbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCa= llbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluat= e(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChil= d(SpringJUnit4ClassRunner.java:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChil= d(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCa= llbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCal= lbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(Spr= ingJUnit4ClassRunner.java:190) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4Te= stReference.java:89) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.j= ava:41) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteT= estRunner.java:541) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteT= estRunner.java:763) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRu= nner.java:463) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestR= unner.java:209) Caused by: org.apache.openjpa.persistence.ArgumentException: Cannot exec= ute query; declared parameters "ParameterExpression" were not given= values. You must supply a value for each of the following parameters, in t= he given order: [ParameterExpression] at org.apache.openjpa.kernel.QueryImpl.assertParameters(QueryImpl.java:184= 9) at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:905) at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:843) at org.apache.openjpa.kernel.DelegatingQuery.execute(DelegatingQuery.java:= 601) at org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:297) at org.apache.openjpa.persistence.QueryImpl.getResultList(QueryImpl.java:3= 14) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.ja= va:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccesso= rImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInv= ocationHandler.invoke(SharedEntityManagerCreator.java:402) at com.sun.proxy.$Proxy77.getResultList(Unknown Source) at org.springframework.data.jpa.repository.query.JpaQueryExecution$Collect= ionExecution.doExecute(JpaQueryExecution.java:129) at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute= (JpaQueryExecution.java:91) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecut= e(AbstractJpaQuery.java:136) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(= AbstractJpaQuery.java:125) at org.springframework.data.repository.core.support.RepositoryFactorySuppo= rt$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:60= 5) at org.springframework.data.repository.core.support.RepositoryFactorySuppo= rt$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.= java:595) at org.springframework.data.repository.core.support.RepositoryFactorySuppo= rt$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Re= flectiveMethodInvocation.java:186) at org.springframework.data.projection.DefaultMethodInvokingMethodIntercep= tor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Re= flectiveMethodInvocation.java:186) at org.springframework.transaction.interceptor.TransactionAspectSupport.in= vokeWithinTransaction(TransactionAspectSupport.java:294) at org.springframework.transaction.interceptor.TransactionInterceptor.invo= ke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Re= flectiveMethodInvocation.java:186) at org.springframework.dao.support.PersistenceExceptionTranslationIntercep= tor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ... 41 more =C2=A0And some of my comments (originally from a reply to the mailing list:= ) I can't upgrade the 3.1 until this issue is fixed as basically, as far as I= can tell, any parameterised call via spring data does not work. =C2=A0 Not sure it's the right place to discuss this but the way I see it the Para= meterExpressionImpl ([https://github.com/apache/openjpa/blob/master/openjpa= -persistence/src/main/java/org/apache/openjpa/persistence/criteria/Paramete= rExpressionImpl.java]) has acquired a hashCode and equals with this release= -=C2=A0[https://github.com/apache/openjpa/commit/0e4ec5b392b978c4515b26c60= e485f2b610de94f#diff-e357856846fb8b88f15c08e60891cc35]=C2=A0and this is the= code of the problem with spring data. =C2=A0 Now what's happening is that the compile is called - and this is called bef= ore the parameter expression has a value. All hashcode calcs are done and s= tuff is added to a set. =C2=A0 Then later on the value for the parameter is set. This causes changes to th= e hashCode and equals, resulting in the problem that I'm seeing. =C2=A0 Now I apologise if I'm completely out of line but I'm wondering why the val= ue is included in the hashCode and equals of a Parameter as surely a value = is a "runtime" concept and it not necessarily available at compile time. =C2=A0 Now the hashCode and equals were added for good reason I assume, and furthe= rmore, the value is included in the hashCode/equals also for good reason. B= ut we arguably need a mechanism to view the parameter purely from a metadat= a point of view (which is I think what we need here) as well as from a meta= data+value point of view. =C2=A0 But I do wonder why the ParamterExpressionImpl does include the value in th= e hashCode and equals. My gut feel is that it's not necessary. =C2=A0 Relevant stack traces: first time hashCode is called - at this point the va= lue is not specified in the ParameterExpressionImpl. Notice that the Criter= iaQueryImpl.compile kicks this off. =C2=A0 org.apache.openjpa.persistence.criteria.ParameterExpressionImpl.hashCode= () line: 154 java.util.HashMap.hash(java.lang.Object) line: 338 java.util.LinkedHashMap(java.util.HashMap).containsKey(java.lang.= Object) line: 595 org.apache.openjpa.lib.util.OrderedMap.containsKey(java.lang.Object) l= ine: 70 org.apache.openjpa.persistence.criteria.CriteriaQueryImpl.registerParame= ter(org.apache.openjpa.persistence.criteria.ParameterExpressionImpl) lin= e: 227 org.apache.openjpa.persistence.criteria.CriteriaExpressionVisitor$Parameter= Visitor.enter(org.apache.openjpa.persistence.criteria.CriteriaExpression) l= ine: 106 org.apache.openjpa.persistence.criteria.Expressions.acceptVisit(org.apache.= openjpa.persistence.criteria.CriteriaExpressionVisitor, org.apache.openjpa.= persistence.criteria.CriteriaExpression, javax.persistence.criteria.Express= ion...) line: 106 org.apache.openjpa.persistence.criteria.ParameterExpressionImpl(org.apac= he.openjpa.persistence.criteria.SelectionImpl).acceptVisit(org.apache.op= enjpa.persistence.criteria.CriteriaExpressionVisitor) line: 156 org.apache.openjpa.persistence.criteria.Expressions.visitChildren(org.apach= e.openjpa.persistence.criteria.CriteriaExpressionVisitor, javax.persistence= .criteria.Expression...) line: 121 org.apache.openjpa.persistence.criteria.Expressions.acceptVisit(org.apache.= openjpa.persistence.criteria.CriteriaExpressionVisitor, org.apache.openjpa.= persistence.criteria.CriteriaExpression, javax.persistence.criteria.Express= ion...) line: 108 org.apache.openjpa.persistence.criteria.Expressions$Equal(org.apache.openjp= a.persistence.criteria.Expressions$BinaryLogicalExpression).acceptVisit(org= .apache.openjpa.persistence.criteria.CriteriaExpressionVisitor) line: 278 org.apache.openjpa.persistence.criteria.CriteriaQueryImpl.collectParamet= ers(org.apache.openjpa.persistence.criteria.CriteriaExpressionVisitor) line= : 681 *org.apache.openjpa.persistence.criteria.CriteriaQueryImpl.compile() lin= e: 672*=20 org.apache.openjpa.persistence.EntityManagerImpl.createQuery(javax.persiste= nce.criteria.CriteriaQuery) line: 1898 =C2=A0 Then the error I get, occurs here - in=C2=A0org.apache.openjpa.kernel.Query= Impl =C2=A0 =C2=A0 protected void assertParameters(StoreQuery q, StoreQuery.Executor ex= , Map params) { =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (!q.requiresParameterDeclarations()) =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 OrderedMap> paramTypes =3D ex.g= etOrderedParameterTypes(q); =C2=A0 =C2=A0 =C2=A0 =C2=A0 *for (Object actual : params.keySet()) {* =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *if (!paramTypes.containsKey(actu= al))* =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 throw new UserException(_loc.get(= "unbound-params", =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 actual, paramTypes.= keySet())); =C2=A0 =C2=A0 =C2=A0 =C2=A0 } =C2=A0 =C2=A0 =C2=A0 =C2=A0 for (Object expected : paramTypes.keySet()) { =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (!params.containsKey(expected)= ) =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 throw new UserException(_loc.get(= "unbound-params", =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 expected, paramType= s.keySet())); =C2=A0 =C2=A0 =C2=A0 =C2=A0 } =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 for (Entry> entry : paramTypes= .entrySet()) { =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (entry.getValue().isPrimitive(= ) =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 && params.get(entry= .getKey()) =3D=3D null) =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 throw new UserExcep= tion(_loc.get("null-primitive-param", entry.getKey())); =C2=A0 =C2=A0 =C2=A0 =C2=A0 } =C2=A0 =C2=A0 } =C2=A0 The error occurs in the bold stuff. =C2=A0 And the fundamental reason as far as I can tell is that the paramtypes map = was populated when the value was set and then the=C2=A0*actual*=C2=A0refere= nce in this code has the value set... =C2=A0 Iow, getOrderedParameterTypes returns the map created before the value was = set and the params.keySet has parameterExpressionImpls that have their valu= es set. =C2=A0 And you know what happens when you use a hashMap and you change the hashCod= e after you've populated the hashmap. =C2=A0 Error stack trace: at org.apache.openjpa.kernel.QueryImpl.assertParameters(QueryImpl.java:1849= ) at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:905) at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:843) at org.apache.openjpa.kernel.DelegatingQuery.execute(DelegatingQuery.java:6= 01) at org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:297) at org.apache.openjpa.persistence.QueryImpl.getResultList(QueryImpl.java:31= 4) at org.apache.openjpa.persistence.QueryImpl.getSingleResult(QueryImpl.java:= 343) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav= a:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor= Impl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.orm.jpa.SharedEntityManagerCreat -- This message was sent by Atlassian JIRA (v7.6.3#76005)