views:

541

answers:

2

Hey there,

I have two JSPs where I am displaying some info from database in a h:dataTable. One of them is showing all the info, and one of them user specifically. I have showXML.jsp that shows the "XML" column of a dataTable row detailedly, since a String that big wouldn't be nice in the dataTable. So what I'm doing is passing the row id and the navigation case, to navigate back to the parent page.

<h:commandLink action="show_xml" value="Show">
   <f:param name="cid" value="#{row.id}" />
   <f:param name="toview" value="history" />
</h:commandLink>

On the xml page I have a h:commandLink with it's action set to a method:

JSP:

<h:outputText value="#{calculationBean.xml}" />
...
<h:commandLink action="#{myBean.toView}" value="Back to history" />

Backing Bean:

public String toView() {
    return "back_to_" + Util.getRequestParameter("toview");
}

Problem is that on the xml page, methods get invoked multiple times. For example the getXML() method in the h:outputText gets called once when it successfully gets the cid parameter with the getRequestParameter, and again, when I click on the Back to history link, but this time the cid parameter is null, traditionally causing NullPointerException.

EDIT:


On the dataTable page, each row has 4 commandLinks, with 2 params each. Not sure this does any harm, however something seems to slow down/crash the server after a few navigation clicks. I always close my resources after database access.

EDIT2: Performance issues were caused because I've been aquiring connections through a @Resource. This has been solved after I started using standalone connections.

Is there any other way to get the name and navigate back to the parent page?


I'm probably stuck with some noobish problem, but I have been trying for some time now. Please if you have any idea, help!

Thanks in advance, Daniel

+2  A: 

Problem is that on the xml page, methods get invoked multiple times.

It should be only the getter methods which are called multiple times. That should actually not harm, unless they incorrectly contains more code logic than only returning the data or at highest lazy loading. Business logic belongs in constructors, initialization blocks and/or JSF event methods (valueChangeListener, action), but certainly not in a getter method. A getter is there to return data, nothing more.

when I click on the Back to history link, but this time the cid parameter is null

If the bean is request scoped and you didn't pass it as a request parameter to the subsequent request, then it will indeed be null. You need to pass it back as parameter as well, the same as you apparently successfully did for "toview" parameter.

On the dataTable page, each row has 4 commandLinks, with 2 params each. Not sure this does any harm, however something seems to slow down/crash the server after a few navigation clicks. I always close my resources after database access.

Maybe the code is unnecessarily loading too much data and/or storing/duplicating the data in the session scope. A java profiler may help in pinpoint the cause.

Is there any other way to get the name of the parent page?

Not as reliable as passing it as a parameter to the subsequent request. You're on the right track, it just needs to be streamlined. An alternative is <f:setPropertyActionListener>, but that's more useful for "complete" objects. You could for example use it for the row object so that it instantly get set during click on the commandlink. Example:

<h:dataTable value="#{bean.list}" var="row">
    ...
    <h:commandLink value="show" action="show">
        <f:setPropertyActionListener target="#{bean.row}" value="#{row}" />
        <f:param name="toview" value="history" />
    </h:commandLink>

This way you can instantly access #{bean.row} on show page.

BalusC
Thanks for all the answers, they are really helpful! The performance issue is because somehow the connections doesn't close, however I'm dealing with those resources with nested try-catch-finally blocks. I will look into that.
wheelie
+1  A: 
<h:outputText value="#{calculationBean.xml}" />
...
<h:commandLink action="#{myBean.toView}" value="Back to history" />

I'd say that the NullPointerException problem lies here. Your model relies on the cid request parameter being present, but when this page is submitted, the form does not send this parameter. I am guessing that calculationBean is request scope and requires the cid parameter to create the value behind the xml property. When the form is submitted, calculationBean is instantiated, causing it to try and read xml from the data source.

It is difficult to say for certain without seeing the complete logic and flow of the application, but changing it to this may do the trick:

<h:outputText value="#{calculationBean.xml}" />
...
<h:commandLink action="#{myBean.toView}" value="Back to history">
    <f:param name="cid" value="#{param.cid}" />
</h:commandLink>
McDowell
I should have pointed out - use an `outputLink` if you don't require any server-side logic to be invoked. It will cause a regular `GET` request versus `commandLink`'s `POST`.
McDowell
Thanks for the answer. `calculationBean` is `session` scoped, but you are right. The `xml` property is only a `getXML()` method, so every invoke causes it to get the parameter, even if it is `null`. I just fixed this by storing the parameter.
wheelie