Let's have a look at the JSP template from our example: TutorialStockQuote8.jsp It's a very simple example of displaying live stock quotes from a web service. The stock quotes are returned in a collection of quote records and stored in request attribute called ?quotes?. Also, the column headers are in a collection of strings and stored in a request attribute called ?columns?.
<%@ taglib uri='/WEB-INF/templates/jsp/tld/template.tld' prefix='jetspeed' %> <%@ page import = "org.apache.turbine.util.Log" %> <%@ page import = "org.apache.jetspeed.webservices.finance.stockmarket.StockQuote" %> <% try{ StockQuote[] quotes = (StockQuote[]) request.getAttribute("quotes"); String[] columns = (String[]) request.getAttribute("columns"); String jspeid = (String) request.getAttribute("js_peid"); %> <FORM METHOD="POST"> <INPUT TYPE="hidden" NAME="js_peid" VALUE="<%=jspeid%>"> Enter symbol(s) separated with commas: <input name="symbols" type="TEXT"><INPUT TYPE="SUBMIT" NAME="refresh" VALUE="Get Quotes"> </FORM> <table> <tr> <td> <table border="true" cellspacing="1" cellpadding="3"> <tr> <%for (int i = 0; columns != null && i < columns.length; i++) {%> <TH><%=columns[i]%></TH> <%}%> </tr> <%for (int j = 0; quotes != null && j < quotes.length; j++) {%> <tr> <TD><%=quotes[j].getSymbol()%></TD> <TD><%=quotes[j].getPrice()%></TD> <TD><%=quotes[j].getChange()%></TD> <TD><%=quotes[j].getVolume()%></TD> </tr> <%}%> </table> </td> </tr> </table> <%} catch (Exception e) { Log.error(e); return; }%>
Also, you will note that one additional request attribute is retrieved: jspeid. The value of this attribute is used to define a hidden field "js_peid" which uniquely identifies this portlet when its form is submitted via the "refresh" button:
<INPUT TYPE="hidden" NAME="js_peid" VALUE="<%=jspeid%>">
Adding the above field in your template assures that when multiple instances of the portlet are used on the same pane, the refresh will only apply to particular portlet instance. This concept applies to Velocity portlets as well.