Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upErrors in EL expressions in User Guide [SPR-5847] #10516
Comments
This comment has been minimized.
This comment has been minimized.
Andy Clement commented What is your jdbcProperties object? If it is a Map then 'jdbcProperties.username' works if a MapAccessor is registered:
A MapAccessor is registered automatically if the EL is used within Spring (I believe), but if the EL is used standalone then a map accessor is not registered by default. We could change this. The second case of 'jdbcProperties['username']' does not currently work. It could be made to work but I think addressing that is actually a separate issue. |
This comment has been minimized.
This comment has been minimized.
Dave Syer commented I think you must be wrong about the way that Spring sets up the EL parser in an ApplicationContext. The first example (as per user guide) gives me a nice fat exception:
The second example works. I'm using last night's snapshot. |
This comment has been minimized.
This comment has been minimized.
Andy Clement commented I did write that first comment in a bit of a hurry. Let me slow down a bit. "jdbcProperties['username']" jdbcProperties.username My final mistake was saying 'jdbcProperties['username']' does not currently work, I meant "jdbcProperties[username]". I'm really in two minds about whether to make it work. An unqualified reference like username in that expression is evaluated as a property of the current active context object (which in this case is whatever you are evaluating jdbcProperties against). I could special case when it is wrapped in a [] and that is being used on a map. If you think it should work, I can make it work that way, but is it such a problem that you need the quotes? All the documentation for the EL, apart from the section on how spring framework exploits the EL, has been converted to test programs (or at least I did a pass of it with the 3.0M3 version of the docs). Guess I should have done that for the spring framework section too! |
This comment has been minimized.
This comment has been minimized.
Andy Clement commented I'm having more success writing tests around that 3rd scenario "jdbcProperties[username]" than application context tests for "jdbcProperties.username" so I'm looking more at that case. As I said, unqualified references are resolved against the current active context object. If we evaluate the expression "jdbcProperties[username]" then first jdbcProperties is first processed, the current context object becomes a Properties object. Then the unqualified reference "username" is resolved against that - this actually finds a value, and evaluates to what you really wanted as the return value, ie. 'Dave' - but then we actually evaluate the indexer construct []. Effectively we are then evaluating jdbcProperties['Dave'] because username got evaluated to 'Dave' - and we don't find it because there is no entry in the jdbcProperties properties object for Dave - and so the whole thing returns null. I think from what I've been playing around with I'll get the 'jdbcProperties[username]' to work and commit that tomorrow. The only possible confusing thing is then what to do for property names with dots in. If the property name was instead 'user.name', then:
|
This comment has been minimized.
This comment has been minimized.
Dave Syer commented Property names with dots work OK in Groovy / OGNL but only if quoted (so the third example is only going to work if "user" is in the root context with a property "name". |
This comment has been minimized.
This comment has been minimized.
Andy Clement commented Thanks Dave. Ok, I've committed changes to make all these things behave nicely. For non-dotted property names you can use: jdbcProperties['username'] Without the brackets, a MapAccessor must be registered as a property resolver, then this works: jdbcProperties.username In the case of dotted property names, they should be quoted: jdbcProperties['user.name'] If unquoted then user.name would be resolved as an expression against the root context object and the resultant value used as the key into jdbcProperties. All this is tested. So the remaining thing to address here is the case of jdbcProperties.username when used through an ApplicationContext and why it appears the map accessor isn't used correctly. I don't suppose you can give me your snippet of test code that causes the failure Dave - I'm a bit incompetent at writing app context tests! |
This comment has been minimized.
This comment has been minimized.
Dave Syer commented Thanks Andy. You will find this interesting:
works (notice the whitespace), but
doesn't. So the MapAccessor is there but broken? (I don't have your changes yet - still on last night's snapshot.) Here's the full ApplicationContext:
and the unit test:
|
This comment has been minimized.
This comment has been minimized.
Andy Clement commented Dave, thanks for giving me all that stuff :) I have the test defined now but it passes just fine even if I change the Andy definition to remove whitespace:
Now I am running with the latest fixes from today which I know you don't have - but I haven't knowingly changed anything that would affect this. The call to trim() in TemplateAwareExpressionParser on line 123 should be trimming the extra whitespace off so that the two variants look identical when passed to the parser. hmmm. If you wanted to debug a little bit, you could breakpoint in the MapAccessor and see what it is using as the map key? That is org.springframework.context.expression.MapAccessor.canRead() and read(). If (in your case) it is using 'usernam' with the e chopped off, that would be interesting as I might start suspecting some of the string chopping code in the template parser. |
This comment has been minimized.
This comment has been minimized.
Dave Syer commented Sorry, maybe the snapshots just changed, or maybe I was being an idiot before, but I can't make it fail now. The only test that fails is |
This comment has been minimized.
This comment has been minimized.
Juergen Hoeller commented Guys, what's the status on this one? Any further changes or testing required? Juergen |
This comment has been minimized.
This comment has been minimized.
Andy Clement commented closing as I believe it is all fixed |
This comment has been minimized.
This comment has been minimized.
Dmitry Katsubo commented Andy, the given syntax does not work in conjunction with
causes The example was taken from SPR-6806. |
This comment has been minimized.
This comment has been minimized.
Andy Clement commented The exception occurs because jobStatusPollInterval does not exist on serviceConfigurationProperties. Right now if you wish to look up something that may not exist (as opposed to something that exists but may be null), use "#{serviceConfigurationProperties[jobStatusPollInterval] ?: '10'}". The current spring mapaccessor will only claim it can read a named property from a map if that map defines the key. If your key isn't there it will say it can't read it and we will fall back to the reflective property resolver which can't find it either (and throws the exception). To make your syntax work we'd have to change the MapAccessor to simply say it can access a property if it is called upon a map, ignoring whether the key exists - this seems a big change. Are you happy with the alternative syntax I suggested? I'll close this now as some work was done for all Dave's cases, but if you would like your alternative syntax to work, it might be worth a new jira to investigate the impact of changing MapAccessor. |
This comment has been minimized.
This comment has been minimized.
Dmitry Katsubo commented I would vote for |
This comment has been minimized.
This comment has been minimized.
mohan commented Hi, This is Mohan, I tried to use Spring EL version 3.2.11.RELEASE. In my application I rid of xml based configuration and using annotations. So, I written Config class to configure beans and loading properties files using annotations. But, I am unable to display the values of property file by giving key using below annotation. import org.springframework.context.annotation.Bean; import com.uprr.app.mcs.spring.dao.DefaultSampleDao;
}
// private
// System.out.println("username : " +username); When I tried to execute this from my client application using the below code I am getting the exception public class SpringTestClient {
} exception : Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 48): Property or field 'url' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public? Please respond on it. |
This comment has been minimized.
This comment has been minimized.
Stéphane Nicoll commented Mohan, please post your question on stackoverflow. Check https://spring.io/questions for more details. |
Dave Syer opened SPR-5847 and commented
Errors in EL expressions in User Guide. It would be nice if properties could be de-referenced as in the guide, e.g.
but empirically it only seems to work as
If EL is supposed to support the first example then I did something wrong? It would be nice if it did support that (consistent with other similar idioms e.g. in Groovy), and also
jdbcProperties[username]
.Affects: 3.0 M3
Issue Links:
Referenced from: commits dbdac9f, a4b7ce1