Upgrading AppFuse to Spring Security 3.1 and Spring 3.1
Before the holiday break, I spent some time upgrading AppFuse to use the latest releases of Spring and Spring Security. I started with Spring Security in early December and quickly discovered its 3.1 XSD required some changes. After changing to the 3.1 XSD in my security.xml, I had to change its <http> element to use security="none"
instead of filters="none"
. With Spring Security 3.0.5, I had:
<http auto-config="true" lowercase-comparisons="false"> <intercept-url pattern="/images/**" filters="none"/> <intercept-url pattern="/styles/**" filters="none"/> <intercept-url pattern="/scripts/**" filters="none"/>After upgrading to 3.1, I had to change this to:
<http pattern="/images/**" security="none"/> <http pattern="/styles/**" security="none"/> <http pattern="/scripts/**" security="none"/> <http auto-config="true">
The next thing I had to change was UserSecurityAdvice.java. Instead of using Collection<GrantedAuthority>
for Authentication's getAuthority() method, I had to change it to use Collection<? extends GrantedAuthority>
.
Authentication auth = ctx.getAuthentication(); Collection<? extends GrantedAuthority> roles = auth.getAuthorities();
Lastly, I discovered that SPRING_SECURITY_CONTEXT_KEY
moved to HttpSessionSecurityContextRepository. Click here to see the changelog for this upgrade in AppFuse's FishEye.
You can read more about what's new in Spring Security 3.1 on InfoQ. I'm especially pumped to see http-only cookie support for Servlet 3.0. I discovered Spring Security didn't support this when Pen-Testing with Zed Attack Proxy.
Upgrading to Spring Framework 3.1
Compared to the Spring Security upgrade, upgrading to Spring 3.1 was a breeze. The first thing I discovered after changing my pom.xml's version was that Spring Security required some additional exclusions in order to get the latest Spring versions. Of course, this was communicated to me through the following cryptic error.
------------------------------------------------------------------------------- Test set: org.appfuse.dao.LookupDaoTest ------------------------------------------------------------------------------- Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.004 sec <<< FAILURE! testGetRoles(org.appfuse.dao.LookupDaoTest) Time elapsed: 0.001 sec <<< ERROR! java.lang.NoSuchMethodError: org.springframework.context.support.GenericApplicationContext.getEnvironment()Lorg/springframework/core/env/ConfigurableEnvironment; at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:97) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228) at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
Without these additional exclusions, Spring Security pulled in Spring 3.0.6. I had to exclude spring-expression, spring-context and spring-web from spring-security-taglibs to get the 3.1.0.RELEASE version of Spring.
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>${spring.security.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </exclusion> </exclusions> </dependency>
I also had to exclude spring-context from spring-security-config and spring-context and spring-expression from spring-security-core. Isn't Maven wonderful?
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring.security.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring.security.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> </exclusions> </dependency>
After making these changes, I got a bit further, but ended up being blocked by a bug in Tapestry 5's Spring support. Basically, after upgrading to Spring 3.1, I started seeing the following error:
java.lang.RuntimeException: Service id 'environment' has already been defined by org.apache.tapestry5.services.TapestryModule.buildEnvironment(PerthreadManager)
Luckily, I was able to easily fix this with advice I found on Tapestry's mailing list. Unfortunately, even though I submitted a fix on December 15th, it didn't make it into Tapestry's 5.3.1 release on December 21st. As soon as Tapestry 5.3.2 is released, I hope to get the AppFuse's build passing again (it's currently failing).
I hope this article helps you upgrade your AppFuse-started applications to the latest versions of Spring and Spring Security. Over the next few weeks, I'll be exploring many of Spring 3.1's new features and implementing them as I see fit. Right now, I'm thinking environments/profiles, Servlet 3 / Java 7 support and Hibernate 4 support. These seem to be the best new features to learn about for my talk in a few weeks.
Posted by Rajesh Chary on January 05, 2012 at 06:00 PM MST #
Thanks Matt,
Good to see you are still keeping appfuse up-to-date. I am still using it for all my new joiners to get started with web app development. Keep up the great work.
Posted by redd on January 07, 2012 at 04:13 PM MST #
Thanks for update ,
I build appfuse 2.1.1-SNAPSHOT and found spring-security 3.1 error
thanks to google bring me here :)
you make a good work!
Posted by Thanit K. on January 17, 2012 at 05:59 AM MST #
Thanks Matt.
We started with web service archetype, upgraded it to the latest spring version ,but then found out we need struts 2. So, we downloaded 2.1.0 archetype for Struts 2, and I am trying to merge it with our working web-service component.
Did you see an exception related to the following in security.xml?
"Attribute 'lowercase-comparisons' is not allowed to appear in element 'http'"
Posted by Viktor on January 27, 2012 at 09:36 PM MST #
Posted by Matt Raible on January 27, 2012 at 09:38 PM MST #
Thanks Matt.
I also found I could fix the dependency issues by adding dependencies into my parent POM's dependency management section, instead of using exclusions.
Posted by Jean on July 05, 2012 at 04:22 PM MDT #
Posted by Richard Cowin on September 24, 2012 at 04:25 PM MDT #