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