Spring Framework

Spring profiles a použití v testech

@ContextConfiguration( locations = { "classpath:/META-INF/lib_mail/spring/test-context.xml" } ) public abstract class AbstractMessageStorageTestCase { @Autowired private MessageStorage messageStorage; @Test public void shouldPersistSimpleMessageBatch() { .... } @Test(expected = RecipientNotDefinedException.class) public void shouldFailToPersistMessageBatchWithoutRecipients() { .... } } @ContextConfiguration( locations = { "classpath:/META-INF/lib_mail/spring/mysql-datasource.xml", "classpath:META-INF/lib_mail/spring/mail-database-dao-config.xml" } ) public class MysqlMessageStorageTest extends AbstractMessageStorageTestCase { } @ContextConfiguration( locations = { "classpath:/META-INF/lib_mail/spring/memory-dao-config.xml" } )public class MemoryMessageStorageTest extends AbstractMessageStorageTestCase { } <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <!-- sdílené konfigurace pro všechny testy --> <import resource="classpath:/META-INF/lib_mail/spring/mail-config.

Springockito - výroba mocků snadno a rychle

<dependencies> ... <dependency> <groupId>org.kubek2k</groupId> <artifactId>springockito</artifactId> <version>1.0.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.kubek2k</groupId> <artifactId>springockito-annotations</artifactId> <version>1.0.2</version> <scope>test</scope> </dependency> ... </dependencies> @ContextConfiguration( loader = SpringockitoContextLoader.class, locations = "classpath:/context.xml" ) @RunWith(SpringJUnit4ClassRunner.class) public class SpringockitoAnnotationsMocksIntegrationTest { @ReplaceWithMock private InnerBean innerBean; ... } @After public void clearMocks() { Mockito.reset(innerBean) }

Combining custom annotations for securing methods with Spring Security

