Spring Java Configuration (i.e. JavaConfig) provides a pure-Java means of configuring the Spring IoC container. This is gaining popularity as it
- gives complete control over instantiation and dependency injection.
- gives type safety & compile-time check
- supports refactorable configuration & supported by IDEs
Here are some industrial strength wiring examples.
#1, #2, #3. Wiring datasource, entity manager, and transactionManager
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
package com.jpa.tutorial.config; import static org.hibernate.cfg.Environment.DIALECT; import static org.hibernate.cfg.Environment.SHOW_SQL; import java.util.Properties; import javax.inject.Inject; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; @Configuration @EnableAspectJAutoProxy @ComponentScan(basePackages = "com.jpa.tutorial.domain") @PropertySource("classpath:my-orm.properties") public class MyDomainConfiguration { @Inject private Environment environment; @Bean public DataSource dataSource() { final JndiDataSourceLookup jndiLookup = new JndiDataSourceLookup(); final String dataSourceJndi = environment.getRequiredProperty("myapp.domain.datasource.jndi"); return jndiLookup.getDataSource(dataSourceJndi); } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); entityManager.setPersistenceUnitName("myapp-persistence-unit"); entityManager.setDataSource(dataSource()); entityManager.setPersistenceXmlLocation("classpath:META-INF/persistence-jpa.xml"); entityManager.setPackagesToScan("com.jpa.tutorial.**.entity"); final HibernateJpaVendorAdapter hibernateAdapter = new HibernateJpaVendorAdapter(); entityManager.setJpaVendorAdapter(hibernateAdapter); final Properties properties = myappCommonsDomainProperties(); entityManager.setJpaProperties(properties); entityManager.afterPropertiesSet(); return entityManager; } @Bean public Properties myappCommonsDomainProperties() { final Properties properties = new Properties(); properties.put(DIALECT, environment.getRequiredProperty(DIALECT)); // debugging properties properties.put(SHOW_SQL, environment.getRequiredProperty(SHOW_SQL)); return properties; } @Bean public PlatformTransactionManager transactionManager() { final PlatformTransactionManager transactionManager; final JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(); jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); jpaTransactionManager.setDataSource(dataSource()); transactionManager = jpaTransactionManager; return transactionManager; } } |
#4. Unit tests require wiring up actual datasource with mock in memory datasource
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.jpa.tutorial.config; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; @Configuration @Import(MyDomainConfiguration.class) public class MyAppCommonsDomainTestConfiguration { @Bean public DataSource dataSource() { final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); builder.setType(EmbeddedDatabaseType.HSQL); builder.addScript("classpath:hsqldb-oracle.sql"); builder.addDefaultScripts();//adds schema.sql return builder.build(); } } |
#5, #6. Wiring RESTful templates and JAXB marshaller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package com.mytutorial.configuration; import static javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestTemplate; import com.google.common.collect.ImmutableMap; import com.mytutorial.RestTemplateExceptionTranslator; @Configuration @EnableTransactionManagement @ComponentScan("com.mytutorial") public class MyAppEnablerServiceConfiguration { @Bean public Jaxb2Marshaller jaxb2Marshaller() { final Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setPackagesToScan( "com.mytutorial.schema.v1.dto", "com.mytutorial.v1" ); marshaller.setMarshallerProperties( ImmutableMap.<String, Object>of(JAXB_FORMATTED_OUTPUT, Boolean.TRUE)); return marshaller; } @Bean public RestTemplate restTemplate() { final RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(restTemplateExceptionTranslator()); return restTemplate; } @Bean public ResponseErrorHandler restTemplateExceptionTranslator() { return new RestTemplateExceptionTranslator(); // custom handler } } |
#7 wiring properties
1 2 3 4 |
@Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } |
1 2 3 |
@PropertySource({ "classpath:myapp-${envTarget:dev}.properties" }) ... |
or
Alternatively,
1 2 3 4 5 6 7 8 9 |
@Bean public static PropertyPlaceholderConfigurer properties(){ PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); Resource[] resources = new ClassPathResource[ ] { new ClassPathResource( "myapp-dev}.properties" ) }; ppc.setLocations( resources ); ppc.setIgnoreUnresolvablePlaceholders( true ); return ppc; } |
and then,
1 2 3 |
@Value( "${ws.url:aDefaultUrl}" ) private String restWsUrl; |
1 2 3 4 |
@Autowired private Environment env; ...env.getProperty("ws.url")); |