1

I have difined my flow as:

    builder.id("", PublisherBean.PUBLISHER_FLOW_NAME);

    builder.viewNode("list", "/pages/publishers.xhtml");
    builder.viewNode("details", "/pages/publishers-details.xhtml");
    builder.viewNode("deleted", "/pages/publishers-deleted.xhtml");
    builder.viewNode("form", "/pages/publishers-form.xhtml");
    builder.viewNode("exit", "/index.xhtml");

    builder.methodCallNode("invoke-update")
            .expression("#{publisherBean.update()}")
            .defaultOutcome("details");

    builder.methodCallNode("switch-fail")
            .defaultOutcome("invoke-publishers")
            .expression("#{publisherBean.switchFail()}");

    builder.switchNode("proceed-action-request")
            .defaultOutcome("switch-fail")
            .switchCase()
            .condition("#{publisherBean.actionType.ifEdit()}").fromOutcome("form");

    builder.switchNode("go-for-it")
            .defaultOutcome("switch-fail")
            .switchCase()
            .switchCase()
            .condition("#{publisherBean.actionType.ifEdit()}").fromOutcome("invoke-update");

as you can see, there is two switch nodes. First directs to a View Node, second one is trying to direct to a Method Call Node.

First one works fine, however second is giving me a headache. Second one is giving me an error

Unable to find matching navigation case with from-view-id '/pages/publishers-form.xhtml' for action '#{publisherBean.proceed()}' with outcome 'proceed-form'.

proceed function is just

public String proceed() {
        LOG.log(Level.OFF, "Form proceed in action type {0}", actionType);
        return "go-for-it";
    }

Logged info confirms, that publisherBean.actionType.ifEdit() returns true, however that fact is ignored. If i change outcome from invoke-update to form or any other View Node id, then it "works fine".

Is it i'm doing something wrong, or Method Call Node cant be used as an outcome to a Switch Node?

T.G
  • 1,913
  • 1
  • 16
  • 29

1 Answers1

0

I run into this issue too. In my case the problem is in calling Method Call Node after another Method Call Node.

I invesigated it a bit and found a problem in: com.sun.faces.application.NavigationHandlerImpl.synthesizeCaseStruct method. This method is used to determine where to go from methodCallNode or switchCallNode and it only looks at viewNodes and returnNodes.

private CaseStruct synthesizeCaseStruct(FacesContext context, Flow flow, String fromAction, String outcome) {
    CaseStruct result = null;

    FlowNode node = flow.getNode(outcome);
    if (null != node) {
        if (node instanceof ViewNode) {
            result = new CaseStruct();
            result.viewId = ((ViewNode)node).getVdlDocumentId();
            result.navCase = new MutableNavigationCase(fromAction, 
                    fromAction, outcome, null, result.viewId, 
                    flow.getDefiningDocumentId(), null, false, false);
        } else if (node instanceof ReturnNode) {
            String fromOutcome = ((ReturnNode)node).getFromOutcome(context);
            FlowHandler flowHandler = context.getApplication().getFlowHandler();
            try {
                flowHandler.pushReturnMode(context);
                result = getViewId(context, fromAction, fromOutcome, FlowHandler.NULL_FLOW);
                // We are in a return node, but no result can be found from that
                // node.  Show the last displayed viewId from the preceding flow.
                if (null == result) {
                    Flow precedingFlow = flowHandler.getCurrentFlow(context);
                    if (null != precedingFlow) {
                        String toViewId = flowHandler.getLastDisplayedViewId(context);
                        if (null != toViewId) {
                            result = new CaseStruct();
                            result.viewId = toViewId;
                            result.navCase = new MutableNavigationCase(context.getViewRoot().getViewId(),
                                    fromAction,
                                    outcome,
                                    null,
                                    toViewId,
                                    FlowHandler.NULL_FLOW,                            
                                    null,
                                    false,
                                    false);

                        }
                    }
                } else {
                    result.newFlow = FlowImpl.SYNTHESIZED_RETURN_CASE_FLOW;
                }
            }
            finally {
                flowHandler.popReturnMode(context);
            }

        }
    } else {
        // See if there is an implicit match within this flow, using outcome
        // to derive a view id within this flow.
        String currentViewId = outcome;
        // If the viewIdToTest needs an extension, take one from the currentViewId.
        String currentExtension;
        int idx = currentViewId.lastIndexOf('.');
        if (idx != -1) {
            currentExtension = currentViewId.substring(idx);
        } else {
            // PENDING, don't hard code XHTML here, look it up from configuration
            currentExtension = ".xhtml";
        }
        String viewIdToTest = "/" + flow.getId() + "/" + outcome + currentExtension;
        ViewHandler viewHandler = Util.getViewHandler(context);
        viewIdToTest = viewHandler.deriveViewId(context, viewIdToTest);
        if (null != viewIdToTest) {
            result = new CaseStruct();
            result.viewId = viewIdToTest;
            result.navCase = new MutableNavigationCase(fromAction, 
                    fromAction, outcome, null, result.viewId, 
                    null, false, false);
        }

    }
    return result;
}