|
From: Chad B. <cwb...@us...> - 2008-07-24 21:03:34
|
User: cwbrandon
Date: 08/07/24 14:03:44
Modified: andromda-jsf2/src/main/resources/templates/jsf2/utils
JsfUtils.java.vsl
andromda-jsf2/src/main/resources/templates/jsf2/controllers
Controller.java.vsl
Log:
Add ability to prevent more than one execution of an action upon either refreshs or multiple clicks (only enabled for portlets at this point).
Revision Changes Path
1.8 +37 -0 cartridges/andromda-jsf2/src/main/resources/templates/jsf2/utils/JsfUtils.java.vsl
Index: JsfUtils.java.vsl
===================================================================
RCS file: /cvsroot/andromdaplugins/cartridges/andromda-jsf2/src/main/resources/templates/jsf2/utils/JsfUtils.java.vsl,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -w -r1.7 -r1.8
--- JsfUtils.java.vsl 1 Jul 2008 15:42:41 -0000 1.7
+++ JsfUtils.java.vsl 24 Jul 2008 21:03:44 -0000 1.8
@@ -342,6 +342,43 @@
}
/**
+ * Finds the command that uses the action method on the given component.
+ *
+ * @param component the component from which to start the search.
+ * @param actionMethod the action method (i.e. controller.myMethod)
+ * @return the component or null of not found.
+ */
+ public static javax.faces.component.UICommand findCommand(final javax.faces.component.UIComponent component, final String actionMethod)
+ {
+ javax.faces.component.UICommand found = null;
+ if (component instanceof javax.faces.component.UICommand)
+ {
+ final javax.faces.el.MethodBinding action = ((javax.faces.component.UICommand)component).getAction();
+ if (action != null)
+ {
+ final String methodName = action.getExpressionString() != null ? action.getExpressionString().replaceAll(".\\{|\\}", "") : null;
+ if (actionMethod.equals(methodName))
+ {
+ found = (javax.faces.component.UICommand)component;
+ }
+ }
+ }
+ if (found == null && component != null)
+ {
+ for (final java.util.Iterator iterator = component.getFacetsAndChildren(); iterator.hasNext();)
+ {
+ final javax.faces.component.UIComponent childComponent = (javax.faces.component.UIComponent)iterator.next();
+ found = findCommand(childComponent, actionMethod);
+ if (found != null)
+ {
+ break;
+ }
+ }
+ }
+ return found;
+ }
+
+ /**
* Uses the converter identified by converterId to convert the value to a String.
* @value the value to be converted
* @converterId the id of the converter to be used
1.25 +136 -44 cartridges/andromda-jsf2/src/main/resources/templates/jsf2/controllers/Controller.java.vsl
Index: Controller.java.vsl
===================================================================
RCS file: /cvsroot/andromdaplugins/cartridges/andromda-jsf2/src/main/resources/templates/jsf2/controllers/Controller.java.vsl,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -w -r1.24 -r1.25
--- Controller.java.vsl 22 Jul 2008 16:08:17 -0000 1.24
+++ Controller.java.vsl 24 Jul 2008 21:03:44 -0000 1.25
@@ -53,37 +53,51 @@
#if ($formPopulationOperationRequired)
final $action.fullyQualifiedFormImplementationName form =
this.$action.formImplementationGetter;
-
- // - pass any properties from the previous form along
- ${managedBeansPackage}.${formPopulatorName}.populateForm(currentForm, form);
- // - populate the form with any event attributes that may match
- // IMPORTANT: it isn't possible to automatically populate any property named "id" since that
- // is a reserved name in JSF (the id of a component), therefore we have to unfortunately ignore any availble "id" attribute
- ${managedBeansPackage}.${formPopulatorName}.populateFormFromPropertyMap(
- form, form.getDateTimeFormatters(), (java.util.Map)this.getRequestAttribute(ACTION_EVENT_ATTRIBUTES), new String[] {"id"});
- // - populate the form with any request attributes that may match
- ${managedBeansPackage}.${formPopulatorName}.populateFormFromRequestAttributes(form, form.getDateTimeFormatters(), false);
- // - populate the form with any request parameters that may match
- ${managedBeansPackage}.${formPopulatorName}.populateFormFromPropertyMap(
- form, form.getDateTimeFormatters(), this.getContext().getExternalContext().getRequestParameterMap());
-#end
- try
- {
-#if (!$action.formFields.empty)
this.setForm("$action.formKey", form, true);
#end
- forward = #processTransition($action)
- final javax.faces.application.FacesMessage.Severity messageSeverity = this.getMaximumMessageSeverity();
- if (messageSeverity != null && javax.faces.application.FacesMessage.SEVERITY_ERROR.getOrdinal() <= messageSeverity.getOrdinal())
+## - For now we'll just have the transaction checking in portlets (might be worth while to add to standalone at some point)
+#set($indent = "")
+#if ($portlet)
+#set($indent = " ")
+ if (this.isTransactionValid("${controller.beanName}.${action.triggerName}"))
{
+#end
+#if ($formPopulationOperationRequired)
+ ${indent}// - pass any properties from the previous form along
+ ${indent}${managedBeansPackage}.${formPopulatorName}.populateForm(currentForm, form);
+ ${indent}// - populate the form with any event attributes that may match
+ ${indent}// IMPORTANT: it isn't possible to automatically populate any property named "id" since that
+ ${indent}// is a reserved name in JSF (the id of a component), therefore we have to unfortunately ignore any availble "id" attribute
+ ${indent}${managedBeansPackage}.${formPopulatorName}.populateFormFromPropertyMap(
+ ${indent}form, form.getDateTimeFormatters(), (java.util.Map)this.getRequestAttribute(ACTION_EVENT_ATTRIBUTES), new String[] {"id"});
+ ${indent}// - populate the form with any request attributes that may match
+ ${indent}${managedBeansPackage}.${formPopulatorName}.populateFormFromRequestAttributes(form, form.getDateTimeFormatters(), false);
+ ${indent}// - populate the form with any request parameters that may match
+ ${indent}${managedBeansPackage}.${formPopulatorName}.populateFormFromPropertyMap(
+ ${indent}form, form.getDateTimeFormatters(), this.getContext().getExternalContext().getRequestParameterMap());
+#end
+ ${indent}forward = #processTransition($action)
+#if ($portlet)
+ ${indent}this.setLastForward(forward);
+#end
+ ${indent}final javax.faces.application.FacesMessage.Severity messageSeverity = this.getMaximumMessageSeverity();
+ ${indent}if (messageSeverity != null && javax.faces.application.FacesMessage.SEVERITY_ERROR.getOrdinal() <= messageSeverity.getOrdinal())
+ ${indent}{
#if ($formPopulationOperationRequired)
// - copy any messages to the 'currentForm'
- org.apache.commons.beanutils.PropertyUtils.setProperty(currentForm,
- "$formMessagesProperty", org.apache.commons.beanutils.PropertyUtils.getProperty(form, "$formMessagesProperty"));
+ ${indent}org.apache.commons.beanutils.PropertyUtils.setProperty(currentForm,
+ ${indent}"$formMessagesProperty", org.apache.commons.beanutils.PropertyUtils.getProperty(form, "$formMessagesProperty"));
#end
- this.setForm("$action.formKey", currentForm, $portlet);
- }
+ ${indent}this.setForm("$action.formKey", currentForm, $portlet);
+ ${indent}}
#saveMessages($action " ")
+#if ($portlet)
+ }
+ else
+ {
+ forward = this.getLastForward();
+ }
+#end
#if (!$action.formFields.empty && $action.formResetRequired)
form.reset();
#end
@@ -92,24 +106,19 @@
{
logger.error(throwable);
this.setForm("$action.formKey", currentForm, $portlet);
- final String messageKey = ${managedBeansPackage}.${patternMatchingExceptionHandler}.instance().handleException(throwable);
- if(org.apache.commons.lang.StringUtils.isEmpty(messageKey))
- {
- throw throwable;
- }
- else
+ try
{
+ final String messageKey = ${managedBeansPackage}.${patternMatchingExceptionHandler}.instance().handleException(throwable);
+ // - the exception is re-thrown by the exception handler and handled by the catch below if it can't get a messageKey
+ // (no reason to check for presence of messageKey)
this.addErrorMessage(${managedBeansPackage}.Messages.get(messageKey, null));
}
- }
- }
- catch (final Throwable throwable)
+ catch (Throwable exception)
{
- this.setForm("$action.formKey", currentForm, $portlet);
- this.addExceptionMessage(throwable);
// - set the forward to null so that we stay on the current view
forward = null;
- logger.error(throwable);
+ this.addExceptionMessage(exception);
+ }
}
return forward;
#end
@@ -734,5 +743,88 @@
this.setPortletMode(javax.portlet.PortletMode.HELP);
return "${controller.useCase.portletHelpForwardName}";
}
+
+ /**
+ * Indicates whether or not the current transaction is valid (i.e. checks
+ * that the transaction token - if available - is different than what is stored
+ * for the last transaction token).
+ * @param actionName the action name.
+ * @return whether or not transaction is valid
+ */
+ protected boolean isTransactionValid(final String actionName)
+ {
+ boolean valid = true;
+ final String transactionTokeName = this.getTransactionTokenName();
+ if (transactionTokeName != null)
+ {
+ final javax.faces.component.UIComponent command = ${managedBeansPackage}.JsfUtils.findCommand(
+ javax.faces.context.FacesContext.getCurrentInstance().getViewRoot(), actionName);
+ final String currentToken = command != null ? (String)command.getAttributes().get(transactionTokeName) : null;
+ if (currentToken != null)
+ {
+ final String lastToken = (String)this.getSessionAttribute(
+ transactionTokeName);
+ valid = !currentToken.equals(lastToken);
+ if (valid)
+ {
+ this.setSessionAttribute(
+ transactionTokeName, currentToken);
+ }
+ }
+ }
+ return valid;
+ }
+
+ /**
+ * Gets the name of the attribute that stores the transaction token.
+ *
+ * @return the name of the transaction token or null if not available.
+ */
+ protected String getTransactionTokenName()
+ {
+ String transactionTokenName = null;
+ try
+ {
+ final Class transactionTokenClass = Thread.currentThread().getContextClassLoader().loadClass(
+ "org.andromda.cartridges.jsf2.component.TransactionToken");
+ transactionTokenName = (String)transactionTokenClass.getField("TRANSACTION_TOKEN").get(null);
+ }
+ catch (Exception exception)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(exception);
+ }
+ }
+ return transactionTokenName;
+ }
+
+ /**
+ * The variable that stores the last forward.
+ */
+ private static final String LAST_FORWARD = "AndroMDA_LastForward";
+
+ /**
+ * Gets the current value of the last forward.
+ *
+ * @return the last forward.
+ */
+ private String getLastForward()
+ {
+ return (String)this.getSessionAttribute(LAST_FORWARD);
+ }
+
+ /**
+ * Sets the current value of the last forward.
+ *
+ * @param forward the last forward
+ */
+ private void setLastForward(String forward)
+ {
+ if (forward != null)
+ {
+ this.setSessionAttribute(LAST_FORWARD, forward);
+ }
+ }
#end
}
\ No newline at end of file
|