Reputation: 4101
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
Upvotes: 1
Views: 1616
Reputation: 108969
<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>
Upvotes: 1
Reputation: 1109635
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.
Upvotes: 2