-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathAbcTest.java
More file actions
269 lines (215 loc) · 9.29 KB
/
AbcTest.java
File metadata and controls
269 lines (215 loc) · 9.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
package xuml.tools.jaxb.compiler.test;
import static abc.A.Attribute.aOne;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import abc.A;
import abc.A.AId;
import abc.A.Events.Create;
import abc.A.Events.StateSignature_DoneSomething;
import abc.Context;
import xuml.tools.model.compiler.runtime.SignalProcessorListener;
import xuml.tools.model.compiler.runtime.SignalProcessorListenerFactory;
import xuml.tools.model.compiler.runtime.actor.EntityActor;
import xuml.tools.model.compiler.runtime.message.Signal;
public class AbcTest {
/**
* Demonstrates the major aspects of using entities generated by
* xuml-model-compiler including reloading signals not fully processed at
* time of last shutdown, creation of entities and asynchronous signalling.
*
* @throws InterruptedException
*/
@Test
public void testCreateEntityManagerFactoryAndCreateAndSignalEntities()
throws InterruptedException {
// Note that the classes Context and A are generated from xml using
// the xuml-tools-maven-plugin
// see the setup() method below for how the Context is initialized.
// send any signals not processed from last shutdown
Context.sendSignalsInQueue();
// create some entities (this happens synchronously)
A a1 = A.create(new A.Events.Create("value1.1", "value2.1", "1234"));
assertEquals("value1.1", a1.getId().getAOne());
A a2 = A.create(new A.Events.Create("value1.2", "value2.2", "1234"));
// use Builder pattern for this one (all Events and Id classes have
// builders)
A a3 = A.create(A.Events.Create.builder().aOne("value1.3").aTwo("value2.3")
.accountNumber("1234").build());
// send asynchronous signals to a1 and a2
a1.signal(new A.Events.SomethingDone(11));
a2.signal(new A.Events.SomethingDone(12));
// send asynchronous signal to a3 after a tiny delay (5ms)
a3.signal(new A.Events.SomethingDone(13), Duration.of(5, ChronoUnit.MILLIS));
// wait a bit for all signals to be processed
Thread.sleep(2000);
// Check the signals were processed
// The load method reloads the entity using a fresh entity manager and
// then closes the entity manager. As a consequence only non-proxied
// fields of the entity will be retrievable using the load method.
assertEquals("11", a1.load().getAThree());
assertEquals("12", a2.load().getAThree());
assertEquals("13", a3.load().getAThree());
// Notice that all the above could be done without explicitly creating
// EntityManagers at all. Nice!
// Refresh the entities from the database using the
// load(em) method and check the signals were processed
EntityManager em = Context.createEntityManager();
// note that the load method below does an em merge and refresh and
// returns a new entity for use within the current entity manager
assertEquals("11", a1.load(em).getAThree());
assertEquals("12", a2.load(em).getAThree());
assertEquals("13", a3.load(em).getAThree());
// demonstrate select statements
{
List<A> list = A.select().many(em);
assertTrue(list.size() >= 3);
}
{
List<A> list = A.select(aOne.eq("value1.1")).many(em);
assertEquals(1, list.size());
assertFalse(A.select(aOne.eq("zz")).any(em).isPresent());
assertFalse(A.select(aOne.eq("zz")).one(em).isPresent());
}
em.close();
}
/**
* Creates the database, initializes the Context and sets the static
* behaviour factory for A.
*/
@BeforeClass
public static void setup() {
// create the entity manager factory
EntityManagerFactory emf = PersistenceHelper.createEmf("abc");
// Intercept entity processing to log activity
// set this before setting EntityManagerFactory
Context.setEntityActorListenerFactory(createSignalProcessorListenerFactory());
// pass the EntityManagerFactory to the generated xuml Context
Context.setEntityManagerFactory(emf, 10);
// set the behaviour factory for the class A
A.setBehaviourFactory(ABehaviour.class);
}
/**
* Stop the actor system and shutdown the database.
*/
@AfterClass
public static void cleanup() {
// shutdown the actor system
Context.stop();
// close the entity manager factory if desired
Context.close();
}
/**
* Tests signal persistence.
*
* @throws InterruptedException
*/
@Test
public void testEntitiesAndSignalsArePersisted() throws InterruptedException {
A a = A.create(new A.Events.Create("value1.4", "value2.4", "1234"));
// check that the entity was persisted
{
EntityManager em = Context.createEntityManager();
Assert.assertNotNull(
em.find(A.class, AId.builder().aOne("value1.4").aTwo("value2.4").build()));
em.close();
}
// test the reloading of a persisted signal to a1
Context.persistSignal("fromSomeId", a.getId(), A.class, new A.Events.SomethingDone(14),
System.currentTimeMillis(), Optional.<Long> absent(), a.uniqueId());
assertEquals(1, Context.sendSignalsInQueue());
// wait a bit for all signals to be processed
Thread.sleep(2000);
// Refresh the entities from the database using the
// load method and check the signals were processed
EntityManager em = Context.createEntityManager();
// note that the load method below does an em merge and refresh and
// returns a new entity for use within the current entity manager
assertEquals("14", a.load(em).getAThree());
em.close();
}
@Test(expected = NullPointerException.class)
public void testSignalCannotBePassedANullDelay() {
A a = A.create(new A.Events.Create("value1.5", "value2.5", "12345"));
a.signal(new A.Events.SomethingDone(12), null);
}
/**
* Behaviour for an A entity.
*
* @author dxm
*
*/
public static class ABehaviour implements A.Behaviour {
private final A self;
public ABehaviour(A self) {
this.self = self;
}
@Override
public void onEntryHasStarted(Create event) {
self.setId(AId.builder().aOne(event.getAOne()).aTwo(event.getATwo()).build());
self.setAThree(event.getAccountNumber());
System.out.println("created");
}
@Override
public void onEntryDoneSomething(StateSignature_DoneSomething event) {
// use the method chaining version of setAThree
// (underscore appended)
System.out.println(self.setAThree_(event.getTheCount() + "").getId());
System.out.println("setting A.athree=" + self.getAThree() + " for " + self.getId());
// demonstrate/unit test getting access to the current
// entity manager when needed
Object count = Context.em().createQuery("select count(b) from B b").getResultList();
System.out.println("counted " + count + " B entities");
// also demonstrate select many using a SelectBuilder
List<A> list = A.select(aOne.eq("value1.1")).many();
System.out.println("list size = " + list.size());
}
}
private static SignalProcessorListenerFactory createSignalProcessorListenerFactory() {
return new SignalProcessorListenerFactory() {
// use the same listener for all entities
private final SignalProcessorListener listener = createSignalProcessorListener();
@Override
public SignalProcessorListener create(String entityUniqueId) {
return listener;
}
};
}
/**
* This listener logs activity using the Akka actor system logger.
*
* @return
*/
private static SignalProcessorListener createSignalProcessorListener() {
return new SignalProcessorListener() {
private final Logger log = LoggerFactory.getLogger("AnonymousSignalProcessorListener");
private int processed = 0;
@Override
public void beforeProcessing(Signal<?> signal, EntityActor actor) {
log.info("before processing");
}
@Override
public void afterProcessing(Signal<?> signal, EntityActor actor) {
// count the number processed and log it
processed++;
log.info("after processing " + processed);
}
@Override
public void failure(Signal<?> signal, Exception e, EntityActor actor) {
log.error(e.getMessage(), e);
}
};
}
}