Yes, one way to do that is using two action methods: one for the validation and another for the real action. That's actually the way I've been doing it myself for some projects.
One good way to do it is to create a composite component wrapping this functionality, so that you can reuse it in other places.
Create a composite component in WebContent/resources/my/confirmButton.xhtml
, with the following code:
resources/my/confirmButton.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
<cc:attribute name="message" default="Do you want to proceed?" />
<cc:attribute name="messageHeader" default="Confirm" />
<cc:attribute name="action" required="true"
method-signature="java.lang.String action()" />
<cc:attribute name="validateMethod" required="true"
method-signature="java.lang.String action()" />
<cc:attribute name="value" default="Submit" />
<cc:attribute name="cancelBtn" default="No" />
<cc:attribute name="confirmBtn" default="Yes" />
</cc:interface>
<cc:implementation>
<rich:popupPanel id="popup" header="#{cc.attrs.messageHeader}">
<p>#{cc.attrs.message}</p>
<input type="button" value="#{cc.attrs.cancelBtn}"
onclick="#{rich:component('popup')}.hide()" />
<a4j:commandButton action="#{cc.attrs.action}"
value="#{cc.attrs.confirmBtn}" execute="@form" render="@form"
onclick="#{rich:component('popup')}.hide()" />
</rich:popupPanel>
<a4j:commandButton action="#{cc.attrs.validateMethod}"
value="#{cc.attrs.value}" execute="@form" render="@form"
oncomplete="if(#{empty facesContext.maximumSeverity}){
#{rich:component('popup')}.show()
}" />
</cc:implementation>
</html>
You may want to change it, adding attributes and styling as you see necessary.
Having done that, you can declare the namespace for your component your JSF views, and use and reuse like this:
<!DOCTYPE html>
<html ... xmlns:my="http://java.sun.com/jsf/composite/my">
...
<h:form>
<rich:messages />
<h:panelGrid>
Please, type something:
<h:inputText value="#{someBean.someValue}" required="true" />
<!-- simple example with the default labels: -->
<my:confirmButton action="#{someBean.action}"
validateMethod="#{someBean.preAction}" />
<!-- second example calling other method and using custom labels: -->
<my:confirmButton action="#{someBean.action2}"
validateMethod="#{someBean.preAction}" value="action 2"
message="Do you REALLY want to proceed?" />
</h:panelGrid>
</h:form>
...
</html>
See also:
Composite Component tag info