I am trying to understand a spring project which uses MongoDB drivers to connect to a db.
The application.properties file has the following properties defined:
spring.data.mongodb.database=${db.name:demo}
spring.data.mongodb.auto-index-creation=false
spring.data.mongodb.uri=mongodb://some-connection-string
And I see two relevant pieces of code in the project:
Application.java
#SpringBootApplication
#EnableCaching
#EnableScheduling
#ComponentScan({ "com.paans.*" })
#PropertySource("classpath:routes.properties")
public class Application extends SpringBootServletInitializer {
public static MongoTemplate _mongoTemplate;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoMappingContext context) {
MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), context);
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
mongoTemplate.setReadPreference(ReadPreference.nearest());
_mongoTemplate = mongoTemplate;
return mongoTemplate;
}
}
MongoConfiguration.java
#Configuration
public class MongoConfiguration {
#Autowired
MongoTemplate mongoTemplate;
#Autowired
MongoConverter mongoConverter;
#EventListener(ApplicationReadyEvent.class)
public void initIndicesAfterStartup() {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = this.mongoConverter.getMappingContext();
if (mappingContext instanceof MongoMappingContext) {
MongoMappingContext mongoMappingContext = (MongoMappingContext) mappingContext;
for (BasicMongoPersistentEntity<?> persistentEntity : mongoMappingContext.getPersistentEntities()) {
Class<?> clazz = persistentEntity.getType();
if (clazz.isAnnotationPresent(Document.class)) {
IndexResolver resolver = new MongoPersistentEntityIndexResolver(mongoMappingContext);
IndexOperations indexOps = mongoTemplate.indexOps(clazz);
resolver.resolveIndexFor(clazz).forEach(indexOps::ensureIndex);
}
}}}}
Now, I am trying to understand the execution sequence of this code and which piece of code is actually picking up the properties set up in application.properties. Any help ?
Related
i would like to load #Configuration classes in an order. i have two configuration classes. i am having a requirement of loading my SampleProperties class before sampleconfiguration class.
I have tried the following annotations but it is not working as expected.
#AutoConfigureAfter(SampleProperties.class )
#AutoConfigureBefore(SampleConfiguration.class)
I have put my congiurations class in diff package in order to read configurations classes in an order.using #Import function, i am including my configuration classes into my application
My Main Class:
#Import({SampleProperties.class,SampleConfiguration.class,})
public class SampleApplication{
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
My SampleProperties Class
#Configuration
#AutoConfigureBefore(SampleConfiguration.class)
#ConfigurationProperties("demo")
#Data
public class SampleProperties {
private String team;
private int teamSize;
private String teamLeader;
}
My sampleconfiguration Class:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef="sampleEntityManager",
transactionManagerRef="sampleTransactionManager",
basePackages= {"com.example.demo.repo"})
#AutoConfigureAfter(SampleProperties.class)
public class SampleConfiguration {
#Autowired
Environment env;
#Bean(name="sampleDataSource")
#Primary
public DataSource dmsDataSource() {
// functions
return null;
}
#Primary
#Bean(name = "sampleEntityManager")
public LocalContainerEntityManagerFactoryBean dmsEntityManagerFactory(EntityManagerFactoryBuilder builder) {
// functions
return null;
}
#Primary
#Bean(name = "sampleTransactionManager")
public PlatformTransactionManager dmsTransactionManager(#Qualifier("sampleEntityManager") EntityManagerFactory entityManagerFactory) {
// functions
return null;
}
}
can anyone tell me what missing and where am making mistakes?
I think you have to use #Order annotation.
#Component
#Order(1)
public class SampleProperties {
// code
}
#Component
#Order(2)
public class SampleConfiguration {
// code
}
I would like to read some properties, like DB access configs, when initializing bean or service in spring boot.
Anyone knows good ways ?
This is my current code snippet.
public class SampleApplication implements ApplicationRunner
{
#Autowired
private YAMLConfig myConfig;
#Override
public void run(ApplicationArguments args) throws Exception
{
System.out.println(myConfig != null); //YAMLConfig has been intialized here
}
public SampleApplication()
{
System.out.println(myConfig == null); //myConfig is null
}
#Configuration
public static class Config
{
#Bean
#ConditionalOnProperty(value = {"batch.execute"}, havingValue = "SampleApplication")
public SampleApplication sampleApplication()
{
return new SampleApplication();
}
}
}
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties
public class YAMLConfig
{
private String environment;
public String getEnvironment()
{
return environment;
}
public void setEnvironment(String environment)
{
this.environment = environment;
}
}
Thanks for taking a look at this!
create this method inside your SampleApplication class
#PostConstruct
public void init() {
// at this point, all the dependency injection has happened already
myConfig.doStuff()
}
it will be called by spring automatically after all bean initialization has been done.
springboot auto config TransactionManager and SqlFactory, it works well ,but when i use #Transactional the program wait in a daze, i flow the code and find
beanFactory.getBean(PlatformTransactionManager.class) is very slow.
but when i add this:
#Autowired
private PlatformTransactionManager platformTransactionManager;
it works. so what's the problem. i have no idea, and i'm using grpc with springboot now, please help thx;
#Configuration
#SpringBootApplication
#ComponentScan(value = "cn.com.autohome.autopay.wallet")
#EnableTransactionManagement
#EnableAutoConfiguration
#EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class AppMain extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AppMain.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(AppMain.class);
}
}
#Configuration
#MapperScan(basePackages = "cn.com.autohome.autopay.wallet.core.dal.mapper")
#ImportResource(locations = {"classpath:wallet-dal-bean.xml"})
public class WalletMyBatisConfig {
#Autowired
private DataBaseProperties dataBaseProperties;
#Primary
#Bean(name = "walletDataSource")
#ConfigurationProperties("spring.datasource.druid")
public DataSource masterDataSource() throws SQLException {
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
dataSource.setDriverClassName(dataBaseProperties.getWallet_data_source_driver_class());
dataSource.setUrl(dataBaseProperties.getWallet_data_source_url());
dataSource.setUsername(dataBaseProperties.getWallet_data_source_username());
dataSource.setPassword(dataBaseProperties.getWallet_data_source_password());
return dataSource;
}
}
Is there a way to check if #Configuration components are being loaded when run a spring boot app ?
I have some 'null pointer' problems when i use this app:
Main class
#ComponentScan(basePackages = "com.pack")
#EnableAutoConfiguration
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Configuration class
package com.pack.config;
#Configuration
public class DataBaseConfig {
#Bean
JedisConnectionFactory jedisConnFactory() {
return new JedisConnectionFactory();
}
#Bean
public StringRedisSerializer stringRedisSerializer() {
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
return stringRedisSerializer;
}
#Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(jedisConnFactory());
redisTemplate.setKeySerializer(stringRedisSerializer());
return redisTemplate;
}
}
And when i try to use RedisTemplate:
public class ServiceDummy {
#Autowired
RedisTemplate<String, Object> redisTemplate;
public void save(String data){
redisTemplate.opsForValue().set("1234", data);
}
}
im getting a nullPointer.
As #Todd correctly pointed out, you can't expect Spring to manage beans that are not registered to Spring context.
So you need to:
Mark that bean as Spring bean with #Component annotation, or in this case #Service annotation would be better.
Make sure that ServiceDummy is under com.pack package, so that Spring can scan that component.
I am trying to build a new annotation based spring boot application.
On the DAO-level I have a configuration class with Dao beans:
#Configuration
#EnableTransactionManagement
public class DatabaseConfig {
#Bean
public DataSource dataSource(){
...
return dataSource;
}
#Bean
public JdbcTemplate jdbcTemplate(){
JdbcTemplate template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
#Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource)
{
....
}
#Bean
public PersonDao personDao(){
return new PersonDao();
}
}
On the server level a controller and a Mein class.
#SpringBootApplication (exclude = SecurityAutoConfiguration.class)
#ComponentScan("my.package")
#Import(DataBaseConfig.class)
public class Main {
private static Logger log = Logger.getLogger(Main.class);
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
The problem is that the main class does not see the beans got from the DatabaseConfig and that's why cannot start the application (because they are user in the controller). How can I correctly import them?