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

Expression evaluator should accept raw collection value for parameterized method argument [SPR-7831] #12487

Closed
spring-projects-issues opened this issue Dec 21, 2010 · 6 comments
Assignees
Labels
has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

Ken Abbott opened SPR-7831 and commented

The evaluator incorrectly throws org.springframework.expression.spel.SpelEvaluationException: EL1004E: when matching a method parameter of parameterized type to an actual argument of the raw type. E.g.

public Object someMethod(List<TaskInstance> tasks); //inferred element type is TaskInstance

List rawList = new List(); //inferred element type is Object

In a Spring weblow, expression "someObject.someMethod(rawList)" fails with EL1004E. The error is in org.springframework.core.convert.TypeDescriptor.isAssignableTo(), which incorrectly checks the element type of the collection.

if (isCollection() && targetType.isCollection() || isArray() && targetType.isArray()) {
     return targetType.getType().isAssignableFrom(getType()) &&
               getElementTypeDescriptor().isAssignableTo(targetType.getElementTypeDescriptor());
}

According to rules of type erasure for parameterized types, only the raw types must match. This is a major issue because some data providers (e.g. jBPM, Ibatis) create and return raw collection types.

Stack trace follows:
org.springframework.webflow.execution.ActionExecutionException: Exception thrown executing [AnnotatedAction@f4388b targetAction = [EvaluateAction@1ac5211 expression = redemptionModel.setInstructionGroupAccountViews(flowScope.instructionGroups), resultExpression = [null]], attributes = map[[empty]]] in state 'null' of flow 'redemption-detail-flow' -- action execution attributes were 'map[[empty]]'
at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:60)
at org.springframework.webflow.engine.ActionList.execute(ActionList.java:155)
at org.springframework.webflow.engine.Flow.start(Flow.java:534)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:364)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:222)
at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:140)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:193)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.fmr.commons.cs203.servlet.CS203CoreServletFilter.doFilter(CS203CoreServletFilter.java:86)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)
at com.fidelity.shares.web.common.Log4jMDCFilter.doFilter(Log4jMDCFilter.java:70)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at com.fidelity.shares.web.security.SecurityTokenFilter.doFilterHttp(SecurityTokenFilter.java:77)
at com.fidelity.shares.web.security.SecurityTokenFilter.doFilter(SecurityTokenFilter.java:34)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at com.fidelity.shares.web.security.TimeoutFilter.doFilterHttp(TimeoutFilter.java:111)
at com.fidelity.shares.web.security.TimeoutFilter.doFilter(TimeoutFilter.java:51)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:379)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.springframework.binding.expression.EvaluationException: An ELException occurred getting the value for expression 'redemptionModel.setInstructionGroupAccountViews(flowScope.instructionGroups)' on context [class org.springframework.webflow.engine.impl.RequestControlContextImpl]
at org.springframework.binding.expression.spel.SpringELExpression.getValue(SpringELExpression.java:86)
at org.springframework.webflow.action.EvaluateAction.doExecute(EvaluateAction.java:75)
at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188)
at org.springframework.webflow.execution.AnnotatedAction.execute(AnnotatedAction.java:145)
at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51)
... 64 more
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 16): Method call: Method setInstructionGroupAccountViews(java.util.ArrayList) cannot be found on com.fidelity.shares.web.admin.model.event.redemption.RedemptionDetailModel type
at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:185)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:107)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:97)
at org.springframework.binding.expression.spel.SpringELExpression.getValue(SpringELExpression.java:78)
... 68 more


Affects: 3.0.5

Referenced from: commits 3bed6cf, 78646f1

Backported to: 3.2.6

15 votes, 15 watchers

@spring-projects-issues
Copy link
Collaborator Author

Paul Bacsik commented

Indeed I have the same issue:

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 6): Method call: Method setUmsaetze(java.util.ArrayList) cannot be found on ...RfmBB type
at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:185)

where RfmBB#setUmsaetze is:

public void setUmsaetze(List<RfmUmsatzKat> umsaetze) {

@spring-projects-issues
Copy link
Collaborator Author

Tim Fulmer commented

Got the same thing here too. For us it was more like:

<evaluate expression="service.getStuff()" result="flowScope.results" result-type="java.util.List"/>
<evaluate expression="flowScope.stuffBB.generateDropDown(flowScope.results)"/>

Where getStuff returning and generateDropDown accepting parameterized lists. The parameter is the same on both lists. Attempting to give result-type a parameterized list got me an EL exception, it doesn't accept the syntax. Removing the result-type config attribute had no effect. I finally had to make the backing bean accept a non-parameterized list, immediately wrapping it in a parameterized list at top of method.

Anyway, thanks for the defect. I don't even want to think about how long it would have taken me to debug it down to the Spring version update we did recently. Hopefully info above will help out a bit until this gets fixed.

@spring-projects-issues
Copy link
Collaborator Author

Sebastian Erbert commented

Any update on this issue?

We had to patch this class to get it work, but a fix in spring itself would be nicer.

@spring-projects-issues
Copy link
Collaborator Author

Tomas Jetelina commented

Same problem when trying to inject result of method call defined in super class. If method is implemented in extended class it works.

@Value("#{controller.getUDA()}")
private UDAAdapter uda;

class Parent
{
public UDAAdapter getUDA(){...}
}
// this is controller bean
class Child extends Parent
{
// works if defined here
}

org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 11): Method call: Method getUDA() cannot be found on 'extended' type

@spring-projects-issues
Copy link
Collaborator Author

Nicolas Mommaerts commented

We have several projects using the same version of Spring (3.0.5), some exhibit this bug, some don't.. Can't point out why
Edit: I know why, those project don't happen to have methods with generic list declared and called from webflow

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

As far as I can tell, this works fine in 4.0 GA and 3.2.6. It probably got fixed as a side effect of an earlier change, but anyway, it works for those recent versions now. If you keep having an issue here, please reproduce it against those recent generations of Spring.

Juergen

@spring-projects-issues spring-projects-issues added status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement in: core Issues in core modules (aop, beans, core, context, expression) has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 4.0 GA milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has: votes-jira Issues migrated from JIRA with more than 10 votes at the time of import in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants