|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 5
"deleter" (DeleteVoAction) is an implementation of AjaxAction, as you can see if you refer back to Figure 1. The idea is to separate the actual knowledge of how to delete an object from the user interface layer and also allow the
delete logic to be used elsewhere. That is, the AjaxCommand interface subclass, whose job it is to deal with the nuts and
bolts of the request, employs the AjaxAction to decouple itself from the business logic.
In this example, the DeleteVoAction just delegates to a facade call. You might start out with the facade call in the AjaxCommand itself and refactor it out later.
You make some gains by moving the facade call into the AjaxAction. First, implementing an interface means the object that knows about the facade (which is presumably in the core of the application)
can be placed into that package or project. That is to say, you may not want to include a reference from an AjaxAction subclass (which might be in a JSF/front-end specific project) to the facade class.
Another benefit of moving the logic out into an interface implementation is that you can defer the actual subclass to someone else, who may not even be a member of your team. This flexibility is useful if you are creating a framework for someone else. Such flexibility is the core motivation behind the GOF Command pattern, although it isn't such a common requirement for Web application developers.
Looking at the handleAjaxRequest method from the DeleteWithId will give you a more concrete idea of how the backing bean deals with the Ajax request.
public class DeleteWithId implements AjaxCommand {
...
public void handleAjaxRequest(FacesContext context) {
HttpServletRequest request =
(HttpServletRequest)context.getExternalContext().getRequest();
String id = request.getParameter("com.company.jsf.id"); // Get id
BusinessObject bo = businessObjectUtil.getNodeFromId(id);
if (bo == null){ log.info("Didn't find object with id: " + id); return; }
boolean success = true;
String detail = vo.getLiteralName() + " deleted.";
try {
deleter.action(bo);
} catch (Exception e){
if (log.isWarnEnabled()) { log.warn("Failed to delete entity: ", e); }
success = false;
detail = e.getMessage(); // Get error message for response
}
HttpServletResponse response =
(HttpServletResponse)context.getExternalContext().getResponse();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
try {
if (success){
String responseString = new String("<message>"+
"<status>OK</status>"+
"<detail>"+detail+"</detail>"+
"<id>"+id+"</id>"+
"</message>");
response.getWriter().write(responseString);
} else {
String responseString = new String("<message>"+
"<status>ERROR</status>"+
"<detail>"+detail+"</detail>"+
"<detail>"+detail+"</detail>"+
"<id>"+id+"</id>"+
"</message>");
response.getWriter().write(responseString);
}
} catch (IOException ioe){
if (log.isErrorEnabled()) { log.error(
"Exception writing ajax response: ", ioe); }
}
}
...
}
The essence of this method is as follows:
responseComplete() back on the PhaseListener.
A quick look at deleter.action() (DeleteVoAction.action()) shows that this method just delegates the job:
public class DeleteVoAction implements JsfAction{
...
public void action(Object o){
CoreVO[] nodePath = (CoreVO[])o;
VOHelper.getFacade().deleteVO(nodePath);
}
...
The last step for the server side is to set up the phase listener, which is easy. Your first step is to define the listener in your faces-config.xml file, as shown in Listing 7.
<faces-config>
...
<lifecycle>
<phase-listener>
ajaxcommand.toolbox.jsf.listeners.AjaxListener
</phase-listener>
</lifecycle>
...
</faces-config>
Next, in the listener itself, you tell JSF when to execute the listener. Start by telling it what phase to run in, like so:
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
You then have a choice of running in the public void afterPhase (PhaseEvent event) method or the public void beforePhase (PhaseEvent event).
In this case you'll choose to run the listener in the RESTORE_VIEW phase. You are handling an Ajax request, so you want to avoid the rest of the processing life cycle. In this example, you
implement the event handling in the beforePhase method. Because you aren't relying on any view components, you don't even require the view to be present. The managed bean
does the work for you.
Archived Discussions (Read only)