fix search for common names in editor and minor
[cdmlib.git] / cdmlib-services / src / test / java / eu / etaxonomy / cdm / api / service / HandlingCdmEntitiesTest.java
1 // $Id$
2 /**
3 * Copyright (C) 2014 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.cdm.api.service;
11
12 import java.util.Arrays;
13 import java.util.List;
14 import java.util.UUID;
15
16 import org.apache.log4j.Logger;
17 import org.hibernate.LazyInitializationException;
18 import org.junit.Assert;
19 import org.junit.Ignore;
20 import org.junit.Test;
21 import org.unitils.database.annotations.Transactional;
22 import org.unitils.database.util.TransactionMode;
23 import org.unitils.dbunit.annotation.DataSet;
24 import org.unitils.spring.annotation.SpringBeanByType;
25
26 import eu.etaxonomy.cdm.model.agent.Person;
27 import eu.etaxonomy.cdm.model.agent.Team;
28 import eu.etaxonomy.cdm.model.common.CdmBase;
29 import eu.etaxonomy.cdm.model.name.BotanicalName;
30 import eu.etaxonomy.cdm.model.name.NonViralName;
31 import eu.etaxonomy.cdm.model.taxon.Taxon;
32 import eu.etaxonomy.cdm.test.integration.CdmIntegrationTest;
33
34 /**
35 * This test class tries to describe how hibernate works with objects (save, update, merge).
36 *
37 * @author cmathew
38 * @date 17 Sep 2014
39 *
40 */
41
42 public class HandlingCdmEntitiesTest extends CdmIntegrationTest {
43
44 private static final Logger logger = Logger.getLogger(CommonServiceImplTest.class);
45
46 private static final String LIE_TEAMMEMBERS_NOSESSION = "failed to lazily initialize a collection of role: eu.etaxonomy.cdm.model.agent.Team.teamMembers, could not initialize proxy - no Session";
47 private static final String LIE_NOSESSION = "could not initialize proxy - no Session";
48
49 @SpringBeanByType
50 private ITaxonService taxonService;
51
52 @SpringBeanByType
53 private IAgentService agentService;
54
55 @SpringBeanByType
56 private ICommonService commonService;
57
58 public static final String[] includeTables = new String[]{
59 "TAXONBASE",
60 "TAXONNAMEBASE",
61 "AGENTBASE",
62 "AGENTBASE_AGENTBASE",
63 "HOMOTYPICALGROUP"
64 };
65
66 @Ignore
67 @Test
68 @Transactional(TransactionMode.DISABLED)
69 public final void createTestDataSet() {
70 Team combAuthor = Team.NewTitledInstance("Avengers", "Avengers");
71 combAuthor.addTeamMember(Person.NewTitledInstance("Iron Man"));
72 BotanicalName name = BotanicalName.NewInstance(null, "Abies alba", null, null, null, null, null, null, null);
73 name.setCombinationAuthorTeam(combAuthor);
74 Taxon taxon = Taxon.NewInstance(name, null);
75 UUID taxonUuid = taxonService.save(taxon);
76 printDataSetWithNull(System.out,false,null,includeTables);
77 }
78
79 @Test
80 @DataSet
81 @Transactional(TransactionMode.DISABLED)
82 public void testNonTransactionalUpdateForExistingTaxon() {
83 // this method tests the updating of a 'truely' detached object which
84 // attempts to initialize a lazy loaded proxy object while trying to
85 // update the same.
86
87 // setting the TransactionMode for this method to DISABLED is important
88 // to ensure that transaction boundaries remain at the service layer calls
89 // to simulate detachment and update of the persisted object
90
91 UUID taxonUuid = UUID.fromString("23c35977-01b5-452c-9225-ecce440034e0");
92
93 // ---- loading taxon with find (uuid) ----
94
95 Taxon taxon = (Taxon)taxonService.find(taxonUuid);
96
97 // at this point the taxonNew object is detached and all lazy loaded proxy
98 // objects in the object graph (including teamMembers) will have values of
99 // initialized=false and session=null
100
101 // since name is lazy loaded the call to getName should fail
102 try {
103 CdmBase.deproxy(taxon.getName(),NonViralName.class);
104 Assert.fail("LazyInitializationException not thrown for lazy loaded Taxon.name");
105 } catch(LazyInitializationException lie) {
106
107 if(!lie.getMessage().equals(LIE_NOSESSION)) {
108 Assert.fail("LazyInitializationException thrown, but not : " + LIE_NOSESSION);
109 }
110 }
111
112 // ---- loading taxon with find (id) ----
113
114 taxon = (Taxon)commonService.find(taxon.getClass(), taxon.getId());
115
116 // at this point the taxonNew object is detached and all lazy loaded proxy
117 // objects in the object graph (including teamMembers) will have values of
118 // initialized=false and session=null
119
120 // since name is lazy loaded the call to getName should fail
121 try {
122 CdmBase.deproxy(taxon.getName(),NonViralName.class);
123 Assert.fail("LazyInitializationException not thrown for lazy loaded Taxon.name");
124 } catch(LazyInitializationException lie) {
125
126 if(!lie.getMessage().equals(LIE_NOSESSION)) {
127 Assert.fail("LazyInitializationException thrown, but not : " + LIE_NOSESSION);
128 }
129 }
130
131 // ---- loading taxon with findTaxonByUuid ----
132
133 List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String[] {
134 "name"
135 });
136
137 // loading the taxon with its taxon name object pre-initialized
138 taxon = (Taxon)taxonService.findTaxonByUuid(taxonUuid, TAXON_INIT_STRATEGY);
139
140 // at this point the taxonNew object is detached and all lazy loaded proxy
141 // objects in the object graph (including teamMembers) will have values of
142 // initialized=false and session=null
143
144 NonViralName nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
145
146 // normally this call should throw a lazy loading exception since
147 // the combinationAuthorTeam object is not initialized, but
148 // the findTaxonByUuid performs this initialization (via the
149 // AdvancedBeanInitializer) since the combinationAuthorTeam
150 // is annotated with CacheUpdate
151
152 Team team = CdmBase.deproxy(nvn.getCombinationAuthorTeam(),Team.class);
153
154 // setting the protected title cache to false to ensure that
155 // TeamDefaultCacheStrategy.getTitleCache is called, which in turn tries
156 // to initialize the teamMembers persistent collection which fails
157
158 team.setProtectedTitleCache(false);
159
160 try {
161 taxonService.update(taxon);
162 Assert.fail("LazyInitializationException not thrown for lazy loaded Team.teamMembers");
163 } catch(LazyInitializationException lie) {
164
165 if(!lie.getMessage().equals(LIE_TEAMMEMBERS_NOSESSION)) {
166 Assert.fail("LazyInitializationException thrown, but not : " + LIE_TEAMMEMBERS_NOSESSION);
167 }
168 }
169
170 // the above fails due to the fact that hibernate does not resolve lazy
171 // loading on a detached object until the object is persisted. The attempt
172 // to initialize teamMembers before the object graph is persisted means that
173 // the current session is not yet attached to the proxy objects and hibernate
174 // tries to use the existing session set in the teamMembers object which is
175 // null, leading to the exception
176
177 // setting the protected title cache to true to ensure that
178 // TeamDefaultCacheStrategy.getTitleCache is not called, implying
179 // that the teamMembers are not initialized, so no exception is thrown
180
181 team.setProtectedTitleCache(true);
182 taxonService.update(taxon);
183
184 }
185
186 @Test
187 @DataSet
188 public void testTransactionalUpdateAfterFindTaxonByUuidForExistingTaxon() {
189 // this method tests the updating of a detached object inside a single
190 // transaction.
191
192 // this method is transactional, meaning that a transaction is started
193 // at the start of the method and ends only with the end of the method
194
195 // since this method is transactional, any object initialized within this method
196 // will have a valid session attached to any lazy loaded proxy objects
197 // in the object graph (including teamMembers)
198
199 UUID taxonUuid = UUID.fromString("23c35977-01b5-452c-9225-ecce440034e0");
200
201 // ---- loading taxon with find (uuid) ----
202
203 Taxon taxon = (Taxon)taxonService.find(taxonUuid);
204
205 // at this point the taxonNew object is detached and all lazy loaded proxy
206 // objects in the object graph (including teamMembers) will have a new
207 // session attached implying that all the following calls will succeed
208
209 NonViralName nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
210 Team team = CdmBase.deproxy(nvn.getCombinationAuthorTeam(),Team.class);
211 taxonService.update(taxon);
212
213 // ---- loading taxon with find (id) ----
214
215 taxon = (Taxon)commonService.find(taxon.getClass(), taxon.getId());
216
217 // at this point the taxonNew object is detached and all lazy loaded proxy
218 // objects in the object graph (including teamMembers) will have a new
219 // session attached implying that all the following calls will succeed
220
221 nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
222 team = CdmBase.deproxy(nvn.getCombinationAuthorTeam(),Team.class);
223 taxonService.update(taxon);
224
225 // ---- loading taxon with findTaxonByUuid ----
226
227 List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String[] {
228 "name"
229 });
230
231 // loading the taxon with its taxon name object pre-initialized
232 taxon = (Taxon)taxonService.findTaxonByUuid(taxonUuid, TAXON_INIT_STRATEGY);
233
234 nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
235 team = CdmBase.deproxy(nvn.getCombinationAuthorTeam(),Team.class);
236
237 // since a valid session is now attached to teamMembers, forcing the
238 // initializing of the teamMembers (in TeamDefaultCacheStrategy.getTitleCache)
239 // by setting the protected title cache to false does not throw an exception
240 // because the teamMember persistent collection now has a valid session,
241 // which is used to initialize the persistent collection
242
243 team.setProtectedTitleCache(false);
244 taxonService.update(taxon);
245 }
246
247 @Test
248 @Transactional(TransactionMode.DISABLED)
249 public void testNonTransactionalUpdateForNewTaxon() {
250
251 // this test is only to prove that the update problem occurs
252 // also for newly created objects (as expected)
253
254 // create / save new taxon with name and author team with team member
255
256 Team combAuthor = Team.NewTitledInstance("X-Men", "X-Men");
257 combAuthor.addTeamMember(Person.NewTitledInstance("Wolverine"));
258
259
260 BotanicalName name = BotanicalName.NewInstance(null, "Pinus Alba", null, null, null, null, null, null, null);
261 name.setCombinationAuthorTeam(combAuthor);
262
263 Taxon taxon = Taxon.NewInstance(name, null);
264
265 UUID taxonUuid = taxonService.save(taxon);
266
267 List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String[] {
268 "name"
269 });
270
271 taxon = (Taxon)taxonService.findTaxonByUuid(taxonUuid, TAXON_INIT_STRATEGY);
272
273 NonViralName nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
274 Team team = CdmBase.deproxy(nvn.getCombinationAuthorTeam(),Team.class);
275 team.setProtectedTitleCache(false);
276
277 try {
278 taxonService.update(taxon);
279 Assert.fail("LazyInitializationException not thrown for lazy loaded Team.teamMembers");
280 } catch(LazyInitializationException lie) {
281
282 if(!lie.getMessage().equals(LIE_TEAMMEMBERS_NOSESSION)) {
283 Assert.fail("LazyInitializationException thrown, but not : " + LIE_TEAMMEMBERS_NOSESSION);
284 }
285 }
286
287 }
288
289 @Test
290 @DataSet
291 @Transactional(TransactionMode.DISABLED)
292 public void testNonTransactionalMergeForExistingTaxon() {
293 // this method tests the updating of a 'truely' detached object
294 // using merge
295
296 // setting the TransactionMode for this method to DISABLED is important
297 // to ensure that transaction boundaries remain at the service layer calls
298 // to simulate detachment and update of the persisted object
299
300 UUID taxonUuid = UUID.fromString("23c35977-01b5-452c-9225-ecce440034e0");
301
302 // ---- loading taxon with find (uuid) ----
303
304 Taxon taxon = (Taxon)taxonService.find(taxonUuid);
305
306 // at this point the taxonNew object is detached and all lazy loaded proxy
307 // objects in the object graph (including teamMembers) will have values of
308 // initialized=false and session=null
309
310 taxonService.merge(taxon);
311
312 // ---- loading taxon with find (id) ----
313
314 taxon = (Taxon)commonService.find(taxon.getClass(), taxon.getId());
315
316 taxonService.merge(taxon);
317
318 // ---- loading taxon with findTaxonByUuid ----
319
320 List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String[] {
321 "name"
322 });
323
324 // loading the taxon with its taxon name object pre-initialized
325 taxon = (Taxon)taxonService.findTaxonByUuid(taxonUuid, TAXON_INIT_STRATEGY);
326
327 // at this point the taxonNew object is detached and all lazy loaded proxy
328 // objects in the object graph (including teamMembers) will have values of
329 // initialized=false and session=null
330
331 NonViralName nvn = CdmBase.deproxy(taxon.getName(),NonViralName.class);
332
333 // normally this call should throw a lazy loading exception since
334 // the combinationAuthorTeam object is not initialized, but
335 // the findTaxonByUuid performs this initialization (via the
336 // AdvancedBeanInitializer) since the combinationAuthorTeam
337 // is annotated with CacheUpdate
338
339 Team team = CdmBase.deproxy(nvn.getCombinationAuthorTeam(),Team.class);
340
341 // setting the protected title cache to false to ensure that
342 // TeamDefaultCacheStrategy.getTitleCache is called, which in turn tries
343 // to initialize the teamMembers persistent collection which fails
344 team.setProtectedTitleCache(false);
345
346
347 taxonService.merge(taxon);
348
349 }
350 }