PDA

View Full Version : Ognl limitation?


activez
Apr 4th, 2006, 09:15 AM
Hi,

I'm trying to call a method of a bean that has the following signature:
AuxiliarDAO::getObjects(String parent, String field, Object value, Class clazz).

The problem arises when I try to call this function from the flow xml as that manner:
<action bean="auxiliarDAO" method="getObjects('aaaa','bbb',${flowScope.variable},@exa mple.MyClass@class)" resultName="result"/>

being flowScope.variable of Long type. I fails because it says that the method signature getObjects(String, String, Long, Class) dosn't exists. Is not supported calling methods from worflow with a parameter of a class that is an extension of another class?

Thanks for all, Mikel.

gudnabrsam
Apr 4th, 2006, 10:04 AM
Is not supported calling methods from worflow with a parameter of a class that is an extension of another class?

I'm not sure I understand exactly what you are asking here. The only "Ognl" part of your example is the ${}-delimited part, I believe. The rest is a spring-binding method signature expression. Maybe if you explained what the method signature looks like in Java, and what the last argument of your action's method attribute was again... the @ symbols confused me.

activez
Apr 4th, 2006, 10:37 AM
the @xxx@ssss part is ognl call. The @ is used when called to static methods in a class
@xxxx@ssss means access to ssss static atribute of xxxx class. But the problem isn't in this part, I use this parameter to pass the class to my method, because my method has a class as parameter.

the problem is:

If I have a bean with a method that has the following signature
example(Object object)

Why I can't call from swf xml with a signature like this:
example(String str) or example(Long lng), knowing that String and Long are subclasses of Object ?

Another option would be to downcast to Object in a Ognl expression, but I think ognl doesn't support this. (Ex: example((Object) ${flowScope.variable})

gudnabrsam
Apr 4th, 2006, 10:57 AM
remember that the base method representation is not OGNL, it's spring-binding. You may be able to use:

method="example(java.lang.Object ${longExpression)"

activez
Apr 4th, 2006, 11:07 AM
Hi!

I've tried the casting as you said method="example(java.lang.Object ${longExpression)"
but it fails saying this :

nested exception is java.lang.IllegalArgumentException: No converter registered to convert from sourceClass 'class java.lang.Long' to target class 'class java.lang.Object'

Christian Dupuis
Apr 4th, 2006, 11:14 AM
Hi,

you wanna try:


<action bean="auxiliarDAO" method="getObjects('aaaa','bbb',${flowScope.variab le},${@example.MyClass@class})" resultName="result"/>


You need to place the '${' and '}' around every OGNL expressions.

Cheers
Christian

gudnabrsam
Apr 4th, 2006, 11:15 AM
Okay, I have been researching the code and it looks as though spring-binding cannot resolve the methods unless they are specifically typed. You could probably set up a converter of Object->Object and add it, but it would be a lot of pain for something that IMHO binding should do inherently; i.e. you shouldn't have to upcast method args. I will submit a patch to ClassMethodKey today.

Christian Dupuis
Apr 4th, 2006, 11:22 AM
Hi,


Okay, I have been researching the code and it looks as though spring-binding cannot resolve the methods unless they are specifically typed. You could probably set up a converter of Object->Object and add it, but it would be a lot of pain for something that IMHO binding should do inherently; i.e. you shouldn't have to upcast method args. I will submit a patch to ClassMethodKey today.


Keith has implemented a pretty nice fallback resolving mechnism in case there is no method with the correctly typed parameters. This is implemented in ClassMethodKey.findMethodConsiderAssignableParamet erTypes.

There is no need for a patch. As I said the problem is caused by missing OGNL expression prefix and suffix.

Cheers
Christian

gudnabrsam
Apr 4th, 2006, 11:23 AM
you wanna try:


<action bean="auxiliarDAO" method="getObjects('aaaa','bbb',${flowScope.variab le},${@example.MyClass@class})" resultName="result"/>


You need to place the '${' and '}' around every OGNL expressions.


was gonna mention that also until I dragged myself down the tangent. Both may be issues; does this change alone solve your problem? I'm not sure it will if your method signature is too generic.

Christian Dupuis
Apr 4th, 2006, 11:24 AM
Nope thats it. As a small JUnit shows....

Christian

