1 / 82

Spring Cleaning How to do more with less XML

Spring Cleaning How to do more with less XML. Craig Walls Gateway Software Symposium 2007 craig@habuma.com Blog: http://www.springinaction.com Wiki: http://wiki.habuma.com. About you…. Java? .NET? Ruby/Rails? Erlang? Java 6? Java 5? Java 1.4? Java 1.3? 1.2 or older?

tomai
Download Presentation

Spring Cleaning How to do more with less XML

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Spring CleaningHow to do more with less XML Craig Walls Gateway Software Symposium 2007 craig@habuma.com Blog: http://www.springinaction.com Wiki: http://wiki.habuma.com

  2. About you… • Java? .NET? Ruby/Rails? Erlang? • Java 6? Java 5? Java 1.4? Java 1.3? 1.2 or older? • Who’s using Spring? How long? • Spring 1.2? Spring 2? Spring 2.1? • Favorite session so far? • What brings you to this session?

  3. About me • Agile developer with Semantra • Natural language business intelligence • Developing software professionally for over 13 years • Telecom, Finance, Retail, Education • Java for most of that • Also some C/C++, C#/.NET, Ruby • Spring fanatic

  4. Spring sucks! He’s not really trying to sell too many books, is he?

  5. Spring sucks • Spring is configured with XML • XML is evil • Evil sucks • Therefore, Spring sucks

  6. The so-called solutions to XML • I don’t need no stinkin’ dependency injection! • I’ll do it myself! • Annotations

  7. The truth about Spring and DI • Spring != XML • Spring’s container is decoupled from its configuration strategy • Spring is more than just DI • Spring is a full application framework

  8. But I’ll concede that… • DI is at the core of everything you do in Spring • Spring DI typically involves lots of XML • XML can be verbose • Let’s see how to do more Spring with less XML

  9. Three plans of attack • Smarter XML - Use Spring XML trickery to reduce verbosity • Annotations - Use annotations to configure Spring • Scripting - Use scripting to configure Spring

  10. Disclaimer • There is no one-size-fits-all fix • Apply an ounce of pragmatism

  11. Spring XML done smartly Honey, I shrunk the XML!

  12. Smart Spring XML • Shorthand XML • Bean inheritence • Property editors • The “p” namespace • Custom configuration • Autowiring • Arid POJOs (aka, extreme autowiring)

  13. Shorthand XML • Introduced in Spring 1.2 • Original <value> and <ref> elements replaced with value and ref attributes.

  14. Shorthand XML in action • Pre-Spring 1.2: <bean id="myBean" class="com.habuma.MyBeanImpl"> <property name="someProperty"> <value>This is a string value</value> </property> <property name="someReference"> <ref bean="someOtherBean" /> </property> </bean> • Spring 1.2+: <bean id="myBean" class="com.habuma.MyBeanImpl"> <property name="someProperty" value="This is a string" /> <property name="someReference" ref="someOtherBean" /> </bean>

  15. Shorthand XML: Tradeoffs • Pros • More terse • Cons • Can’t be used to when specifying values in collections (well…maybe)

  16. Bean inheritence • Available in Spring since ??? • Declare common configuration details in a parent bean • Create sub-beans that inherit from the parent

  17. Bean inheritence example 1 <bean id="knightParent” class="com.springinaction.knight. KnightOfTheRoundTable" abstract="true"> <property name="quest" ref="quest" /> <property name="horse" ref="horse" /> <property name="sword" ref="sword" /> <property name="armor" ref="armor" /> <property name="shield" ref="shield" /> </bean> <bean id="knight" parent="knightParent"> <constructor-arg value="Bedivere" /> </bean> Parent type and properties are inherited

  18. Bean inheritence example 2 <bean id="knightParent" abstract="true"> <property name="quest" ref="quest" /> <property name="horse" ref="horse" /> <property name="sword" ref="sword" /> <property name="armor" ref="armor" /> <property name="shield" ref="shield" /> </bean> <bean id="knight" class="com.springinaction.knight. KnightOfTheRoundTable" parent="knightParent"> <constructor-arg value="Bedivere" /> </bean> Only properties are inherited

  19. Bean inheritence tradeoffs • Pros • Helps keep Spring configurations more DRY • Cons • A little tricky to navigate bean hierarchies…especially without tool support

  20. Property editors • Supported in all versions of Spring • Actually part of the JavaBeans spec • Express complex configurations as simpler strings • Property editors help Spring convert simple strings to complex objects

  21. ByteArrayPropertyEditor CharacterEditor CharArrayPropertyEditor ClassArrayEditor ClassEditor CustomBooleanEditor CustomCollectionEditor CustomDateEditor CustomMapEditor CustomNumberEditor FileEditor InputStreamEditor LocaleEditor PatternEditor PropertiesEditor ResourceBundleEditor StringArrayPropertyEditor StringTrimmerEditor URIEditor URLEditor Spring’s built-in property editors

  22. Property editors in action In Java… public class KnightOnCall implements Knight { ... private URL url; public void setUrl(URL url) { this.url = url; } private PhoneNumber phoneNumber; public void setPhoneNumber(PhoneNumber phoneNumber) { this.phoneNumber = phoneNumber; } } In the XML… <bean id="knight" class="com.springinaction.knight.KnightOnCall"> <property name="url" value="http://www.knightoncall.com" /> <property name="phoneNumber" value="940-555-1234" /> </bean>

  23. Registering a customer editor <bean id="customEditorConfigurer" class= "org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="com.springinaction.knight.PhoneNumber"> <bean id="phoneEditor" class= "com.springinaction.springcleaning.PhoneNumberEditor" /> </entry> </map> </property> </bean>

  24. Spring MVC & property editors • In Spring MVC, you might configure SimpleUrlHandlerMapping like this… <bean id="urlMapping" class="org.springframework.web.servlet.handler. SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/home.htm">homeController</prop> <prop key="/login.htm">loginController</prop> <prop key="/addspittle.htm">addSpittleController</prop> <prop key="/addspitter.htm">addSpitterController</prop> </props> </property> </bean> “mappings” is java.util.Properties

  25. Spring MVC w/property editors • But PropertiesEditor can make it simpler <bean id="urlMapping" class="org.springframework.web.servlet.handler. SimpleUrlHandlerMapping"> <property name="mappings"> <value> /home.htm=homeController /login.htm=loginController /addSpittle.htm=addSpittleController /addSpitter.htm=addSpitterController </value> </property> </bean>

  26. Allow me to digress… • Although not related to property mappings at all, Spring 2.0 introduces some handy XML-saving features… <bean id="urlMapping” class="org.springframework.web.servlet.mvc.support. ControllerClassNameHandlerMapping" /> • ControllerClassNameHandlerMapping automatically maps controllers to URL patterns based on the controller’s class name.

  27. Property editors tradeoffs • Pros • Complex types that normally would require lines of XML can be expressed as simple strings • Cons • Not always apparent what type is being created • Looks weird if you don’t know what’s going on

  28. The “p” namespace • New in Spring 2.0 • Enables very terse injection of properties as attributes of the <bean> element • Made available with… <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  29. “p” example <bean id="knight" class="com.springinaction.knight.KnightOfTheRoundTable" p:quest-ref="quest" p:horse-ref="horse" p:sword-ref="sword" p:armor-ref="armor" p:shield-ref="shield"> <constructor-arg value="Bedivere" /> </bean>

  30. “p” namespace tradeoffs • Pros • Super terse • Cons • May seem alien to developers not familiar with it

  31. Custom configuration elements • Available since Spring 2.0 • Encapsulate complex bean configuration behind simpler XML elements. • Spring 2.0 comes with several out-of-the-box namespaces • aop, jee, lang, tx, util • More coming in Spring 2.1: • context, jms • Other Spring projects include (or will include) custom elements: • Spring Security, Spring Modules, etc

  32. “jee” namespace example • Configure JNDI object using <bean>: <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="/jdbc/RantzDatasource" /> <property name="resourceRef" value="true" /> </bean> • Using <jee:jndi-lookup>: <jee:jndi-lookup id="dataSource" jndi-name="/jdbc/RantzDatasource" resource-ref="true" />

  33. How to build custom element • Create namespace schema (XSD) • Create namespace handler class • Create element parser class • Create META-INF/spring.schemas • Maps schemas to physical XSD file • Create META-INF/spring.handlers • Maps schemas to namespace handlers

  34. Custom element tradeoffs • Pros • Simplifies XML configuration • Enables domain-specific configuration • More expressive • Cons • Hides what is really being configured (that may be a good thing, though)

  35. Autowiring • Spring’s so smart…let it figure out how to wire up your bean properties • Autowiring comes in five flavors: • No - Do not autowire • byName - Inject beans into properties where the bean’s ID matches the property’s name • byType - Inject beans into properties where the bean’s type is assignable to a property • constructor - Choose a constructor where Spring can inject beans (by type) into the constructor’s arguments • autoDetect - Try constructor first, then byType

  36. Autowiring • Autowiring strategy can be specified on a per-bean basis or a per-XML file basis: • Per bean: Set the autowire attribute on the individual <bean> elements. • Available in all versions of Spring • Per XML-file: Set the default-autowire attribute on the <beans> element. • Available since Spring 2.0

  37. Autowiring example (per bean) <bean id="knight” class="com.springinaction.knight.KnightOfTheRoundTable" autowire="byType"> <constructor-arg value="Bedivere" /> </bean> Injects all properties Still must inject constructor args

  38. Autowiring example (per file) <?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="…" default-autowire="byType"> <bean id="knight" class="com.springinaction.knight.KnightOfTheRoundTable” autowire="no"> <constructor-arg value="Bedivere" /> </bean> ... </beans> All beans will be autowired “byType” Unless overridden on each bean

  39. Autowiring tradeoffs • Pros • Can dramatically reduce the amount of XML in a Spring configuration • Cons • Along with terseness comes lack of clarity. What was wired where? • Visualization tools (Spring IDE, BeanDoc) won’t recognize autowired beans as being wired. • byName autowiring couples configuration to implementation details • byType and constructor can be problematic when there are ambiguities

  40. Arid POJOs • Spring add-on by Chris Richardson (POJOs in Action) • Available at http://code.google.com/p/aridpojos • Turns auto-wiring up a notch • Automatically declare and autowire all beans in a specified package (or packages) • Based on notion that all beans are declared similarly • Also has an auto-DAO feature

  41. Arid POJOs • Add to Spring config with… <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:arid="http://chrisrichardson.net/schema/arid" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://chrisrichardson.net/schema/arid http://chrisrichardson.net/schema/arid.xsd">

  42. Arid POJOs example 1 • Automatically declare all beans in a package and then autowire them “byType”… <arid:define-beans package="com.habuma.dao" autowire="byType" />

  43. Arid POJOs tradeoffs • All the same pros and cons as autowiring… • Just more so

  44. Annotating Spring Dependency injection is where it’s @

  45. Annotations and Spring • Use @AspectJ for aspects • Use @Transactional for transactions • Spring JavaConfig • Spring 2.1 annotations

  46. Spring without @AspectJ • Prior to Spring 2.0, AOP was a clumsy mess of XML: <bean id="knight" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="knightTarget" /> <property name="interceptorNames" value="pointcutAdvisor" /> <property name="proxyInterfaces" value="com.springinaction.knight.Knight" /> </bean> <bean id="knightTarget" class="com.springinaction.knight.KnightOfTheRoundTable"> ... </bean> <bean id="pointcutAdvisor" class="org.springframework.aop.support.RegExpPointcutAdvisor"> <property name="pattern" value=".*embark.*" /> <property name="advice" value="minstrel" /> </bean> <bean id="minstrel" class="com.springinaction.knight.MinstrelAdvice" /> This is just weird

  47. Spring without @AspectJ • Spring 2.0’s “aop” namespace made things a little bit better… <bean id="minstrel" class="com.springinaction.knight.Minstrel" /> <aop:config> <aop:aspect ref="minstrel"> <aop:after-returning method="sing" pointcut= "execution(* *.Knight.embarkOnQuest(..))" /> </aop:aspect> </aop:config>

  48. Spring with @AspectJ • Spring 2.0 also introduced integration with @AspectJ • Now aspects require only minimal XML • <aop:aspectj-autoproxy/> • One bean declaration for each aspect class • Not true AspectJ aspect • Still Spring proxy • Just uses @AspectJ annotations

  49. @AspectJ example @Aspect public class Minstrel { @Pointcut("execution(* *.Knight.embarkOnQuest(..))") public void embark() {} @AfterReturning("embark()") public void sing() { System.out.println("Fa la la!"); System.out.println("The brave knight is embarking on a quest!"); } }

  50. @AspectJ example • In the XML… <aop:aspectj-autoproxy /> <bean class="Minstrel" /> • Yep…that’s it.

More Related