Search in sources :

Example 1 with ViewMetadata

use of jakarta.faces.view.ViewMetadata in project myfaces by apache.

the class NavigationHandlerImpl method handleNavigation.

@Override
public void handleNavigation(FacesContext facesContext, String fromAction, String outcome, String toFlowDocumentId) {
    NavigationContext navigationContext = new NavigationContext();
    NavigationCase navigationCase = null;
    try {
        navigationCase = getNavigationCommand(facesContext, navigationContext, fromAction, outcome, toFlowDocumentId);
    } finally {
        navigationContext.finish(facesContext);
    }
    if (navigationCase != null) {
        if (log.isLoggable(Level.FINEST)) {
            log.finest("handleNavigation fromAction=" + fromAction + " outcome=" + outcome + " toViewId =" + navigationCase.getToViewId(facesContext) + " redirect=" + navigationCase.isRedirect());
        }
        boolean isViewActionProcessingBroadcastAndRequiresRedirect = false;
        if (UIViewAction.isProcessingBroadcast(facesContext)) {
            // f:viewAction tag always triggers a redirect to enforce execution of
            // the lifecycle again. Note this requires enables flash scope
            // keepMessages automatically, because a view action can add messages
            // and these ones requires to be renderer afterwards.
            facesContext.getExternalContext().getFlash().setKeepMessages(true);
            String fromViewId = (facesContext.getViewRoot() == null) ? null : facesContext.getViewRoot().getViewId();
            String toViewId = navigationCase.getToViewId(facesContext);
            // lifecycle is not necessary.
            if (fromViewId == null && toViewId != null) {
                isViewActionProcessingBroadcastAndRequiresRedirect = true;
            } else if (fromViewId != null && !fromViewId.equals(toViewId)) {
                isViewActionProcessingBroadcastAndRequiresRedirect = true;
            }
        }
        if (navigationCase.isRedirect() || isViewActionProcessingBroadcastAndRequiresRedirect) {
            // Need to add the FlowHandler parameters here.
            FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
            List<Flow> activeFlows = FlowHandlerImpl.getActiveFlows(facesContext, flowHandler);
            Flow currentFlow = flowHandler.getCurrentFlow(facesContext);
            Flow targetFlow = calculateTargetFlow(facesContext, outcome, flowHandler, activeFlows, toFlowDocumentId);
            Map<String, List<String>> navigationCaseParameters = navigationCase.getParameters();
            // sourceFlow and targetFlow could both be null so need to have multiple checks here
            if (currentFlow != targetFlow) {
                // Ensure that at least one has a value and check for equality
                if ((currentFlow != null && !currentFlow.equals(targetFlow)) || (targetFlow != null && !targetFlow.equals(currentFlow))) {
                    if (navigationCaseParameters == null) {
                        navigationCaseParameters = new HashMap<>(5, 1f);
                    }
                    // include the following entries:
                    if (currentFlow != null && targetFlow == null) {
                        // Set the TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME parameter
                        navigationCaseParameters.put(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, Arrays.asList(FlowHandler.NULL_FLOW));
                        // Set the FLOW_ID_REQUEST_PARAM_NAME
                        navigationCaseParameters.put(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, Arrays.asList(""));
                    } else {
                        // If current flow (sourceFlow) is null and new flow (targetFlow) is not null,
                        // include the following entries:
                        // If we make it this far we know the above statement is true due to the other
                        // logical checks we have hit to this point.
                        // Set the TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME parameter
                        navigationCaseParameters.put(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, Arrays.asList((toFlowDocumentId == null ? "" : toFlowDocumentId)));
                        // Set the FLOW_ID_REQUEST_PARAM_NAME
                        navigationCaseParameters.put(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, Arrays.asList(targetFlow.getId()));
                    }
                }
            }
            ExternalContext externalContext = facesContext.getExternalContext();
            ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
            String toViewId = navigationCase.getToViewId(facesContext);
            String redirectPath = viewHandler.getRedirectURL(facesContext, toViewId, NavigationUtils.getEvaluatedNavigationParameters(facesContext, navigationCaseParameters), navigationCase.isIncludeViewParams());
            // The spec doesn't say anything about how to handle redirect but it is
            // better to apply the transition here where we have already calculated the
            // route than add the parameters and delegate to
            // FlowHandler.clientWindowTransition(facesContext)
            applyFlowTransition(facesContext, navigationContext);
            // Clear ViewMap if we are redirecting to other resource
            UIViewRoot viewRoot = facesContext.getViewRoot();
            if (viewRoot != null && !toViewId.equals(viewRoot.getViewId())) {
                // call getViewMap(false) to prevent unnecessary map creation
                Map<String, Object> viewMap = viewRoot.getViewMap(false);
                if (viewMap != null) {
                    viewMap.clear();
                }
            }
            // JSF 2.0 the javadoc of handleNavigation() says something like this
            // "...If the view has changed after an application action, call
            // PartialViewContext.setRenderAll(true)...". The effect is that ajax requests
            // are included on navigation.
            PartialViewContext partialViewContext = facesContext.getPartialViewContext();
            String viewId = facesContext.getViewRoot() != null ? facesContext.getViewRoot().getViewId() : null;
            if (partialViewContext.isPartialRequest() && !partialViewContext.isRenderAll() && toViewId != null && !toViewId.equals(viewId)) {
                partialViewContext.setRenderAll(true);
            }
            // Dispose view if the view has been marked as disposable by default action listener
            ViewPoolProcessor processor = ViewPoolProcessor.getInstance(facesContext);
            if (processor != null && processor.isViewPoolEnabledForThisView(facesContext, facesContext.getViewRoot())) {
                processor.disposeView(facesContext, facesContext.getViewRoot());
            }
            // JSF 2.0 Spec call Flash.setRedirect(true) to notify Flash scope and take proper actions
            externalContext.getFlash().setRedirect(true);
            try {
                externalContext.redirect(redirectPath);
                facesContext.responseComplete();
            } catch (IOException e) {
                throw new FacesException(e.getMessage(), e);
            }
        } else {
            ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
            // create new view
            String newViewId = navigationCase.getToViewId(facesContext);
            // JSF 2.0 the javadoc of handleNavigation() says something like this
            // "...If the view has changed after an application action, call
            // PartialViewContext.setRenderAll(true)...". The effect is that ajax requests
            // are included on navigation.
            PartialViewContext partialViewContext = facesContext.getPartialViewContext();
            String viewId = facesContext.getViewRoot() != null ? facesContext.getViewRoot().getViewId() : null;
            if (partialViewContext.isPartialRequest() && !partialViewContext.isRenderAll() && newViewId != null && !newViewId.equals(viewId)) {
                partialViewContext.setRenderAll(true);
            }
            if (facesContext.getViewRoot() != null && facesContext.getViewRoot().getAttributes().containsKey(CALL_PRE_DISPOSE_VIEW)) {
                try {
                    facesContext.getAttributes().put(MyFacesVisitHints.SKIP_ITERATION_HINT, Boolean.TRUE);
                    VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, MyFacesVisitHints.SET_SKIP_ITERATION);
                    facesContext.getViewRoot().visitTree(visitContext, PreDisposeViewCallback.INSTANCE);
                } finally {
                    facesContext.getAttributes().remove(MyFacesVisitHints.SKIP_ITERATION_HINT);
                }
            }
            applyFlowTransition(facesContext, navigationContext);
            // Dispose view if the view has been marked as disposable by default action listener
            ViewPoolProcessor processor = ViewPoolProcessor.getInstance(facesContext);
            if (processor != null && processor.isViewPoolEnabledForThisView(facesContext, facesContext.getViewRoot())) {
                processor.disposeView(facesContext, facesContext.getViewRoot());
            }
            // create UIViewRoot for new view
            UIViewRoot viewRoot = null;
            String derivedViewId = viewHandler.deriveViewId(facesContext, newViewId);
            if (derivedViewId != null) {
                ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(facesContext, derivedViewId);
                if (vdl != null) {
                    ViewMetadata metadata = vdl.getViewMetadata(facesContext, newViewId);
                    if (metadata != null) {
                        viewRoot = metadata.createMetadataView(facesContext);
                    }
                }
            }
            // - viewHandler.deriveViewId() returned null
            if (viewRoot == null) {
                viewRoot = viewHandler.createView(facesContext, newViewId);
            }
            facesContext.setViewRoot(viewRoot);
            facesContext.renderResponse();
        }
    } else {
        // no navigationcase found, stay on current ViewRoot
        if (log.isLoggable(Level.FINEST)) {
            log.finest("handleNavigation fromAction=" + fromAction + " outcome=" + outcome + " no matching navigation-case found, staying on current ViewRoot");
        }
    }
}
Also used : ViewHandler(jakarta.faces.application.ViewHandler) VisitContext(jakarta.faces.component.visit.VisitContext) IOException(java.io.IOException) ViewDeclarationLanguage(jakarta.faces.view.ViewDeclarationLanguage) ViewPoolProcessor(org.apache.myfaces.view.facelets.ViewPoolProcessor) FacesException(jakarta.faces.FacesException) Flow(jakarta.faces.flow.Flow) NavigationCase(jakarta.faces.application.NavigationCase) ExternalContext(jakarta.faces.context.ExternalContext) List(java.util.List) ArrayList(java.util.ArrayList) PartialViewContext(jakarta.faces.context.PartialViewContext) FlowHandler(jakarta.faces.flow.FlowHandler) UIViewRoot(jakarta.faces.component.UIViewRoot) ViewMetadata(jakarta.faces.view.ViewMetadata)