activez
Apr 4th, 2006, 11:48 AM
gudnabrsam, I think the same, that the binding should be 'intellillent' enought to know that the class is a subclass of the main class. But I don't know how the binding is implemented and if it has to been an algorithm to find al binding posibilities ex:

example( Object o1, Object o2)

we call example (Long , String) for example and the binding has to find all posibilities:

example (Long , String) no? then
example (Long , Object ) no? then
example (Object , String) no? then
example (Object, Object) no? ....

But I think finding all posibilities would be very costly.

cdupuis: I'm using @example.MyClass@class without ${} and it works for me.

Christian Dupuis
Apr 4th, 2006, 11:50 AM
Hi,

so does it work for you now? What have you changed to solve your problem?


example (Long , String) no? then
example (Long , Object ) no? then
example (Object , String) no? then
example (Object, Object) no? ....


That behaviour is implemented in ClassMethodKey.findMethodConsiderAssignableParamet erTypes().

If you use @example.MyClass@class without ${} it will be interpreted as a String in spring-binding and not as a class instance. Basically that is because @example.MyClass@class is not known to be a OGNL expression as long as you don't put ${} around.

As far as I see it from the source code and my unit tests. Furthermore I need to say that I'm working against the CVS head.

Christian

gudnabrsam
Apr 4th, 2006, 12:05 PM
SMACK! I hadn't gotten all the way down to the catch where findMethodConsider... was called. :) Oops.

activez
Apr 4th, 2006, 12:09 PM
cdupuis:

I think we are talking about two things

1º thing. You say that for using @ ognl expresions you need to use ${}
I use with ${} and without ${} and runs in both cases with and example like this

example(Class clazz)

That was what I said that was working for me, the use of @ expresions without ${}.

2º thing, the problem:
if you have a method like this
example (Object obj)

and you call from swf xml whith method="example(${long variable})" it fails. Then gudnabrsam propose me to doing this:
method="java.lang.Object ${long variable}" but fails because it says that doesn't exist a converter from Long to Object (it don't need any converter is a subclass :confused: )

I've also tried:
method=" ${java.lang.Object longVariable}" but also fails

gudnabrsam
Apr 4th, 2006, 12:19 PM
cdupuis:

I think we are talking about two things

1º thing. You say that for using @ ognl expresions you need to use ${}
I use with ${} and without ${} and runs in both cases with and example like this

example(Class clazz)

That was what I said that was working for me, the use of @ expresions without ${}.


That part works? The TextToMethodSignature code looked like it might, but I didn't really expect it to.


2º thing, the problem:
if you have a method like this
example (Object obj)

and you call from swf xml whith method="example(${long variable})" it fails. Then gudnabrsam propose me to doing this:
method="java.lang.Object ${long variable}" but fails because it says that doesn't exist a converter from Long to Object (it don't need any converter is a subclass :confused: )


do you mean literally "example(${long variable})" ? Or
"example(${someLongVariable})" ?


I've also tried:
method=" ${java.lang.Object longVariable}" but also fails

That's the one that would definitely fail, as the class specification is not an OGNL thing.

Christian Dupuis
Apr 4th, 2006, 12:28 PM
Hmmm,

1) For me example(Class clazz) is only working if I use ${@java.lang.String@class}

2) example (Object obj) is working for me if I use method="example(${flowScope.variable})", being flowScope.variable a String instance. The method is selected based on the ClassMethodKey.findMethodConsiderAssignableParamet erTypes implementation.

3) method="java.lang.Object ${long variable}" fails for me as well. But that really shouldn't matter because the Converter stuff is basically to Convert Text (String) to Object instances (look to the shipped implementations of the spring-binding Converter interface)

What version of Web Flow and Binding are you using?

Cheers
Christian

activez
Apr 4th, 2006, 12:35 PM
Originally Posted by activez
cdupuis:

I think we are talking about two things

1º thing. You say that for using @ ognl expresions you need to use ${}
I use with ${} and without ${} and runs in both cases with and example like this

example(Class clazz)

That was what I said that was working for me, the use of @ expresions without ${}.

That part works? The TextToMethodSignature code looked like it might, but I didn't really expect it to.

Yes, is working with and without ${} for me.

do you mean literally "example(${long variable})" ? Or
"example(${someLongVariable})" ?
I tried ${flowScope.someLongVariable}. Sorry, It was a bit informal code :)


