1ea78e255d6e9e6bb1c712431c4dac3085637de0
[utils] / test / enterprise / src / main / java / org / wamblee / support / 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  * </ul>
43  * 
44  * <p>
45  *   See the <a href="#design-overview">design overview</a> for a an overview of the design.  
46  * </p>
47  * 
48  * <a name="db-basic">
49  *   <h2>Basic database testing, transparently connecting to a database</h2>
50  * </a>
51  * Starting the database: 
52  * <pre>
53  *      Database db = DatabaseBuilder.getDatabase();
54  *      DataSource dataSource = db.start();
55  * </pre>
56  * If nothing is specified in the user's environment, an inmemory database is started (derby).
57  * Using the datasource is just standard JDBC now. 
58  * Stopping the database
59  * <pre>
60  *      db.stop();
61  * </pre>
62  * 
63  * <a name="db-basic-external">
64  *   <h2>Connecting to an external database</h2>
65  * </a>
66  * 
67  * Connecting to an external database can be done by requiring the 'external' capability on 
68  * the database provider. 
69  * <pre>
70  *      Database db = DatabaseBuilder.getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL); 
71  * </pre>
72  * This also requires a number of environment variables or system properties to be set, 
73  * see {@link ExternalDatabase}. 
74  * 
75  * <p>
76  * However, the most convenient way to set the capabilities is usually to set a system property or environment 
77  * variable see the javadocs of {@link DatabaseBuilder}. and 
78  * specifically {@link DatabaseBuilder#DB_CAPABILITIES_PROP}
79  * </p>
80  * 
81  * 
82  * <a name="db-utils">
83  *   <h2>Executing code within a JDBC transaction</h2>
84  * </a>
85  * <p>
86  *   To execute code withing a JDBC transaction, use the {@link DatabaseUtils} and 
87  *   use the {@link DatabaseUtils#executeInTransaction(org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork)}
88  *   method. 
89  * </p>
90  * <pre>
91  *       DatabaseUtils dbutils = new DatabaseUtils(dataSource);
92  *       boolean result = dbutils.executeInTransaction(
93  *           new JdbcUnitOfWork&lt;Boolean&gt;() {
94  *               &#064;Override
95  *               public Boolean execute(Connection aConnection) throws Exception {
96  *                   ResultSet res = jpaTester.getDbUtils().executeQuery(
97  *                       aConnection, GROUP_QUERY, aGroup);
98  *                   return res.next();
99  *               }
100  *           });
101  * </pre>
102  * {@link DatabaseUtils} also provides various other utility methods to work with JDBC queries. 
103  * 
104  * <a name="db-unit">
105  *   <h2>Using DB Unit in your tests</h2>
106  * </a>
107  * 
108  * <p>To work with <a href="http://dbunit.org">DBUnit</a>, {@link DatabaseUtils#createDbTester(org.dbunit.dataset.filter.ITableFilterSimple)}
109  * must be used passing it in the tables to use in the form of a {@link org.dbunit.dataset.filter.ITableFilterSimple}
110  * object. </p>
111  * 
112  * <pre>
113  *      IDatabaseTester dbtester = dbutils.createDbTester(new ITableFilterSimple() {
114  *          public boolean accept(String aTableName) throws DataSetException {
115  *              return aTableName.startsWith("XYZ_");
116  *          }
117  *      });
118  * </pre>
119  * 
120  * <p>The reason for using a <code>DatabaseUtils</code> instead of DBUnit directly is that 
121  * <code>DatabseUtils</code> will keep track of connections and close them when <code>DatabaseUtils</code>
122  * is closed</p>
123  * 
124  * <a name="db-jpa-basic">
125  *   <h2>Basic JPA testing</h2>
126  * </a>
127  * <p>
128  *    First step is to create a {@link PersistenceUnitDescription} that matches the persistence unit you
129  *    want to test. 
130  * </p>
131  * <p>Second step is to make sure that all entities are listed explicitly in your
132  *    <pre>persistence.xml</pre>. Currently, class path scanning appears to fail when
133  *    run from junit. 
134  *    Specifying all entities explicitly is not necessarily a bad thing as it is also more efficient. 
135  * </p>
136  * 
137  * <p>
138  *    Now create a <code>JpaTester</code> in your test code: 
139  * </p>
140  * <pre>
141  *      &#064;Before
142  *      public void setUp() throws Exception {
143  * 
144  *          // First we create the JpaTester by telling us which persistence unit we
145  *          // are going to test
146  *          jpaTester = new JpaTester(new MyPersistenceUnit());
147  *          jpaTester.start();     
148  *      }
149  * </pre>
150  * 
151  * <p>
152  * Then in test code execute some JPA code within a unit of work: 
153  * </p>
154  * <pre>
155  *      jpaTester.getJpaBuilder().execute(new JpaUnitOfWork<Void>() {
156  *          public Void execute(EntityManager aEm) {
157  *              MyEntity entity = new MyEntity("a", "b");
158  *              aEm.persist(entity);
159  *              return null;
160  *          }
161  *      });
162  * </pre>
163  * 
164  * <a name="db-jpa-plus-jdbc">
165  *   <h2>JPA testing combined with JDBC and DBUnit</h2>
166  * </a>
167  * <p>The <code>JPATester</code> provides access to all required object. It is usually convenient to 
168  * get them directly from the <code>JPATester</code> after initializing it: 
169  * <pre>
170  *      builder = jpaTester.getJpaBuilder();
171  *      dbtester = jpaTester.getDbUtils().createDbTester(new MyTables());
172  *      dbutils = jpaTester.getDbUtils();
173  * </pre>
174  * 
175  * <a name="db-jpa-services">
176  *   <h2>Testing a service that requires a transaction</h2>
177  * </a>
178  * 
179  * <p>Using {@link TransactionProxyFactory} it is possible to create a proxy for a given
180  * service interface to provide the semantics of 'requires new' transaction semantics. 
181  * <pre>
182  *      TransactionProxyFactory<Service> factory = new TransactionProxyFactory<Service>(
183  *           jpaTester.getJpaBuilder(), Service.class);
184  *      Service service = new ServiceImpl(factory.getTransactionScopedEntityManager()); 
185  *      Service proxy = factory.getProxy(service);
186  *      proxy.execute(...);
187  * </pre>
188  * 
189  * <p>
190  * In the above example, the <code>Service</code> POJO requires an {@link EntityManager} in its 
191  * constructor and it is passed a transaction scoped entitymanager from the factory. This entitymanager
192  * is in fact a so-called contextual reference.
193  * Next, the proxy is obtained from the factory. Invoking any method on it will make sure a new 
194  * transaction is started and a new entity manager is created for the scope of that transaction.
195  * </p> 
196  * 
197  * <a name="design-overview">
198  *   <h2>Design overview</h2>
199  * </a>
200  * 
201  * <h3>Database transparency</h3>
202  * 
203  * <br/>
204  * <img src="doc-files/Class_Diagram__org.wamblee.support.persistence__database.jpg"
205  *   alt="database"/>
206  * </br/>
207  * <p>
208  *   {@link DatabaseProvider} uses <code>java.util.ServiceLoader</code> to find all implementations
209  *   of {@link DatabaseProvider} on the classpath. It then asks the database providers whether
210  *   they support the required capabilities (by default inmemory), and the first provider that 
211  *   supports the capabilities is used to create the database. 
212  * </p>
213  * <p>
214  *   Note that the <code>Database</code> interface is not intended to always create a database. 
215  *   It will do so for {@link DerbyDatabase} (inmemory), but with {@link ExternalDatabase}
216  *   it simply connects to an external database based on system properties or environment 
217  *   variables. 
218  * </p>
219  *  
220  * <h3>JPA tester overview</h3>
221  * 
222  * <br/>
223  * <img src="doc-files/Class_Diagram__org.wamblee.support.persistence__jpatester.jpg"
224  *   alt="database"/>
225  * </br/>
226  * 
227  * <p><code>JPATester</code> is responsible for:</p>
228  * <ul>
229  *   <li> Starting or connecting to a database, using {@link DatabaseBuilder}. 
230  *   </li>
231  *   <li>  Registering the acquired datasource in JNDI by first stubbing JNDI
232  *       using {@link org.wamblee.support.jndi.StubInitialContextFactory}. 
233  *   </li>
234  *   <li>  Creating the {@link JPABuilder} that will do the JPA heavy lifting. 
235  *   </li>
236  *   <li> Creating the {@link DatabaseUtils} for JDBC and DBUnit testing. 
237  *   </li>
238  * </ul> 
239  * 
240  * 
241  */
242 package org.wamblee.support.persistence;
243
244