Example 2 with ViewMetadata

use of jakarta.faces.view.ViewMetadata in project myfaces by apache.

the class ViewHandlerImpl method getViewParameterList.

private Map<String, List<String>> getViewParameterList(FacesContext context, String viewId, Map<String, List<String>> parametersFromArg) {
    UIViewRoot viewRoot = context.getViewRoot();
    String currentViewId = viewRoot.getViewId();
    Collection<UIViewParameter> toViewParams = null;
    Collection<UIViewParameter> currentViewParams = ViewMetadata.getViewParameters(viewRoot);
    if (currentViewId.equals(viewId)) {
        toViewParams = currentViewParams;
    } else {
        String calculatedViewId = getViewIdSupport(context).deriveLogicalViewId(context, viewId);
        // we cannot use this.getVDL() directly (see getViewHandler())
        // ViewDeclarationLanguage vdl = getViewHandler(context).
        // getViewDeclarationLanguage(context, calculatedViewId);
        // -= Leonardo Uribe =- Temporally reverted by TCK issues.
        ViewDeclarationLanguage vdl = getViewDeclarationLanguage(context, calculatedViewId);
        ViewMetadata viewMetadata = vdl.getViewMetadata(context, viewId);
        if (viewMetadata != null) {
            UIViewRoot viewFromMetaData = viewMetadata.createMetadataView(context);
            toViewParams = ViewMetadata.getViewParameters(viewFromMetaData);
        }
    }
    if (toViewParams == null || toViewParams.isEmpty()) {
        return parametersFromArg;
    }
    // we need to use a custom Map to add the view parameters,
    // otherwise the current value of the view parameter will be added to
    // the navigation case as a static (!!!) parameter, thus the value
    // won't be updated on any following request
    // (Note that parametersFromArg is the Map from the NavigationCase)
    // Also note that we don't have to copy the Lists, because they won't be changed
    Map<String, List<String>> parameters = new HashMap<>(parametersFromArg);
    for (UIViewParameter viewParameter : toViewParams) {
        if (!parameters.containsKey(viewParameter.getName())) {
            String parameterValue = viewParameter.getStringValueFromModel(context);
            if (parameterValue == null) {
                if (currentViewId.equals(viewId)) {
                    parameterValue = viewParameter.getStringValue(context);
                } else {
                    if (viewParameter.getName() != null) {
                        for (UIViewParameter curParam : currentViewParams) {
                            if (viewParameter.getName().equals(curParam.getName())) {
                                parameterValue = curParam.getStringValue(context);
                                break;
                            }
                        }
                    }
                }
            }
            if (parameterValue != null) {
                // since we have checked !parameters.containsKey(viewParameter.getName())
                // here already, the parameters Map will never contain a List under the
                // key viewParameter.getName(), thus we do not have to check it here (again).
                List<String> parameterValueList = new ArrayList<>(1);
                parameterValueList.add(parameterValue);
                parameters.put(viewParameter.getName(), parameterValueList);
            }
        }
    }
    return parameters;
}
Also used : HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) UIViewParameter(jakarta.faces.component.UIViewParameter) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) ViewDeclarationLanguage(jakarta.faces.view.ViewDeclarationLanguage) UIViewRoot(jakarta.faces.component.UIViewRoot) ViewMetadata(jakarta.faces.view.ViewMetadata)

