Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

modern enterprise app config

Slide 3

Slide 3 text

chris beams

Slide 4

Slide 4 text

you

Slide 5

Slide 5 text

github.com/cbeams/modern-config

Slide 6

Slide 6 text

modern enterprise app config

Slide 7

Slide 7 text

enterprise think big (big enough to hire own devs) typically not tech companies finance, media, insurance, gov't, ...

Slide 8

Slide 8 text

enterprise application typically long-lived teams change over time tech and requirements do too

Slide 9

Slide 9 text

enterprise application often large ... in size of codebase ... in no. of devs

Slide 10

Slide 10 text

enterprise application legacy and diversity are the rule

Slide 11

Slide 11 text

enterprise app configuration what components are involved? how are they parameterized? what dependencies exist? how are they satisfied?

Slide 12

Slide 12 text

modern enterprise app config concise comprehensive clear and communicative flexible and extensible code-based and typesafe

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

the Spring mission to provide comprehensive infrastructural support for building enterprise applications

Slide 15

Slide 15 text

ok... but what exactly is Spring?

Slide 16

Slide 16 text

Spring Framework 1.x

Slide 17

Slide 17 text

(2004)

Slide 18

Slide 18 text

2004 spring ~= spring-framework

Slide 19

Slide 19 text

Spring Framework 3.x

Slide 20

Slide 20 text

(2012)

Slide 21

Slide 21 text

2012 spring != spring-framework

Slide 22

Slide 22 text

2012 spring >> spring-framework

Slide 23

Slide 23 text

spring == spring-framework spring-security spring-integration spring-batch spring-data-* spring-social

Slide 24

Slide 24 text

spring == spring-roo spring-amqp spring-webflow spring-ws spring-net ...

Slide 25

Slide 25 text

spring == spring-*

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

spring == comprehensive infrastructural support ...and there's a lot of infrastructure out there! configuration is just one (important) concern

Slide 29

Slide 29 text

which brings us back to...

Slide 30

Slide 30 text

modern enterprise app config

Slide 31

Slide 31 text

the approach · ·

Slide 32

Slide 32 text

the approach POJOs + 3rd party components ·

Slide 33

Slide 33 text

the approach POJOs + 3rd party components configuration instructions ·

Slide 34

Slide 34 text

the approach POJOs + 3rd party components ↓ configuration ┌─────────────────────┐ instructions → │ the Spring container│ └─────────────────────┘ ·

Slide 35

Slide 35 text

the approach POJOs + 3rd party components ↓ configuration ┌─────────────────────┐ instructions → │ (ApplicationContext)│ └─────────────────────┘ ·

Slide 36

Slide 36 text

the approach POJOs + 3rd party components ↓ configuration ┌─────────────────────┐ instructions → │ the Spring container│ └─────────────────────┘ ·

Slide 37

Slide 37 text

the approach POJOs + 3rd party components ↓ configuration ┌─────────────────────┐ instructions → │ the Spring container│ └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 38

Slide 38 text

you get one consistent mechanism for config fail-fast behavior at startup dependency injection vs dependency lookup ... leading to simple, testable POJO components ability to enhance behavior through AOP

Slide 39

Slide 39 text

config style POJOs + 3rd party components ↓ configuration ┌─────────────────────┐ instructions → │ the Spring container│ └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 40

Slide 40 text

config style POJOs + 3rd party components ↓ ┌─────────────────────┐ XML → │ the Spring container│ └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 41

Slide 41 text

Slide 42

Slide 42 text

Slide 43

Slide 43 text

Slide 44

Slide 44 text

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

Slide 51

Slide 51 text

Slide 52

Slide 52 text

Slide 53

Slide 53 text

Slide 54

Slide 54 text

xml simple general purpose flexible

Slide 55

Slide 55 text

but...

Slide 56

Slide 56 text

xml verbose not typesafe wants special tooling

Slide 57

Slide 57 text

xml helps

Slide 58

Slide 58 text

e.g.

Slide 59

Slide 59 text

xml concise powerful easier to use

Slide 60

Slide 60 text

but...

Slide 61

Slide 61 text

xml opaque non-extensible difficult to write your own

Slide 62

Slide 62 text

config style POJOs + 3rd party components ↓ ┌─────────────────────┐ XML → │ the Spring container│ └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 63

Slide 63 text