@PreAuthorize("principal.userObject.administrator") public void approveOrganization(Organization organization) { //... content ... } @PreAuthorize("principal.userObject.isOwnerOf(#organization.id) or principal.userObject.administrator") public void updateOrganization(Organization organization) { //... content ... } @PreAuthorize("(branch.isPartOf(organization) and principal.userObject.isManagerOf(#branch.id)) or principal.userObject.isOwnerOf(#organization.id) or principal.userObject.administrator") public void updateOrganizationBranch(Organization organization, Branch branch) { //... content ... } //and more ... example was shortened principal.userObject.administrator // means administrator with super rights is logged in principal.userObject.isOwnerOf(#organization.id) // means user that is owner of particular organization //(has super rights related to his organization) is logged in branch.

Jak se zbavit nepříjemných závislostí v testech

import org.springframework.beans.factory.FactoryBean; import static org.mockito.Mockito.mock; /** * Simple factory bean creating mock object for specified class. * Mock object is a prototype that means it is created * everytime Spring bean retrieval occurs. In practice it means * that each test method has its own new and pretty mock * object created before it starts. */ public class MockitoFactoryBean implements FactoryBean { private Class mockClass; public void setMockClass(Class mockClass) { this.

When does your Spring @Transactional attribute apply on CgLib proxies

<tx:annotation-driven proxy-target-class="true"/> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> <property name="proxyTargetClass" value="true"/> </bean> <bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"> <property name="transactionInterceptor" ref="transactionInterceptor"/> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributeSource"> <bean class="cz.novoj.business.transactionalRelover.CglibOptimizedAnnotationTransactionAttributeSource"/> </property> </bean> public class CglibOptimizedAnnotationTransactionAttributeSource extends AnnotationTransactionAttributeSource { private static final Log log = LogFactory.getLog(CglibOptimizedAnnotationTransactionAttributeSource.class); @Override protected TransactionAttribute findTransactionAttribute(Method method) { Class declaringClass = method.getDeclaringClass(); if (AopUtils.isCglibProxyClass(declaringClass)) { try { //find appropriate method on parent class Method superMethod = declaringClass.getSuperclass().getMethod(method.getName(), method.getParameterTypes()); return super.findTransactionAttribute(superMethod); } catch (Exception ex) { if(log.

Jednoduché logování ve Springu

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="proxyTargetClass" value="true"/> <property name="beanNames" value="*Manager,*Storage"/> <property name="interceptorNames" value="loggingAdvice"/> </bean> <bean id="loggingAdvice" class="org.springframework.aop.interceptor.CustomizableTraceInterceptor"> <property name="useDynamicLogger" value="true"/> <property name="hideProxyClassNames" value="true"/> <property name="enterMessage" value="Entering method '$[methodName]' of class [$[targetClassShortName]], args: $[arguments]"/> <property name="exitMessage" value="Exiting method '$[methodName]' of class [$[targetClassShortName]], returned: $[returnValue], execution time: $[invocationTime]"/> <property name="exceptionMessage" value="Exception $[exception] thrown in method '$[methodName]' of class [$[targetClassShortName]]"/> </bean>

Spring One - závěrečný den

@PreAuthorize('hasRole('ROLE_DIRECTOR') or (hasRole('ROLE_USER') and (#account.balance < 1000))') public void wihtdrawFromAccount(BigDecimal amount) { //do something }

Spring CgLib Dynamic AOP Proxies - proper Pointcut equals method is simply essential

public Object getProxiedVersion(Object original) { //will create proxy factory based on original object ProxyFactory proxyFactory = new ProxyFactory(original); //this will add our result caching advisor proxyFactory.addAdvisor( new DefaultPointcutAdvisor( new DataProviderPointcut(), new ResultCachingAdvice() ) ); //this will cause CgLib will be used to generate proxy class //and not JDK proxy proxying only interfaces that orignal object implements proxyFactory.setProxyTargetClass(true); //this is only optimalization thing - means we won't touch advisors //after proxy has been created - so Spring could optimalize calls proxyFactory.

Překonaný ResourceBundle, Spring MessageSource vítězí v prvním kole KO

ResourceBundle myResources = ResourceBundle.getBundle("MyResources", currentLocale); <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames"> <list> <value>file:/projekt/neco/messages</value> <value>file:/projekt/neco/exceptions</value> <value>file:/projekt/neco/disclaimer</value> </list> </property> <property name="defaultEncoding" value="UTF-8"/> <property name="fallbackToSystemLocale" value="false"/> <property name="cacheSeconds" value="0"/> </bean>

Testing Aspect Pointcuts - is there an easy way?

private void testAdvice(Map beans, Class testedAdviceClass) { Iterator it = beans.keySet().iterator(); while(it.hasNext()) { String beanName = (String)it.next(); Object strg = beans.get(beanName); if(strg instanceof Advised) { Advised advised = ((Advised)strg); Advisor[] advisors = advised.getAdvisors(); boolean transactionAdvice = false; for(int i = 0; i < advisors.length; i++) { Advisor advisor = advisors[i]; if(testedAdviceClass.isAssignableFrom(advisor.getAdvice().getClass())) { transactionAdvice = true; } } assertTrue(beanName + " has no " + testedAdviceClass.getName() + " advice on it.", transactionAdvice); } else { fail(beanName + " is not Advised!

Beans introspection - základy Springu

//create custom pojo instance User myJavaBean = new User(); //create wrapper BeanWrapper wrapper = new BeanWrapperImpl(myJavaBean); //use simple population wrapper.setPropertyValue("login", "novoj"); wrapper.setPropertyValue("password", "heslo"); //check it assertEquals("novoj", myJavaBean.getLogin()); assertEquals("heslo", myJavaBean.getPassword()); //use collected values population MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue("address.street", "U řeky 1"); pvs.addPropertyValue("address.town", "Královec"); pvs.addPropertyValue("address.country", "Česká republika"); wrapper.setPropertyValues(pvs); //check it assertEquals("U řeky 1", myJavaBean.getAddress().getStreet()); assertEquals("Královec", myJavaBean.getAddress().getTown()); assertEquals("Česká republika", myJavaBean.getAddress().getCountry()); //populate list data wrapper.setPropertyValue("tags[0]", "redTeam"); wrapper.setPropertyValue("tags[1]", "management"); //check it assertTrue(myJavaBean.getTags().contains("redTeam")); assertTrue(myJavaBean.getTags().contains("management")); //populate even map properties wrapper.

Spring AOP - Pozor na AspectJExpressionPointcut!

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.bin <aop:pointcut id="myPointcut" expression="execution(* com.pckg.*.*(..))"/> <aop:advisor advice-ref="someAdvice" pointcut-ref="myPointcut"/> <bean id="myPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="classFilter"> <bean class="org.springframework.aop.support.RootClassFilter"> <constructor-arg value="com.pckg.SomeClassOrInterface"/> </bean> </property> <property name="pattern" value=".*"/> </bean> <aop:advisor advice-ref="someAdvice" pointcut-ref="myPointcut"/>

Část #4: Modulární systémy ve Spring Framework

/** * Module listeners can implement this interface whenever they need to listen to events fired in other modules. * By default events fired in module are listenable only in module itself and in parent (root) context. */ public interface ExternalEventListener { /** * Method returns class specifications of event types, that should be forwarded to this module * by root context. * * BEWARE: do not listen to events that are fired by your module, this would cause this event * to be forwarded too, and you'll receive it two times!

Část #3: Modulární systémy ve Spring Framework

/** * This postprocessor exports all beans marked as ModulePublicInterface into root CPS * application context. */ public class ModulePublicInterfacePostProcessor implements BeanPostProcessor { private static Log log = LogFactory.getLog(ModulePublicInterfacePostProcessor.class); private AbstractRefreshableApplicationContext rootContext; public ModulePublicInterfacePostProcessor(AbstractRefreshableApplicationContext rootContext) { this.rootContext = rootContext; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof ModulePublicInterface) { if (log.isInfoEnabled()) { log.info("Exporting module public interface bean: " + beanName); } DefaultListableBeanFactory rootFactory = (DefaultListableBeanFactory)rootContext.

Část #2: Modulární systémy ve Spring Frameworku

/** * Listens to root application context reload event. Performs refresh of local application context * so the beans in local context will be linked properly to new parent ones. */ public class GenericRefreshingListener implements ApplicationListener, ApplicationContextAware { private static Log log = LogFactory.getLog(GenericRefreshingListener.class); private final List childApplicationContexts = new ArrayList(); private final List notifiedObjects = new ArrayList(); private ApplicationContext ctxListenerIsDeclaredIn; private static final String RELOADING_LISTENER_BEAN_NAME = "reloadingListener"; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ctxListenerIsDeclaredIn = applicationContext; } /** * Handle an application event.

Část #1: Modulární systémy ve Spring Frameworku

public class RootContextLocator { private static ApplicationContext rootContext; static { //ve statickém konstruktoru inicializujeme konfiguraci rootContext = new ClasspathXmlApplicationContext("classpath:META-INF/rootApplicationContext.xml"); } public static ApplicationContext getRootApplicationContext() { return rootContext; } }