Adrian,
I have to resurrect this old thread because a customer reported this issue
recently and I can confirm it is still outstanding.
In rev. 1627718 I have committed a unit test to prove the use case that I was
trying to explain the last time; just comment out the last assertion and it
will fail.
This can be fixed by the following code change:
Index:
framework/base/src/org/ofbiz/base/util/collections/FlexibleMapAccessor.java
===================================================================
--- framework/base/src/org/ofbiz/base/util/collections/FlexibleMapAccessor.java
(revision 1627543)
+++ framework/base/src/org/ofbiz/base/util/collections/FlexibleMapAccessor.java
(working copy)
@@ -206,7 +206,7 @@
private String getExpression(Map<String, ? extends Object> base) {
String expression = null;
if (this.fse != null) {
- expression =
FlexibleStringExpander.openBracket.concat(UelUtil.prepareExpression(this.fse.expandString(base)).concat(FlexibleStringExpander.closeBracket));
+ expression =
UelUtil.prepareExpression(this.fse.expandString(base));
} else {
expression = this.bracketedOriginal;
}
However, since you are the original contributor of the code I am patching, I
would like your review.
Thanks,
Jacopo
On May 15, 2012, at 12:46 PM, Adrian Crum <[email protected]>
wrote:
> On 5/15/2012 11:41 AM, Jacopo Cappellato wrote:
>> HiAdrian,
>>
>> I am still getting an error; I did some debugging and here are my findings:
>>
>> On May 15, 2012, at 10:50 AM, Adrian Crum wrote:
>>
>>> On 5/15/2012 7:22 AM, Jacopo Cappellato wrote:
>>>> Thank you Adrian, much appreciated.
>>>> I have a question about one of the changes you have committed:
>>>>
>>>> + if (this.resultFma.containsNestedExpression()) {
>>> ^^^ If this result-name attribute contains a nested expression, like
>>> "${result1}"
>>>> + String expression = (String)
>>>> this.resultFma.get(methodContext.getEnvMap());
>>> ^^^ then evaluate the expression using the main context (expression =
>>> "result1")
>> This doesn't work as expected and "expression" is null.
>>
>> If I have the following code:
>> <set field="total" value="10" type="BigDecimal"/>
>> <set field="result1" value="totalOrders"/>
>> <field-to-result field="total" result-name="${result1}"/>
>>
>> I would expect that the above returns: expression == "totalOrders"
>> Is it correct assumption?
>
> Yes, that it the way it should work.
>
>> The problem I think is in FMA.getExpression(...):
>>
>> protected String getExpression(Map<String, ? extends Object> base) {
>> String expression = null;
>> if (this.fse != null) {
>> expression =
>> FlexibleStringExpander.openBracket.concat(UelUtil.prepareExpression(this.fse.expandString(base)).concat(FlexibleStringExpander.closeBracket));
>> } else {
>> expression = this.bracketedOriginal;
>> }
>> return expression;
>> }
>>
>> and specifically in line:
>>
>> expression =
>> FlexibleStringExpander.openBracket.concat(UelUtil.prepareExpression(this.fse.expandString(base)).concat(FlexibleStringExpander.closeBracket));
>>
>> because this.fse.expandString(base) returns:
>>
>> "${totalOrders}"
>>
>> rather than "totalOrders"
>
> That should not happen. I will look into it.
>
> -Adrian
>
>>
>> and then (I guess) the value is not found in the resultmap and the
>> expression comes as null.
>>
>> Is it possible?
>>
>> Jacopo
>>
>>
>>>> + FlexibleMapAccessor<Object> resultFma =
>>>> FlexibleMapAccessor.getInstance(expression);
>>> ^^^ Create a new FMA for the nested expression
>>>> + resultFma.put(methodContext.getResults(), fieldVal);
>>> ^^^ then evaluate the nested expression using the result Map.
>>>
>>> -Adrian
>>>
>>>> + }...
>>>>
>>>> if I read it correctly, if a nested expression is detected then a new FMA
>>>> is created as a local variable and the result value is added to that
>>>> instead of adding it to the instance FMA. Aren't we loosing the result in
>>>> this way?
>>>>
>>>> Thanks,
>>>>
>>>> Jacopo
>>>>
>>>> On May 14, 2012, at 10:50 PM, Adrian Crum wrote:
>>>>
>>>>> Jacopo,
>>>>>
>>>>> I committed a fix in rev 1338394. Let me know if that solves your problem.
>>>>>
>>>>> -Adrian
>>>>>
>>>>> On 5/14/2012 1:54 PM, Adrian Crum wrote:
>>>>>> Then that seems to be a flaw in the<field-to-result> logic. I will
>>>>>> look into it.
>>>>>>
>>>>>> -Adrian
>>>>>>
>>>>>> On 5/14/2012 1:51 PM, Jacopo Cappellato wrote:
>>>>>>> Ok, I am debugging it and the problem is actually in the method
>>>>>>> FlexibleMapAccessor.put at line:
>>>>>>>
>>>>>>> UelUtil.setValue(base, getExpression(base), value == null ?
>>>>>>> Object.class : value.getClass(), value);
>>>>>>>
>>>>>>> The problem is that the "base" map is the map containing the results
>>>>>>> and not the "context" of the method.
>>>>>>> For example:
>>>>>>>
>>>>>>> <set field="total" value="10" type="BigDecimal"/>
>>>>>>> <set field="result1" value="totalOrders"/>
>>>>>>> <field-to-result field="total" result-name="${result1}"/>
>>>>>>>
>>>>>>> This should add to the output the entry: ["totalOrders": 10]
>>>>>>>
>>>>>>> It instead throws the error because the ${result1} is expanded using
>>>>>>> the "result" map rather than the "context" map where the "result1"
>>>>>>> field is set.
>>>>>>>
>>>>>>> Jacopo
>>>>>>>
>>>>>>>
>>>>>>> On May 14, 2012, at 12:34 PM, Adrian Crum wrote:
>>>>>>>
>>>>>>>> It must be an old bug. As far as I know, the expression parsing hasn't
>>>>>>>> changed recently (with the exception of the recent security fix).
>>>>>>>>
>>>>>>>> -Adrian
>>>>>>>>
>>>>>>>> On 5/14/2012 11:27 AM, Jacopo Cappellato wrote:
>>>>>>>>> Ok, I will try to look at it and find a fix... do you have any idea
>>>>>>>>> about why the content of the brackets is removed during parsing? Is
>>>>>>>>> it related to recent changes or it is an old bug? They may be silly
>>>>>>>>> questions but I actually don't know much about this code.
>>>>>>>>>
>>>>>>>>> Jacopo
>>>>>>>>>
>>>>>>>>> On May 14, 2012, at 12:03 PM, Adrian Crum wrote:
>>>>>>>>>
>>>>>>>>>> That is a nested expression: The result name is contained in the
>>>>>>>>>> variable named "key".
>>>>>>>>>>
>>>>>>>>>> UEL does not support nested expressions, but we make it work in
>>>>>>>>>> FlexibleStringExpander by pre-parsing the String and extracting
>>>>>>>>>> nested expressions.
>>>>>>>>>>
>>>>>>>>>> In addition, FlexibleMapAccessor contains some code to handle nested
>>>>>>>>>> expressions (line 66 and 192). So, maybe that code can be improved
>>>>>>>>>> to be smarter.
>>>>>>>>>>
>>>>>>>>>> -Adrian
>>>>>>>>>>
>>>>>>>>>> On 5/14/2012 10:37 AM, Jacopo Cappellato wrote:
>>>>>>>>>>> Hi Adrian,
>>>>>>>>>>>
>>>>>>>>>>> we have noticed that the following instruction:
>>>>>>>>>>>
>>>>>>>>>>> <field-to-result field="val" result-name="${key}"/>
>>>>>>>>>>>
>>>>>>>>>>> (from ContentServices.xml) returns an error in the console:
>>>>>>>>>>>
>>>>>>>>>>> 2012-05-14 14:12:02,679 (default-invoker-Thread-11)
>>>>>>>>>>> [FlexibleMapAccessor.java:163:ERROR] UEL exception while setting
>>>>>>>>>>> value: javax.el.ELException: Error parsing '${}': syntax error at
>>>>>>>>>>> position 2, encountered '}',
>>>>>>>>>>> expected<IDENTIFIER>|<STRING>|<FLOAT>|<INTEGER>|'true'|'false'|'null'|'-'|'!'|'not'|'empty'|'(',
>>>>>>>>>>> original = ${key}
>>>>>>>>>>>
>>>>>>>>>>> However it seems that the value is still returned properly. Any
>>>>>>>>>>> idea of how we could fix it?
>>>>>>>>>>>
>>>>>>>>>>> Thanks,
>>>>>>>>>>>
>>>>>>>>>>> Jacopo
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>