You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by ta...@apache.org on 2006/02/10 20:52:08 UTC
svn commit: r376821 - in
/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors:
MethodReplayDecisionMaker.java MethodReplayInterceptor.java
TransactionalMethodReplayDecisionMaker.java
Author: taylor
Date: Fri Feb 10 11:52:07 2006
New Revision: 376821
URL: http://svn.apache.org/viewcvs?rev=376821&view=rev
Log:
transactional interceptors to playback failed DAO DML operations
useful for databases such as Oracle TAF for failover of client connections
Added:
portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayDecisionMaker.java
portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayInterceptor.java
portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/TransactionalMethodReplayDecisionMaker.java
Added: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayDecisionMaker.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayDecisionMaker.java?rev=376821&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayDecisionMaker.java (added)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayDecisionMaker.java Fri Feb 10 11:52:07 2006
@@ -0,0 +1,22 @@
+package org.apache.jetspeed.util.interceptors;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * A interface which is akin to a <B>gateway</B>
+ * in BPMN notation. Concrete implementations can make a decision
+ * as to whether or not a method invocation should be replayed.
+ *
+ * @author a336317
+ */
+public interface MethodReplayDecisionMaker {
+
+ /**
+ *
+ * @param invocation The MethodInvocation object
+ * @param exception Exception thrown on previous invocation attempt
+ * @return True if we should replay the method, false otherwise
+ */
+ public boolean shouldReplay(MethodInvocation invocation, Exception exception);
+
+}
Added: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayInterceptor.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayInterceptor.java?rev=376821&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayInterceptor.java (added)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/MethodReplayInterceptor.java Fri Feb 10 11:52:07 2006
@@ -0,0 +1,126 @@
+package org.apache.jetspeed.util.interceptors;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Generic aspect that will attempt to replay a method invocation
+ * if one of a set of specified exceptions is thrown from its execution.
+ *
+ * @author a336317
+ */
+public class MethodReplayInterceptor implements MethodInterceptor {
+
+ /** Log reference */
+ private Log log = LogFactory.getLog(MethodReplayInterceptor.class);
+
+ /** Serialization version identifier */
+ private static final long serialVersionUID = -1316279974504594833L;
+
+ /** How many times we should attempt to retry the method invocation if it fails */
+ private int retryCount;
+
+ /** How long we should wait before retrying - specified in milliseconds **/
+ private int retryInterval;
+
+ /** Object which decides whether or not a method invocation should be replayed */
+ private TransactionalMethodReplayDecisionMaker replayDecisionMaker;
+
+ /**
+ * Encloses <code>super.invoke()</code> in a try/catch block, where the
+ * catch block contains additional retry logic.
+ */
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ //TODO Make this more elegant - this logic can be simpler
+ try{
+ return invocation.proceed();
+ }
+ catch(Exception exp){
+
+ //determine whether to retry or just throw the exception back up
+ if(!this.isReplayable(invocation,exp)){
+ throw exp;
+ }
+
+ //TODO should this be at level WARN/ERROR?
+ if(log.isDebugEnabled()){
+ log.debug("Invocation for method ["+ invocation.getMethod().toString()
+ +"] failed. Will attempt to replay method invocation ["+ retryCount +"] times with an interval of ["+ retryInterval +"] milliseconds");
+ }
+
+ int retryCounter = 1;
+ Exception lastExp = null;
+
+ while((retryCounter<retryCount)){
+
+ try{
+ if(log.isDebugEnabled()){
+ log.debug("Sleeping for ["+ retryInterval +"] milliseconds before replaying invocation for method ["+ invocation.getMethod().toString() +"].");
+ }
+ Thread.sleep(this.retryInterval);
+
+ if(log.isDebugEnabled()){
+ log.debug("Attempt invocation ["+ retryCounter +"] for method ["+ invocation.getMethod().toString() +"].");
+ }
+ //returning from a finally block will discard the
+ //exception
+ return invocation.proceed();
+ }
+ catch(Exception exp2){
+ //determine whether to retry or just throw the exception back up
+ if(!this.isReplayable(invocation,exp)){
+ throw exp;
+ }
+
+ if(log.isDebugEnabled()){
+ log.debug("Attempt ["+ retryCounter +"] to replay invocation for method ["+ invocation.getMethod().toString()
+ +"] failed. ["+ (retryCount - retryCounter) +"] attempts left.");
+ }
+
+ lastExp = exp2;
+ retryCounter++;
+ }
+ }
+ if(log.isDebugEnabled()){
+ log.debug("["+ retryCounter +"] attempts to replay invocation for method ["+ invocation.getMethod().toString()
+ +"] failed. Throwing exception ["+ lastExp.getClass().getName() +"]");
+ }
+ throw lastExp;
+ }
+
+ }
+
+ public int getRetryCount() {
+ return retryCount;
+ }
+
+ public void setRetryCount(int retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ public int getRetryInterval() {
+ return retryInterval;
+ }
+
+ public void setRetryInterval(int retryInterval) {
+ this.retryInterval = retryInterval;
+ }
+
+ /**
+ * Determine if we should attempt to replay the method given that the previous
+ * invocation returned the passed exception.
+ * @param exp
+ * @return True if we should replay the method.
+ */
+ private boolean isReplayable(MethodInvocation invocation, Exception exp){
+ return replayDecisionMaker.shouldReplay(invocation,exp);
+ }
+
+ public void setReplayDecisionMaker(
+ TransactionalMethodReplayDecisionMaker replayDecisionMaker) {
+ this.replayDecisionMaker = replayDecisionMaker;
+ }
+
+}
Added: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/TransactionalMethodReplayDecisionMaker.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/TransactionalMethodReplayDecisionMaker.java?rev=376821&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/TransactionalMethodReplayDecisionMaker.java (added)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/util/interceptors/TransactionalMethodReplayDecisionMaker.java Fri Feb 10 11:52:07 2006
@@ -0,0 +1,82 @@
+package org.apache.jetspeed.util.interceptors;
+
+import java.sql.SQLException;
+import java.util.StringTokenizer;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * MethodReplayDecisionMaker intended for use with methods marked as transactional,
+ * where the decision to replay the method is based on the content of the underlying
+ * exception from the resource.
+ *
+ * @author a336317
+ */
+public class TransactionalMethodReplayDecisionMaker implements
+ MethodReplayDecisionMaker {
+
+ private int[] sqlErrorCodes;
+
+ public boolean shouldReplay(MethodInvocation invocation, Exception exception) {
+
+ //TODO This needs to be a lot more elegant than it currently is - see Spring code
+ //for exception translators to see what we can do here.
+
+ //exception must be of type SQLException and have an error code value, else we keep
+ //walking down the root cause tree to a maximum depth of 3
+ if(exception.getCause() instanceof SQLException){
+ SQLException sqlExp = (SQLException)exception.getCause();
+ int errorCode = sqlExp.getErrorCode();
+
+ if(errorCode!=0){
+ return isErrorCodeListed(errorCode);
+ }
+ }
+
+ if(exception.getCause().getCause() instanceof SQLException){
+
+ SQLException sqlExp = (SQLException)exception.getCause().getCause();
+ int errorCode = sqlExp.getErrorCode();
+
+
+ if(errorCode!=0){
+ return isErrorCodeListed(errorCode);
+ }
+ }
+
+ if(exception.getCause().getCause().getCause() instanceof SQLException){
+ SQLException sqlExp = (SQLException)exception.getCause().getCause().getCause();
+ int errorCode = sqlExp.getErrorCode();
+
+
+ if(errorCode!=0){
+ return isErrorCodeListed(errorCode);
+ }
+ }
+
+
+ return false;
+ }
+
+
+ public void setSqlErrorCodes(String sqlErrorCodesString) {
+ StringTokenizer tokenizer = new StringTokenizer(sqlErrorCodesString,",");
+
+ this.sqlErrorCodes = new int[tokenizer.countTokens()];
+
+ for(int i=0;tokenizer.hasMoreTokens();i++){
+ this.sqlErrorCodes[i] = new Integer(tokenizer.nextToken()).intValue();
+ }
+ }
+
+
+ private boolean isErrorCodeListed(int errorCode){
+ for(int i=0;i<this.sqlErrorCodes.length;i++){
+
+ if(this.sqlErrorCodes[i]==errorCode) return true;
+
+ }
+ return false;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org