Quote:
Originally Posted by activez
I've also tried:
method=" ${java.lang.Object longVariable}" but also fails

That's the one that would definitely fail, as the class specification is not an OGNL thing.

Yes I previously thinked that that doesn't work but I tried because I was a bit desesperate :)

activez
Apr 4th, 2006, 12:44 PM
Hmmm,

1) For me example(Class clazz) is only working if I use ${@java.lang.String@class}

2) example (Object obj) is working for me if I use method="example(${flowScope.variable})", being flowScope.variable a String instance. The method is selected based on the ClassMethodKey.findMethodConsiderAssignableParamet erTypes implementation.

3) method="java.lang.Object ${long variable}" fails for me as well. But that really shouldn't matter because the Converter stuff is basically to Convert Text (String) to Object instances (look to the shipped implementations of the spring-binding Converter interface)

What version of Web Flow and Binding are you using?

Cheers
Christian

I'm using Spring Webflow 1.0-EA and Spring binding 1.0-EA.

If you say that this is working for you then I think that either I'm using a wrong version of the software or that I'm configuring wrong something :confused:

Christian Dupuis
Apr 4th, 2006, 12:48 PM
I'm using Spring Webflow 1.0-EA and Spring binding 1.0-EA.

If you say that this is working for you then I think that either I'm using a wrong version of the software or that I'm configuring wrong something :confused:

Keith did a lot of polishing in the area of expression parsing recently and - more importantly for you - after the EA1 release. So maybe that explains the different behaviour we are seeing here.

I would recommend that you try out the CVS head.

Cheers
Christian

gudnabrsam
Apr 4th, 2006, 12:52 PM
Hmmm,
2) example (Object obj) is working for me if I use method="example(${flowScope.variable})", being flowScope.variable a String instance. The method is selected based on the ClassMethodKey.findMethodConsiderAssignableParamet erTypes implementation.


Agreed. I have tested this now and it works. Since I did it by adding to the ClassKeyMethodTests test case I might as well submit to JIRA for inclusion against the possibility this will come up again.


3) method="java.lang.Object ${long variable}" fails for me as well. But that really shouldn't matter because the Converter stuff is basically to Convert Text (String) to Object instances (look to the shipped implementations of the spring-binding Converter interface)


I disagree. Because (2) works, (3) is a non-issue here; however if you had a different scenario:

public void example(MyFooClass o) {}

and method="example(${myBarVariable})

it should be simple to create a bar-to-foo converter that would handle this, if somewhat verbose to register it. ;)

-Matt

