1
2
3
4
5
6
7 package org.mule.component;
8
9 import org.mule.api.component.LifecycleAdapter;
10 import org.mule.api.lifecycle.InitialisationException;
11 import org.mule.api.object.ObjectFactory;
12 import org.mule.config.PoolingProfile;
13 import org.mule.object.PrototypeObjectFactory;
14 import org.mule.tck.services.UniqueComponent;
15 import org.mule.tck.testmodels.fruit.Orange;
16 import org.mule.tck.testmodels.fruit.WaterMelon;
17 import org.mule.util.ExceptionUtils;
18 import org.mule.util.pool.AbstractPoolingTestCase;
19
20 import java.util.NoSuchElementException;
21
22 import org.junit.Test;
23
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.assertNotSame;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assert.fail;
31
32 public class PooledJavaComponentTestCase extends AbstractPoolingTestCase
33 {
34 @Test
35 public void testComponentCreation() throws Exception
36 {
37 PrototypeObjectFactory objectFactory = getDefaultObjectFactory();
38
39 PoolingProfile pp = createDefaultPoolingProfile();
40 pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_FAIL);
41
42 PooledJavaComponent component = new PooledJavaComponent(objectFactory, pp);
43 component.setMuleContext(muleContext);
44 assertNotNull(component.getObjectFactory());
45 assertEquals(objectFactory, component.getObjectFactory());
46 assertEquals(Orange.class, component.getObjectType());
47
48 assertNotNull(component.getPoolingProfile());
49 assertEquals(pp, component.getPoolingProfile());
50 }
51
52 @Test
53 public void testPoolManagement() throws Exception
54 {
55 PooledJavaComponent component = new PooledJavaComponent(getDefaultObjectFactory(), createDefaultPoolingProfile());
56 assertNull(component.lifecycleAdapterPool);
57
58 component.setFlowConstruct(getTestService());
59 component.setMuleContext(muleContext);
60 component.initialise();
61 assertNull(component.lifecycleAdapterPool);
62
63 component.start();
64 assertNotNull(component.lifecycleAdapterPool);
65
66 component.stop();
67 assertNull(component.lifecycleAdapterPool);
68 }
69
70 @Test
71 public void testStartStop() throws Exception
72 {
73 PooledJavaComponent component = createPooledComponent();
74 assertNotSame(component.borrowComponentLifecycleAdaptor(), component.borrowComponentLifecycleAdaptor());
75
76 component.stop();
77 component.start();
78
79 Object la1 = ((DefaultComponentLifecycleAdapter) component.borrowComponentLifecycleAdaptor()).componentObject;
80 Object la2 = ((DefaultComponentLifecycleAdapter) component.borrowComponentLifecycleAdaptor()).componentObject;
81 assertNotSame(la1, la2);
82 }
83
84 @Test
85 public void testCreateLifecycleAdapters() throws Exception
86 {
87 PooledJavaComponent component = createPooledComponent();
88 assertEquals(0, component.lifecycleAdapterPool.getNumActive());
89
90 LifecycleAdapter borrowed = component.borrowComponentLifecycleAdaptor();
91 assertNotNull(borrowed);
92 assertEquals(1, component.lifecycleAdapterPool.getNumActive());
93
94 component.returnComponentLifecycleAdaptor(borrowed);
95 assertEquals(0, component.lifecycleAdapterPool.getNumActive());
96
97 borrowed = component.borrowComponentLifecycleAdaptor();
98 assertNotNull(borrowed);
99 assertEquals(1, component.lifecycleAdapterPool.getNumActive());
100
101 Object borrowed2 = component.borrowComponentLifecycleAdaptor();
102 assertNotNull(borrowed2);
103 assertEquals(2, component.lifecycleAdapterPool.getNumActive());
104 }
105
106 @Test
107 public void testFailOnExhaust() throws Exception
108 {
109 PoolingProfile pp = createDefaultPoolingProfile();
110 pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_FAIL);
111
112 PooledJavaComponent component = createPooledComponent(pp);
113 borrowLifecycleAdaptersUntilPoolIsFull(component);
114
115 try
116 {
117 component.borrowComponentLifecycleAdaptor();
118 fail("Should throw an Exception");
119 }
120 catch (NoSuchElementException nse)
121 {
122
123 }
124 }
125
126 @Test
127 public void testBlockExpiryOnExhaust() throws Exception
128 {
129 PoolingProfile pp = createDefaultPoolingProfile();
130 pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_WAIT);
131
132 PooledJavaComponent component = createPooledComponent(pp);
133 assertEquals(0, component.lifecycleAdapterPool.getNumActive());
134
135 borrowLifecycleAdaptersUntilPoolIsFull(component);
136
137 long startTime = System.currentTimeMillis();
138 try
139 {
140 component.borrowComponentLifecycleAdaptor();
141 fail("Should throw an Exception");
142 }
143 catch (NoSuchElementException e)
144 {
145 long totalTime = System.currentTimeMillis() - startTime;
146 assertTrue(totalTime >= MAX_WAIT);
147 }
148 }
149
150 @Test
151 public void testBlockOnExhaust() throws Exception
152 {
153 PoolingProfile pp = createDefaultPoolingProfile();
154 pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_WAIT);
155
156 PooledJavaComponent component = createPooledComponent(pp);
157 assertEquals(0, component.lifecycleAdapterPool.getNumActive());
158
159
160 int oneRemainingInPool = (MAX_ACTIVE - 1);
161 for (int i = 0; i < oneRemainingInPool; i++)
162 {
163 LifecycleAdapter borrowed = component.borrowComponentLifecycleAdaptor();
164 assertNotNull(borrowed);
165 assertEquals(component.lifecycleAdapterPool.getNumActive(), i + 1);
166 }
167 assertEquals(oneRemainingInPool, component.lifecycleAdapterPool.getNumActive());
168
169 long startTime = System.currentTimeMillis();
170 int borrowerWait = 500;
171 Borrower borrower = new Borrower(component, borrowerWait);
172 new Thread(borrower, "BorrowThread").start();
173
174
175 try
176 {
177 Thread.sleep(200);
178 }
179 catch (InterruptedException e)
180 {
181
182 }
183
184
185 Object borrowed = component.borrowComponentLifecycleAdaptor();
186 assertNotNull(borrowed);
187 long totalTime = System.currentTimeMillis() - startTime;
188 assertTrue(totalTime >= borrowerWait);
189 }
190
191 @Test
192 public void testGrowOnExhaust() throws Exception
193 {
194 PoolingProfile pp = createDefaultPoolingProfile();
195 pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_GROW);
196
197 PooledJavaComponent component = createPooledComponent(pp);
198
199 borrowLifecycleAdaptersUntilPoolIsFull(component);
200
201
202 Object borrowed = component.borrowComponentLifecycleAdaptor();
203 assertNotNull(borrowed);
204 assertEquals(MAX_ACTIVE + 1, component.lifecycleAdapterPool.getNumActive());
205 }
206
207 @Test
208 public void testClearPool() throws Exception
209 {
210 PoolingProfile pp = createDefaultPoolingProfile();
211 pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_FAIL);
212
213 PooledJavaComponent component = createPooledComponent(pp);
214
215 LifecycleAdapter borrowed = component.borrowComponentLifecycleAdaptor();
216 assertEquals(1, component.lifecycleAdapterPool.getNumActive());
217 component.returnComponentLifecycleAdaptor(borrowed);
218 assertEquals(0, component.lifecycleAdapterPool.getNumActive());
219
220 component.stop();
221 component.start();
222 assertEquals(0, component.lifecycleAdapterPool.getNumActive());
223 }
224
225 @Test
226 public void testObjectUniqueness() throws Exception
227 {
228 PrototypeObjectFactory objectFactory = new PrototypeObjectFactory(UniqueComponent.class);
229 PooledJavaComponent component = createPooledComponent(objectFactory);
230 assertEquals(0, component.lifecycleAdapterPool.getNumActive());
231
232 String id1 = getIdFromObjectCreatedByPool(component);
233 String id2 = getIdFromObjectCreatedByPool(component);
234 String id3 = getIdFromObjectCreatedByPool(component);
235
236 assertFalse("Service IDs " + id1 + " and " + id2 + " should be different", id1.equals(id2));
237 assertFalse("Service IDs " + id2 + " and " + id3 + " should be different", id2.equals(id3));
238 assertFalse("Service IDs " + id1 + " and " + id3 + " should be different", id1.equals(id3));
239 }
240
241 @Test
242 public void testDisposingFactoryDisposesObject() throws Exception
243 {
244 PrototypeObjectFactory objectFactory = new PrototypeObjectFactory(WaterMelon.class);
245 PooledJavaComponent component = createPooledComponent(objectFactory);
246
247 DefaultComponentLifecycleAdapter lifecycleAdapter = (DefaultComponentLifecycleAdapter) component.borrowComponentLifecycleAdaptor();
248 component.returnComponentLifecycleAdaptor(lifecycleAdapter);
249 component.stop();
250 component.dispose();
251
252 assertNull(lifecycleAdapter.componentObject);
253 }
254
255 private PrototypeObjectFactory getDefaultObjectFactory() throws InitialisationException
256 {
257 PrototypeObjectFactory objectFactory = new PrototypeObjectFactory(Orange.class);
258 objectFactory.initialise();
259 return objectFactory;
260 }
261
262 private PooledJavaComponent createPooledComponent() throws Exception
263 {
264 return createPooledComponent(createDefaultPoolingProfile(), getDefaultObjectFactory());
265 }
266
267 private PooledJavaComponent createPooledComponent(ObjectFactory objectFactory) throws Exception
268 {
269 return createPooledComponent(createDefaultPoolingProfile(), objectFactory);
270 }
271
272 private PooledJavaComponent createPooledComponent(PoolingProfile poolingProfile) throws Exception
273 {
274 return createPooledComponent(poolingProfile, getDefaultObjectFactory());
275 }
276
277 private PooledJavaComponent createPooledComponent(PoolingProfile poolingProfile, ObjectFactory objectFactory) throws Exception
278 {
279 PooledJavaComponent component = new PooledJavaComponent(objectFactory, poolingProfile);
280 component.setMuleContext(muleContext);
281 component.setFlowConstruct(getTestService());
282 component.initialise();
283 component.start();
284 return component;
285 }
286
287 private void borrowLifecycleAdaptersUntilPoolIsFull(PooledJavaComponent component) throws Exception
288 {
289 for (int i = 0; i < MAX_ACTIVE; i++)
290 {
291 Object borrowed = component.borrowComponentLifecycleAdaptor();
292 assertNotNull(borrowed);
293 assertEquals(component.lifecycleAdapterPool.getNumActive(), i + 1);
294 }
295 assertEquals(MAX_ACTIVE, component.lifecycleAdapterPool.getNumActive());
296 }
297
298 private String getIdFromObjectCreatedByPool(PooledJavaComponent component) throws Exception
299 {
300 DefaultComponentLifecycleAdapter lifecycleAdapter =
301 (DefaultComponentLifecycleAdapter) component.borrowComponentLifecycleAdaptor();
302 Object obj = lifecycleAdapter.componentObject;
303
304
305
306 assertNotNull(obj);
307
308 assertTrue("Object should be of type UniqueComponent", obj instanceof UniqueComponent);
309
310 String id = ((UniqueComponent) obj).getId();
311 assertNotNull(id);
312 return id;
313 }
314
315 private static class Borrower implements Runnable
316 {
317 private PooledJavaComponent component;
318 private long time;
319
320 public Borrower(PooledJavaComponent component, long time)
321 {
322 super();
323 if (component == null)
324 {
325 throw new IllegalArgumentException("Pool cannot be null");
326 }
327 this.component = component;
328 if (time < 500)
329 {
330 time = 500;
331 }
332 this.time = time;
333 }
334
335 public void run()
336 {
337 try
338 {
339 LifecycleAdapter object = component.borrowComponentLifecycleAdaptor();
340 try
341 {
342 Thread.sleep(time);
343 }
344 catch (InterruptedException e)
345 {
346
347 }
348 component.returnComponentLifecycleAdaptor(object);
349 }
350 catch (Exception e)
351 {
352 fail("Borrower thread failed:\n" + ExceptionUtils.getStackTrace(e));
353 }
354 }
355 }
356 }