543166662e8446ea71bef4e181284b2e58583dda
[utils] / test / enterprise / src / main / java / org / wamblee / test / persistence / package-info.java
1 /*
2  * Copyright 2005-2010 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */ 
16 /**
17  * <p>
18  * This package provides test library for database testing in general and JPA testing
19  * specifically. As part of this it provides a means to transparently start an inmemory 
20  * database from a junit test or connect to an external database. Also, given a persistence 
21  * unit it is easy to start testing it in a junit test with only a few lines of code.
22  * </p> 
23  * 
24  * <p>
25  * The main use cases are explained below:
26  * </p> 
27  * <ul>
28  *   <li> <a href="#db-basic">Basic database testing, transparently connecting to a database</a>  
29  *   </li>
30  *   <li> <a href="#db-basic-external">Connecting to an external database</a>
31  *   </li>
32  *   <li> <a href="#db-utils">Executing code within a JDBC transaction</a>
33  *   </li>
34  *   <li> <a href="#db-unit">Using DB Unit in your tests</a>
35  *   </li>
36  *   <li> <a href="#db-jpa-basic">Basic JPA testing</a> 
37  *   </li>
38  *   <li> <a href="#db-jpa-plus-jdbc">JPA testing combined with JDBC and DBUnit</a>
39  *   </li>
40  *   <li> <a href="#db-jpa-services">Testing a service that requires a transaction</a>
41  *   </li>
42  *   <li> <a href="#db-user-transaction">Controlling transactions through a <code>UserTransaction</code></a>
43  *   </li>
44  * </ul>
45  * 
46  * <p>
47  *   See also the <a href="#design-overview">design overview</a>.  
48  * </p>
49  * 
50  * <a name="db-basic">
51  *   <h2>Basic database testing, transparently connecting to a database</h2>
52  * </a>
53  * Starting the database: 
54  * <pre>
55  *      Database db = DatabaseBuilder.getDatabase();
56  *      DataSource dataSource = db.start();
57  * </pre>
58  * <p>
59  * If nothing is specified in the user's environment, an inmemory database is started (derby).
60  * Using the datasource is just standard JDBC now.
61  * </p>
62  * <p>
63  * After a test it is good practice to stop the database:
64  * </p>
65  * <pre>
66  *      db.stop();
67  * </pre>
68  * 
69  * <a name="db-basic-external">
70  *   <h2>Connecting to an external database</h2>
71  * </a>
72  * 
73  * Connecting to an external database can be done by requiring the 'external' capability on 
74  * the database provider. 
75  * <pre>
76  *      Database db = DatabaseBuilder.getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL); 
77  * </pre>
78  * This also requires a number of environment variables or system properties to be set, 
79  * see {@link ExternalDatabase}. 
80  * 
81  * <p>
82  * However, the most convenient way to set the capabilities is usually to set a system property or environment 
83  * variable see the javadocs of {@link DatabaseBuilder}. and 
84  * specifically <code>DatabaseBuilder.DB_CAPABILITIES_PROP</code>
85  * </p>
86  * 
87  * 
88  * <a name="db-utils">
89  *   <h2>Executing code within a JDBC transaction</h2>
90  * </a>
91  * <p>
92  *   To execute code withing a JDBC transaction, use the {@link DatabaseUtils} and 
93  *   use the {@link DatabaseUtils#executeInTransaction(org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork)}
94  *   method. 
95  * </p>
96  * <pre>
97  *       DatabaseUtils dbutils = new DatabaseUtils(dataSource);
98  *       boolean result = dbutils.executeInTransaction(
99  *           new JdbcUnitOfWork&lt;Boolean&gt;() {
100  *               &#064;Override
101  *               public Boolean execute(Connection aConnection) throws Exception {
102  *                   ResultSet res = jpaTester.getDbUtils().executeQuery(
103  *                       aConnection, GROUP_QUERY, aGroup);
104  *                   return res.next();
105  *               }
106  *           });
107  * </pre>
108  * {@link DatabaseUtils} also provides various other utility methods to work with JDBC queries. 
109  * 
110  * <a name="db-unit">
111  *   <h2>Using DB Unit in your tests</h2>
112  * </a>
113  * 
114  * <p>To work with <a href="http://dbunit.org">DBUnit</a>, 
115  * <code>DatabaseUtils#createDbTester(org.dbunit.dataset.filter.ITableFilterSimple)</code>
116  * must be used passing it in the tables to use in the form of a {@link org.dbunit.dataset.filter.ITableFilterSimple}
117  * object. </p>
118  * 
119  * <pre>
120  *      IDatabaseTester dbtester = dbutils.createDbTester(new ITableFilterSimple() {
121  *          public boolean accept(String aTableName) throws DataSetException {
122  *              return aTableName.startsWith("XYZ_");
123  *          }
124  *      });
125  * </pre>
126  * 
127  * <p>The reason for using a <code>DatabaseUtils</code> instead of DBUnit directly is that 
128  * <code>DatabseUtils</code> will keep track of connections and close them when <code>DatabaseUtils</code>
129  * is closed</p>
130  * 
131  * <a name="db-jpa-basic">
132  *   <h2>Basic JPA testing</h2>
133  * </a>
134  * <p>
135  *    First step is to create a {@link PersistenceUnitDescription} that matches the persistence unit you
136  *    want to test. 
137  * </p>
138  * <p>Second step is to make sure that all entities are listed explicitly in your
139  *    <code>persistence.xml</code>. Currently, class path scanning appears to fail when
140  *    run from junit. 
141  *    Specifying all entities explicitly is not necessarily a bad thing as it is also more efficient. 
142  * </p>
143  * 
144  * <p>
145  *    Now create a <code>JpaTester</code> in your test code: 
146  * </p>
147  * <pre>
148  *      &#064;Before
149  *      public void setUp() throws Exception {
150  * 
151  *          // First we create the JpaTester by telling us which persistence unit we
152  *          // are going to test
153  *          jpaTester = new JpaTester(new MyPersistenceUnit());
154  *          jpaTester.start();     
155  *      }
156  * </pre>
157  * 
158  * <p>
159  * Then in test code execute some JPA code within a unit of work: 
160  * </p>
161  * <pre>
162  *      jpaTester.getJpaBuilder().execute(new JpaUnitOfWork<Void>() {
163  *          public Void execute(EntityManager aEm) {
164  *              MyEntity entity = new MyEntity("a", "b");
165  *              aEm.persist(entity);
166  *              return null;
167  *          }
168  *      });
169  * </pre>
170  * 
171  * <p>
172  *   Note that in addition to this method it is also possible to directly control transactions
173  *   through {@link JpaBuilder#begin()}, {@link JpaBuilder#commit(javax.persistence.EntityManager)}, 
174  *   and {@link JpaBuilder#rollback(javax.persistence.EntityManager)}. 
175  * </p>
176  * 
177  * <a name="db-jpa-plus-jdbc">
178  *   <h2>JPA testing combined with JDBC and DBUnit</h2>
179  * </a>
180  * <p>The <code>JPATester</code> provides access to all required object. It is usually convenient to 
181  * get them directly from the <code>JPATester</code> after initializing it: 
182  * <pre>
183  *      builder = jpaTester.getJpaBuilder();
184  *      dbutils = jpaTester.getDbUtils();
185  *      dbtester = dbutils.createDbTester(new MyTables());
186  * </pre>
187  * 
188  * <a name="db-jpa-services">
189  *   <h2>Testing a service that requires a transaction</h2>
190  * </a>
191  * 
192  * <p>Using {@link TransactionProxyFactory} it is possible to create a proxy for a given
193  * service interface to provide the semantics of 'requires new' transaction semantics. 
194  * <pre>
195  *      TransactionProxyFactory<Service> factory = new TransactionProxyFactory<Service>(
196  *           jpaTester.getJpaBuilder(), Service.class);
197  *      Service service = new ServiceImpl(factory.getTransactionScopedEntityManager()); 
198  *      Service proxy = factory.getProxy(service);
199  *      proxy.execute(...);
200  * </pre>
201  * 
202  * <p>
203  * In the above example, the <code>Service</code> POJO requires an {@link EntityManager} in its 
204  * constructor and it is passed a transaction scoped entitymanager from the factory. This entitymanager
205  * is in fact a so-called contextual reference.
206  * Next, the proxy is obtained from the factory. Invoking any method on it will make sure a new 
207  * transaction is started and a new entity manager is created for the scope of that transaction.
208  * </p>
209  * 
210  * <a name="db-user-transaction">
211  *   <h2>Controlling transactions through a <code>UserTransaction</h2>
212  * </a>
213  * 
214  * <p>
215  * It is also possible to manage JPA transaction through a <code>UserTransaction</code>. 
216  * This is mostly useful if you are test software that uses <code>UserTransaction</code> for 
217  * managing transactions, or if you want to manage multiple transactional resources. 
218  * See the explanation at {@link org.wamblee.test.transactions.SimpleTransactionManager} for more details. 
219  * </p>
220  * 
221  * <a name="design-overview">
222  *   <h2>Design overview</h2>
223  * </a>
224  * 
225  * <h3>Database transparency</h3>
226  * 
227  * <br/>
228  * <img src="doc-files/Class_Diagram__org.wamblee.support.persistence__database.jpg"
229  *   alt="database"/>
230  * </br/>
231  * <p>
232  *   {@link DatabaseProvider} uses <code>java.util.ServiceLoader</code> to find all implementations
233  *   of {@link DatabaseProvider} on the classpath. It then asks the database providers whether
234  *   they support the required capabilities (by default inmemory), and the first provider that 
235  *   supports the capabilities is used to create the database. 
236  * </p>
237  * <p>
238  *   Note that the <code>Database</code> interface is not intended to always create a database. 
239  *   It will do so for {@link DerbyDatabase} (inmemory), but with {@link ExternalDatabase}
240  *   it simply connects to an external database based on system properties or environment 
241  *   variables. 
242  * </p>
243  *  
244  * <h3>JPA tester overview</h3>
245  * 
246  * <br/>
247  * <img src="doc-files/Class_Diagram__org.wamblee.support.persistence__jpatester.jpg"
248  *   alt="database"/>
249  * </br/>
250  * 
251  * <p><code>JPATester</code> is responsible for:</p>
252  * <ul>
253  *   <li> Starting or connecting to a database, using {@link DatabaseBuilder}. 
254  *   </li>
255  *   <li>  Registering the acquired datasource in JNDI by first stubbing JNDI
256  *       using {@link org.wamblee.support.jndi.StubInitialContextFactory}. 
257  *   </li>
258  *   <li>  Creating the {@link JPABuilder} that will do the JPA heavy lifting. 
259  *   </li>
260  *   <li> Creating the {@link DatabaseUtils} for JDBC and DBUnit testing. 
261  *   </li>
262  * </ul> 
263  * 
264  * 
265  */
266 package org.wamblee.test.persistence;
267
268