Example 3 with ViewMetadata

use of jakarta.faces.view.ViewMetadata in project myfaces by apache.

the class UIViewRoot method encodeEnd.

@Override
public void encodeEnd(FacesContext context) throws IOException {
    Assert.notNull(context, "context");
    if (!context.getResponseComplete()) {
        super.encodeEnd(context);
        // the call to encodeAll() on every UIViewParameter here is only necessary
        // if the current request is _not_ an AJAX request, because if it was an
        // AJAX request, the call would already have happened in PartialViewContextImpl and
        // would anyway be too late here, because the state would already have been generated
        PartialViewContext partialContext = context.getPartialViewContext();
        if (!partialContext.isAjaxRequest()) {
            ViewDeclarationLanguage vdl = context.getApplication().getViewHandler().getViewDeclarationLanguage(context, getViewId());
            if (vdl != null) {
                // If the current view has view parameters, as indicated by a non-empty
                // and non-UnsupportedOperationException throwing
                // return from ViewDeclarationLanguage.getViewMetadata(jakarta.faces.context.FacesContext, String)
                ViewMetadata metadata = null;
                try {
                    metadata = vdl.getViewMetadata(context, getViewId());
                } catch (UnsupportedOperationException e) {
                    _getLogger().log(Level.SEVERE, "Exception while obtaining the view metadata: " + e.getMessage(), e);
                }
                if (metadata != null) {
                    try {
                        Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(this);
                        if (!viewParams.isEmpty()) {
                            // call UIViewParameter.encodeAll(jakarta.faces.context.FacesContext) on each parameter.
                            for (UIViewParameter param : viewParams) {
                                param.encodeAll(context);
                            }
                        }
                    } catch (UnsupportedOperationException e) {
                    // If calling getViewParameters() causes UnsupportedOperationException
                    // to be thrown, the exception must be silently swallowed.
                    }
                }
            }
        }
    }
    try {
        notifyListeners(context, PhaseId.RENDER_RESPONSE, getAfterPhaseListener(), false);
    } catch (Exception e) {
        // following the spec we have to swallow the exception
        _getLogger().log(Level.SEVERE, "Exception while processing phase listener: " + e.getMessage(), e);
    }
}
Also used : PartialViewContext(jakarta.faces.context.PartialViewContext) ViewDeclarationLanguage(jakarta.faces.view.ViewDeclarationLanguage) AbortProcessingException(jakarta.faces.event.AbortProcessingException) IOException(java.io.IOException) ViewMetadata(jakarta.faces.view.ViewMetadata)

