001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.kfs.context;
017:
018: import java.lang.reflect.Method;
019:
020: import org.kuali.core.document.Document;
021: import org.kuali.core.service.DocumentService;
022: import org.kuali.core.service.impl.DocumentServiceImpl;
023: import org.kuali.core.service.impl.KualiConfigurationServiceImpl;
024: import org.kuali.core.service.impl.PersistenceStructureServiceImpl;
025: import org.kuali.core.util.cache.MethodCacheInterceptor;
026: import org.kuali.core.util.spring.Cached;
027: import org.kuali.core.util.spring.ClassOrMethodAnnotationFilter;
028: import org.kuali.kfs.service.impl.ParameterServiceImpl;
029: import org.kuali.module.chart.service.BalanceTypService;
030: import org.kuali.module.chart.service.PriorYearAccountService;
031: import org.kuali.module.chart.service.impl.BalanceTypServiceImpl;
032: import org.kuali.test.ConfigureContext;
033: import org.kuali.test.suite.AnnotationTestSuite;
034: import org.kuali.test.suite.PreCommitSuite;
035: import org.springframework.aop.Advisor;
036: import org.springframework.aop.support.AopUtils;
037: import org.springframework.transaction.TransactionDefinition;
038: import org.springframework.transaction.annotation.Transactional;
039: import org.springframework.transaction.interceptor.TransactionAttribute;
040: import org.springframework.transaction.interceptor.TransactionAttributeSource;
041:
042: @AnnotationTestSuite(PreCommitSuite.class)
043: @ConfigureContext
044: public class SpringAOPUsageTest extends KualiTestBase {
045: public void testCaching() throws Exception {
046: ClassOrMethodAnnotationFilter classOrMethodAnnotationFilter = new ClassOrMethodAnnotationFilter(
047: Cached.class);
048: assertTrue(ParameterServiceImpl.class
049: .isAnnotationPresent(Cached.class));
050: assertFalse(BalanceTypServiceImpl.class
051: .isAnnotationPresent(Cached.class));
052: assertTrue(classOrMethodAnnotationFilter
053: .matches(ParameterServiceImpl.class));
054: assertTrue(classOrMethodAnnotationFilter
055: .matches(BalanceTypServiceImpl.class));
056: // should be cached cause of method annotation
057: SpringContext.getBean(BalanceTypService.class)
058: .getAllBalanceTyps();
059: assertTrue(methodIsCached(BalanceTypService.class.getMethod(
060: "getAllBalanceTyps", new Class[] {}), new Object[] {}));
061: // should not be cached cause no method annotation and no class annotation
062: SpringContext.getBean(BalanceTypService.class)
063: .getEncumbranceBalanceTypes();
064: assertFalse(methodIsCached(BalanceTypService.class.getMethod(
065: "getEncumbranceBalanceTypes", new Class[] {}),
066: new Object[] {}));
067: // should not be cached, cause no annotations on the class or its methods
068: SpringContext.getBean(PriorYearAccountService.class)
069: .getByPrimaryKey("BL", "1031490");
070: assertFalse(methodIsCached(PriorYearAccountService.class
071: .getMethod("getByPrimaryKey", new Class[] {
072: String.class, String.class }), new Object[] {
073: "BL", "1031490" }));
074: }
075:
076: /**
077: * Assures the removeCacheKey method of methodCacheInterceptor is actually removing the method cache.
078: * Depends on method implementations for BalanceTypService.getAllBalanceTyps() and PersistenceStructureService.getPrimaryKeys(Class clazz)
079: * having the @Cached annotation.
080: */
081: public void testClearMethodCache() throws Exception {
082: SpringContext.getBean(BalanceTypService.class)
083: .getAllBalanceTyps();
084: assertTrue(methodIsCached(BalanceTypService.class.getMethod(
085: "getAllBalanceTyps", new Class[] {}), new Object[] {}));
086: removeCachedMethod(BalanceTypService.class.getMethod(
087: "getAllBalanceTyps", new Class[] {}), new Object[] {});
088: assertFalse(methodIsCached(BalanceTypService.class.getMethod(
089: "getAllBalanceTyps", new Class[] {}), new Object[] {}));
090: }
091:
092: @Transactional
093: public void testTransactions() throws Exception {
094: ClassOrMethodAnnotationFilter classOrMethodAnnotationFilter = new ClassOrMethodAnnotationFilter(
095: Transactional.class);
096: Exception exception = null;
097: try {
098: classOrMethodAnnotationFilter.matches(getClass());
099: } catch (Exception e) {
100: exception = e;
101: }
102: assertNotNull(exception);
103: assertEquals(
104: "The @Transactional annotation should be specified at the class level and overriden at the method level, if need be.",
105: exception.getMessage());
106: Advisor transactionAdvisor = SpringContext
107: .getBean(Advisor.class);
108: // should be transaction applicable because the class has the annotation
109: assertTrue(AopUtils.canApply(transactionAdvisor,
110: DocumentServiceImpl.class));
111: // should not be transaction applicable since there's no annotation in the class hierarchy
112: assertFalse(AopUtils.canApply(transactionAdvisor,
113: PersistenceStructureServiceImpl.class));
114: TransactionAttributeSource transactionAttributeSource = SpringContext
115: .getBean(TransactionAttributeSource.class);
116: // should be transactionalized because the class that defines it has the transactional annotation
117: TransactionAttribute documentServiceSaveDocumentAttribute = transactionAttributeSource
118: .getTransactionAttribute(DocumentService.class
119: .getMethod("saveDocument",
120: new Class[] { Document.class }),
121: DocumentServiceImpl.class);
122: assertNotNull(documentServiceSaveDocumentAttribute);
123: TransactionAttribute documentServiceSaveDocumentWithEventAttribute = transactionAttributeSource
124: .getTransactionAttribute(DocumentService.class
125: .getMethod("saveDocument", new Class[] {
126: Document.class, Class.class }),
127: DocumentServiceImpl.class);
128: assertNotNull(documentServiceSaveDocumentWithEventAttribute);
129: assertTrue(TransactionDefinition.PROPAGATION_REQUIRED == documentServiceSaveDocumentWithEventAttribute
130: .getPropagationBehavior());
131: }
132:
133: private void removeCachedMethod(Method method, Object[] arguments) {
134: MethodCacheInterceptor methodCacheInterceptor = SpringContext
135: .getBean(MethodCacheInterceptor.class);
136: if (methodCacheInterceptor
137: .containsCacheKey(methodCacheInterceptor.buildCacheKey(
138: method.toString(), arguments))) {
139: String cacheKey = methodCacheInterceptor.buildCacheKey(
140: method.toString(), arguments);
141: System.out.println(cacheKey);
142: methodCacheInterceptor.removeCacheKey(cacheKey);
143: assertFalse(methodCacheInterceptor
144: .containsCacheKey(methodCacheInterceptor
145: .buildCacheKey(method.toString(), arguments)));
146: }
147: }
148:
149: private boolean methodIsCached(Method method, Object[] arguments) {
150: MethodCacheInterceptor methodCacheInterceptor = SpringContext
151: .getBean(MethodCacheInterceptor.class);
152: return methodCacheInterceptor
153: .containsCacheKey(methodCacheInterceptor.buildCacheKey(
154: method.toString(), arguments));
155: }
156: }
|