开发者

View parameters in different beans

I've got a page called trip.xhtml where I take parameters out of the URL using the following code:

<f:metadata>
    <f:viewParam name="tripid" value="#{tripBean.tripId}" />
    <f:viewParam name="seats" value="#{tripBean.seats}" />
    <f:event type="preRenderView" listener="#{tripBean.processParams}" />
</f:metadata>

The TripBean looks like this (simplified):

@ManagedBean
@RequestScoped
public class TripBean implements Serializable {

    private static final long serialVersionUID = -4885781058258859229L;

    private Long tripId;
    private int seats;

    // Getters and setters for tripId and seats

On the bottom of the trip.xhtml page I have a h:link:

<h:link outcome="/customer/booking.xhtml" value="Book this trip"
    includeViewParams="true" />

What I expect is that the URL I get when I click this link is something like "/customer/booking.jsf?tripid=2&seats=1". This is only the case when I put the following code on my booking.xhtml page:

<f:metadata>
    <f:viewParam name="tripid" value="#{tripBean.tripId}" />
    <f:viewParam name="seats" value="#{tripBean.seats}" />
</f:metadata>

Although what I actually want is to use another bean. Changing the code to:

<f:metadata>
    <f:viewParam name="tripid"开发者_运维技巧 value="#{bookingBean.tripId}" />
    <f:viewParam name="seats" value="#{bookingBean.seats}" />
</f:metadata>

The BookingBean also has 2 properties tripId and seats which are identical to the TripBean, but when I try to click the link now, I only see a seats-parameter which is set to 0. ("/customer/booking.jsf?seats=0")

Does anyone have any idea why I can't seem to pass the viewparams to the other page when I'm trying to use another bean to store them in? And IF it is impossible to store it in another bean, how can I put those values from TripBean in BookingBean?

Quick work-around I used: Not using includeViewParams="true" , but adding parameters to the link manually (see below) "fixes" the problem. Although I'm still wondering why it won't work with includeViewParams!

<h:link outcome="/customer/booking.xhtml" value="#{msg['page.trip.booking']}">
    <f:param name="tripid" value="#{tripBean.tripId}" />
    <f:param name="seats" value="#{tripBean.seats}" />
</h:link>


f:viewParam works exactly like h:inputText. This means that it uses the same expression as a source (when rendering) and as a target (when updating the model). If you had:

<h:inputText value="#{a.test}" />

You would never ask "how to make the inputText read from b.foo and write to a.test", yet everyone seems to expect such behavior from f:viewParam.

Anyway, there is a simple answer. To append any values to link, you just need to use f:param:

<h:link outcome="/customer/booking.xhtml" value="Book this trip" >
    <f:param name="tripid" value="#{bookingBean.tripId}" />
    <f:param name="seats" value="#{bookingBean.seats}" />
</h:link>


The link content corresponding to the following tag:

<h:link outcome="/customer/booking.xhtml" value="Book this trip"
            includeViewParams="true" />

is generated during the render-response phase of the request for the trip.xhtml view. If you need the URL to contain the view parameter values, then you must provide these values in the URL used to access the view, or you must set these values in the model, before the render-response phase is complete. If you do not perform either of these, the generated hyperlink will contain the default values for the view parameters.

In simpler words, you must:

  • either ensure that the trip.xhtml view is accessed with the necessary parameters: trip.xhtml?tripid=x&seats=y, especially if the view is to be accessed with parameters at all times.
  • or you must set the values in a method that gets executed before the link is rendered by the JSF runtime. The constructor of the BookingBean class or a @PostConstruct annotated method in the class would be ideal places to set the values. You could also reset/update the values of the bean in other methods of your managed bean, in the event of actions being performed in the view. Note, that JSF runtime will invoke getTripId and getSeats to include the values of the view parameters tripId and seats in the resulting URL, so you ought to verify the behavior of these methods as well.

Your question on why you are unable to specify bookingBean in the EL expression for booking.xhtml, instead requiring you to specify the supposedly unexpected value of tripBean is due to the fact that the includeViewParams attribute of the link tag, will include the parameters of the to-view and not the from-view. Simply put, the JSF runtime will invoke bookingBean.getTripId() and bookingBean.getSeats() and not tripBean.getTripId() and tripBean.getSeats().

While this might seem counter-intuitive, you ought to understand that the JSF specification treats this scenario quite differently. In most interactions performed by a user, the action URL of a component is generated when the user performs the action and not until then. The link tag on the other hand, requires preemptive computation of the URL, and hence the JSF runtime treats this quite differently as "pre-emptive navigation". When the URL is being constructed, the objects pertaining to the view parameters of the target view must be accessible, in order for the URL to be meaningful. The reason for the values being 0 in the URL, is that a new BookingBean instance is created during this evaluation and the default values are being used instead. You can quite obviously avoid this by using the TripBean instead (and most examples of includeViewParams demonstrate this), or you can set values during the construction of the BookingBean object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