20ae13d0fd98353852903664a2791f3012a0fe0b
[policy/drools-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * feature-session-persistence
4  * ================================================================================
5  * Copyright (C) 2017-2018, 2020 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.drools.persistence;
22
23 import static org.assertj.core.api.Assertions.assertThatCode;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertNull;
28 import static org.junit.Assert.assertTrue;
29 import static org.junit.Assert.fail;
30 import static org.mockito.ArgumentMatchers.any;
31 import static org.mockito.ArgumentMatchers.anyLong;
32 import static org.mockito.ArgumentMatchers.anyString;
33 import static org.mockito.Mockito.doThrow;
34 import static org.mockito.Mockito.mock;
35 import static org.mockito.Mockito.never;
36 import static org.mockito.Mockito.times;
37 import static org.mockito.Mockito.verify;
38 import static org.mockito.Mockito.when;
39
40 import java.io.FileNotFoundException;
41 import java.io.FileReader;
42 import java.io.IOException;
43 import java.sql.Connection;
44 import java.sql.DriverManager;
45 import java.sql.PreparedStatement;
46 import java.sql.ResultSet;
47 import java.sql.SQLException;
48 import java.sql.Timestamp;
49 import java.util.ArrayList;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.Properties;
53 import java.util.concurrent.CountDownLatch;
54 import java.util.concurrent.TimeUnit;
55
56 import javax.persistence.EntityManager;
57 import javax.persistence.EntityManagerFactory;
58 import javax.transaction.TransactionManager;
59 import javax.transaction.TransactionSynchronizationRegistry;
60 import javax.transaction.UserTransaction;
61
62 import org.apache.commons.dbcp2.BasicDataSource;
63 import org.junit.After;
64 import org.junit.Before;
65 import org.junit.BeforeClass;
66 import org.junit.Test;
67 import org.kie.api.KieBase;
68 import org.kie.api.KieServices;
69 import org.kie.api.persistence.jpa.KieStoreServices;
70 import org.kie.api.runtime.Environment;
71 import org.kie.api.runtime.EnvironmentName;
72 import org.kie.api.runtime.KieContainer;
73 import org.kie.api.runtime.KieSession;
74 import org.kie.api.runtime.KieSessionConfiguration;
75 import org.mockito.ArgumentCaptor;
76 import org.onap.policy.drools.core.PolicyContainer;
77 import org.onap.policy.drools.core.PolicySession;
78 import org.onap.policy.drools.core.PolicySession.ThreadModel;
79 import org.onap.policy.drools.persistence.PersistenceFeature.PersistenceFeatureException;
80 import org.onap.policy.drools.persistence.PersistenceFeature.PersistentThreadModel;
81 import org.onap.policy.drools.system.PolicyController;
82 import org.slf4j.Logger;
83 import org.slf4j.LoggerFactory;
84
85 public class PersistenceFeatureTest {
86
87     private static final String MY_KIE_BASE = "mybase";
88
89     private static final String MY_SESS_NAME = "myname";
90
91     private static final String MISSING_EXCEPTION = "missing exception";
92
93     private static final String EXPECTED = "expected exception";
94
95     private static final Logger logger = LoggerFactory.getLogger(PersistenceFeatureTest.class);
96
97     private static final String JDBC_DRIVER = "fake.driver";
98     private static final String JDBC_URL = "fake.url";
99     private static final String JDBC_USER = "fake.user";
100     private static final String JDBC_PASSWD = "fake.password";
101     private static final String JTA_OSDIR = "target";
102     private static final String SRC_TEST_RESOURCES = "src/test/resources";
103
104     private static Properties stdprops;
105
106     private JpaDroolsSessionConnector jpa;
107     private DroolsSession sess;
108     private KieSession kiesess;
109     private BasicDataSource bds;
110     private EntityManagerFactory emf;
111     private Connection conn;
112     private Properties props;
113     private KieServices kiesvc;
114     private Environment kieenv;
115     private KieSessionConfiguration kiecfg;
116     private KieBase kiebase;
117     private KieStoreServices kiestore;
118     private TransactionManager transmgr;
119     private UserTransaction usertrans;
120     private TransactionSynchronizationRegistry transreg;
121     private PolicyController polctlr;
122     private PolicyContainer polcont;
123     private PolicySession polsess;
124     private int emfCount;
125     private int jpaCount;
126     private String propName;
127
128     private PersistenceFeature feat;
129
130     /**
131      * Setup before class.
132      *
133      * @throws Exception exception
134      */
135     @BeforeClass
136     public static void setUpBeforeClass() throws Exception {
137         stdprops = new Properties();
138
139         stdprops.put(DroolsPersistenceProperties.DB_DRIVER, JDBC_DRIVER);
140         stdprops.put(DroolsPersistenceProperties.DB_URL, JDBC_URL);
141         stdprops.put(DroolsPersistenceProperties.DB_USER, JDBC_USER);
142         stdprops.put(DroolsPersistenceProperties.DB_PWD, JDBC_PASSWD);
143         stdprops.put(DroolsPersistenceProperties.JTA_OBJECTSTORE_DIR, JTA_OSDIR);
144         stdprops.put(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT, "50");
145
146         System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
147         System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
148     }
149
150     /**
151      * Setup.
152      *
153      * @throws Exception exception
154      */
155     @Before
156     public void setUp() throws Exception {
157         jpa = mock(JpaDroolsSessionConnector.class);
158         sess = mock(DroolsSession.class);
159         bds = mock(BasicDataSource.class);
160         emf = mock(EntityManagerFactory.class);
161         kiesess = mock(KieSession.class);
162         conn = null;
163         props = new Properties();
164         kiesvc = mock(KieServices.class);
165         kieenv = mock(Environment.class);
166         kiecfg = mock(KieSessionConfiguration.class);
167         kiebase = mock(KieBase.class);
168         kiestore = mock(KieStoreServices.class);
169         transmgr = mock(TransactionManager.class);
170         usertrans = mock(UserTransaction.class);
171         transreg = mock(TransactionSynchronizationRegistry.class);
172         polcont = mock(PolicyContainer.class);
173         polctlr = mock(PolicyController.class);
174         polsess = mock(PolicySession.class);
175         emfCount = 0;
176         jpaCount = 0;
177         propName = null;
178
179         feat = new PersistenceFeatureImpl();
180
181         props.putAll(stdprops);
182
183         System.setProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir", "target/tm");
184         System.setProperty("ObjectStoreEnvironmentBean.objectStoreDir", "target/tm");
185
186         when(kiesvc.newEnvironment()).thenReturn(kieenv);
187         when(kiesvc.getStoreServices()).thenReturn(kiestore);
188         when(kiesvc.newKieSessionConfiguration()).thenReturn(kiecfg);
189
190         KieContainer kiecont = mock(KieContainer.class);
191         when(polcont.getKieContainer()).thenReturn(kiecont);
192
193         when(polsess.getPolicyContainer()).thenReturn(polcont);
194
195         when(kiecont.getKieBase(anyString())).thenReturn(kiebase);
196     }
197
198     /**
199      * Tear down.
200      */
201     @After
202     public void tearDown() {
203         // this will cause the in-memory test DB to be dropped
204         if (conn != null) {
205             try {
206                 conn.close();
207             } catch (SQLException e) {
208                 logger.warn("failed to close connection", e);
209             }
210         }
211
212         if (emf != null) {
213             try {
214                 emf.close();
215             } catch (IllegalArgumentException e) {
216                 logger.trace("ignored exception", e);
217             }
218         }
219     }
220
221     @Test
222     public void testGetContainerAdjunct_New() throws Exception {
223         setUpKie(MY_SESS_NAME, 999L, true);
224         mockDbConn(5);
225
226         // force getContainerAdjunct() to be invoked
227         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
228
229         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
230                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
231
232         verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
233
234         assertNotNull(adjcap.getValue());
235     }
236
237     @Test
238     public void testGetContainerAdjunct_Existing() throws Exception {
239         setUpKie(MY_SESS_NAME, 999L, true);
240         mockDbConn(5);
241
242         // force getContainerAdjunct() to be invoked
243         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
244
245         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
246                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
247
248         verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
249
250         // return adjunct on next call
251         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
252
253         // force getContainerAdjunct() to be invoked again
254         setUpKie("myname2", 999L, true);
255         mockDbConn(5);
256         feat.activatePolicySession(polcont, "myname2", MY_KIE_BASE);
257
258         // ensure it isn't invoked again
259         verify(polcont, times(1)).setAdjunct(any(), any());
260     }
261
262     @Test
263     public void testGetContainerAdjunct_WrongType() throws Exception {
264         setUpKie(MY_SESS_NAME, 999L, true);
265         mockDbConn(5);
266
267         // return false adjunct on next call
268         when(polcont.getAdjunct(any())).thenReturn("not-a-real-adjunct");
269
270         // force getContainerAdjunct() to be invoked
271         setUpKie("myname2", 999L, true);
272         mockDbConn(5);
273         feat.activatePolicySession(polcont, "myname2", MY_KIE_BASE);
274
275         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
276                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
277
278         verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
279
280         assertNotNull(adjcap.getValue());
281     }
282
283     @Test
284     public void testGetSequenceNumber() {
285         assertEquals(1, feat.getSequenceNumber());
286     }
287
288     @Test
289     public void testGlobalInit() throws Exception {
290
291         feat.globalInit(null, SRC_TEST_RESOURCES);
292
293         // verify that various factory methods were invoked
294         assertEquals("src/test/resources/feature-session-persistence.properties", propName);
295     }
296
297     @Test(expected = NullPointerException.class)
298     public void testGlobalInitIoEx() throws Exception {
299
300         feat = new PersistenceFeatureImpl() {
301             @Override
302             protected Properties loadProperties(String filenm) throws IOException {
303                 throw new IOException(EXPECTED);
304             }
305         };
306
307         feat.globalInit(null, SRC_TEST_RESOURCES);
308     }
309
310     @Test
311     public void testActivatePolicySession() throws Exception {
312         setUpKie(MY_SESS_NAME, 999L, true);
313         final PreparedStatement ps = mockDbConn(5);
314
315         feat.beforeActivate(null);
316
317         KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
318
319         verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
320         verify(kiestore, never()).newKieSession(any(), any(), any());
321
322         assertEquals(session, kiesess);
323
324         verify(ps).executeUpdate();
325
326         verify(kieenv, times(4)).set(anyString(), any());
327
328         verify(jpa).get(MY_SESS_NAME);
329         verify(jpa).replace(any());
330     }
331
332     @Test
333     public void testActivatePolicySession_NoPersistence() throws Exception {
334         setUpKie(MY_SESS_NAME, 999L, true);
335         final PreparedStatement ps = mockDbConn(5);
336
337         props.remove("persistence.type");
338
339         feat.beforeStart(null);
340
341         assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
342
343         verify(ps, never()).executeUpdate();
344         verify(kiestore, never()).loadKieSession(anyLong(), any(), any(), any());
345         verify(kiestore, never()).newKieSession(any(), any(), any());
346     }
347
348     /** Verifies that a new KIE session is created when there is no existing session entity. */
349     @Test
350     public void testActivatePolicySession_New() throws Exception {
351         setUpKie("noName", 999L, true);
352         mockDbConn(5);
353
354         KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
355
356         verify(kiestore, never()).loadKieSession(anyLong(), any(), any(), any());
357         verify(kiestore).newKieSession(any(), any(), any());
358
359         assertEquals(session, kiesess);
360
361         verify(kieenv, times(4)).set(anyString(), any());
362
363         verify(jpa).get(MY_SESS_NAME);
364         verify(jpa).replace(any());
365     }
366
367     /**
368      * Verifies that a new KIE session is created when there KIE fails to load an existing session.
369      */
370     @Test
371     public void testActivatePolicySession_LoadFailed() throws Exception {
372         setUpKie(MY_SESS_NAME, 999L, false);
373         mockDbConn(5);
374
375         KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
376
377         verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
378         verify(kiestore).newKieSession(any(), any(), any());
379
380         assertEquals(session, kiesess);
381
382         verify(kieenv, times(4)).set(anyString(), any());
383
384         verify(jpa).get(MY_SESS_NAME);
385
386         ArgumentCaptor<DroolsSession> drools = ArgumentCaptor.forClass(DroolsSession.class);
387         verify(jpa).replace(drools.capture());
388
389         assertEquals(MY_SESS_NAME, drools.getValue().getSessionName());
390         assertEquals(100L, drools.getValue().getSessionId());
391     }
392
393     @Test
394     public void testLoadDataSource() throws Exception {
395         setUpKie(MY_SESS_NAME, 999L, false);
396         mockDbConn(5);
397
398         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
399
400         assertEquals(1, emfCount);
401     }
402
403     @Test
404     public void testConfigureSysProps() throws Exception {
405         setUpKie(MY_SESS_NAME, 999L, false);
406         mockDbConn(5);
407
408         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
409
410         assertEquals("60", System.getProperty("com.arjuna.ats.arjuna.coordinator.defaultTimeout"));
411         assertEquals(JTA_OSDIR, System.getProperty("com.arjuna.ats.arjuna.objectstore.objectStoreDir"));
412         assertEquals(JTA_OSDIR, System.getProperty("ObjectStoreEnvironmentBean.objectStoreDir"));
413     }
414
415     @Test
416     public void testConfigureKieEnv() throws Exception {
417         setUpKie(MY_SESS_NAME, 999L, false);
418         mockDbConn(5);
419
420         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
421
422         verify(kieenv, times(4)).set(any(), any());
423
424         verify(kieenv).set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
425         verify(kieenv).set(EnvironmentName.TRANSACTION, usertrans);
426         verify(kieenv).set(EnvironmentName.TRANSACTION_MANAGER, transmgr);
427         verify(kieenv).set(EnvironmentName.TRANSACTION_SYNCHRONIZATION_REGISTRY, transreg);
428
429         verify(bds, times(1)).close();
430     }
431
432     @Test
433     public void testConfigureKieEnv_RtEx() throws Exception {
434         setUpKie(MY_SESS_NAME, 999L, false);
435         mockDbConn(5);
436
437         feat = new PersistenceFeatureMockDb() {
438             @Override
439             protected UserTransaction getUserTrans() {
440                 throw new IllegalArgumentException(EXPECTED);
441             }
442         };
443
444         feat.globalInit(null, SRC_TEST_RESOURCES);
445
446         try {
447             feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
448             fail(MISSING_EXCEPTION);
449
450         } catch (IllegalArgumentException ex) {
451             logger.trace(EXPECTED, ex);
452         }
453
454         verify(bds, times(2)).close();
455     }
456
457     @Test
458     public void testLoadKieSession() throws Exception {
459         setUpKie(MY_SESS_NAME, 999L, true);
460         mockDbConn(5);
461
462         KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
463
464         verify(kiestore).loadKieSession(999L, kiebase, kiecfg, kieenv);
465         verify(kiestore, never()).newKieSession(any(), any(), any());
466
467         assertEquals(session, kiesess);
468     }
469
470     /*
471      * Verifies that loadKieSession() returns null (thus causing newKieSession()
472      * to be called) when an Exception occurs.
473      */
474     @Test
475     public void testLoadKieSession_Ex() throws Exception {
476         setUpKie(MY_SESS_NAME, 999L, false);
477         mockDbConn(5);
478
479         when(kiestore.loadKieSession(anyLong(), any(), any(), any()))
480             .thenThrow(new IllegalArgumentException(EXPECTED));
481
482         KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
483
484         verify(kiestore).loadKieSession(anyLong(), any(), any(), any());
485         verify(kiestore).newKieSession(any(), any(), any());
486
487         assertEquals(session, kiesess);
488     }
489
490     @Test
491     public void testNewKieSession() throws Exception {
492         setUpKie(MY_SESS_NAME, 999L, false);
493         mockDbConn(5);
494
495         KieSession session = feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
496
497         verify(kiestore).newKieSession(kiebase, null, kieenv);
498
499         assertEquals(session, kiesess);
500     }
501
502     @Test
503     public void testLoadDataSource_DiffSession() throws Exception {
504         setUpKie(MY_SESS_NAME, 999L, false);
505         mockDbConn(5);
506
507         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
508
509         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
510                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
511
512         verify(polcont).setAdjunct(any(), adjcap.capture());
513
514         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
515
516         setUpKie("myname2", 999L, false);
517         mockDbConn(5);
518
519         // invoke it again
520         feat.activatePolicySession(polcont, "myname2", MY_KIE_BASE);
521
522         assertEquals(2, emfCount);
523     }
524
525     @Test
526     public void testSelectThreadModel_Persistent() throws Exception {
527         setUpKie(MY_SESS_NAME, 999L, true);
528
529         ThreadModel model = feat.selectThreadModel(polsess);
530         assertNotNull(model);
531         assertTrue(model instanceof PersistentThreadModel);
532     }
533
534     @Test
535     public void testSelectThreadModel_NotPersistent() throws Exception {
536         assertNull(feat.selectThreadModel(polsess));
537     }
538
539     @Test
540     public void testSelectThreadModel_Start__Run_Update_Stop() throws Exception {
541         setUpKie(MY_SESS_NAME, 999L, true);
542
543         ThreadModel model = feat.selectThreadModel(polsess);
544         assertNotNull(model);
545         assertTrue(model instanceof PersistentThreadModel);
546
547         when(polsess.getKieSession()).thenReturn(kiesess);
548
549         model.start();
550         new CountDownLatch(1).await(10, TimeUnit.MILLISECONDS);
551         model.updated();
552         model.stop();
553     }
554
555     @Test
556     public void testDisposeKieSession() throws Exception {
557         setUpKie(MY_SESS_NAME, 999L, false);
558         mockDbConn(5);
559
560         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
561
562         verify(emf, never()).close();
563
564         final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
565                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
566
567         verify(polcont).setAdjunct(any(), adjcap.capture());
568
569         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
570
571         feat.disposeKieSession(polsess);
572
573         // call twice to ensure it isn't re-closed
574         feat.disposeKieSession(polsess);
575
576         verify(emf, times(1)).close();
577     }
578
579     @Test
580     public void testDisposeKieSession_NoAdjunct() throws Exception {
581         feat.globalInit(null, SRC_TEST_RESOURCES);
582
583         assertThatCode(() -> feat.disposeKieSession(polsess)).doesNotThrowAnyException();
584     }
585
586     @Test
587     public void testDisposeKieSession_NoPersistence() throws Exception {
588         setUpKie(MY_SESS_NAME, 999L, false);
589         mockDbConn(5);
590
591         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
592
593         verify(emf, never()).close();
594
595         final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
596                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
597
598         verify(polcont).setAdjunct(any(), adjcap.capture());
599
600         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
601
602         // specify a session that was never loaded
603         when(polsess.getName()).thenReturn("anotherName");
604
605         feat.disposeKieSession(polsess);
606
607         verify(emf, never()).close();
608     }
609
610     @Test
611     public void testDestroyKieSession() throws Exception {
612         setUpKie(MY_SESS_NAME, 999L, false);
613         mockDbConn(5);
614
615         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
616
617         verify(emf, never()).close();
618
619         final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
620                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
621
622         verify(polcont).setAdjunct(any(), adjcap.capture());
623
624         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
625
626         feat.destroyKieSession(polsess);
627
628         // call twice to ensure it isn't re-closed
629         feat.destroyKieSession(polsess);
630
631         verify(emf, times(1)).close();
632     }
633
634     @Test
635     public void testDestroyKieSession_NoAdjunct() throws Exception {
636         feat.globalInit(null, SRC_TEST_RESOURCES);
637
638         assertThatCode(() -> feat.destroyKieSession(polsess)).doesNotThrowAnyException();
639     }
640
641     @Test
642     public void testDestroyKieSession_NoPersistence() throws Exception {
643         setUpKie(MY_SESS_NAME, 999L, false);
644         mockDbConn(5);
645
646         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
647
648         verify(emf, never()).close();
649
650         final ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
651                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
652
653         verify(polcont).setAdjunct(any(), adjcap.capture());
654
655         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
656
657         // specify a session that was never loaded
658         when(polsess.getName()).thenReturn("anotherName");
659
660         feat.destroyKieSession(polsess);
661
662         verify(emf, never()).close();
663     }
664
665     @Test
666     public void testAfterStart() {
667         assertFalse(feat.afterStart(null));
668     }
669
670     @Test
671     public void testBeforeStart() {
672         assertFalse(feat.beforeStart(null));
673     }
674
675     @Test
676     public void testBeforeShutdown() {
677         assertFalse(feat.beforeShutdown(null));
678     }
679
680     @Test
681     public void testAfterShutdown() {
682         assertFalse(feat.afterShutdown(null));
683     }
684
685     @Test
686     public void testBeforeConfigure() {
687         assertFalse(feat.beforeConfigure(null, null));
688     }
689
690     @Test
691     public void testAfterConfigure() {
692         assertFalse(feat.afterConfigure(null));
693     }
694
695     @Test
696     public void testBeforeActivate() {
697         assertFalse(feat.beforeActivate(null));
698     }
699
700     @Test
701     public void testAfterActivate() {
702         assertFalse(feat.afterActivate(null));
703     }
704
705     @Test
706     public void testBeforeDeactivate() {
707         assertFalse(feat.beforeDeactivate(null));
708     }
709
710     @Test
711     public void testAfterDeactivate() {
712         assertFalse(feat.afterDeactivate(null));
713     }
714
715     @Test
716     public void testBeforeStop() {
717         assertFalse(feat.beforeStop(null));
718     }
719
720     @Test
721     public void testAfterStop() {
722         assertFalse(feat.afterStop(null));
723     }
724
725     @Test
726     public void testBeforeLock() {
727         assertFalse(feat.beforeLock(null));
728     }
729
730     @Test
731     public void testAfterLock() {
732         assertFalse(feat.afterLock(null));
733     }
734
735     @Test
736     public void testBeforeUnlock() {
737         assertFalse(feat.beforeUnlock(null));
738     }
739
740     @Test
741     public void testAfterUnlock() {
742         assertFalse(feat.afterUnlock(null));
743     }
744
745     @Test
746     public void testGetPersistenceTimeout_Valid() throws Exception {
747         setUpKie(MY_SESS_NAME, 999L, true);
748         final PreparedStatement statement = mockDbConn(5);
749
750         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
751
752         verify(statement).executeUpdate();
753     }
754
755     @Test
756     public void testGetPersistenceTimeout_Missing() throws Exception {
757
758         props.remove(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT);
759
760         setUpKie(MY_SESS_NAME, 999L, true);
761         final PreparedStatement statement = mockDbConn(0);
762
763         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
764
765         verify(statement, never()).executeUpdate();
766     }
767
768     @Test
769     public void testGetPersistenceTimeout_Invalid() throws Exception {
770         props.setProperty(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT, "abc");
771
772         setUpKie(MY_SESS_NAME, 999L, true);
773         final PreparedStatement s = mockDbConn(0);
774
775         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
776
777         verify(s, never()).executeUpdate();
778     }
779
780     @Test
781     public void testCleanUpSessionInfo() throws Exception {
782         setUpKie(MY_SESS_NAME, 999L, true);
783
784         // use a real DB so we can verify that the "delete" works correctly
785         feat = new PartialFeature();
786
787         makeSessionInfoTbl(20000);
788
789         // create mock entity manager for use by JPA connector
790         EntityManager em = mock(EntityManager.class);
791         when(emf.createEntityManager()).thenReturn(em);
792
793         feat.globalInit(null, SRC_TEST_RESOURCES);
794
795         feat.beforeStart(null);
796         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
797
798         assertEquals("[1, 4, 5]", getSessions().toString());
799     }
800
801     @Test
802     public void testCleanUpSessionInfo_WithBeforeStart() throws Exception {
803         setUpKie(MY_SESS_NAME, 999L, true);
804         final PreparedStatement statement = mockDbConn(0);
805
806         // reset
807         feat.beforeStart(null);
808
809         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
810         verify(statement, times(1)).executeUpdate();
811
812         // should not clean-up again
813         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
814         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
815         verify(statement, times(1)).executeUpdate();
816
817         // reset
818         feat.beforeStart(null);
819
820         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
821         verify(statement, times(2)).executeUpdate();
822
823         // should not clean-up again
824         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
825         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
826         verify(statement, times(2)).executeUpdate();
827     }
828
829     @Test
830     public void testCleanUpSessionInfo_WithBeforeActivate() throws Exception {
831         setUpKie(MY_SESS_NAME, 999L, true);
832         final PreparedStatement statement = mockDbConn(0);
833
834         // reset
835         feat.beforeActivate(null);
836
837         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
838         verify(statement, times(1)).executeUpdate();
839
840         // should not clean-up again
841         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
842         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
843         verify(statement, times(1)).executeUpdate();
844
845         // reset
846         feat.beforeActivate(null);
847
848         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
849         verify(statement, times(2)).executeUpdate();
850
851         // should not clean-up again
852         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
853         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
854         verify(statement, times(2)).executeUpdate();
855     }
856
857     @Test
858     public void testCleanUpSessionInfo_NoTimeout() throws Exception {
859
860         props.remove(DroolsPersistenceProperties.DB_SESSIONINFO_TIMEOUT);
861
862         setUpKie(MY_SESS_NAME, 999L, true);
863         final PreparedStatement statement = mockDbConn(0);
864
865         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
866
867         verify(statement, never()).executeUpdate();
868     }
869
870     @Test
871     public void testCleanUpSessionInfo_NoUrl() throws Exception {
872         props.remove(DroolsPersistenceProperties.DB_URL);
873
874         setUpKie(MY_SESS_NAME, 999L, true);
875         final PreparedStatement statement = mockDbConn(0);
876
877         try {
878             feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
879             fail(MISSING_EXCEPTION);
880         } catch (RuntimeException e) {
881             logger.trace(EXPECTED, e);
882         }
883
884         verify(statement, never()).executeUpdate();
885     }
886
887     @Test
888     public void testCleanUpSessionInfo_NoUser() throws Exception {
889         props.remove(DroolsPersistenceProperties.DB_USER);
890
891         setUpKie(MY_SESS_NAME, 999L, true);
892         final PreparedStatement statement = mockDbConn(0);
893
894         try {
895             feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
896             fail(MISSING_EXCEPTION);
897         } catch (RuntimeException e) {
898             logger.trace(EXPECTED, e);
899         }
900
901         verify(statement, never()).executeUpdate();
902     }
903
904     @Test
905     public void testCleanUpSessionInfo_NoPassword() throws Exception {
906         props.remove(DroolsPersistenceProperties.DB_PWD);
907
908         setUpKie(MY_SESS_NAME, 999L, true);
909         final PreparedStatement statement = mockDbConn(0);
910
911         try {
912             feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
913             fail(MISSING_EXCEPTION);
914         } catch (RuntimeException e) {
915             logger.trace(EXPECTED, e);
916         }
917
918         verify(statement, never()).executeUpdate();
919     }
920
921     @Test
922     public void testCleanUpSessionInfo_SqlEx() throws Exception {
923         setUpKie(MY_SESS_NAME, 999L, true);
924         final PreparedStatement statement = mockDbConn(-1);
925
926         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
927
928         verify(statement).executeUpdate();
929     }
930
931     @Test
932     public void testGetDroolsSessionConnector() throws Exception {
933         setUpKie(MY_SESS_NAME, 999L, true);
934         mockDbConn(5);
935
936         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
937
938         assertEquals(1, jpaCount);
939     }
940
941     @Test
942     public void testReplaceSession() throws Exception {
943         setUpKie(MY_SESS_NAME, 999L, true);
944         mockDbConn(5);
945
946         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
947
948         final ArgumentCaptor<DroolsSession> sesscap = ArgumentCaptor.forClass(DroolsSession.class);
949
950         verify(jpa).replace(sesscap.capture());
951
952         assertEquals(MY_SESS_NAME, sesscap.getValue().getSessionName());
953         assertEquals(999L, sesscap.getValue().getSessionId());
954     }
955
956     @Test
957     public void testIsPersistenceEnabled_Auto() throws Exception {
958         setUpKie(MY_SESS_NAME, 999L, true);
959         mockDbConn(5);
960
961         props.setProperty("persistence.type", "auto");
962
963         assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
964     }
965
966     @Test
967     public void testIsPersistenceEnabled_Native() throws Exception {
968         setUpKie(MY_SESS_NAME, 999L, true);
969         mockDbConn(5);
970
971         props.setProperty("persistence.type", "native");
972
973         assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
974     }
975
976     @Test
977     public void testIsPersistenceEnabled_None() throws Exception {
978         setUpKie(MY_SESS_NAME, 999L, true);
979         mockDbConn(5);
980
981         props.remove("persistence.type");
982
983         assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
984     }
985
986     @Test
987     public void testGetProperties_Ex() throws Exception {
988         setUpKie(MY_SESS_NAME, 999L, true);
989         mockDbConn(5);
990
991         feat = new PersistenceFeatureMockDb() {
992             @Override
993             protected PolicyController getPolicyController(PolicyContainer container) {
994                 throw new IllegalArgumentException(EXPECTED);
995             }
996         };
997
998         assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
999     }
1000
1001     @Test
1002     public void testGetProperty_Specific() throws Exception {
1003         setUpKie(MY_SESS_NAME, 999L, true);
1004         mockDbConn(5);
1005
1006         props.remove("persistence.type");
1007         props.setProperty("persistence.myname.type", "auto");
1008
1009         assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
1010     }
1011
1012     @Test
1013     public void testGetProperty_Specific_None() throws Exception {
1014         setUpKie(MY_SESS_NAME, 999L, true);
1015         mockDbConn(5);
1016
1017         props.remove("persistence.type");
1018         props.setProperty("persistence.xxx.type", "auto");
1019
1020         assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
1021     }
1022
1023     @Test
1024     public void testGetProperty_Both_SpecificOn() throws Exception {
1025         setUpKie(MY_SESS_NAME, 999L, true);
1026         mockDbConn(5);
1027
1028         props.setProperty("persistence.type", "other");
1029         props.setProperty("persistence.myname.type", "auto");
1030
1031         assertNotNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
1032     }
1033
1034     @Test
1035     public void testGetProperty_Both_SpecificDisabledOff() throws Exception {
1036         setUpKie(MY_SESS_NAME, 999L, true);
1037         mockDbConn(5);
1038
1039         props.setProperty("persistence.type", "auto");
1040         props.setProperty("persistence.myname.type", "other");
1041
1042         assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
1043     }
1044
1045     @Test
1046     public void testGetProperty_None() throws Exception {
1047         setUpKie(MY_SESS_NAME, 999L, true);
1048         mockDbConn(5);
1049
1050         props.remove("persistence.type");
1051
1052         assertNull(feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE));
1053     }
1054
1055     @Test
1056     public void testPersistenceFeatureException() {
1057         SecurityException secex = new SecurityException(EXPECTED);
1058         PersistenceFeatureException ex = new PersistenceFeatureException(secex);
1059
1060         assertEquals(secex, ex.getCause());
1061     }
1062
1063     @Test
1064     public void testDsEmf_RtEx() throws Exception {
1065         setUpKie(MY_SESS_NAME, 999L, false);
1066         mockDbConn(5);
1067
1068         feat = new PersistenceFeatureMockDb() {
1069             @Override
1070             protected EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
1071                 throw new IllegalArgumentException(EXPECTED);
1072             }
1073         };
1074
1075         feat.globalInit(null, SRC_TEST_RESOURCES);
1076
1077         try {
1078             feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
1079             fail(MISSING_EXCEPTION);
1080
1081         } catch (IllegalArgumentException ex) {
1082             logger.trace(EXPECTED, ex);
1083         }
1084
1085         verify(bds, times(2)).close();
1086     }
1087
1088     @Test
1089     public void testDsEmf_Close_RtEx() throws Exception {
1090         setUpKie(MY_SESS_NAME, 999L, false);
1091         mockDbConn(5);
1092
1093         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
1094
1095         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
1096                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
1097
1098         verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
1099
1100         // return adjunct on next call
1101         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
1102
1103         try {
1104             doThrow(new IllegalArgumentException(EXPECTED)).when(emf).close();
1105
1106             feat.destroyKieSession(polsess);
1107             fail(MISSING_EXCEPTION);
1108
1109         } catch (IllegalArgumentException ex) {
1110             logger.trace(EXPECTED, ex);
1111         }
1112
1113         verify(bds, times(2)).close();
1114     }
1115
1116     @Test
1117     public void testDsEmf_CloseDataSource_RtEx() throws Exception {
1118         setUpKie(MY_SESS_NAME, 999L, false);
1119         mockDbConn(5);
1120
1121         feat.activatePolicySession(polcont, MY_SESS_NAME, MY_KIE_BASE);
1122
1123         ArgumentCaptor<PersistenceFeature.ContainerAdjunct> adjcap =
1124                 ArgumentCaptor.forClass(PersistenceFeature.ContainerAdjunct.class);
1125
1126         verify(polcont, times(1)).setAdjunct(any(), adjcap.capture());
1127
1128         // return adjunct on next call
1129         when(polcont.getAdjunct(any())).thenReturn(adjcap.getValue());
1130
1131         try {
1132             doThrow(new SQLException(EXPECTED)).when(bds).close();
1133
1134             feat.destroyKieSession(polsess);
1135             fail(MISSING_EXCEPTION);
1136
1137         } catch (PersistenceFeatureException ex) {
1138             logger.trace(EXPECTED, ex);
1139         }
1140     }
1141
1142     /**
1143      * Gets an ordered list of ids of the current SessionInfo records.
1144      *
1145      * @return ordered list of SessInfo IDs
1146      * @throws SQLException sql exception
1147      * @throws IOException io exception
1148      */
1149     private List<Integer> getSessions() throws SQLException, IOException {
1150         attachDb();
1151
1152         ArrayList<Integer> lst = new ArrayList<>(5);
1153
1154         try (PreparedStatement stmt = conn.prepareStatement("SELECT id from sessioninfo order by id");
1155                 ResultSet rs = stmt.executeQuery()) {
1156
1157             while (rs.next()) {
1158                 lst.add(rs.getInt(1));
1159             }
1160         }
1161
1162         return lst;
1163     }
1164
1165     /**
1166      * Sets up for doing invoking the newKieSession() method.
1167      *
1168      * @param sessnm name to which JPA should respond with a session
1169      * @param sessid session id to be returned by the session
1170      * @param loadOk {@code true} if loadKieSession() should return a value, {@code false} to return
1171      *     null
1172      * @throws Exception exception
1173      */
1174     private void setUpKie(String sessnm, long sessid, boolean loadOk) throws Exception {
1175         props.setProperty("persistence.type", "auto");
1176
1177         when(polctlr.getProperties()).thenReturn(props);
1178
1179         when(jpa.get(sessnm)).thenReturn(sess);
1180
1181         when(sess.getSessionId()).thenReturn(sessid);
1182
1183         when(polsess.getPolicyContainer()).thenReturn(polcont);
1184         when(polsess.getName()).thenReturn(sessnm);
1185
1186         if (loadOk) {
1187             when(kiesess.getIdentifier()).thenReturn(sessid);
1188             when(kiestore.loadKieSession(anyLong(), any(), any(), any())).thenReturn(kiesess);
1189
1190         } else {
1191             // use an alternate id for the new session
1192             when(kiesess.getIdentifier()).thenReturn(100L);
1193             when(kiestore.loadKieSession(anyLong(), any(), any(), any())).thenReturn(null);
1194         }
1195
1196         when(kiestore.newKieSession(any(), any(), any())).thenReturn(kiesess);
1197
1198         feat = new PersistenceFeatureKie();
1199         feat.globalInit(null, SRC_TEST_RESOURCES);
1200     }
1201
1202     /**
1203      * Creates the SessionInfo DB table and populates it with some data.
1204      *
1205      * @param expMs number of milli-seconds for expired sessioninfo records
1206      * @throws SQLException exception
1207      * @throws IOException exception
1208      */
1209     private void makeSessionInfoTbl(int expMs) throws SQLException, IOException {
1210
1211         attachDb();
1212
1213         try (PreparedStatement stmt =
1214                 conn.prepareStatement("CREATE TABLE sessioninfo(id int, lastmodificationdate timestamp)")) {
1215
1216             stmt.executeUpdate();
1217         }
1218
1219         try (PreparedStatement stmt =
1220                 conn.prepareStatement("INSERT into sessioninfo(id, lastmodificationdate) values(?, ?)")) {
1221
1222             Timestamp ts;
1223
1224             // current data
1225             ts = new Timestamp(System.currentTimeMillis());
1226             stmt.setTimestamp(2, ts);
1227
1228             stmt.setInt(1, 1);
1229             stmt.executeUpdate();
1230
1231             stmt.setInt(1, 4);
1232             stmt.executeUpdate();
1233
1234             stmt.setInt(1, 5);
1235             stmt.executeUpdate();
1236
1237             // expired data
1238             ts = new Timestamp(System.currentTimeMillis() - expMs);
1239             stmt.setTimestamp(2, ts);
1240
1241             stmt.setInt(1, 2);
1242             stmt.executeUpdate();
1243
1244             stmt.setInt(1, 3);
1245             stmt.executeUpdate();
1246         }
1247     }
1248
1249     /**
1250      * Attaches {@link #conn} to the DB, if it isn't already attached.
1251      *
1252      * @throws SQLException sql exception
1253      * @throws IOException if the property file cannot be read
1254      */
1255     private void attachDb() throws SQLException, IOException {
1256         if (conn == null) {
1257             Properties props = loadDbProps();
1258
1259             conn =
1260                     DriverManager.getConnection(
1261                             props.getProperty(DroolsPersistenceProperties.DB_URL),
1262                             props.getProperty(DroolsPersistenceProperties.DB_USER),
1263                             props.getProperty(DroolsPersistenceProperties.DB_PWD));
1264             conn.setAutoCommit(true);
1265         }
1266     }
1267
1268     /**
1269      * Loads the DB properties from the file, <i>feature-session-persistence.properties</i>.
1270      *
1271      * @return the properties that were loaded
1272      * @throws IOException if the property file cannot be read
1273      * @throws FileNotFoundException if the property file does not exist
1274      */
1275     private Properties loadDbProps() throws IOException, FileNotFoundException {
1276
1277         Properties props = new Properties();
1278
1279         try (FileReader rdr =
1280                 new FileReader("src/test/resources/feature-session-persistence.properties")) {
1281             props.load(rdr);
1282         }
1283
1284         return props;
1285     }
1286
1287     /**
1288      * Create a mock DB connection and statement.
1289      *
1290      * @param retval value to be returned when the statement is executed, or negative to throw an
1291      *     exception
1292      * @return the statement that will be returned by the connection
1293      * @throws SQLException sql exception
1294      */
1295     private PreparedStatement mockDbConn(int retval) throws SQLException {
1296         Connection connection = mock(Connection.class);
1297         PreparedStatement statement = mock(PreparedStatement.class);
1298
1299         when(bds.getConnection()).thenReturn(connection);
1300         when(connection.prepareStatement(anyString())).thenReturn(statement);
1301
1302         if (retval < 0) {
1303             // should throw an exception
1304             when(statement.executeUpdate()).thenThrow(new SQLException(EXPECTED));
1305
1306         } else {
1307             // should return the value
1308             when(statement.executeUpdate()).thenReturn(retval);
1309         }
1310
1311         feat = new PersistenceFeatureMockDb();
1312         feat.globalInit(null, SRC_TEST_RESOURCES);
1313
1314         return statement;
1315     }
1316
1317     /**
1318      * Feature with a mock DB.
1319      */
1320     private class PersistenceFeatureMockDb extends PersistenceFeatureKie {
1321
1322         @Override
1323         protected BasicDataSource makeDataSource(Properties dsProps) {
1324             return bds;
1325         }
1326     }
1327
1328     /**
1329      * Feature supporting newKieSession.
1330      */
1331     private class PersistenceFeatureKie extends PersistenceFeatureImpl {
1332
1333         @Override
1334         protected EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
1335             ++emfCount;
1336             return emf;
1337         }
1338
1339         @Override
1340         protected DroolsSessionConnector makeJpaConnector(EntityManagerFactory emf) {
1341             ++jpaCount;
1342             return jpa;
1343         }
1344     }
1345
1346     /**
1347      * Feature with overrides.
1348      */
1349     private class PersistenceFeatureImpl extends PartialFeature {
1350
1351         @Override
1352         protected Properties loadProperties(String filenm) throws IOException {
1353             propName = filenm;
1354             return props;
1355         }
1356
1357         @Override
1358         protected BasicDataSource makeDataSource(Properties dsProps) {
1359             return null;
1360         }
1361
1362         @Override
1363         protected DroolsSessionConnector makeJpaConnector(EntityManagerFactory emf) {
1364             ++jpaCount;
1365             return null;
1366         }
1367     }
1368
1369     /**
1370      * Feature with <i>some</i> overrides.
1371      */
1372     private class PartialFeature extends PersistenceFeature {
1373
1374         @Override
1375         protected TransactionManager getTransMgr() {
1376             return transmgr;
1377         }
1378
1379         @Override
1380         protected UserTransaction getUserTrans() {
1381             return usertrans;
1382         }
1383
1384         @Override
1385         protected TransactionSynchronizationRegistry getTransSyncReg() {
1386             return transreg;
1387         }
1388
1389         @Override
1390         protected KieServices getKieServices() {
1391             return kiesvc;
1392         }
1393
1394         @Override
1395         protected EntityManagerFactory makeEntMgrFact(Map<String, Object> props) {
1396             ++emfCount;
1397             return emf;
1398         }
1399
1400         @Override
1401         protected PolicyController getPolicyController(PolicyContainer container) {
1402             return polctlr;
1403         }
1404     }
1405 }