EMMA Coverage Report (generated Sat Nov 03 21:53:04 GMT 2007)
[all classes][sf.qof.session]

COVERAGE SUMMARY FOR SOURCE FILE [RetrySessionRunner.java]

nameclass, %method, %block, %line, %
RetrySessionRunner.java100% (1/1)100% (6/6)98%  (79/81)99%  (25.7/26)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RetrySessionRunner100% (1/1)100% (6/6)98%  (79/81)99%  (25.7/26)
execute (Object []): Object 100% (1/1)95%  (40/42)98%  (13.7/14)
RetrySessionRunner (TransactionRunnable, String, int): void 100% (1/1)100% (7/7)100% (2/2)
RetrySessionRunner (TransactionRunnable, String, int, long): void 100% (1/1)100% (13/13)100% (5/5)
RetrySessionRunner (TransactionRunnable, int): void 100% (1/1)100% (6/6)100% (2/2)
RetrySessionRunner (TransactionRunnable, int, long): void 100% (1/1)100% (7/7)100% (2/2)
run (Connection, Object []): Object 100% (1/1)100% (6/6)100% (1/1)

1/*
2 * Copyright 2007 brunella ltd
3 *
4 * Licensed under the LGPL Version 3 (the "License");
5 * you may not use this file except in compliance with the License.
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
11 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
12 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
15 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
16 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
17 * THE POSSIBILITY OF SUCH DAMAGE.
18 */
19package sf.qof.session;
20 
21import java.sql.Connection;
22import java.sql.SQLException;
23 
24/**
25 * <code>RetrySessionRunner</code> is an implementation of <code>SessionRunner</code>
26 * that runs a <code>TransactionRunnable</code> in a session context and retries
27 * if an error occured. 
28 * 
29 * Calling <code>execute</code> starts a new session call the <code>run</code>
30 * method of the <code>TransactionRunnable</code> and commits or rolls back 
31 * the transaction on success or failure. If an error occured it retries up to 
32 * <code>numberOfRetries</code> times. <code>delayInMilliSeconds</code> can be
33 * used to wait a specified amount of time between the retries. 
34 * 
35 * <p>Typical usage is like this:</p>
36 * 
37 * <p><blockquote><pre>
38 * List&lt;Person&gt; personList = ...
39 * PersonUpdaterRunnable runnable = new PersonUpdaterRunnable();
40 * Integer numberOfUpdates = 
41 *   new RetrySessionRunner&lt;Integer&gt;(runnable, "MY_CONTEXT_NAME").execute(personList, 3);
42 * </pre></blockquote></p>
43 * 
44 * @param <T> the type of the result of the <code>TransactionRunnable</code>. If
45 *            no result is returned this type should be <code>Void</code>
46 * 
47 * @see SessionRunner
48 */
49public class RetrySessionRunner<T> extends BaseSessionRunner<T> {
50 
51  private int numberOfRetries;
52  private long delayInMilliSeconds;
53  private TransactionRunnable<T> runnable;
54 
55  /**
56   * Creates a <code>RetrySessionRunner</code> that creates a session
57   * from the default session context.
58   *
59   * @param runnable         a <code>TransactionRunnable</code>
60   * @param numberOfRetries  max number of retries
61   */
62  public RetrySessionRunner(TransactionRunnable<T> runnable, int numberOfRetries) {
63        this(runnable, numberOfRetries, 0);
64  }
65 
66  /**
67   * Creates a <code>RetrySessionRunner</code> that creates a session
68   * from the default session context.
69   *
70   * @param runnable             a <code>TransactionRunnable</code>
71   * @param numberOfRetries      max number of retries
72   * @param delayInMilliSeconds  delay inbetween retries in milli seconds
73   */
74  public RetrySessionRunner(TransactionRunnable<T> runnable, int numberOfRetries, long delayInMilliSeconds) {
75        this(runnable, SessionContext.DEFAULT_CONTEXT_NAME, numberOfRetries, delayInMilliSeconds);
76  }
77 
78  /**
79   * Creates a <code>RetrySessionRunner</code> that creates a session
80   * from the session context with the given name.
81   *
82   * @param runnable         a <code>TransactionRunnable</code>
83   * @param contextName      the context name
84   * @param numberOfRetries  max number of retries
85   */
86  public RetrySessionRunner(TransactionRunnable<T> runnable, String contextName, int numberOfRetries) {
87        this(runnable, contextName, numberOfRetries, 0);
88  }
89 
90  /**
91   * Creates a <code>RetrySessionRunner</code> that creates a session
92   * from the session context with the given name.
93   *
94   * @param runnable             a <code>TransactionRunnable</code>
95   * @param contextName          the context name
96   * @param numberOfRetries      max number of retries
97   * @param delayInMilliSeconds  delay inbetween retries in milli seconds
98   */
99  public RetrySessionRunner(TransactionRunnable<T> runnable, String contextName, int numberOfRetries, long delayInMilliSeconds) {
100        super(contextName);
101        this.runnable = runnable;
102        this.numberOfRetries = numberOfRetries;
103        this.delayInMilliSeconds = delayInMilliSeconds;
104  }
105 
106  /**
107   * @see SessionRunner#execute(Object[])
108   */
109  @Override
110  public T execute(Object... arguments) throws SystemException {
111    T result = null;
112    int tries = 0;
113    boolean success = false;
114    while (!success && tries++ <= numberOfRetries) {
115      try {
116        result = super.execute(arguments);
117        success = true;
118      } catch (SystemException e) {
119        if (tries > numberOfRetries) {
120          throw e;
121        }
122      }
123      if (!success && delayInMilliSeconds > 0) {
124        try {
125          Thread.sleep(delayInMilliSeconds);
126        } catch (InterruptedException e) {}
127      }
128    }
129    return result;
130  }
131 
132  @Override
133  protected T run(Connection connection, Object... arguments) throws SQLException {
134        return runnable.run(connection, arguments);
135  }
136}

[all classes][sf.qof.session]
EMMA 2.0.5312 (C) Vladimir Roubtsov