Announcement Announcement Module
Collapse

JavaConfig forum decommissioned in favor of Core Container

As described at

http://static.springsource.org/sprin...fig/README.TXT

key features of the Spring JavaConfig project have been migrated into the core Spring Framework as of version 3.0.

Please see the Spring 3.0 documentation on @Configuration and @Bean support:

http://static.springsource.org/sprin...tml#beans-java

For any questions related to @Configuration classes and @Bean methods in Spring 3.0, please post in the dedicated 'Core Container' forum at

http://forum.springsource.org/forumdisplay.php?f=26
See more
See less
Can Spring JavaConfig handle load-time-weaeving yet? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can Spring JavaConfig handle load-time-weaeving yet?

    I was experimenting with seeing if my app's XML-configuration could be replaced with Spring JavaConfig. I really like the ideas in this project.

    However, I ran into issues where I have load-time-weaving tied in with annotation-based security settings. This is fragment of my XML that shows load-time-weaving activated, as well as SecurityAnnotations turned on and some Acegi Security stuff plugged in.
    Code:
    	<context:load-time-weaver/>
        
    	<bean id="attributes" class="org.acegisecurity.annotation.SecurityAnnotationAttributes"/>
     	
    	<bean id="objectDefinitionSource" class="org.acegisecurity.intercept.method.MethodDefinitionAttributes">
    		<property name="attributes"><ref bean="attributes"/></property>
    	</bean>
    	
    	<bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
    		<property name="decisionVoters">
    			<list>
    				<bean class="org.acegisecurity.vote.RoleVoter"/>
    			</list>
    		</property>
    	</bean>
    	
    	<bean id="securityInterceptor" class="org.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor">
    		<property name="authenticationManager"><ref bean="authenticationManager"/></property>
    		<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
    		<property name="objectDefinitionSource"><ref bean="objectDefinitionSource"/></property>
    	</bean>
    	
    	<bean id="securityAspect" class="com.harris.cims.aop.SecurityAspect" factory-method="aspectOf">
    		<property name="securityInterceptor"><ref bean="securityInterceptor"/></property>
    	</bean>
    Is there a current solution with m3 that would work? Or do I need to wait until this type of support is added on?

    BTW, thanks for all the effort so far! This is a great project for Spring.

  • #2
    In follow-up, I have managed to get a solution working. It requires I sacrifice some of the features, but I think it still works alright.

    1) One key thing I use with Spring XML is PropertyPlaceHolderConfigurer
    Code:
    <bean id="properties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    	<property name="locations">
    		<list>
    			<value>classpath:MyApp_${context}.props</value>
    			<value>classpath:Common.props</value>
    		</list>
    	</property>
    	<property name="systemPropertiesModeName">
    		<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
    	</property>
    </bean>
    Because I want it to pick out a certain properties file (dev/test/production), I launch my app with "-Dcontext=production" argument. This doesn't carry over to Spring JavaConfig very handily.

    To deal with this, I wrote a static method call that loads all my system properties into a class filled with static attributes. The static function call reads the system property, and then conveniently uses DefaultResourceLoader (from Spring core) to load things up:
    Code:
    public static void loadProperties() {
    	if (System.getProperty("context") == null) {
    		throw new RuntimeException("System property 'context' must be specified. Suggest 'dev', 'test', or 'production'");
    	}
    		
    	if (resourceLoader == null) {
    		resourceLoader = new DefaultResourceLoader();
    	}
    
    	if (props == null) {
    		props = new Properties();
    		try {
    			props.load(resourceLoader.getResource("classpath:MyApp" + "_" + System.getProperty("context") + ".props").getInputStream());
    			props.load(resourceLoader.getResource("classpath:Common.props").getInputStream());
    		} catch (IOException e) {
    			e.printStackTrace();
    			throw new RuntimeException(e);
    		}
    		MyAppProperties.init(props);
    	}
    }
    To bring this into Spring JavaConfig, I just created a constructor call that calls this static function, and now I have programmatic access to all of these properties.
    Code:
    @Configuration
    public class AppContextConfig {
    	
    	public AppContextConfig() {
    		MyApp.loadProperties();
    	}
    	
    	@Bean
    	public BasicDataSource dataSource() {
    		BasicDataSource dataSource = new BasicDataSource();
    		dataSource.setDriverClassName(MyAppProperties.DatabaseDriver);
    		dataSource.setUrl(MyAppProperties.DatabaseConnection);
    		dataSource.setUsername(MyAppProperties.DBUserName);
    		dataSource.setPassword(MyAppProperties.DBPassword);
    		return dataSource;
    	}
    ...
    This seems to do the trick for me.

    2) Because I have both Spring AOP and AspectJ proxies a la load time weaving, I must still use a wrapping ClassPathXmlApplicationContext in order to define those parts. On the positive side, Spring JavaConfig already documented how to do that. On the negative side, my Java code can't see the nice APIs of JavaConfigApplicationContext.
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="
    	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
    	<bean class="com.harris.myapp.AppContextConfig"/>
    	
    	<bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>
    	
    	<context:load-time-weaver/>
    	
    	<bean id="securityAspect" class="com.harris.myapp.aop.SecurityAspect" factory-method="aspectOf">
    		<property name="securityInterceptor"><ref bean="securityInterceptor"/></property>
    	</bean>
    
    </beans>
    One downside to this is the fact that Spring IDE has a warning where I have securityAspect referring to securityInterceptor, both of which are defined in separate places. However, running the app appears to work correctly.

    3) My TestNG/JUnit regression test suite passed with flying colors! That tells me this is usable. Hooray!

    Comment


    • #3
      Greg,

      Looks like you've gotten what you need - let me know if you have further questions.

      Regarding load time weaving, see http://jira.springframework.org/browse/SJC-212 (@LoadTimeWeaver)

      In the meantime, you could always just declare a LoadTimeWeaver bean explicitly. For an example, see https://fisheye.springframework.org/...ava?r=856#l139

      Comment

      Working...
      X