001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.core.stateless;
017:
018: import org.apache.openejb.assembler.classic.Assembler;
019: import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
020: import org.apache.openejb.assembler.classic.SecurityServiceInfo;
021: import org.apache.openejb.assembler.classic.StatelessSessionContainerInfo;
022: import org.apache.openejb.assembler.classic.TransactionServiceInfo;
023: import org.apache.openejb.assembler.classic.EjbJarInfo;
024: import org.apache.openejb.config.ConfigurationFactory;
025: import org.apache.openejb.config.EjbModule;
026: import org.apache.openejb.core.ivm.naming.InitContextFactory;
027: import org.apache.openejb.jee.EjbJar;
028: import org.apache.openejb.jee.StatelessBean;
029: import org.apache.openejb.jee.Interceptor;
030: import org.apache.openejb.jee.EnterpriseBean;
031: import org.apache.openejb.jee.InterceptorBinding;
032: import org.apache.openejb.jee.AssemblyDescriptor;
033: import org.apache.openejb.jee.NamedMethod;
034: import org.junit.Test;
035: import org.junit.Before;
036:
037: import javax.annotation.PostConstruct;
038: import javax.interceptor.AroundInvoke;
039: import javax.interceptor.InvocationContext;
040: import javax.interceptor.ExcludeClassInterceptors;
041: import javax.interceptor.ExcludeDefaultInterceptors;
042: import javax.interceptor.Interceptors;
043: import javax.naming.InitialContext;
044: import javax.naming.Context;
045: import javax.ejb.EJBException;
046: import javax.ejb.Local;
047: import java.util.*;
048:
049: import junit.framework.TestCase;
050:
051: /**
052: * @version $Rev: 637726 $ $Date: 2008-03-16 22:34:37 -0700 $
053: */
054: public class StatelessInterceptorTest extends TestCase {
055:
056: InitialContext ctx;
057:
058: @Before
059: public void setUp() throws Exception {
060: ConfigurationFactory config = new ConfigurationFactory();
061: Assembler assembler = new Assembler();
062:
063: assembler.createProxyFactory(config
064: .configureService(ProxyFactoryInfo.class));
065: assembler.createTransactionManager(config
066: .configureService(TransactionServiceInfo.class));
067: assembler.createSecurityService(config
068: .configureService(SecurityServiceInfo.class));
069:
070: assembler.createContainer(config
071: .configureService(StatelessSessionContainerInfo.class));
072:
073: EjbJarInfo ejbJar = config.configureApplication(buildTestApp());
074: assertNotNull(ejbJar);
075:
076: assembler.createApplication(ejbJar);
077:
078: Properties properties = new Properties(System.getProperties());
079: properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
080: InitContextFactory.class.getName());
081: ctx = new InitialContext(properties);
082: }
083:
084: public void test() throws Exception {
085: Target target = (Target) ctx.lookup("TargetBeanLocal");
086: target.echo(new ArrayList());
087:
088: assertCalls(Call.values());
089:
090: calls.clear();
091:
092: int i = target.echo(123);
093: assertEquals(123, i);
094:
095: assertCalls(Call.Default_Invoke_BEFORE,
096: Call.Method_ann_Invoke_BEFORE,
097: Call.Method_dd_Invoke_BEFORE, Call.Bean_Invoke_BEFORE,
098: Call.Bean_Invoke, Call.Bean_Invoke_AFTER,
099: Call.Method_dd_Invoke_AFTER,
100: Call.Method_ann_Invoke_AFTER, Call.Default_Invoke_AFTER);
101: calls.clear();
102:
103: boolean b = target.echo(true);
104: assertTrue(b);
105:
106: assertCalls(Call.Method_ann_Invoke_BEFORE,
107: Call.Method_dd_Invoke_BEFORE, Call.Bean_Invoke_BEFORE,
108: Call.Bean_Invoke, Call.Bean_Invoke_AFTER,
109: Call.Method_dd_Invoke_AFTER,
110: Call.Method_ann_Invoke_AFTER);
111: calls.clear();
112:
113: try {
114: target.throwAppException();
115: fail("Should have thrown app exception");
116: } catch (AppException e) {
117: // pass
118: }
119:
120: try {
121: target.throwSysException();
122: fail("Should have thrown a sys exception");
123: } catch (EJBException e) {
124: // so far so good
125: Throwable cause = e.getCause();
126: if (!(cause instanceof SysException)) {
127: fail("Inner Exception should be a SysException");
128: }
129: }
130:
131: calls.clear();
132:
133: Target target2 = (Target) ctx.lookup("Target2BeanLocal");
134:
135: i = target2.echo(123);
136: assertEquals(123, i);
137:
138: calls.clear();
139:
140: i = target2.echo(123);
141: assertEquals(123, i);
142:
143: assertCalls(Call.Method_ann_Invoke_BEFORE,
144: Call.Bean_Invoke_BEFORE, Call.Bean_Invoke,
145: Call.Bean_Invoke_AFTER, Call.Method_ann_Invoke_AFTER);
146: calls.clear();
147:
148: b = target2.echo(true);
149: assertTrue(b);
150:
151: assertCalls(Call.Method_ann_Invoke_BEFORE,
152: Call.Bean_Invoke_BEFORE, Call.Bean_Invoke,
153: Call.Bean_Invoke_AFTER, Call.Method_ann_Invoke_AFTER);
154: calls.clear();
155: }
156:
157: @Test
158: public void testExcludeClassAndDefaultInterceptors()
159: throws Exception {
160:
161: // 1. Look up the bean it's to be tested against
162: Target target3 = (Target) ctx.lookup("Target3BeanLocal");
163:
164: // 2. Execute intercepted method
165: target3.echo(Collections.EMPTY_LIST);
166:
167: // 3. Assert that appropriate interceptors were executed
168: assertCalls(Call.Bean_PostConstruct,
169: Call.Method_ann_Invoke_BEFORE, Call.Bean_Invoke_BEFORE,
170: Call.Bean_Invoke, Call.Bean_Invoke_AFTER,
171: Call.Method_ann_Invoke_AFTER);
172:
173: // 4. Clean up after yourself
174: calls.clear();
175: }
176:
177: private void assertCalls(Call... expectedCalls) {
178: List expected = Arrays.asList(expectedCalls);
179: assertEquals(join("\n", expected), join("\n", calls));
180: }
181:
182: public static enum Call {
183: Default_PostConstruct_BEFORE, SuperClass_PostConstruct_BEFORE, Class_PostConstruct_BEFORE, Bean_PostConstruct, Class_PostConstruct_AFTER, SuperClass_PostConstruct_AFTER, Default_PostConstruct_AFTER,
184:
185: Default_Invoke_BEFORE, SuperClass_Invoke_BEFORE, Class_Invoke_BEFORE, Method_ann_Invoke_BEFORE, Method_dd_Invoke_BEFORE, Bean_Invoke_BEFORE, Bean_Invoke, Bean_Invoke_AFTER, Method_dd_Invoke_AFTER, Method_ann_Invoke_AFTER, Class_Invoke_AFTER, SuperClass_Invoke_AFTER, Default_Invoke_AFTER,
186:
187: }
188:
189: public EjbModule buildTestApp() throws Exception {
190: EjbJar ejbJar = new EjbJar();
191: ejbJar.setId(this .getClass().getName());
192:
193: AssemblyDescriptor ad = ejbJar.getAssemblyDescriptor();
194:
195: ejbJar.addEnterpriseBean(new StatelessBean(Target2Bean.class));
196:
197: EnterpriseBean bean = ejbJar
198: .addEnterpriseBean(new StatelessBean(TargetBean.class));
199:
200: Interceptor interceptor;
201:
202: interceptor = ejbJar.addInterceptor(new Interceptor(
203: DefaultInterceptor.class));
204: ad.addInterceptorBinding(new InterceptorBinding("*",
205: interceptor));
206:
207: {
208: interceptor = ejbJar.addInterceptor(new Interceptor(
209: EchoMethodInterceptorViaDD.class));
210: InterceptorBinding binding = ad
211: .addInterceptorBinding(new InterceptorBinding(bean,
212: interceptor));
213: binding.setMethod(new NamedMethod(TargetBean.class
214: .getMethod("echo", List.class)));
215: }
216:
217: {
218: interceptor = ejbJar.addInterceptor(new Interceptor(
219: EchoMethodInterceptorViaDD.class));
220: InterceptorBinding binding = ad
221: .addInterceptorBinding(new InterceptorBinding(bean,
222: interceptor));
223: binding.setMethod(new NamedMethod(TargetBean.class
224: .getMethod("echo", int.class)));
225: }
226:
227: {
228: interceptor = ejbJar.addInterceptor(new Interceptor(
229: EchoMethodInterceptorViaDD.class));
230: InterceptorBinding binding = ad
231: .addInterceptorBinding(new InterceptorBinding(bean,
232: interceptor));
233: binding.setMethod(new NamedMethod(TargetBean.class
234: .getMethod("echo", boolean.class)));
235: }
236:
237: EnterpriseBean bean3 = ejbJar
238: .addEnterpriseBean(new StatelessBean(Target3Bean.class));
239: InterceptorBinding binding = ad
240: .addInterceptorBinding(new InterceptorBinding(bean3));
241: binding.setExcludeDefaultInterceptors(true);
242: binding.setExcludeClassInterceptors(true);
243:
244: return new EjbModule(ejbJar);
245: }
246:
247: public static List<Call> calls = new ArrayList<Call>();
248:
249: @Interceptors({ClassInterceptor.class})
250: public static class TargetBean implements Target {
251:
252: @PostConstruct
253: public void construct() {
254: calls.add(Call.Bean_PostConstruct);
255: }
256:
257: @AroundInvoke
258: public Object invoke(InvocationContext context)
259: throws Exception {
260: calls.add(Call.Bean_Invoke_BEFORE);
261: Object o = context.proceed();
262: calls.add(Call.Bean_Invoke_AFTER);
263: return o;
264: }
265:
266: @Interceptors({EchoMethodInterceptorViaAnn.class})
267: public List echo(List data) {
268: calls.add(Call.Bean_Invoke);
269: return data;
270: }
271:
272: public void throwAppException() throws AppException {
273: throw new AppException();
274: }
275:
276: public void throwSysException() {
277: throw new SysException();
278: }
279:
280: @Interceptors({EchoMethodInterceptorViaAnn.class})
281: @ExcludeClassInterceptors
282: public int echo(int i) {
283: calls.add(Call.Bean_Invoke);
284: return i;
285: }
286:
287: @Interceptors({EchoMethodInterceptorViaAnn.class})
288: @ExcludeClassInterceptors
289: @ExcludeDefaultInterceptors
290: public boolean echo(boolean i) {
291: calls.add(Call.Bean_Invoke);
292: return i;
293: }
294: }
295:
296: @ExcludeDefaultInterceptors
297: @Interceptors({ClassInterceptor.class})
298: public static class Target2Bean implements Target {
299:
300: @AroundInvoke
301: public Object invoke(InvocationContext context)
302: throws Exception {
303: calls.add(Call.Bean_Invoke_BEFORE);
304: Object o = context.proceed();
305: calls.add(Call.Bean_Invoke_AFTER);
306: return o;
307: }
308:
309: @Interceptors({EchoMethodInterceptorViaAnn.class})
310: public List echo(List data) {
311: calls.add(Call.Bean_Invoke);
312: return data;
313: }
314:
315: public void throwAppException() throws AppException {
316: throw new AppException();
317: }
318:
319: public void throwSysException() {
320: throw new SysException();
321: }
322:
323: @Interceptors({EchoMethodInterceptorViaAnn.class})
324: @ExcludeClassInterceptors
325: public int echo(int i) {
326: calls.add(Call.Bean_Invoke);
327: return i;
328: }
329:
330: @Interceptors({EchoMethodInterceptorViaAnn.class})
331: @ExcludeClassInterceptors
332: @ExcludeDefaultInterceptors
333: public boolean echo(boolean i) {
334: calls.add(Call.Bean_Invoke);
335: return i;
336: }
337: }
338:
339: @Local({Target.class})
340: public static class Target3Bean extends TargetBean {
341: }
342:
343: public static interface Target {
344: List echo(List data);
345:
346: void throwAppException() throws AppException;
347:
348: void throwSysException();
349:
350: int echo(int i);
351:
352: boolean echo(boolean b);
353: }
354:
355: public static class AppException extends Exception {
356: public AppException() {
357: }
358: }
359:
360: public static class SysException extends RuntimeException {
361: public SysException() {
362: }
363: }
364:
365: public static class EchoMethodInterceptorViaAnn {
366:
367: @AroundInvoke
368: public Object invoke(InvocationContext context)
369: throws Exception {
370: calls.add(Call.Method_ann_Invoke_BEFORE);
371: Object o = context.proceed();
372: calls.add(Call.Method_ann_Invoke_AFTER);
373: return o;
374: }
375: }
376:
377: public static class EchoMethodInterceptorViaDD {
378:
379: @AroundInvoke
380: public Object invoke(InvocationContext context)
381: throws Exception {
382: calls.add(Call.Method_dd_Invoke_BEFORE);
383: Object o = context.proceed();
384: calls.add(Call.Method_dd_Invoke_AFTER);
385: return o;
386: }
387: }
388:
389: public static class ClassInterceptor extends SuperClassInterceptor {
390:
391: @PostConstruct
392: public void construct(InvocationContext context)
393: throws Exception {
394: calls.add(Call.Class_PostConstruct_BEFORE);
395: context.proceed();
396: calls.add(Call.Class_PostConstruct_AFTER);
397: }
398:
399: @AroundInvoke
400: public Object invoke(InvocationContext context)
401: throws Exception {
402: calls.add(Call.Class_Invoke_BEFORE);
403: Object o = context.proceed();
404: calls.add(Call.Class_Invoke_AFTER);
405: return o;
406: }
407: }
408:
409: public static class SuperClassInterceptor {
410:
411: @PostConstruct
412: public void super Construct(InvocationContext context)
413: throws Exception {
414: calls.add(Call.SuperClass_PostConstruct_BEFORE);
415: context.proceed();
416: calls.add(Call.SuperClass_PostConstruct_AFTER);
417: }
418:
419: @AroundInvoke
420: public Object super Invoke(InvocationContext context)
421: throws Exception {
422: calls.add(Call.SuperClass_Invoke_BEFORE);
423: Object o = context.proceed();
424: calls.add(Call.SuperClass_Invoke_AFTER);
425: return o;
426: }
427: }
428:
429: public static class DefaultInterceptor {
430:
431: @PostConstruct
432: public void construct(InvocationContext context)
433: throws Exception {
434: calls.add(Call.Default_PostConstruct_BEFORE);
435: context.proceed();
436: calls.add(Call.Default_PostConstruct_AFTER);
437: }
438:
439: @AroundInvoke
440: public Object invoke(InvocationContext context)
441: throws Exception {
442: calls.add(Call.Default_Invoke_BEFORE);
443: Object o = context.proceed();
444: calls.add(Call.Default_Invoke_AFTER);
445: return o;
446: }
447: }
448:
449: private static String join(String delimeter, List items) {
450: StringBuffer sb = new StringBuffer();
451: for (Object item : items) {
452: sb.append(item.toString()).append(delimeter);
453: }
454: return sb.toString();
455: }
456: }
|