Hello, On Wed, 2006-07-26 at 15:54 +0200, tetaslap tetaslap wrote: > Hi, > I'm currently working on a web-application wich use MyFace, > Tomahawk, Spring, Hibernate, AcegiSecurity and Birt. > I would like to prevent the user from submiting a form several times. > Which is the best practice for that ? > I read about filters, but I got no idea how to user it. i looked also for a solution but did not find one.
So i wrote an EpochPhaseListener that uses the jsf_sequence that i found
in myfaces. This listener checks if the sequence is higher than in the
last request, and otherwise directly invokes jsfContext.renderResponse.
You have to register the listener in the faces-config.xml, just add the
following below the application element:
<lifecycle>
<phase-listener>com.freiheit.ark.control.EpochPhaseListener</phase-listener>
</lifecycle>
See the code below, but be aware that's it's not yet really tested... ;)
public final class EpochPhaseListener implements PhaseListener {
private static final String JSF_SEQUENCE_OLD = "jsf_sequence_old";
private static final long serialVersionUID = 2L;
private static final Log LOG = LogFactory.getLog( EpochPhaseListener.class
);
/* (non-Javadoc)
* @see
javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
*/
public void afterPhase( PhaseEvent e ) {
}
/* (non-Javadoc)
* @see
javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
*/
public void beforePhase( PhaseEvent e ) {
/* get the current epoch from the request
*/
final Map params =
e.getFacesContext().getExternalContext().getRequestParameterMap();
Integer epoch = null;
if ( params != null ) {
final Object epochObj = params.get( RendererUtils.SEQUENCE_PARAM );
if ( epochObj != null ) {
if ( LOG.isDebugEnabled() )
LOG.debug( "Have jsf sequence from request with value " +
epochObj );
try {
epoch = Integer.valueOf( (String)epochObj );
} catch ( Exception ex ) {
LOG.warn( "Could not read epoch from value " + epochObj, ex
);
}
}
}
final Object session =
e.getFacesContext().getExternalContext().getSession( false );
/* if we have no epoch from the form, we read it from the session
*/
if ( epoch == null ) {
if ( session instanceof HttpSession ) {
epoch = (Integer) ((HttpSession)session).getAttribute(
JSF_SEQUENCE_OLD );
}
}
if ( epoch != null && session instanceof HttpSession ) {
final HttpSession httpSession = (HttpSession)session;
if ( LOG.isDebugEnabled() )
LOG.debug( "Have jsf sequence from session with value " +
httpSession.getAttribute( RendererUtils.SEQUENCE_PARAM ) );
final Integer epochOld = (Integer) httpSession.getAttribute(
JSF_SEQUENCE_OLD );
if ( epochOld != null ) {
/* if the current epoch is not higher than the old one,
* we do not want to invoke the application, but render
* directly the response.
*/
if ( epoch <= epochOld ) {
LOG.info( "Got invalid request, ommitting application
invocation." );
e.getFacesContext().renderResponse();
}
}
if ( epochOld == null || epochOld < epoch ) {
httpSession.setAttribute( JSF_SEQUENCE_OLD, epoch );
}
}
}
/* (non-Javadoc)
* @see javax.faces.event.PhaseListener#getPhaseId()
*/
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
I hope that is what you looked for,
cheers,
Martin
signature.asc
Description: This is a digitally signed message part

