PDA

View Full Version : Invoking actions configured in context in Java Based Flows


curtney
Apr 5th, 2006, 01:21 AM
Greetings everyone!

I have several actions (FormAction and MultiAction) defined within my webflow context file. Before I would use the following method

protected AnnotatedAction (http://static.springframework.org/spring-webflow/docs/1.0-ea/api/org/springframework/webflow/AnnotatedAction.html) method (http://static.springframework.org/spring-webflow/docs/1.0-ea/api/org/springframework/webflow/builder/AbstractFlowBuilder.html#method(java.lang.String, org.springframework.webflow.Action))(java.lang.Str ing encodedMethodKey, Action (http://static.springframework.org/spring-webflow/docs/1.0-ea/api/org/springframework/webflow/Action.html) action)

to invoke my actions. However, from the latest cvs head it seems this method is no longer available. What is now the preferred way of accessing actions that are configured in a context?

I have tried using the following but it does not work. I get a null pointer exception.

protected Action action (java.lang.String id, org.springframework.binding.method.MethodSignature method)

For example,

action ("MyActionId", method("metod to invoke"))

The only thing that works, is directly instantiating an AnnotatedAction and passing it a a map with the "method" property.


AnnotatedAction (Action targetAction, AttributeMap attributes)


Curtney

gudnabrsam
Apr 5th, 2006, 09:50 AM
yeah, that works... see also http://forum.springframework.org/showthread.php?t=23228 . The end of this thread shows another (somewhat convoluted) way of doing this...

curtney
Apr 5th, 2006, 11:10 AM
That is a convoluted way for something that should be very simple to do. Why the following didn't work? I likit it!:) It is simple and straight to the point.

action ("MyAction", method("my method on my action to invoke"))
Currently, this is what I am doing

AttributeMap map1 = new AttributeMap(1);
map1.put ("method", SETUP_DEFAULT_CATEGORY_TREE);
AnnotatedAction(action(CatalogAction.ACTION_ID),ma p1)
The reason I am looking for a standard is because, I have over 20 Java base flows that would need to be updated.

Curtney

curtney
Apr 6th, 2006, 04:48 PM
For those flows that are java base. It is just a matter of doing the following

getFlowArtifactFactory().getAction(new FlowArtifactParameters(actionId)
Since, you already have access to an instance of FlowArtifactFactory in your builder, just call it to get the configured action in your spring context. Simple!

I recommend having a base flow builder that you extend and implement convient/helper methods that retrieve whatever action you need.

Curtney

Keith Donald
Apr 8th, 2006, 07:52 PM
Curtney,

See also the Phonebook sample application Java builder examples. There is even a easier way--use of the action(String id, method("encodedSignature")) set of methods.

curtney
Apr 11th, 2006, 08:32 PM
Ok, I did try that (see previous post) and it did not work. I got a null pointer exception everytime. However, at that time, I was using the latest code from cvs.

I will try updating and compiling the swf code again.

Curtney

curtney
Apr 17th, 2006, 02:25 PM
Hi Keith,

looking at the example you gave,

action(String id, method("encodedSignature"))
If I wanted to call the following method how would I do so? What variable expression would I need to pass as the method argument?

public Event myMethod(RequestContext context) {
do something.
}

I am thinking...

action ("myId", method(myMethod("${?}"));

Thanks inadvance.

Keith Donald
Apr 17th, 2006, 07:48 PM
Well, it depends :-)

This is documented in detail within the DTD for the action 'method' attribute, but not yet in the builder code.

Basically, if you are binding to a MultiAction the 'method' expression is just the method name--as all MultiAction methods adhere to the same general signature (only the name varies). e.g. method("myMethod")

OTOH, If you are binding to a POJO the method needs to match the sig of a arbitrary method on that POJO... e.g method("myMethod("${flowScope.variableName}")).

curtney
Apr 17th, 2006, 09:09 PM
Basically, if you are binding to a MultiAction the 'method' expression is just the method name--as all MultiAction methods adhere to the same general signature (only the name varies). e.g. method("myMethod")

Ok, I am doing exactly that, however I am getting an exception.

addViewState ("updateCategoryRollup", "updateCategoryRollup",
new Transition [] {
transition (on(xxxx) to (xxx)),
transition (on(xxxx) to (xxx))
}
).addEntryAction (new ComposiiteAction(new Action[] {
action ("myActionId", method ("exposeForm"),
.
.
)}));
Unable to resolve multi action method with name 'updateCategoryRollup' and signature 'public org.springframework.webflow.Event updateCategoryRollup(interface org.springframework.webflow.RequestContext);'; make sure the method name is correct and such a public method is defined on targetClass com.oim.commerce.product.web.spring.flow.action.Ca tegoryRollupFormAction; nested exception is java.lang.NoSuchMethodException: com.oim.commerce.product.web.spring.flow.action.Ca tegoryRollupFormAction.updateCategoryRollup(org.sp ringframework.webflow.RequestContext)

The error is essentially correct, in that I don't have such a method define in my form action. Actually, it seems to be taking the id of the "viewState" ('updateCategoryRollup') as the method name, instead of the name that is actually pass to 'method("myMethod")', in this case "exposeForm".

This might potentially be a bug, I am not to sure since I am the only one experiencing this; I don't see any other posts regarding this issue.

Sorry, if I am missing something obvious. :confused:

Keith Donald
Apr 17th, 2006, 10:43 PM
Actually, there is arguably a bug here. It seems use of the 'method' factory bean only works with bean invoking actions now, not multi actions (it is effectively ignored, which explains the stateId fallback).

Good catch. We'll resolve this for 1.0 RC1.

Keith

curtney
Apr 17th, 2006, 10:59 PM
Will the fix be available in the nightly build or latest cvs head? Hoping to continue testing (and thus feedback) my code with the latest snapshots

Curtney

Keith Donald
Apr 18th, 2006, 06:54 PM
Curtney,

Actually, the fix is documentation.

The "method" factory method is for use with bean invoking actions only. The "invoke(String methodName, MultiAction action)" is for use with MultiActions, which is what you want.

Here is a test case I've added illustrating. I've also improved the docs.


public void testConfigureMultiAction() throws Exception {
MultiAction multiAction = new MultiAction(new MultiActionTarget());
AnnotatedAction action = builder.invoke("foo", multiAction);
assertEquals("foo", action.getAttributeMap().get(MultiAction.METHOD_AT TRIBUTE));
assertEquals("success", action.execute(new MockRequestContext()).getId());
}

public static class MultiActionTarget {
public Event foo(RequestContext context) {
return new Event(this, "success");
}
}