Example 4 with ViewMetadata

use of jakarta.faces.view.ViewMetadata in project myfaces by apache.

the class FaceletViewDeclarationLanguageTest method testBuildViewUIViewParameters.

/**
 * Test case for MYFACES-3002.
 */
@Test
public void testBuildViewUIViewParameters() throws Exception {
    // build a UIViewRoot with a UIViewParameter
    ViewMetadata viewMetadata = this.vdl.getViewMetadata(facesContext, "viewparameter1.xhtml");
    UIViewRoot root = viewMetadata.createMetadataView(facesContext);
    facesContext.setViewRoot(root);
    // UIViewParameter must be there
    checkUIViewParameter(root);
    // build and render view (must not remove UIViewParameter)
    vdl.buildView(facesContext, root, "viewparameter1.xhtml");
    vdl.renderView(facesContext, root);
    // UIViewParameter must still be there, because its value is saved in the state!
    checkUIViewParameter(root);
}
Also used : UIViewRoot(jakarta.faces.component.UIViewRoot) ViewMetadata(jakarta.faces.view.ViewMetadata) Test(org.junit.Test)

Example 5 with ViewMetadata

use of jakarta.faces.view.ViewMetadata in project myfaces by apache.

the class ViewMetadataTestCase method testSimpleViewMetadata.

