Spring Cleaning How to do more with less XML

Download Spring Cleaning How to do more with less XML

Post on 06-Jan-2016




0 download


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? - PowerPoint PPT Presentation


<ul><li><p>Spring CleaningHow to do more with less XMLCraig WallsGateway Software Symposium 2007craig@habuma.comBlog: http://www.springinaction.comWiki: http://wiki.habuma.com</p></li><li><p>About youJava? .NET? Ruby/Rails? Erlang?Java 6? Java 5? Java 1.4? Java 1.3? 1.2 or older?Whos using Spring? How long?Spring 1.2? Spring 2? Spring 2.1?Favorite session so far?What brings you to this session?</p></li><li><p>About meAgile developer with SemantraNatural language business intelligenceDeveloping software professionally for over 13 yearsTelecom, Finance, Retail, EducationJava for most of thatAlso some C/C++, C#/.NET, RubySpring fanatic</p></li><li><p>Spring sucks!Hes not really trying to sell too many books, is he?</p></li><li><p>Spring sucks</p><p>Spring is configured with XMLXML is evilEvil sucksTherefore, Spring sucks</p></li><li><p>The so-called solutions to XMLI dont need no stinkin dependency injection!</p><p>Ill do it myself!</p><p>Annotations</p></li><li><p>The truth about Spring and DI</p><p>Spring != XMLSprings container is decoupled from its configuration strategy</p><p>Spring is more than just DISpring is a full application framework</p></li><li><p>But Ill concede thatDI is at the core of everything you do in SpringSpring DI typically involves lots of XMLXML can be verbose</p><p>Lets see how to do more Spring with less XML</p></li><li><p>Three plans of attack</p><p>Smarter XML - Use Spring XML trickery to reduce verbosityAnnotations - Use annotations to configure SpringScripting - Use scripting to configure Spring</p></li><li><p>Disclaimer</p><p>There is no one-size-fits-all fixApply an ounce of pragmatism</p></li><li><p>Spring XML done smartlyHoney, I shrunk the XML!</p></li><li><p>Smart Spring XMLShorthand XMLBean inheritenceProperty editorsThe p namespaceCustom configurationAutowiringArid POJOs (aka, extreme autowiring)</p></li><li><p>Shorthand XML</p><p>Introduced in Spring 1.2</p><p>Original and elements replaced with value and ref attributes.</p></li><li><p>Shorthand XML in actionPre-Spring 1.2:</p><p> This is a string value </p><p>Spring 1.2+: </p></li><li><p>Shorthand XML: Tradeoffs</p><p>ProsMore terse</p><p>ConsCant be used to when specifying values in collections (wellmaybe)</p></li><li><p>Bean inheritence</p><p>Available in Spring since ???</p><p>Declare common configuration details in a parent bean</p><p>Create sub-beans that inherit from the parent</p></li><li>Bean inheritence example 1</li><li><p>Bean inheritence example 2</p><p>Only propertiesare inherited</p></li><li><p>Bean inheritence tradeoffsProsHelps keep Spring configurations more DRY</p><p>ConsA little tricky to navigate bean hierarchiesespecially without tool support</p></li><li><p>Property editorsSupported in all versions of SpringActually part of the JavaBeans spec</p><p>Express complex configurations as simpler stringsProperty editors help Spring convert simple strings to complex objects</p></li><li><p>Springs built-in property editorsByteArrayPropertyEditorCharacterEditorCharArrayPropertyEditorClassArrayEditorClassEditorCustomBooleanEditorCustomCollectionEditorCustomDateEditorCustomMapEditorCustomNumberEditorFileEditorInputStreamEditorLocaleEditorPatternEditorPropertiesEditorResourceBundleEditorStringArrayPropertyEditorStringTrimmerEditorURIEditorURLEditor</p></li><li><p>Property editors in actionIn Javapublic class KnightOnCall implements Knight { ... private URL url; public void setUrl(URL url) { this.url = url; }</p><p> private PhoneNumber phoneNumber; public void setPhoneNumber(PhoneNumber phoneNumber) { this.phoneNumber = phoneNumber; }}</p><p>In the XML</p></li><li><p>Registering a customer editor</p></li><li><p>Spring MVC &amp; property editorsIn Spring MVC, you might configure SimpleUrlHandlerMapping like this</p><p> homeController loginController addSpittleController addSpitterController </p><p>mappings isjava.util.Properties</p></li><li><p>Spring MVC w/property editorsBut PropertiesEditor can make it simpler</p><p> /home.htm=homeController /login.htm=loginController /addSpittle.htm=addSpittleController /addSpitter.htm=addSpitterController </p></li><li><p>Allow me to digressAlthough not related to property mappings at all, Spring 2.0 introduces some handy XML-saving features</p></li><li><p>Property editors tradeoffsProsComplex types that normally would require lines of XML can be expressed as simple strings</p><p>ConsNot always apparent what type is being createdLooks weird if you dont know whats going on</p></li><li><p>The p namespaceNew in Spring 2.0Enables very terse injection of properties as attributes of the elementMade available with</p></li><li><p>p example</p></li><li><p>p namespace tradeoffs</p><p>ProsSuper terse</p><p>ConsMay seem alien to developers not familiar with it</p></li><li><p>Custom configuration elementsAvailable since Spring 2.0Encapsulate complex bean configuration behind simpler XML elements.Spring 2.0 comes with several out-of-the-box namespacesaop, jee, lang, tx, utilMore coming in Spring 2.1:context, jmsOther Spring projects include (or will include) custom elements:Spring Security, Spring Modules, etc</p></li><li><p>jee namespace exampleConfigure JNDI object using :</p><p>Using :</p></li><li><p>How to build custom elementCreate namespace schema (XSD)Create namespace handler classCreate element parser classCreate META-INF/spring.schemasMaps schemas to physical XSD fileCreate META-INF/spring.handlersMaps schemas to namespace handlers</p></li><li><p>Custom element tradeoffsProsSimplifies XML configurationEnables domain-specific configurationMore expressiveConsHides what is really being configured (that may be a good thing, though)</p></li><li><p>AutowiringSprings so smartlet it figure out how to wire up your bean properties</p><p>Autowiring comes in five flavors:No - Do not autowirebyName - Inject beans into properties where the beans ID matches the propertys namebyType - Inject beans into properties where the beans type is assignable to a propertyconstructor - Choose a constructor where Spring can inject beans (by type) into the constructors argumentsautoDetect - Try constructor first, then byType</p></li><li><p>AutowiringAutowiring strategy can be specified on a per-bean basis or a per-XML file basis:Per bean: Set the autowire attribute on the individual elements.Available in all versions of SpringPer XML-file: Set the default-autowire attribute on the element.Available since Spring 2.0</p></li><li><p>Autowiring example (per bean)</p></li><li><p>Autowiring example (per file)</p></li><li><p>Autowiring tradeoffsProsCan dramatically reduce the amount of XML in a Spring configuration</p><p>ConsAlong with terseness comes lack of clarity. What was wired where?Visualization tools (Spring IDE, BeanDoc) wont recognize autowired beans as being wired.byName autowiring couples configuration to implementation detailsbyType and constructor can be problematic when there are ambiguities</p></li><li><p>Arid POJOsSpring add-on by Chris Richardson (POJOs in Action)Available at http://code.google.com/p/aridpojosTurns auto-wiring up a notchAutomatically declare and autowire all beans in a specified package (or packages)Based on notion that all beans are declared similarlyAlso has an auto-DAO feature</p></li><li><p>Arid POJOs</p><p>Add to Spring config with</p></li><li><p>Arid POJOs example 1Automatically declare all beans in a package and then autowire them byType</p></li><li><p>Arid POJOs tradeoffs</p><p>All the same pros and cons as autowiringJust more so</p></li><li><p>Annotating SpringDependency injection is where its @</p></li><li><p>Annotations and Spring</p><p>Use @AspectJ for aspectsUse @Transactional for transactionsSpring JavaConfigSpring 2.1 annotations</p></li><li><p>Spring without @AspectJPrior to Spring 2.0, AOP was a clumsy mess of XML:</p><p>...</p><p>This is just weird</p></li><li><p>Spring without @AspectJSpring 2.0s aop namespace made things a little bit better</p></li><li><p>Spring with @AspectJSpring 2.0 also introduced integration with @AspectJNow aspects require only minimal XML</p><p>One bean declaration for each aspect classNot true AspectJ aspectStill Spring proxyJust uses @AspectJ annotations</p></li><li><p>@AspectJ example</p><p>@Aspectpublic class Minstrel { @Pointcut("execution(* *.Knight.embarkOnQuest(..))") public void embark() {}</p><p> @AfterReturning("embark()") public void sing() { System.out.println("Fa la la!"); System.out.println("The brave knight is embarking on a quest!"); }}</p></li><li><p>@AspectJ exampleIn the XML</p><p>Yepthats it.</p></li><li><p>@AspectJ tradeoffs</p><p>ProsSignificantly less XML required for aspects</p><p>ConsCouples aspect classes to AspectJNot all AspectJ pointcuts available; still proxy-based</p></li><li><p>@Transactional</p><p>Prior to Spring 2.0, transactions were just as messy as other types of aspectsTransactionProxyFactoryBean instead of ProxyFactoryBeanBean inheritence helped a little</p></li><li><p>The tx namespaceSpring 2.0 added the tx namespaceMade things a bit simpler</p></li><li><p>@Transactional</p><p>Spring 2.0 also introduced the @Transactional annotationVery appropriate use of annotationsTransactions declared with minimal XML</p></li><li><p>@Transactional exampleIn Java:@Transactional(propagation=Propagation.SUPPORTS)public class CustomerServiceImpl implements CustomerService { @Transactional(propagation=Propagation.REQUIRED) public void addNewCustomer(Customer customer) { ... }...}In XML:</p></li><li><p>@Transactional tradeoffs</p><p>ProsLike @AspectJ, very very little XML requiredConsInvasive--Spring annotations couple your code to Spring</p></li><li><p>Spring JavaConfigAdd-on for Springhttp://www.springframework.org/javaconfigCurrently at version 1.0-M2aRecreates Spring XML configuration in Java using annotationsProvides several annotations for Spring configuration:@Configuration - Declares class as a configuration class@Bean - Declares a method as a bean declaration@ExternalBean - Declares an abstract method as a reference to an externally defined bean@AutoBean - Declares an abstract method to server as a holder for automatically instantiated/wired bean@ScopedProxy - Used to declare scoped proxy for a bean (non-singleton/non-prototype)</p></li><li><p>Spring JavaConfigTwo ways to use JavaConfig:Use AnnotationApplicationContextSimple, no-XML approachHard to use with webappsCant parameterize configuration instancesConfigure a ConfigurationPostProcessor (in XML)Easy to use with web apps (using minimal bootstrap XML)Configuration can be parameterized</p></li><li><p>Loading JavaConfigAnnotationApplicationContext:ApplicationContext ctx = new AnnotationApplicationContext( MyConfig.class.getName());</p><p>ConfigurationPostProcessor:</p></li><li><p>JavaConfig example@Configurationpublic abstract class KnightConfig { @Bean public Knight knight() { KnightofTheRoundTable knight = new KnightOfTheRoundTable("Bedivere"); knight.setQuest(quest()); return knight; }</p><p> @Bean private Quest quest() { return new HolyGrailQuest(); }</p><p> @ExternalBean private abstract Horse horse();}</p></li><li><p>JavaConfig tradeoffsProsMinimally invasive - annotations are confined to configuration-specific classesDynamic - Use any Java constructs you likeTestable - Easily write unit tests against configuration itselfRefactorable - No static identifiersOffers bean visibility using Java constructsParameterizable if using bootstrap XMLConsNon-intuitive - Structured like Spring XML, but looks like Java</p></li><li><p>Spring 2.5 annotationsSpring 2.5 will add a few new annotations@Component - Indicates that a class is a component that should be registered in Spring@Autowired - Indicates that a property should be autowired@Scoped - Declares scoping on auto-detected beanWorks with new configuration element</p></li><li><p>Scans a package and all of its subpackagesAuto-configures all beans annotated with @Component, @Repository, or @AspectAutowires (byType) all properties and methods that are annotated with @AutowiredAlso supports some JSR-250 annotations@PostConstruct, @PreDestroy, @Resource, @Resources</p></li><li><p>Spring 2.5 annotation example@Component("knight")public class KnightOfTheRoundTable implements Knight { private String name; private Quest quest; private Horse horse;</p><p>... public KnightOfTheRoundTable(String name) { this.name = name; }</p><p> @Resource public void setQuest(Quest quest) { this.quest = quest; }</p><p> @Autowired private void myKingdomForAHorse(Horse horse) { this.horse = horse; }}</p></li><li><p>Spring 2.5 annotation example</p></li><li><p>Spring 2.5 annotation tradeoffsProsMoves configuration details closer to the beans being configured (DRY)Injection no longer limited to public setter methods and constructorsConsMoves configuration details closer to the beans being configured (invasive)Could be static identifiers</p></li><li><p>Scripting SpringCut XML and be buzzword compliant at the same time</p></li><li><p>Scripting Spring Configuration</p><p>Springy (JRuby)</p><p>Grails Spring Builder (Groovy)</p></li><li><p>Springy</p><p>Provides a Ruby DSL for configuring a Spring application contexthttp://code.trampolinesystems.com/springyCurrent version is 0.2Apache license</p></li><li><p>Loading a Springy contextProgramatically:</p><p>ApplicationContext ctx = new JRubyApplicationContext( new ClassPathResource("com/habuma/samples/ctx.rb"));</p><p>No obvious way to use with web applicationsbummer</p></li><li><p>Springy examplebean :knight, "com.springinaction.knight.KnightOfTheRoundTable" do |b| b.new "Bedivere b.quest = :quest...end</p><p>bean :quest, "com.springinaction.knight.HolyGrailQuest" do |b| b.newend</p></li><li><p>Springy example 2</p><p>Can you do this in Spring XML?</p><p>for num in (1..10) bean :"knight#{num}", "com.springinaction.knight.KnightOfTheRoundTable" do |b| b.new "Bedivere" b.quest = :quest endend</p></li><li><p>Springy and inline XMLIf you absolutely must use XML</p><p>inline_xml do </p></li><li><p>Springy: Serialize to XML</p><p>Get Spring XML from a JRuby-defined context:</p><p>((JRubyApplicationContext) ctx).getContextAsXml();</p></li><li><p>Springy tradeoffsProsCompletely XML freeUnless you want to inline some XMLAll of JRuby available for defining a Spring contextConsSerializes to XML then reloads itPerformance implicationsNo clear way to use in a web app</p></li><li><p>Grails Spring Bean Builder</p><p>Provides a Groovy DSL to configure a Spring contextPart of GrailsIn grails-core-0.5.6.jarhttp://www.grails.org/Spring+Bean+Builder</p></li><li><p>Bean Builder exampledef bb = new grails.spring.BeanBuilder()bb.beans { quest(HolyGrailQuest) {} horse(Horse) {} sword(Sword) {} shield(Shield) {} armor(Armor) {} knight(KnightOfTheRoundTable, "Bedivere") { delegate.quest = quest delegate.horse = horse delegate.sword = sword delegate.shield = shield delegate.armor = armor }}</p><p>ApplicationContext ctx = bb.createApplicationContext()def knight = ctx.getBean("knight")knight.embarkOnQuest()</p></li><li><p>Bean Builder tradeoffsProsCompletely XML freeCan use all of Groovys goodness to configure SpringConsNot clear how to use it outside of a Groovy scriptNot clear how to use it in a web app (aside from Grails)(just a nit) Not separate from GrailsMust include Grails in your application classpath</p></li><li><p>RecapHe made the XML shortertoo bad he couldnt have done the same thing with the presentation</p></li><li><p>What we have learnedSpring XML sucksIf you dont take advantage of the tricks to cut the clutterSpring and annotations : Not a zero sum gameSpring encourages proper use of annotations (and tolerates improper use)Spring != XMLSpring is more than just a configuration mechanismJRuby, Groovy, and annotation configuration alternatives</p></li><li><p>A few final Spring tipsYou dont have to wire everything!Use sensible defaultsCase in point: Spring MVC command controllers commandName and commandClass propertiesRemember that there are two types of configurationInternal: Use SpringExternal: Perhaps PropertyPlaceholderConfigurer or PropertyOverrideConfigurerDont put all of your beans in one XML fileBreak your Spring context downPerhaps by application layer or functional divisions</p></li><li><p>Q &amp; ADont forget to turn in evals!!!http://www.springinaction.comcraig@habuma.com</p></li></ul>