Download - Testing with Spring Framework 4.x
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense Unless otherwise indicated, these slides are © 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense: http://creativecommons.org/licenses/by-nc/3.0/
Testing with Spring 4.x Sam Brannen @sam_brannen
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Sam Brannen
• Spring and Java Consultant @ Swiftmind • Java Developer for over 15 years
• Spring Framework Core Committer since 2007 • Component lead for spring-test
• Spring Trainer • Speaker on Spring, Java, and testing
• Swiss Spring User Group Lead
2
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Areas of expertise – Spring * – Java EE – Software Architecture – Software Engineering Best
Practices
Where you find us • Zurich, Switzerland • @swiftmind • http://www.swiftmind.com
3
Your experts for Spring and Enterprise Java
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
A show of hands…
4
?
? ?
?
?
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Agenda
• Deprecations, Pruning, & Dependencies
• Recap of Testing with Spring 3.x
• Testing Themes in 4.x
• Details, Tips, & Examples
• Q&A
5
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Deprecations, Pruning, & Dependencies
6
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Spring Cleaning in 4.x
• All deprecated packages removed
• Many deprecated methods and fields removed as well
• Mind the deprecation warnings… before upgrading from 3.x
7
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Pruning in 4.0
• JUnit 3.8 support • Use JUnit 4 or TestNG
• @ExpectedException • Use @Test(expected) or @Rule ExpectedException in JUnit • Use @Test(expectedExceptions) in TestNG
• @NotTransactional • Use @Transactional(propagation=NOT_SUPPORTED)
• SimpleJdbcTestUtils • Use JdbcTestUtils, ScriptUtils, or @Sql
8
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Dependency Upgrades in 4.0
• Servlet API mocks • Now based on Servlet 3.0 • Servlet 2.5 still supported in production
• JUnit • Tested against à 4.11
• TestNG • Tested against à 6.8.5
9
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Dependency Upgrades in 4.1
• JUnit • Minimum version à 4.9 • Recommended à 4.11
• TestNG • Tested against à 6.8.8
10
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing with Spring 3.x
11
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing Themes from Spring 3.x (1/2)
• Embedded databases • <jdbc:embedded-database /> & <jdbc:initialize-database /> • EmbeddedDatabaseBuilder & EmbeddedDatabaseFactoryBean
• @Configuration classes
• @ActiveProfiles
• ApplicationContextInitializers
12
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing Themes from Spring 3.x (2/2)
• @WebAppConfiguration • Loading WebApplicationContexts • Testing request- and session-scoped beans
• @ContextHierarchy • Web, Batch, etc.
• Spring MVC Test framework • Server-side MVC and REST tests • Client-side REST tests
13
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Web Integration Test (1/2)
14
@RunWith(SpringJUnit4ClassRunner.class)@WebAppConfiguration@ContextHierarchy({
@ContextConfiguration(classes = RootConfig.class),@ContextConfiguration(classes = WebConfig.class)
})@ActiveProfiles("dev")public class ControllerIntegrationTests { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; // ...
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Web Integration Test (2/2)
15
@Before public void setup() { this.mockMvc = MockMvcBuilders .webAppContextSetup(this.wac).build(); } @Test public void person() throws Exception { this.mockMvc.perform(get("/person/42") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().string("{\"name\":\"Sam\"}")); }
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing Themes in Spring 4.0
16
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.0 (1/3)
• SocketUtils • Scan for available UDP & TCP ports
• ActiveProfilesResolver API • Programmatic alternative to static profile strings • Set via new resolver attribute in @ActiveProfiles
• Meta-annotation support for tests • Attribute overrides (optional and required)
17
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.0 (2/3)
• New deleteFromTableWhere() method in AbstractTransactional*SpringContextTests
• * à JUnit4 or TestNG
• New verify() and reset() methods in AnnotationDrivenStaticEntityMockingControl
• Multi-line SQL comments: • ResourceDatabasePopulator, JdbcTestUtils, ScriptUtils
18
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.0 (3/3)
• TestContext converted to an interface • Allows TestContext to be mocked in unit tests
• Simultaneous use of classes and locations in @ContextConfiguration for hybrid loaders
• See Spring Boot
• Servlet API mock improvements
19
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing Themes in Spring 4.1
20
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.1 – Context Config
• Context config with Groovy scripts
• Declarative configuration for test property sources
• @TestPropertySource
21
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.1 – Transactions and SQL
• Programmatic test transaction management • TestTransaction API
• Declarative SQL script execution • @Sql, @SqlConfig, @SqlGroup
• Improved docs for transactional tests
22
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.1 – Bootstrap & TestExecutionListeners
• TestContext bootstrap strategy • TestContextBootstrapper & @BootstrapWith
• Automatic discovery of default TestExecutionListeners • Uses SpringFactoriesLoader • Already used by Spring Security
• Merging custom TestExecutionListeners with defaults • @TestExecutionListeners(mergeMode=MERGE_WITH_DEFAULTS) • Defaults to REPLACE_DEFAULTS
23
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.1 – Spring MVC Test
• Assert JSON responses with JSON Assert • Complements JSONPath support
• Create MockMvcBuilder recipes with MockMvcConfigurer • Developed to apply Spring Security setup but can be used by anyone
• AsyncRestTemplate support in MockRestServiceServer • For asynchronous client-side testing
24
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.1 – Odds & Ends
• AssertThrows: refactored to support Throwable
• Various improvements to Servlet API mocks
25
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Details, Tips, & Examples
26
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
SocketUtils
• Utility class introduced in Spring Framework 4.0 • Located in spring-core • Can be used in production code • But ideal for embedded testing scenarios (SMTP, FTP, etc.)
• Finds available TCP and UDP ports on localhost • Default port range: 1024 à 65535 • See Javadoc for all options
• Straightforward usage in Java and @Configuration classes
27
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Using SocketUtils in XML Config
• Via fully qualified class name and SpEL <bean id="bean1" ... p:port="#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" /> • Via socketUtils bean and SpEL (as of Spring 4.0.8 & 4.1.1) <bean id="socketUtils" class="org.springframework.util.SocketUtils" /><bean id="bean1" ... p:port="#{socketUtils.findAvailableTcpPort(12000)}" /><bean id="bean2" ... p:port="#{socketUtils.findAvailableTcpPort(30000)}" />
28
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Tip: Define Free Port as Bean
• Define the free port as a Spring Bean… <bean id="serverPort" class="java.lang.Integer" c:_="#{T(socketUtils.findAvailableTcpPort()}" />• Then reference the serverPort from other beans
• Or inject it into components, @Configuration classes, and tests
29
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @ActiveProfiles – Declarative
30
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration@ActiveProfiles("dev")public class IntegrationTests { // ...}
But what if static isn’t good enough?
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @ActiveProfiles – Programmatic
31
public class MyResolver implements ActiveProfilesResolver { public String[] resolve(Class<?> testClass) { // resolve bean definition profiles for test class }}@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration@ActiveProfiles(resolver = MyProfileResolver.class)public class IntegrationTests { // ...}
Implement custom resolver
And declare it
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Composable Stereotypes – Quick Review
• Combining meta-annotations on a custom stereotype • Automatically detected: no configuration necessary!
32
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Duplicate Test Configuration == Bad
@ContextConfiguration("/test-config.xml")@ActiveProfiles("dev")@Transactionalpublic class OrderRepositoryTests {}@ContextConfiguration("/test-config.xml")@ActiveProfiles("dev")@Transactionalpublic class UserRepositoryTests {}
33
duplication
duplication
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Custom Test Annotation == Good
@Target(TYPE)@Retention(RUNTIME)@ContextConfiguration("/test-config.xml")@ActiveProfiles("dev")@Transactionalpublic @interface TransactionalDevTest { }@TransactionalDevTestpublic class OrderRepositoryTests { }@TransactionalDevTestpublic class UserRepositoryTests { }
34
common config
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Composable Annotations with Overrides
• Composable annotations may override attributes of meta-annotations
• Purely convention-based • Matched by attribute name and type • Can lead to potential naming conflicts
• Cannot override the value attribute
35
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Optional Annotation Attribute Override
@Target(TYPE)@Retention(RUNTIME)@ContextConfiguration@Transactionalpublic @interface TransactionalTest {
String[] locations() default "/test-config.xml";}@TransactionalTest(locations = "/order-test-config.xml")public class OrderRepositoryTests { }
36
optional: overrides default
default
locations declared here will be ignored
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Required Annotation Attribute Override
@Target(TYPE)@Retention(RUNTIME)@ContextConfiguration@Transactionalpublic @interface TransactionalTest {
String[] locations();}@TransactionalTest(locations = "/order-test-config.xml")public class OrderRepositoryTests { }
37
required
no default
locations declared here will be ignored
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Groovy Beans in Spring
• Spring Framework 4.0 introduced support for the Groovy Bean Definition DSL via the GroovyBeanDefinitionReader and GenericGroovyApplicationContext
• Spring Framework 4.1 introduces support for Groovy scripts in web applications via the GroovyWebApplicationContext
• Testing support added in 4.1…
38
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Spring Bean Definitions with Groovy DSL
import org.mypackage.domain.Person;
beans { xmlns util: 'http://www.springframework.org/schema/util'
person1(Person) { name = "homer" age = 45 props = [overweight: true, height: "1.8m"] children = ["bart", "lisa"] } util.list(id: 'foo') { value 'one' value 'two' }}
39
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Groovy Scripts for Context Config in Tests
• Spring Framework 4.1 introduces support for Groovy scripts in integration tests via @ContextConfiguration
• Scripts are configured via the locations or value attribute o Resource semantics identical to XML o Default detected with “Context.groovy” suffix in same package
• The inheritLocations flag is fully supported
• Groovy and XML configuration can be declared together
• Groovy WebApplicationContexts supported via @WebAppConfiguration
40
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Groovy Script Config
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/context.groovy")public class GroovyPersonTests { @Autowired private Person person; /* test methods using person bean */}
41
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Default Groovy Script Detection
public com.example;@RunWith(SpringJUnit4ClassRunner.class)// ApplicationContext will be loaded from// “classpath:com/example/MyTestContext.groovy”@ContextConfigurationpublic class MyTest { /* ... */}
42
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Groovy & XML Config Together
@RunWith(SpringJUnit4ClassRunner.class)// ApplicationContext will be loaded from// “/context.groovy” and “/context.xml”@ContextConfiguration({ "/context.groovy", "/context.xml" })public class MyTest { /* ... */}
43
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Test Property Sources
• Spring 3.1 introduced PropertySources abstraction • Configured via Environment or via @PropertySource
• Spring 4.1 supports declarative test property sources • Configured via @TestPropertySource
• Test property sources are declared via annotation attributes • locations or value: resource locations • properties: inlined properties • both are inherited by default
44
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@TestPropertySource – locations
• String array of resource locations for Java Properties files
• Both traditional *.properties and XML formats are supported
• Resource semantics are identical to those for locations in @ContextConfiguration
45
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @TestPropertySource – locations
@ContextConfiguration@TestPropertySource("/test.properties")public class MyIntegrationTests {
// class body...}
46
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@TestPropertySource – properties
• Inlined properties can be declared as key/value pairs
• Uses syntax for entries in Java properties files: • "key=value" • "key:value" • "key value"
47
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @TestPropertySource – properties
@ContextConfiguration@TestPropertySource( properties = {"foo=bar", "port: 4242"})public class MyIntegrationTests {
// class body...}
48
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Default Properties File Detection
• If neither locations nor properties are defined, a default properties file will be detected
• Default is detected with “.properties” suffix in same package
• If the class is com.example.MyTest, the default properties file is “classpath:com/example/MyTest.properties”
• Exception is thrown if default is not present
49
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@TestPropertySource – Precedence
50
Inlined
Files
Application & System
test
prec
eden
ce
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @TestPropertySource – locations & properties
@ContextConfiguration@TestPropertySource( locations = "/test.properties", properties = "port: 4242")public class MyIntegrationTests {
// class body...}
51
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Programmatic Transaction Management in Tests
• History Lesson: Spring’s JUnit 3.8 testing framework supported endTransaction() and startNewTransaction() methods in AbstractTransactionalSpringContextTests
• But… the Spring TestContext Framework, introduced in Spring 2.5, did not… until now
• Due to popular demand, Spring 4.1 introduces a new TestTransaction API
52
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Transactions in Spring
• Spring-managed transactions: managed by Spring in the ApplicationContext
• @Transactional and AOP
• Application-managed transactions: managed programmatically within application code
• TransactionTemplate and TransactionSynchronizationManager
• Test-managed transactions: managed by the Spring TestContext Framework
• @Transactional on test classes and test methods • Transaction is rolled back by default!
53
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Declarative Transaction Management in Tests
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration@Transactionalpublic class TransactionalTests { @Test public void withinTransaction() { /* ... */ }
54
What if we want to stop & start the
transaction within the test method?
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
TestTransaction API
• Static methods for interacting with test-managed transactions
• isActive() • isFlaggedForRollback()
• flagForCommit() • flagForRollback()
• end() • start()
55
query status
change default rollback setting
end: roll back or commit based on flag start: new tx with default rollback setting
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Programmatic Transaction Management in Tests
@Testpublic void withinTransaction() { // assert initial state in test database: assertNumUsers(2); deleteFromTables("user"); // changes to the database will be committed TestTransaction.flagForCommit(); TestTransaction.end(); assertFalse(TestTransaction.isActive()); assertNumUsers(0); TestTransaction.start(); // perform other actions against the database that will // be automatically rolled back after the test completes...}
56
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Executing SQL Scripts
57
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Embedded Database in Java Config
58
@Beanpublic DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("schema.sql") .addScripts("user_data.sql", "country_data.sql") .build();}
API greatly improved in Spring 4.0.3
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Embedded Database in XML Config
<jdbc:embedded-database id="dataSource" type="H2"> <jdbc:script location="classpath:/schema.sql" /> <jdbc:script location="classpath:/user_data.sql" /></jdbc:embedded-database>
59
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Populate Database in XML Config
<jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:/schema_01.sql" /> <jdbc:script location="classpath:/schema_02.sql" /> <jdbc:script location="classpath:/data_01.sql" /> <jdbc:script location="classpath:/data_02.sql" /></jdbc:initialize-database>
60
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Executing SQL per Test Method
• The previous techniques are very useful for setting up the initial database state
• Q: But how can we execute SQL scripts per test method? • A: Programmatically via ScriptUtils,
ResourceDatabasePopulator, or abstract transactional base test classes for JUnit and TestNG.
• Q: OK, but how can we do that declaratively? • A: Via @Sql in Spring Framework 4.1!
61
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Executing SQL Scripts Declaratively with @Sql
• @Sql: declared on a test class or test method • method-level overrides class-level
• The scripts attribute is used to declare resource locations for SQL scripts
• semantics analogous to locations in @ContextConfiguration
• Scripts can be executed before or after a test method • configured via the executionPhase attribute of @Sql
62
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @Sql in Action
@ContextConfiguration@Sql({ "schema1.sql", "data1.sql" })public class SqlScriptsTests { @Test public void classLevelScripts() { /* ... */ } @Test @Sql({ "schema2.sql", "data2.sql" }) public void methodLevelScripts() { /* ... */ }
63
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Default SQL Script Detection
• If no scripts are declared, a default script will be detected • Depending on where @Sql is declared
• Class-level: for com.example.DbTest, the default is “classpath:com/example/DbTest.sql”
• Method-level: for com.example.DbTest.test(), the default is “classpath:com/example/DbTest.test.sql”
• If the default is not present, an exception is thrown
64
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Declaring Multiple @Sql Sets
• Declare multiple sets of @Sql scripts for varying configuration
• Java 8: use @Sql as a repeatable annotation
• Java 6 & 7: wrap @Sql sets in @SqlGroup
65
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@Sql as a Repeatable Annotation (Java 8)
66
@Test@Sql( scripts="/test-schema.sql", config = @SqlConfig(commentPrefix = "`")@Sql("/user-data.sql")public void userTest() { // code that uses the test schema and test data}
Schema uses custom syntax
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@Sql wrapped in @SqlGroup (Java 6 & 7)
67
@Test@SqlGroup({ @Sql( scripts="/test-schema.sql", config = @SqlConfig(commentPrefix = "`"), @Sql("/user-data.sql")})public void userTest() { // code that uses the test schema and test data}
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Configuring SQL Scripts with @SqlConfig
• @SqlConfig: configures script parsing and error handling • Class-level: serves as global configuration for the test class • @Sql(config): serves as local configuration for the enclosing @Sql
• Local configuration inherits global configuration and can selectively override global configuration
• Transaction management for script execution is configured via the dataSource, transactionManager, and transactionMode attributes
• See Javadoc and reference manual for details
68
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
In closing…
69
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Related Sessions @ SpringOne 2GX 2014
70
• The Quest for the Holy Integration Test • Ken Krueger and Rob Winch • September 10, 2014 • 4:30 PM - 6:00 PM
• Building highly modular and testable business systems with Spring Integration
• Marius Bogoevici • September 11, 2014 • 10:30 AM - 12:00 PM
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Spring Resources
Spring Framework: http://projects.spring.io/spring-framework Spring Guides: http://spring.io/guides Spring JIRA: https://jira.spring.io
Spring on GitHub: https://github.com/spring-projects/spring-framework Stack Overflow: spring, spring-test, spring-mvc, …
71
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Blogs
Spring Blog: http://spring.io/blog Swiftmind Blog: http://www.swiftmind.com/blog
72
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Q & A Sam Brannen
@sam_brannen
www.slideshare.net/sbrannen
www.swiftmind.com
73
@springcentral | spring.io/video