Index: java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.132 diff -u -r1.132 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 9 Apr 2003 18:37:59 -0000 1.132 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 18 Apr 2003 02:17:41 -0000 @@ -216,10 +216,9 @@ private HostConfiguration hostConfiguration; /** - * The maximum number of attempts to attempt recovery from an - * HttpRecoverableException. + * Handles method retries */ - private int maxRetries = 3; + private MethodRetryHandler methodRetryHandler; /** true if we are currently executing */ private boolean inExecute = false; @@ -2399,15 +2398,19 @@ */ private void processRequest(HttpState state, HttpConnection connection) throws HttpException, IOException { - LOG.trace( - "enter HttpMethodBase.processRequest(HttpState, HttpConnection)"); + LOG.trace("enter HttpMethodBase.processRequest(HttpState, HttpConnection)"); - //try to do the write - int retryCount = 0; - do { - retryCount++; + int execCount = 0; + boolean requestSent = false; + + // loop until the method is successfully processed, the retryHandler + // returns false or a non-recoverable exception is thrown + while (true) { + execCount++; + requestSent = false; + if (LOG.isTraceEnabled()) { - LOG.trace("Attempt number " + retryCount + " to write request"); + LOG.trace("Attempt number " + execCount + " to process request"); } try { if (!connection.isOpen()) { @@ -2415,40 +2418,30 @@ connection.open(); } writeRequest(state, connection); - used = true; //write worked, mark this method as used - break; //move onto the write + requestSent = true; + readResponse(state, connection); + // the method has successfully executed + used = true; + break; } catch (HttpRecoverableException httpre) { if (LOG.isDebugEnabled()) { LOG.debug("Closing the connection."); } - + connection.close(); + LOG.info("Recoverable exception caught when processing request"); // update the recoverable exception count. recoverableExceptionCount++; - - connection.close(); - LOG.info("Recoverable exception caught when writing request"); - if (retryCount == maxRetries) { + + // test if this method should be retried + if (!getMethodRetryHandler().retryMethod(this, httpre, execCount, requestSent)) { LOG.warn( - "Attempt to write request has reached max retries: " - + maxRetries); + "Recoverable exception caught but MethodRetryHandler.retryMethod() " + + "returned false, rethrowing exception" + ); throw httpre; } } - } while (retryCount <= maxRetries); - - //try to do the read - try { - readResponse(state, connection); - } catch (HttpRecoverableException httpre) { - LOG.warn("Recoverable exception caught when reading response"); - if (LOG.isDebugEnabled()) { - LOG.debug("Closing the connection."); - } - - connection.close(); - throw httpre; } - //everything should be OK at this point } /** @@ -2565,6 +2558,36 @@ */ public void setHostConfiguration(HostConfiguration hostConfiguration) { this.hostConfiguration = hostConfiguration; + } + + /** + * @return the methodRetryHandler + */ + public MethodRetryHandler getMethodRetryHandler() { + + if (methodRetryHandler == null) { + // a retry handler that will retry 3 times as long as the request has + // not been sent + methodRetryHandler = new MethodRetryHandler() { + public boolean retryMethod( + HttpMethod method, + HttpRecoverableException recoverableException, + int executionCount, + boolean requestSent + ) { + return (!requestSent && (executionCount <= 3)); + } + }; + } + + return methodRetryHandler; + } + + /** + * @param handler the methodRetryHandler to use when this method executed + */ + public void setMethodRetryHandler(MethodRetryHandler handler) { + methodRetryHandler = handler; } } Index: java/org/apache/commons/httpclient/MethodRetryHandler.java =================================================================== RCS file: java/org/apache/commons/httpclient/MethodRetryHandler.java diff -N java/org/apache/commons/httpclient/MethodRetryHandler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/org/apache/commons/httpclient/MethodRetryHandler.java 18 Apr 2003 02:17:41 -0000 @@ -0,0 +1,96 @@ +/* + * $Header: /home/cvspublic/jakarta-commons/httpclient/LICENSE.txt,v 1.4 2003/01/27 15:28:26 jsdever Exp $ + * $Revision: 1.4 $ + * $Date: 2003/01/27 15:28:26 $ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * [Additional notices, if required by prior licensing conditions] + * + */ + +package org.apache.commons.httpclient; + +/** + * A handler for determining if an HttpMethod should be retried after a + * recoverable exception during execution. + * + * @see HttpMethod#execute(HttpState, HttpConnection) + * @see HttpRecoverableException + * + * @author Michael Becke + */ +public interface MethodRetryHandler { + + /** + * Determines if a method should be retried after an HttpRecoverableException + * occurs during execution. + * + * @param method the method being executed + * @param recoverableException the exception that occurred + * @param executionCount the number of times this method has been + * unsuccessfully executed + * @param requestSent a flag indicating if the request has been fully sent or not + * + * @return true if the method should be retried, false + * otherwise + */ + boolean retryMethod( + HttpMethod method, + HttpRecoverableException recoverableException, + int executionCount, + boolean requestSent); + +}