Class | Line # | Actions | |||||
---|---|---|---|---|---|---|---|
ProvidingTransactionRunnable | 104 | 2 | 0% | 2 | 2 |
1 | /* | |
2 | * See the NOTICE file distributed with this work for additional | |
3 | * information regarding copyright ownership. | |
4 | * | |
5 | * This is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU Lesser General Public License as | |
7 | * published by the Free Software Foundation; either version 2.1 of | |
8 | * the License, or (at your option) any later version. | |
9 | * | |
10 | * This software is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this software; if not, write to the Free | |
17 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |
18 | * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | |
19 | */ | |
20 | package org.xwiki.store; | |
21 | ||
22 | /** | |
23 | * A special type of TransactionRunnable which guarentees to provide state to the TransactionRunnables | |
24 | * which are run inside of it. It can also provide them with data. | |
25 | * Suppose you have a unit of work which loads data and that data must be saved in a later | |
26 | * TransactionRunnable in the same transaction. | |
27 | * | |
28 | * IE: | |
29 | * TR1 fetch data A1 | |
30 | * TR2 update another data A2 | |
31 | * TR3 perform some operation involving A1 | |
32 | * | |
33 | * A TR3 can only run inside of a TR1. | |
34 | * To make things interesting we will assume that TR1, TR2, and TR3 all must run inside of a database | |
35 | * transaction. | |
36 | * TR1 is interesting because it <i>requires</i> a database transaction and it <i>provides</i> some data | |
37 | * (data A1). | |
38 | * | |
39 | * To implement this safely, TR1 should be a ProvidingTransactionRunnable. | |
40 | * We will assume that there already exists a TransactionRunnable for handling the begin and commit of the | |
41 | * database transaction, this will be called: DBStartableTransactionRunnable and we will assume that it | |
42 | * <i>provides</i> an interface called DBTransaction so TR1, TR2, and TR3 will all <i>require</i> | |
43 | * DBTransaction. | |
44 | * | |
45 | * <pre><code> | |
46 | * // MyInterfaceWithDataA1 must extend DBTransaction because all | |
47 | * // ProvidingTransactionRunnables must provide more than they require. | |
48 | * public interface MyInterfaceWithDataA1 extends DBTransaction { Data getA1(); } | |
49 | * | |
50 | * public class ImplementationWithDataA1 implements MyInterfaceWithDataA1 { ... } | |
51 | * | |
52 | * public class TR1 extends ProvidingTransactionRunnable<DBTransaction, MyInterfaceWithDataA1> | |
53 | * { | |
54 | * private Data dataA1; | |
55 | * | |
56 | * protected void onRun() { this.dataA1 = ..... } | |
57 | * | |
58 | * {@literal @}Override | |
59 | * protected MyInterfaceWithDataA1 getProvidedContext() | |
60 | * { | |
61 | * // this.getContext() will return a DBTransaction which our implementation can wrap. | |
62 | * return new ImplementationWithDataA1(this.getContext(), this.dataA1); | |
63 | * } | |
64 | * } | |
65 | * | |
66 | * public class TR2 extends TransactionRunnable<DBTransaction> { ... } | |
67 | * | |
68 | * public class TR3 extends TransactionRunnable<MyInterfaceWithDataA1> | |
69 | * { | |
70 | * protected void onRun() | |
71 | * { | |
72 | * final Data A1 = this.getContext(); | |
73 | * ... | |
74 | * } | |
75 | * } | |
76 | * | |
77 | * To use these classes: | |
78 | * | |
79 | * DBStartableTransactionRunnable run = new DBStartableTransactionRunnable(dataSourceName); | |
80 | * TransactionRunnable<MyInterfaceWithDataA1> tr1 = new TR1(); | |
81 | * tr1.runIn(run); | |
82 | * TransactionRunnable<DBTransaction> tr2 = new TR2(); | |
83 | * TransactionRunnable<MyInterfaceWithDataA1> tr2WithNewCapabilities = tr2.runIn(tr1.asProvider()); | |
84 | * new TR3().runIn(tr2WithNewCapabilities); | |
85 | * // This would fail at compile time: new TR3().runIn(tr2); | |
86 | * run.start(); | |
87 | * </code></pre> | |
88 | * | |
89 | * @param <R> The type of transaction or transaction state which this runnable requires. | |
90 | * A TransactionRunnable which alters a database through Hibernate would fail if it was | |
91 | * started outside of a TransactionRunnable which began and committed a transaction around | |
92 | * it. A class which extends {@code TransactionRunnable<DatabaseTransaction>} can only be | |
93 | * run inside of another {@code TransactionRunnable<DatabaseTransaction>} or inside of a | |
94 | * {@code ProvidingTransactionRunnable<?, DatabaseTransaction>} | |
95 | * Breaking that rule will be a compile time error. | |
96 | * | |
97 | * @param <P> the transaction state which this TransactionRunnable provides. Any | |
98 | * {@code TransactionRunnable<P>} may be {@link TransactionRunnable#runIn(TransactionRunnable)} | |
99 | * This runnable. | |
100 | * | |
101 | * @version $Id: d1b3ee449ee98c6d4aa70f4995940aa8a20b0a6f $ | |
102 | * @since 3.0M2 | |
103 | */ | |
104 | public class ProvidingTransactionRunnable<R, P extends R> extends TransactionRunnable<R> | |
105 | { | |
106 | /** | |
107 | * Get whatever is provided by this ProvidingTransactionRunnable. | |
108 | * | |
109 | * @return an implementation of P, the transaction type which this runnable runs in. | |
110 | * null by default. | |
111 | * @see TransactionRunnable#getContext() | |
112 | */ | |
113 | 0 | ![]() |
114 | { | |
115 | 0 | return null; |
116 | } | |
117 | ||
118 | /** | |
119 | * View this as what it provides. | |
120 | * Cast this ProvidingTransactionRunnable to the type of | |
121 | * TransactionRunnable which can run inside of it. | |
122 | * | |
123 | * @return this ProvidingTransactionRunnable cast to a TransactionRunnable<P> | |
124 | */ | |
125 | 2 | ![]() |
126 | { | |
127 | // This cast is ok because every PTR<R, P> promises to provide P. | |
128 | // calling runIn on the output from this cast is also safe because P extends R. | |
129 | 2 | return (TransactionRunnable<P>) this; |
130 | } | |
131 | } |