P.S. I should have mentioned earlier that I, like Christian, am running CVS HEAD of binding and SWF (they're kind of inextricably linked). ;)

activez
Apr 4th, 2006, 12:57 PM
I've tried with a String parameter for seeing if the problem was something particular to Long objects. But the same ocurs:

<action bean="auxiliarDAO" method="getObjectsByParentField('provincia','id',java.lang .Object ${flowScope.operacionesOperador.nif},@es.sgi.bruce murray.model.Provincia@class)" resultName="localidades"/>

The important thing about this code is the 'java.lang.Object ${flowScope.operacionesOperador.nif}' code

Being operacionesOperador an object with a String property called nif.


Request processing failed; nested exception is org.springframework.webflow.ActionExecutionExcepti on: Exception thrown executing [AnnotatedAction@1c1b26c targetAction = org.springframework.webflow.action.LocalBeanInvoki ngAction@1a8e0bd, attributes = map['resultName' -> 'localidades', 'method' -> [MethodSignature@3acc6f methodName = 'getObjectsByParentField', parameters = [Parameters@43a52c parameters = list[[Parameter@111057b type = [null], name = [OgnlExpression@7f0b4e expression = "provincia"]], [Parameter@bf6ec3 type = [null], name = [OgnlExpression@e87e expression = "id"]], [Parameter@19fca0c type = Object, name = [OgnlExpression@189ff97 expression = flowScope.operacionesOperador.nif]], [Parameter@eb1f9a type = [null], name = [OgnlExpression@67d193 expression = @es.sgi.brucemurray.model.Provincia@class]]]]]]] in state 'operacionesOperador' of flow 'cuestionario-flow'; nested exception is java.lang.IllegalArgumentException: No converter registered to convert from sourceClass 'class java.lang.String' to target class 'class java.lang.Object'


the trace:

2006-04-04 18:50:07,294 [SocketListener0-6] WARN org.mortbay.jetty.context./gensol - /gensol/flowAction.html?_flowId=cuestionario-flow:
org.springframework.webflow.ActionExecutionExcepti on: Exception thrown executing [AnnotatedAction@1c1b26c targetAction = org.springframework.webflow.action.LocalBeanInvoki ngAction@1a8e0bd, attributes = map['resultName' -> 'localidades', 'method' -> [MethodSignature@3acc6f methodName = 'getObjectsByParentField', parameters = [Parameters@43a52c parameters = list[[Parameter@111057b type = [null], name = [OgnlExpression@7f0b4e expression = "provincia"]], [Parameter@bf6ec3 type = [null], name = [OgnlExpression@e87e expression = "id"]], [Parameter@19fca0c type = Object, name = [OgnlExpression@189ff97 expression = flowScope.operacionesOperador.nif]], [Parameter@eb1f9a type = [null], name = [OgnlExpression@67d193 expression = @es.sgi.brucemurray.model.Provincia@class]]]]]]] in state 'operacionesOperador' of flow 'cuestionario-flow'; nested exception is java.lang.IllegalArgumentException: No converter registered to convert from sourceClass 'class java.lang.String' to target class 'class java.lang.Object'
java.lang.IllegalArgumentException: No converter registered to convert from sourceClass 'class java.lang.String' to target class 'class java.lang.Object'
at org.springframework.binding.convert.support.Defaul tConversionService.getConversionExecutor(DefaultCo nversionService.java:175)
at org.springframework.binding.method.MethodInvoker.a pplyTypeConversion(MethodInvoker.java:120)
at org.springframework.binding.method.MethodInvoker.i nvoke(MethodInvoker.java:79)
at org.springframework.webflow.action.AbstractBeanInv okingAction.doExecute(AbstractBeanInvokingAction.j ava:109)
at org.springframework.webflow.action.AbstractAction. execute(AbstractAction.java:67)
at org.springframework.webflow.AnnotatedAction.execut e(AnnotatedAction.java:208)
at org.springframework.webflow.ActionExecutor.execute (ActionExecutor.java:54)
at org.springframework.webflow.ActionList.execute(Act ionList.java:162)
at org.springframework.webflow.State.enter(State.java :200)
at org.springframework.webflow.TransitionableState.re enter(TransitionableState.java:134)
at org.springframework.webflow.Transition.execute(Tra nsition.java:229)
at org.springframework.webflow.TransitionableState.on Event(TransitionableState.java:105)
at org.springframework.webflow.Flow.onEvent(Flow.java :545)
...

activez
Apr 4th, 2006, 01:00 PM
P.S. I should have mentioned earlier that I, like Christian, am running CVS HEAD of binding and SWF (they're kind of inextricably linked). ;)

Then the problem is solved using the last version of the cvs? If that is correct sorry for the thread and thank you very much for you patience :)

Christian Dupuis
Apr 4th, 2006, 01:02 PM
<action bean="auxiliarDAO" method="getObjectsByParentField('provincia','id',java.lang .Object ${flowScope.operacionesOperador.nif},@es.sgi.bruce murray.model.Provincia@class)" resultName="localidades"/>


Can you change your definition to and post the resulting stacktrace:


<action bean="auxiliarDAO" method="getObjectsByParentField('provincia','id',${flowSco pe.operacionesOperador.nif},@es.sgi.brucemurray.mo del.Provincia@class)" resultName="localidades"/>


Cheers
Christian

activez
Apr 4th, 2006, 01:27 PM
<action bean="auxiliarDAO" method="getObjectsByParentField('provincia','id',java.lang .Object ${flowScope.operacionesOperador.nif},@es.sgi.bruce murray.model.Provincia@class)" resultName="localidades"/>


Can you change your definition to and post the resulting stacktrace:


<action bean="auxiliarDAO" method="getObjectsByParentField('provincia','id',${flowSco pe.operacionesOperador.nif},@es.sgi.brucemurray.mo del.Provincia@class)" resultName="localidades"/>




Cheers
Christian

Now It works :), I don't know what I was doing bad. But I'm sure that was something that I typed wrong in my code. Sorry for the inconveniences.

Keith Donald
Apr 4th, 2006, 01:28 PM
Nice to see this works :-)

Thanks for the assist Christian. Much appreciated.

Keith