1

Most of my page navigation uses get requests and now I have a form where the parameters should be included as query-string parameters using f:param inside h:commandButton or checking attributes for includeViewParams to use UIViewParameter.

I do not want to use includeViewParams since this would include all view defined parameters, I just want to use the ones provided as child's of the command component.

<h:form>
    <p:inputText value="#{bean.value1}"/>
    <p:selectOneMenu value="#{bean.value2}"/>
    <p:commandButton action="#{utilBean.performActionParams(outcome)}">
        <f:param name="key1" value="#{bean.value1}"/>
        <o:param name="key1" value="#{bean.value2}" converter="#{bean.converter}/>
    </p:commandButton>
</h:form>

public String performActionParams(final String outcome)
{
    final UriBuilder uriBuilder = UriBuilder.fromPath(outcome);

    final FacesContext context = FacesContext.getCurrentInstance();
    final UIComponent component = UIComponent.getCurrentComponent(context);

    for (final UIComponent child : component.getChildren())
        if (child instanceof UIParameter)
        {
            final UIParameter param = (UIParameter) child;

            if (!param.isDisable() && !StringUtils.isBlank(param.getName()))
            {
                final Object value = param.getValue();

                if (value != null)
                    uriBuilder.queryParam(param.getName(), value);
            }
        }

    return uriBuilder.build().toString();
}

This logic is not really complicated but it seems so redundant since it seems to be the same logic as in h:link and h:button.

So does someone knows where this logic is implemented?

djmj
  • 5,579
  • 5
  • 54
  • 92
  • Don't really understand your question. The check is done in the `RESTORE_VIEW` phase, with a call to `ViewDeclarationLanguage.getViewMetadata()` which, in your case will return an instance of `ViewMetadata` **because** you're using GET navigation *and* your destination page has a ``. What is your question? Do you want to override metadata handling? – kolossus May 26 '13 at 16:46
  • Somewhere in jsf there must be the code which reads `f:param` from within `h:link` and creates a target uri. I editet answer and posted my code which basically is a workaround and does the same as `h:link`, just for the usage with a commandbutton. I just think my code is redundant since somewhere in jsf this is already coded. – djmj May 27 '13 at 01:53

1 Answers1

0

In Mojarra, this kind of logic is also buried in OutcomeTargetRenderer#getEncodedTargetURL() (and in HtmlBasicRenderer#getParamList()). The only public part which is provided by the API is the ViewHandler#getBookmarkableURL(), however it takes a Map as parameter map, not a list of UIParameter components.

I'm not sure what the concrete functional requirement is, but so far it seems that you actually want to fire a simple GET request and not a POST request. In that case, you should be using <h:link> or <h:button> (or <p:button>). Their renderers extend from OutcomeTargetRenderer having this logic internally implemented. You can just use EL in outcome attribute (the probable assumption that this is not possible was perhaps your reason why you tried a command button).

<p:button outcome="#{outcome}">
    <f:param name="key1" value="#{value1}" />
    <o:param name="key1" value="#{value2}" converter="#{bean.converter}" />
</p:button>

Update: as per the comments, the concrete functional requirement is basically to turn a JSF POST form along with the submitted data into a GET request. In that case, it'd be easier if you bind the inputs to a Map which is ready for use in getBookmarkableURL().

<h:inputText value="#{bean.params.key1}" />
<h:inputText value="#{bean.params.key2}" />
<p:commandButton value="#{bean.submit(outcome)}" />

with

private Map<String, String> params;

@PostConstruct
public void init() {
    params = new HashMap<>();
}

public String submit(outcome) {
    // ...

    return context.getApplication().getViewHandler()
        .getBookmarkableURL(context, outcome, params, false);

    // TODO: Is faces-redirect=true also considered?
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • But the form input parameters '#{bean.query}' for example would not be evaluated since we have no postback in this case (those values could also be set via viewParam). I edited my example to use a form with input parameters, sorry to forgot that. Will have a look at your method references. – djmj May 27 '13 at 15:18
  • Oh, this way. That makes completely sense. Well, there's a way, I will update the answer. – BalusC May 27 '13 at 15:26
  • 1
    Doesn't need your map be of type: `Map>`?. For certain use cases this looks promising, but what if not just String's with `inputText` should be handled (hence the Converter in my example using `o:param`). Furthermore if the bean values could also be set via `f:viewParam` this would force me to always use a map (just with String's?) for those or at least create it. Maybe using combination of `HtmlBasicRenderer.getParamList()` with `getBookmarkableURL()`. But this would enforce to be tied to mojarra which is also not a good idea. – djmj May 27 '13 at 16:05