The action events link to a data entry form for entering Coffee records. The form supports Add, Edit and Delete modes. Here we see edit mode:
This portlet is also a Velocity Portlet. Like all Velocity portlets, it has a templates and an action.
<parameter name="template" value="coffees-form" hidden="true"/> <parameter name="action" value="portlets.TutorialCoffeesAction" />
The form posts back to itself by default.
<form method="post" action="$jslink.setAction("portlets.TutorialCoffeesAction")">
An action event is connected to the button:
<input type="submit" name="eventSubmit_doUpdate" value="Save"/>
<tr> #formCell ("Brand of Coffee" "coffeeName" $!coffee.CoffeeName) </tr> <tr> #formCell ("Supplier Id" "supplierId" $!coffee.SupplierId) </tr> <tr> #formCell ("Unit Price" "price" $!coffee.Price) </tr> <tr> #formCell ("Sales Tax" "sales" $!coffee.Sales) </tr> <tr> #formCell ("Total Price" "total" $!coffee.Total) </tr>
Finally we have an action event (TutorialCoffeesAction) that stores the row to the database.
public void doUpdate(RunData rundata, Context context) throws Exception { Coffees coffee = null; Connection con = null; try { con = Torque.getConnection(); coffee = (Coffees)rundata.getUser().getTemp(SESSION_COFFEE); if(coffee == null) { Log.error(NO_CURRENT_REC); rundata.setMessage(NO_CURRENT_REC); return; } rundata.getParameters().setProperties(coffee); validate(coffee); coffee.save(con); con.commit(); returnToBrowser(rundata, true); } catch (Exception e) { Log.error("error in saving coffee: " + e); rundata.setMessage(e.toString()); if (con != null) { con.rollback(); } } finally { try { Torque.closeConnection(con); } catch (Exception e) {} } }
The update method is used by both Add and Update modes. Take note of the usage of Torque's object-relational programming model. The objects can store themselves. The Coffees objects were automatically generated for you as a task in the tutorials ant build. First we get a connection:
con = Torque.getConnection();
then get the object from the session, which was placed there when the link was clicked on from the database browser.
coffee = (Coffees)rundata.getUser().getTemp(SESSION_COFFEE);
The parameter parser will automatically populate any bean, as long as the names of the inputs on the HTML form match (case-insensitive) the names of the properties on the bean.
rundata.getParameters().setProperties(coffee);
We then validate and save the input, finally committing it:
validate(coffee); coffee.save(con); con.commit();
If there is an error, we store the error message for later retrieval from our template:
rundata.setMessage(e.toString());
#if ($data.Message) <tr> <td colspan="2"> <table bgcolor="red"> <tr> <td> $data.Message </td> </tr> </table> </td> </tr> #end
Finally, we redirect to the browser on success and invalidate the browser to refresh and pick up the modifications:
JetspeedLink link = JetspeedLinkFactory.getInstance(rundata); DynamicURI duri = link.getPaneByName("TutorialCoffeesBrowser"); if (refresh) { duri.addQueryData(CoffeesBrowserAction.BROWSER_COMMAND, CoffeesBrowserAction.BROWSER_REFRESH); } rundata.setRedirectURI(duri.toString()); JetspeedLinkFactory.putInstance(link);