Gerrit Brehmer opened SPR-7614 and commented

I want to inject a single value of a request-url-parameter from JSF Faces Context: @Value("#{param.test}").

If I call the JSF-Page without this parameter first time, I get a SpEL exception:

EL1008E:(pos 6): Field or property 'test' cannot be found on object of type 'java.util.Collections$UnmodifiableMap'.

After that I make a valid call with 'test'-Parameter added and MapAccessor will be cached.

All calls after that valid call will not throw an exception. For missing parameter-requests, null value will be injected.

My expected behavior would be a null value, if the key doesn't exist in the map.

Is this possible?

I think the behavior between canRead (before caching) and read (after caching) is different for missing keys in the map.


Affects: 3.0.4

Referenced from: commits https://github.com/spring-projects/spring-framework/commit/1f1577e33ea5440160d984f7ae1a8629066ea8e3, https://github.com/spring-projects/spring-framework/commit/1933b648c3d46715009ca27eb628ee8d98a14dcc, https://github.com/spring-projects/spring-framework/commit/722778c74a048d5b1a091f56090cc0e91e782272

1 votes, 3 watchers

Comment From: spring-projects-issues

Juergen Hoeller commented

Good catch - this should actually consistently fail, since "target.key" style access is based on properties and fields and only being translated to Maps according to those semantics. Since we have a chain of PropertyAccessors there, this is only allowed to work for an actual existing key; otherwise subsequent PropertyAccessors would never kick in.

As a solution for your scenario, considering using "target[key]" style access as known from arrays and from Map access in Spring's traditional BeanWrapper. That syntax is defined to return null in case of a non-existing key.

Juergen

Comment From: spring-projects-issues

Gerrit Brehmer commented

Thanks for the fast solution, but for ever reason, with map-style (target[key]) access it's neraly the same behaviour in 3.0.4

  1. without request-parameter: null
  2. with request parameter: null (but FacesRequestAttributes will not be accessed anymore -> map cached?)

after app restart

  1. with request parameter: requested value
  2. without request-parameter: null
  3. with request parameter: requested value

Comment From: spring-projects-issues

Juergen Hoeller commented

So it consistently works if the first-ever request parameter is non-null, but it consistently doesn't work if the first-ever parameter is null?

Juergen

Comment From: spring-projects-issues

Gerrit Brehmer commented

yes, that's the observed behaviour.

For the setter-injection case I debugged a little bit: If the first request parameter is null, in AutowiredAnnotationBeanPostProcessor.inject-method the cached-flag is set to true and cachedMethodArguments is set to null. So during next request, the cached arguments are used. But because the value is null, there was no further attempt to resolve the value. Is this a known limitation?

Comment From: spring-projects-issues

Juergen Hoeller commented

Thanks for pointing this out: It turned out to be a problem with AutowiredAnnotationBeanPostProcessor's caching which needs to respect temporary null values when coming from @Value annotations. Fixed for tonight's 3.0.5 snapshot.

Juergen

Comment From: spring-projects-issues

Iwein Fuld commented

I'm running into a very similar scenario in https://jira.springframework.org/browse/INT-988. In this case it is caused by the caching of a read accessor in PropertyOrFieldReference (line 193). I'll have a look if the fix for 3.0.5 also fixes INT-988.

Comment From: spring-projects-issues

Iwein Fuld commented

I've confirmed that INT-988 is fixed against 3.0.5.BUILD-SNAPSHOT. Thanks Jürgen!