3

The following seems to be ignore inside XHTML facelet templates:

<f:metadata>
    <f:viewParam name="id" value="#{backingBean.id}" />
</f:metadata>

(At least with Mojarra as per Glassfish2.2)

Java Server Faces 2.0 Complete Reference says p.540:

The f:metadata tag encapsulates the set of elements used to specify the metadata for a Facelet view, and therefore must be a child of the f:view tag and may not appear in a template. As of JSF2.0, the only purpose of this tag is to encapsulate f:viewParam tags.

It is tedious for my current application to have to include the above in every one of hundreds of XHTML pages, but it fails in the template, I can't introduce view parameter handling policies. Indeed what I would like is both, a mixture of view parameter handling policies common to all pages and then some extra handling for specific pages that take additional query parameters.

Glad for advice,

Webel

2 Answers2

3

Unfortunately, that's by spec. Your best bet is to use @ManagedProperty instead.

public class BackingBean {

    @ManagedProperty("#{param.id}")
    private Long id;

    // ...
}

The only disadvantage is that this doesn't offer the advantage of using declarative conversion/validation by XHTML. You can if necessary do this job in a @PostConstruct method.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for this suggestion (and for your many other postings here on Stackoverflow which have helped me so often). By chance I have just been reading about this capability in JSF2 Complete Reference, but had not made the connection that I could use it for this purpose. – Webel IT Australia - upvoter Sep 13 '11 at 05:27
  • I've temporarily "unaccepted" this answer to invite more help with my specific problem. On implementing [com.sun.faces.mgbean.ManagedBeanCreationException: Unable to create managed bean tracker. The following problems were found: - The scope of the object referenced by expression #{param.idFrom}, request, is shorter than the referring managed beans (tracker) scope of session], where the session-scoped Tracker has [@ManagedProperty("#{param.idFrom}") private Long idFrom;] It is intrinsic to the problem, and my desire for policy across the application, that I use session scope. Any ideas ? – Webel IT Australia - upvoter Sep 13 '11 at 09:01
  • Am seeing whether I can get away with a separate RequestTracker for my problem, and also found this tip from BalusC that works for View scope "grab it manually from the request parameter map during bean's construction." public ViewBean() { id = Integer.valueOf(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id"));} http://stackoverflow.com/questions/4579711/managedpropertyvalue-param-id-in-a-non-request-scope-bean – Webel IT Australia - upvoter Sep 13 '11 at 09:29
  • Ok I now have a session scoped Tracker (still has purpose) and siphoned off a dedicated request scoped RequestTracker that has a @ManagedProperty idFrom and performs a specific task well. Instead of 2 lines (f:viewParam and usage component insertion) in each of 100s or 1000s of XHTML pages I now have a single line (for usage component insertion for the #{requestTracker} in my template, and a ManagedProperty declaration in RequestTracker. Super ! – Webel IT Australia - upvoter Sep 13 '11 at 09:44
  • You're welcome. Sorry for not responding sooner, it was just bed time for me (GMT-4) :) – BalusC Sep 13 '11 at 12:19
0

Answering my own question so can share solution with code markup (I wish one could put code markup in comments instead of needing an answer, or if one can please advise how):

/** Unlike {@link Tracker}, only tracks within a single request.
 * 
 * This is useful for the idFrom request parameter tracking in combination
 * with an idFrom @ManagedProperty.
 * 
 * This can't be done in session scope.
 *
 * @author darrenkelly
 */
@ManagedBean
@RequestScoped
public class RequestTracker extends All_ {

    /** Creates a new instance of RequestTracker */
    public RequestTracker() {
    }

    @EJB private ElementQuery elementQuery;    

    @ManagedProperty("#{param.idFrom}")
    private Long idFrom;    
    /**
     * The id of the element page one came from to reach a tracked overview page.
     * 
     * @return 
     */
    public Long getIdFrom() {
        return idFrom;
    }    

    public void setIdFrom(Long idFrom) {
        if (idFrom != null) {
            this.idFrom = idFrom;
            elementFrom = elementQuery.find(idFrom);
            if (elementFrom == null) {
                String $error = "No element with identifier idFrom(" + idFrom + ") found as referring element";
                JsfUtil.addErrorMessage($error);
            }
        }
    }

    private Element elementFrom;

    /** The Element from whose page one came to a another page.
     */
    public Element getElementFrom() {
        return elementFrom;
    }

    public void setElementFrom(Element elementFrom) {
        this.elementFrom = elementFrom;
    }    
}