config style POJOs + 3rd party components ↓ + ┌─────────────────────┐ → │ the Spring container│ XML └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 64

Slide 64 text

config style POJOs + 3rd party components ↓ @Component- ┌─────────────────────┐ scanning → │ the Spring container│ + @Autowired └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 65

Slide 65 text

@Component public class Foo { // ... } @Component public class Bar { private Foo foo;

Slide 66

Slide 66 text

@Autowired public void setFoo(Foo foo) { this.foo = foo; } }

Slide 67

Slide 67 text

@Component-scanning + @Autowired eliminates a lot of xml really concise, convenient now widely used especially for MVC @Controllers

Slide 68

Slide 68 text

but...

Slide 69

Slide 69 text

@Component-scanning + @Autowired can't wire up third-party code ambiguities can arise (enter @Qualifier) still requires xml to bootstrap

Slide 70

Slide 70 text

I mean, if you've got this package com.foo; @Component public class Bar { @Autowired public void setFoo(Foo foo) { ... } }

Slide 71

Slide 71 text

I mean, if you've got this package com.foo; @Component public class Bar { @Autowired public void setFoo(Foo foo) { ... } } ... then this is kind of ironic, right?

Slide 72

Slide 72 text

config style POJOs + 3rd party components ↓ @Component- ┌─────────────────────┐ scanning → │ the Spring container│ + @Autowired └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 73

Slide 73 text

config style POJOs + 3rd party components ↓ @Configuration ┌─────────────────────┐ + @Bean → │ the Spring container│ └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 74

Slide 74 text

bean definition @Configuration public class AppConfig { @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; return quoteService; } }

Slide 75

Slide 75 text

bean definition // @Configuration classes =~ documents @Configuration public class AppConfig { @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; return quoteService; } }

Slide 76

Slide 76 text

