1

I am finding view params will not be passed from a page where the backing bean is different on the target page. How can I pass the product param from test1.xhtml to test2.xhtml?

test.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">

<body>
    <f:metadata>
        <o:viewParam name="product" value="#{holder.value}"
            converter="#{productConverter}"
            converterMessage="Bad request. Unknown product." required="true"
            requiredMessage="Bad request. Please use a link from within the system." />
    </f:metadata>
    <h:link outcome="/test2.xhtml" includeViewParams="true">link</h:link>

</body>
</html>

test2.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">

<h:head></h:head>
<body>
    <f:metadata>
        <o:viewParam name="product" value="#{holder2.value}"
            converter="#{productConverter}"
            converterMessage="Bad request. Unknown product." required="true"
            requiredMessage="Bad request. Please use a link from within the system." />
    </f:metadata>
    <h:link outcome="/test.xhtml" includeViewParams="true">link</h:link>
</body>
</html>

Holder.java

@ManagedBean
@ViewScoped
public class Holder<T> implements Serializable {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }


}

Holder2.java

@ManagedBean
@ViewScoped
public class Holder2<T> implements Serializable {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }


}

Product.java

public class Product {

    private String name;

    public Product(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }



}

Product Converter

public class ProductConverter implements Converter {

        private Map<String,Product> productMap=new HashMap<String, Product>();

        public ProductConverter(List<Product> products) {
            for (Product product:products){
                productMap.put(product.getName().toLowerCase(), product);
            }
        }

        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            return productMap.get(value.toLowerCase());
        }

        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
              if (!(value instanceof Product) ) {
                    return null;
                }

                return ((Product) value).getName().toLowerCase();
        }





    }
DD.
  • 21,498
  • 52
  • 157
  • 246

2 Answers2

1
<h:link outcome="/test2.xhtml?includeViewParams=true">link</h:link>

This is not the right way to let JSF include view parameters in a <h:link>. Supplying it as a query string parameter is only valid in action attribute of UICommand components.

You need the includeViewParams attribute of the <h:link> instead.

<h:link outcome="/test2.xhtml" includeViewParams="true">link</h:link>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I've changed my question to reflect your suggestions but still have the same issue. – DD. Dec 27 '12 at 14:04
  • What JSF impl/version? Note that it's only included if the target view has also those view parameters declared in the meta data. So based on your code snippets posted so far, this should be already fine. – BalusC Dec 27 '12 at 15:12
  • Sorry, I can't reproduce your problem on Mojarra 2.1.13 with the code posted so far. Didn't you oversimplify too much? Are you certain that the `getAsString()` of the converter isn't broken? – BalusC Dec 27 '12 at 19:31
  • I've included all the classes without any simplifications. – DD. Dec 27 '12 at 20:37
  • How is the converter registered/created? Its constructor taking `List` wouldn't be used by JSF at all. – BalusC Dec 27 '12 at 20:43
  • Registered using Spring...the converter seems to work ok everywhere else. – DD. Dec 27 '12 at 21:43
  • I was able to reproduce your problem. Completely unexpectedly, it includes the view parameter from the model of the target view instead of from the model of the current view. If you've had used `#{holder.value}` in the both views (like I did during my initial test, sorry for that), then it'd have worked. If you really need 2 separate beans holding the same value, then you should use `` in the link. I'm not posting this as answer yet because this behavior is too much like a bug in Mojarra. I'd have to investigate it tomorrow or this weekend. – BalusC Dec 28 '12 at 04:11
0

@ViewScoped is only valid for postbacks - if you change the URL, the bean dies.

To pass parameters between facelets, use <ui:param>

8bitjunkie
  • 12,793
  • 9
  • 57
  • 70
  • 2
    Whilst your statement is true, this is not exactly the cause of OP's concrete problem. The OP is attempting to auto-include the view parameters in the link URL. Plus, the `` deserves an entirely different purpose, it's to pass parameters between Facelets (within a single request/composition!), you probably meant to suggest `` to pass parameters between requests. – BalusC Dec 27 '12 at 13:23
  • Isn't the usage of `` just the answer? – djmj Dec 28 '12 at 01:13