@Test
public void testSimpleViewMetadata() throws Exception {
    HelloWorld helloWorld = new HelloWorld();
    facesContext.getExternalContext().getRequestMap().put("helloWorldBean", helloWorld);
    Set<NavigationCase> cases = new HashSet<NavigationCase>();
    NavigationCase navCase = new NavigationCase("viewMetadata.xhtml", null, "somePage.xhtml", null, "somePage.xhtml", null, false, false);
    cases.add(navCase);
    navigationHandler.getNavigationCases().put("somePage.xhtml", cases);
    navigationHandler.getNavigationCase(facesContext, null, "somePage.xhtml");
    ViewMetadata metadata = vdl.getViewMetadata(facesContext, "viewMetadata.xhtml");
    UIViewRoot root = metadata.createMetadataView(facesContext);
    Collection<UIViewParameter> viewParameters = metadata.getViewParameters(root);
    Assert.assertEquals(1, viewParameters.size());
    // root.setViewId("viewMetadata.xhtml");
    vdl.buildView(facesContext, root, "viewMetadata.xhtml");
    facesContext.setViewRoot(root);
    StringWriter sw = new StringWriter();
    ResponseWriter mrw = new HtmlResponseWriterImpl(sw, "text/html", "UTF-8");
    facesContext.setResponseWriter(mrw);
    root.encodeAll(facesContext);
    sw.flush();
    System.out.print(sw.toString());
}
Also used : StringWriter(java.io.StringWriter) NavigationCase(jakarta.faces.application.NavigationCase) ResponseWriter(jakarta.faces.context.ResponseWriter) HtmlResponseWriterImpl(org.apache.myfaces.renderkit.html.HtmlResponseWriterImpl) UIViewParameter(jakarta.faces.component.UIViewParameter) UIViewRoot(jakarta.faces.component.UIViewRoot) HelloWorld(org.apache.myfaces.view.facelets.bean.HelloWorld) HashSet(java.util.HashSet) ViewMetadata(jakarta.faces.view.ViewMetadata) Test(org.junit.Test)

Aggregations

ViewMetadata (jakarta.faces.view.ViewMetadata)13 UIViewRoot (jakarta.faces.component.UIViewRoot)10 ViewDeclarationLanguage (jakarta.faces.view.ViewDeclarationLanguage)9 FacesException (jakarta.faces.FacesException)5 ViewHandler (jakarta.faces.application.ViewHandler)4 UIViewParameter (jakarta.faces.component.UIViewParameter)3 FlowHandler (jakarta.faces.flow.FlowHandler)3 IOException (java.io.IOException)3 Test (org.junit.Test)3 MessageUtils.getExceptionMessageString (com.sun.faces.util.MessageUtils.getExceptionMessageString)2 Application (jakarta.faces.application.Application)2 NavigationCase (jakarta.faces.application.NavigationCase)2 ViewExpiredException (jakarta.faces.application.ViewExpiredException)2 PartialViewContext (jakarta.faces.context.PartialViewContext)2 ResponseStateManager (jakarta.faces.render.ResponseStateManager)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Util.getViewHandler (com.sun.faces.util.Util.getViewHandler)1 ValueExpression (jakarta.el.ValueExpression)1