]> git.somenet.org - pub/jan/dst18.git/blob - ass1-jpa/src/test/java/dst/ass1/jpa/ORMService.java
[1.4] Dataloss As A Service. DONE.
[pub/jan/dst18.git] / ass1-jpa / src / test / java / dst / ass1 / jpa / ORMService.java
1 package dst.ass1.jpa;
2
3 import javax.persistence.EntityManager;
4 import javax.persistence.EntityManagerFactory;
5 import javax.persistence.EntityTransaction;
6 import javax.persistence.Persistence;
7
8 import org.junit.rules.ExternalResource;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11
12 import dst.ass1.jpa.dao.IDAOFactory;
13 import dst.ass1.jpa.dao.impl.DAOFactory;
14 import dst.ass1.jpa.model.IModelFactory;
15 import dst.ass1.jpa.model.impl.ModelFactory;
16 import dst.ass1.jpa.util.Constants;
17
18 // DO NOT MODIFY THIS CLASS.
19
20 /**
21  * The ORMService class is used as a JUnit rule that, before each test run,
22  * a) creates an entity manager factory from the persistence unit referenced in {@link Constants#JPA_PERSISTENCE_UNIT},
23  * b) creates an entity manager using the factory,
24  * c) creates dao and model factory instances, and
25  * d) creates a database gateway for the entity manager.
26  *
27  * It provides methods to access these services, and it closes the entity manager and corresponding factory after each
28  * test run. If you pass an {@link ITestData} instance to the constructor, the {@link ORMService} will also insert test
29  * data via a transaction before each run, and truncate tables after each run.
30  */
31 public class ORMService extends ExternalResource {
32
33     private static final Logger LOG = LoggerFactory.getLogger(ORMService.class);
34
35     private static EntityManagerFactory emf;
36     private EntityManager em;
37
38     private DatabaseGateway databaseGateway;
39
40     private IModelFactory modelFactory;
41     private IDAOFactory daoFactory;
42
43     private ITestData testData;
44     private boolean insertTestData;
45     private boolean truncateTables;
46
47     /**
48      * Creates a new ORMService. By default, the ORMService rule only creates the database connection and other
49      * ORM facilities. If you want to also insert a test fixture, use {@link #ORMService(ITestData)}.
50      */
51     public ORMService() {
52         this(null, false, false);
53     }
54
55     /**
56      * Creates a new ORMService that also inserts the given {@link ITestData} before each run and truncates the tables
57      * afterwards.
58      *
59      * @param testData the test data to insert
60      */
61     public ORMService(ITestData testData) {
62         this(testData, true, true);
63     }
64
65     public ORMService(ITestData testData, boolean insertTestData, boolean truncateTables) {
66         this.testData = testData;
67         this.insertTestData = insertTestData;
68         this.truncateTables = truncateTables;
69     }
70
71     public EntityManager getEntityManager() {
72         return em;
73     }
74
75     public EntityManager createEntityManager() {
76         return emf.createEntityManager();
77     }
78
79     public IModelFactory getModelFactory() {
80         return modelFactory;
81     }
82
83     public IDAOFactory getDaoFactory() {
84         return daoFactory;
85     }
86
87     public DatabaseGateway getDatabaseGateway() {
88         return databaseGateway;
89     }
90
91     /**
92      * Alias for {@link #getEntityManager()}.
93      *
94      * @return an entity manager
95      */
96     public EntityManager em() {
97         return getEntityManager();
98     }
99
100     @Override
101     protected void before() throws Throwable {
102         LOG.debug("Creating EntityManagerFactory");
103         emf = createEntityManagerFactory();
104
105         LOG.debug("Creating EntityManager");
106         em = emf.createEntityManager();
107         databaseGateway = new DatabaseGateway(em);
108
109         LOG.debug("Initializing factories");
110         // initialize factories
111         modelFactory = new ModelFactory();
112         daoFactory = new DAOFactory(em);
113
114         if (testData != null && insertTestData) {
115             insertTestData(testData);
116         }
117     }
118
119     @Override
120     protected void after() {
121         if (truncateTables) {
122             truncateTables();
123         }
124
125         try {
126             LOG.debug("Closing EntityManager");
127             em.close();
128         } catch (Exception e) {
129             LOG.error("Error while closing entity manager", e);
130         }
131
132         try {
133             LOG.debug("Closing EntityManagerFactory");
134             emf.close();
135         } catch (Exception e) {
136             LOG.error("Error while closing entity manager factory", e);
137         }
138     }
139
140     protected void insertTestData(ITestData data) {
141         EntityTransaction tx = getEntityManager().getTransaction();
142
143         tx.begin();
144         try {
145             data.insert(getModelFactory(), getEntityManager());
146             tx.commit();
147         } catch (Exception e) {
148             try {
149                 if (tx.isActive()) {
150                     tx.rollback();
151                 }
152             } catch (Exception rollbackException) {
153                 LOG.error("Error while rolling back transaction after exception", rollbackException);
154             } finally {
155                 throw new IllegalStateException("Couldn't insert fixture. Can't proceed with tests", e); // rethrow original exception
156             }
157         }
158     }
159
160     protected void truncateTables() {
161         try {
162             LOG.debug("Truncating database tables");
163             getDatabaseGateway().truncateTables();
164         } catch (Exception e) {
165             LOG.error("Error while trying to truncate tables after test", e);
166         }
167     }
168
169     private static EntityManagerFactory createEntityManagerFactory() {
170         return Persistence.createEntityManagerFactory(Constants.JPA_PERSISTENCE_UNIT);
171     }
172
173 }