bean definition @Configuration public class AppConfig { // @Bean methods ~= elements @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; return quoteService; } }

Slide 77

Slide 77 text

bean definition @Configuration public class AppConfig { @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = // instantiate return quoteService; } }

Slide 78

Slide 78 text

bean definition @Configuration public class AppConfig { @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; // configure return quoteService; } }

Slide 79

Slide 79 text

bean definition @Configuration public class AppConfig { @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; return quoteService; // object managed by Spring } }

Slide 80

Slide 80 text

bean definition @Import(OtherConfig.class) // =~ @Configuration public class AppConfig { @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; return quoteService; } }

Slide 81

Slide 81 text

bean definition @Import(OtherConfig.class) @Configuration public class AppConfig { @Autowired QuoteSource quoteSource; // from OtherConfig @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; return quoteService; } }

Slide 82

Slide 82 text

bean definition @Import(OtherConfig.class) @Configuration public class AppConfig { @Autowired QuoteSource quoteSource; @Bean public QuoteService quoteService() { RealTimeQuoteService quoteService = ...; quoteService.setQuoteSource(quoteSource); // inject return quoteService; } }

Slide 83

Slide 83 text

bootstrap and use public class Main { public static void main(String... args) { } }

Slide 84

Slide 84 text

bootstrap and use public class Main { public static void main(String... args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); QuoteService quoteService = ctx.getBean(QuoteService.class); System.out.println(quoteService.currentValue("AAPL")); } }

Slide 85

Slide 85 text

bootstrap and use public class Main { public static void main(String... args) { // bootstrap the Spring container ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); QuoteService quoteService = ctx.getBean(QuoteService.class); System.out.println(quoteService.currentValue("AAPL")); } }

Slide 86

Slide 86 text

bootstrap and use public class Main { public static void main(String... args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); // retrieve the bean we want to use in typesafe fashion QuoteService quoteService = ctx.getBean(QuoteService.class); System.out.println(quoteService.currentValue("AAPL")); } }

Slide 87

Slide 87 text

bootstrap and use public class Main { public static void main(String... args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); QuoteService quoteService = ctx.getBean(QuoteService.class); // use the bean however desired System.out.println(quoteService.currentValue("AAPL")); } }

Slide 88

Slide 88 text

@Configuration typesafe, object-oriented can configure any component complete programmatic control no special tooling required centralized, blueprint-style

Slide 89

Slide 89 text

but...

Slide 90

Slide 90 text

@Configuration no equivalent to xml still required for tx mgmt, aop, etc

Slide 91

Slide 91 text

@Enable*

Slide 92

Slide 92 text

@Enable* (and friends)

Slide 93

Slide 93 text

e.g. @EnableTransactionManagement @EnableAspectJAutoProxy @EnableLoadTimeWeaving @EnableScheduling @EnableAsync @EnableWebMvc @ComponentScan

Slide 94

Slide 94 text

simple.

Slide 95

Slide 95 text

if you've got this package com.foo; @Component public class Bar { @Autowired public void setFoo(Foo foo) { ... } }

Slide 96

Slide 96 text

if you've got this package com.foo; @Component public class Bar { @Autowired public void setFoo(Foo foo) { ... } } ... then this is kind of ironic ...

Slide 97

Slide 97 text

I mean, if you've got this package com.foo; @Component public class Bar { @Autowired public void setFoo(Foo foo) { ... } } ... but this makes a lot more sense. @ComponentScan("com.foo")

Slide 98

Slide 98 text

and if you've got this package com.foo; @Repository public class WidgetRepo { @Transactional public void add(Widget widget) { ... } }

Slide 99

Slide 99 text

and if you've got this package com.foo; @Repository public class WidgetRepo { @Transactional public void add(Widget widget) { ... } } ... then why do this ...

Slide 100

Slide 100 text

and if you've got this package com.foo; @Repository public class WidgetRepo { @Transactional public void add(Widget widget) { ... } } ... when you could do this? @EnableTransactionManagement

Slide 101

Slide 101 text

example

Slide 102

Slide 102 text

example @EnableScheduling

Slide 103

Slide 103 text

some component package com.foo; public class ChatterBox { public void saySomething() { System.out.println(randomWord()); } }

Slide 104

Slide 104 text

some component package com.foo; public class ChatterBox { @Scheduled(fixedRate=1000) public void saySomething() { System.out.println(randomWord()); } }

Slide 105

Slide 105 text

some component package com.foo; public class ChatterBox { // (@Scheduled has been @Scheduled(fixedRate=1000) // around since Spring 3.0) public void saySomething() { System.out.println(randomWord()); } }

Slide 106

Slide 106 text

some component package com.foo; public class ChatterBox { // "hey Spring, call this @Scheduled(fixedRate=1000) // method every second" public void saySomething() { System.out.println(randomWord()); } }

Slide 107

Slide 107 text

configuration package com.foo.config; @Configuration public class Config { @Bean public ChatterBox chatterBox() { return new ChatterBox(); } }

Slide 108

Slide 108 text

configuration package com.foo.config; @Configuration @EnableScheduling public class Config { @Bean public ChatterBox chatterBox() { return new ChatterBox(); } }

Slide 109

Slide 109 text

configuration package com.foo.config; @Configuration @EnableScheduling // look for and process @Scheduled public class Config { @Bean public ChatterBox chatterBox() { return new ChatterBox(); } }

Slide 110

Slide 110 text

configuration package com.foo.config; @Configuration @EnableScheduling public class Config { @Bean public ChatterBox chatterBox() { // Spring ensures return new ChatterBox(); // saySomething() method is } // called once per second }

Slide 111

Slide 111 text

@Enable* benefits easy to see what's going on easy to write your own adapts smoothly from simple to sophisticated supported beyond core spring-framework e.g. spring-data's @EnableMongoRepositories

Slide 112

Slide 112 text

code-based configuration is complete as of Spring Framework 3.1 can configure all major container features mix and match styles as desired

Slide 113

Slide 113 text

but...

Slide 114

Slide 114 text

but... ?

Slide 115

Slide 115 text

no buts.

Slide 116

Slide 116 text

no buts. code-based configuration: can be adopted incrementally but can go all the way which means...

Slide 117

Slide 117 text

No content

Slide 118

Slide 118 text

No content

Slide 119

Slide 119 text

XML IS OVER!

Slide 120

Slide 120 text

XML IS OVER! for dependency injection

Slide 121

Slide 121 text

XML IS OVER! for enabling features of the Spring container

Slide 122

Slide 122 text

XML IS OVER! for Hibernate integration, too

Slide 123

Slide 123 text

Hibernate 4 support Spring 3.1 builds against Hibernate 4 new orm.hibernate4 packaging

Slide 124

Slide 124 text

familiar? com.foo.Person com.foo.Account hibernate.dialect=org.hibernate.dialect.HSQLDialect

Slide 125

Slide 125 text

we can do better than that.

Slide 126

Slide 126 text

@Bean public SessionFactory sessionFactory() { return new LocalSessionFactoryBuilder(dataSource()) .addAnnotatedClasses(Person.class, Account.class) .buildSessionFactory(); }

Slide 127

Slide 127 text

XML IS OVER!

Slide 128

Slide 128 text

XML IS OVER! and not just Spring XML

Slide 129

Slide 129 text

JPA

Slide 130

Slide 130 text

persistence.xml java:/DefaultDS

Slide 131

Slide 131 text

say goodbye.

Slide 132

Slide 132 text

@Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource()); emf.setPersistenceXmlLocation( "classpath:META-INF/persistence.xml"); return emf; }

Slide 133

Slide 133 text

@Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource()); emf.setPersistenceXmlLocation( "classpath:META-INF/persistence.xml"); // no more! return emf; }

Slide 134

Slide 134 text

@Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource()); emf.setPackagesToScan("com.foo.domain"); return emf; }

Slide 135

Slide 135 text

@Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource()); // scan classpath for JPA @Entity types emf.setPackagesToScan("com.foo.domain"); return emf; }

Slide 136

Slide 136 text

XML IS OVER! and not just Spring XML

Slide 137

Slide 137 text

web.xml

Slide 138

Slide 138 text

dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/spring/dispatcher-config.xml 1 dispatcher /

Slide 139

Slide 139 text

gone. (if you've got Servlet 3)

Slide 140

Slide 140 text

public class WebInit implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext() ctx.register(DispatcherConfig.class); ServletRegistration.Dynamic dispatcher = container.addServlet( "dispatcher", new DispatcherServlet(ctx)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }

Slide 141

Slide 141 text

No content

Slide 142

Slide 142 text

WebApplicationInitializer allows code-based config of servlet container builds on Servlet 3's ServletContainerInitializer auto-detected on Servlet container startup

Slide 143

Slide 143 text

application-context.xml persistence.xml web.xml

Slide 144

Slide 144 text

XML IS OVER.

Slide 145

Slide 145 text

No content

Slide 146

Slide 146 text

No content

Slide 147

Slide 147 text

No content

Slide 148

Slide 148 text

XML IS OVER, if you want it*

Slide 149

Slide 149 text

*which means that you really shouldn't worry, because XML support is definitely not going anywhere. This is a concern that commonly comes up when we talk about annotations and such, but we've said it before and we'll say it again: XML was, is, and ever will be a first class citizen in Spring. These new features just mean that if you don't want XML, you don't have to use it. That's all. kthx, bye.

Slide 150

Slide 150 text

config style POJOs + 3rd party components ↓ @Configuration ┌─────────────────────┐ + @Bean → │ the Spring container│ └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 151

Slide 151 text

config style POJOs + 3rd party components ↓ @Configuration ┌─────────────────────┐ + @Bean → │ the Spring container│ + @Enable* └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 152

Slide 152 text

config style POJOs + 3rd party components (hybrid) ↓ + ┌─────────────────────┐ @Component + → │ the Spring container│ @Configuration └─────────────────────┘ ┌─────────────────────────┐ │ fully configured system │ │ ready for use │ └─────────────────────────┘

Slide 153

Slide 153 text

recommendations

Slide 154

Slide 154 text

recommendations go for 100% code-based config @Component + @Autowired for "your" components @Bean for third-party components @Enable to control framework features

Slide 155

Slide 155 text

modern enterprise app config concise comprehensive clear and communicative flexible and extensible code-based and typesafe

Slide 156

Slide 156 text

much more Environment and PropertySource APIs bean definition profiles testing support for @Configuration classes brand-new spring-scala project spring-integration Scala & Groovy DSLs

Slide 157

Slide 157 text

check it out everything in this talk available in 3.1 spring-framework 3.2 RC1 is now out a great time for feedback RC2 in a few weeks GA by year end

Slide 158

Slide 158 text

get involved everything's on GitHub see CONTRIBUTING.md new Gradle build in 3.2 makes it easy

Slide 159

Slide 159 text

questions?

Slide 160

Slide 160 text

thanks! @cbeams | cbeams.github.com/modern-config @springframework | github.com/springsource example code: github.com/cbeams/distyles