spring boot- unable to read yaml properties file application.yml - java

I am trying to configure ldap server with spring-boot for this i am using application.yml file to read ldap url,base,userdn,password etc. from code if i try to read the application.yml properties they are always returning null.
below are my files please help me in fixing the issue.
//application.yml
//---------------
spring:
profiles:
active: TEST
---
spring:
profiles: PROD
logging:
config: classpath:PROD/log4j2.yml
ldap:
url: ldap://pod-url
base: XXX
userDn: yyy
password: password
---
spring:
profiles: TEST
logging:
config: classpath:UAT/log4j2.yml
ldap:
url: ldap://ldap.forumsys.com:389
base: dc=example,dc=com
userDn: cn=read-only-admin,dc=example,dc=com
password: password
//LdapConfig.java
//----------------
#Configuration
#ComponentScan(basePackages = {"com.base.package.*"})
public class LdapConfig {
#Autowired
Environment env;
#Bean
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(env.getProperty("ldap.url"));
contextSource.setBase(env.getProperty("ldap.base"));
contextSource.setUserDn(env.getProperty("ldap.userDn"));
contextSource.setPassword(env.getProperty("ldap.password"));
contextSource.afterPropertiesSet();
return contextSource;
}
#Bean
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSource());
}
}
//from the below file i will be trying use ldapconfig properties
//AuthenticationServiceimpl.java
//------------------------------
public class AuthenticationServiceImpl implements AuthenticationService {
Logger logger = LogManager.getLogger(AuthenticationServiceImpl.class);
private LdapTemplate ldapTemplate;
private LdapContextSource ldapContextSource;
public boolean authenticateUser(String username, String password) {
ApplicationContext context = new AnnotationConfigApplicationContext(LdapConfig.class);
ldapTemplate = (LdapTemplate) context.getBean(LdapTemplate.class);
ldapContextSource = (LdapContextSource) context.getBean(LdapContextSource.class);
DirContext ctx = null;
try {
return ldapTemplate.authenticate(ldapContextSource.getBaseLdapPathAsString(), "(uid=" + username + ")",
password);
} catch (Exception e) {
logger.error("user " + username + " failed to authenticated " + e);
return false;
} finally {
if (ctx != null) {
org.springframework.security.ldap.LdapUtils.closeContext(ctx);
}
}
}
}
//and my main application is
#SpringBootApplication
public class Application {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(Application.class);
SpringApplication.run(Application.class, args);
}
}

Use #Value :
#Configuration
#ComponentScan(basePackages = {"com.base.package.*"})
public class LdapConfig {
#Autowired
Environment env;
#Value("${ldap.url}")
private String ldapUrl;
#Bean
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(ldapUrl);
// ...
}
#Bean
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSource());
}
}

Related

The dependencies of some of the beans in the application context form a cycle email sender

Cycle is formed after adding EmailSender code.
I did everything just by tutorials.
And then I got that error, tbh I didn't get how this cycle works, but I tried, though couldn't find this connection between classes.
application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/med
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=
spring.mail.password=
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
Here is my security config, JavaMailSender bean was firstly in EmailSenderImpl, but I got similar problem with cycle, but the picture was another.
SecurityConfig:
#Configuration
#EnableWebSecurity
#RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
#Value("${spring.mail.username}")
private String username;
#Value("${spring.mail.password}")
private String password;
#Value("${spring.mail.host}")
private String host;
#Value("${spring.mail.port}")
private int port;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(STATELESS)
.and()
.authorizeRequests().antMatchers("/login/**", "/api/v1/user/token/refresh/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new AuthenticationFilter(authenticationManagerBean()))
.addFilterBefore(new AuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public JavaMailSender getJavaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(host);
mailSender.setPort(port);
mailSender.setUsername(username);
mailSender.setPassword(password);
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.debug", "true");
return mailSender;
}
}
This class actually calls email method.
UserImpl:
#RequiredArgsConstructor
#Service("userImpl")
public class UserImpl implements UserService, UserDetailsService {
private final UserRepository userRepository;
private final EmailSenderService emailSenderService;
#Override
public List<User> getUsers() {
return userRepository.findAll();
}
#Override
public User getUserById(Long id) {
User user = userRepository.findById(id).orElseThrow();
return user;
}
#Override
public User getUserByEmail(String email) {
User user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("User was not found with email: " + email);
}
return user;
}
#Override
public User registerUser(User user) {
emailSenderService.sendOTPEmail(user.getEmail());
user.setPassword(passwordEncoder().encode(user.getPassword()));
return userRepository.save(user);
}
#Override
public User updateUser(UserModel userModel) {
return null;
}
#Override
public User deleteUser(Long id) {
return null;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByEmail(username);
if (user == null) {
throw new UsernameNotFoundException("User was not found with email: " + username);
}
return UserModel.getUserDetails(user);
}
protected PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public static UserModel toUserModel(User user) {
UserModel userModel = new UserModel();
userModel.setUserId(user.getUserId());
userModel.setEmail(user.getEmail());
userModel.setPassword(user.getPassword());
userModel.setPhoneNumber(user.getPhoneNumber());
userModel.setOtpUsed(user.isOtpUsed());
userModel.setRole(user.getRole());
userModel.setStatus(user.getStatus());
return userModel;
}
}
Here is sendotp method which had to work and before in sendOTPEmail method instead of String email it was User user, but I though calling entity is the source of problem which it wasn't.
EmailSenderImpl:
#Service
public class EmailSenderImpl implements EmailSenderService {
private final JavaMailSender mailSender;
public EmailSenderImpl(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
#SneakyThrows
#Override
public void sendOTPEmail(String email) {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
char[] otp = generateOtp();
helper.setFrom("tilekzh0701#gmail.com");
helper.setTo(email);
String subject = "Here's your One Time Password (OTP) - Expire in 5 minutes!";
String content = "<p>Hello! </p>"
+ "<p>For security reason, you're required to use the following "
+ "One Time Password to login:</p>"
+ "<p><b>" + Arrays.toString(otp) + "</b></p>"
+ "<br>"
+ "<p>Note: this OTP is set to expire in 5 minutes.</p>";
helper.setSubject(subject);
helper.setText(content, true);
mailSender.send(message);
}
static char[] generateOtp()
{
String Capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String Small_chars = "abcdefghijklmnopqrstuvwxyz";
String numbers = "0123456789";
String symbols = "!##$%^&*_=+-/.?<>)";
String values = Capital_chars + Small_chars + numbers + symbols;
Random random = new Random();
char[] password = new char[8];
for (int i = 0; i < 8; i++)
{
password[i] = values.charAt(random.nextInt(values.length()));
}
return password;
}
}
Here is issue. Hope to get a help.
Run:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-06-21 09:44:13.078 ERROR 12284 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfig defined in file [C:\Users\User\Desktop\project\medtech\target\classes\com\project\medtech\config\SecurityConfig.class]
↑ ↓
| userImpl defined in file [C:\Users\User\Desktop\project\medtech\target\classes\com\project\medtech\service\UserImpl.class]
↑ ↓
| emailSenderImpl defined in file [C:\Users\User\Desktop\project\medtech\target\classes\com\project\medtech\service\EmailSenderImpl.class]
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

Springbatch is unable to detect database type for mysql

I am using springboot 2.6.6 with mysql and quite new to springbatch. I was getting an error "spring context is forming a cycle" when I kept the datasource in the same config file where readers and writers are kept in SampleJob.java. Suggested solution was to put the datasource in another class so I placed the datasource within the same class as main().
Now I am getting this issue:
Error
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigure.batch.BatchDataSourceScriptDatabaseInitializer]: Factory method 'batchDataSourceInitializer' threw exception; nested exception is java.lang.IllegalStateException: Unable to detect database type
Caused by: java.lang.IllegalStateException: Unable to detect database type
SampleJob.java
#Configuration
public class SampleJob {
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Bean
public Job chunkJob() {
return jobBuilderFactory.get("Chunk Job")
.incrementer(new RunIdIncrementer())
.start(firstChunkStep())
.build();
}
private Step firstChunkStep() {
return stepBuilderFactory.get("First Chunk Step")
.<StudentJdbc, StudentJdbc>chunk(3)
.reader(jdbcItemReader())
.writer(flatFileItemWriter(null))
.build();
}
#Bean
#StepScope
public JdbcCursorItemReader<StudentJdbc> jdbcItemReader(){
JdbcCursorItemReader<StudentJdbc> jdbcReader = new JdbcCursorItemReader<StudentJdbc>();
jdbcReader.setSql("select id, first_name as firstName, last_name as lastName, email from students");
jdbcReader.setDataSource(universitydatasource());
jdbcReader.setRowMapper(new BeanPropertyRowMapper<StudentJdbc>() {
{
setMappedClass(StudentJdbc.class);
}
});
return jdbcReader;
}
#StepScope
#Bean
public FlatFileItemWriter<StudentJdbc> flatFileItemWriter(
#Value("#{jobParameters['outputFile']}") FileSystemResource fileSystemResource
){
FlatFileItemWriter<StudentJdbc> flatFileItemWriter = new FlatFileItemWriter<StudentJdbc>();
flatFileItemWriter.setResource(fileSystemResource);
flatFileItemWriter.setResource(fileSystemResource);
flatFileItemWriter.setHeaderCallback(new FlatFileHeaderCallback() {
#Override
public void writeHeader(Writer writer) throws IOException {
writer.write("Id, First Name, Last Name, Email");
}
});
flatFileItemWriter.setLineAggregator(new DelimitedLineAggregator(){
{
setFieldExtractor(new BeanWrapperFieldExtractor<StudentResponse>() {
{
setNames(new String[] {"id","firstName","lastName","email"});
}
});
}
});
flatFileItemWriter.setFooterCallback(new FlatFileFooterCallback() {
#Override
public void writeFooter(Writer writer) throws IOException {
writer.write("Created # "+new Date());
}
});
return flatFileItemWriter;
}
}
Main class file
#SpringBootApplication
#EnableBatchProcessing
public class ChunksApplication {
public static void main(String[] args) {
SpringApplication.run(ChunksApplication.class, args);
}
#Bean
#Primary
#ConfigurationProperties(prefix="spring.datasource")
public DataSource datasource() {
return DataSourceBuilder.create().build();
}
#Bean
#ConfigurationProperties(prefix="spring.universitydatasource")
public DataSource universitydatasource() {
return DataSourceBuilder.create().build();
}
}
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/udemy-springbatch-chunks
spring.datasource.username=____
spring.datasource.password=____
spring.datasource.platform=mysql
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#alternate datasource for db input for reader
spring.universitydatasource.url=jdbc:mysql://localhost:3306/university?createDatabaseIfNotExist=true
spring.universitydatasource.username=____
spring.universitydatasource.password=____
spring.universitydatasource.platform=mysql
spring.universitydatasource.driverClassName=com.mysql.cj.jdbc.Driver
Found the solution. It seems that #ConfigurationProperties weren't picking up the url, username and password from application.properties so this worked in the main class file itself:
#Bean
#Primary
public DataSource datasource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url("jdbc:mysql://localhost:3306/udemy-springbatch-chunks");
dataSourceBuilder.username("____");
dataSourceBuilder.password("____");
return dataSourceBuilder.build();
}
#Bean("universityDatasource")
public DataSource universitydatasource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url("jdbc:mysql://localhost:3306/university?createDatabaseIfNotExist=true");
dataSourceBuilder.username("____");
dataSourceBuilder.password("____");
return dataSourceBuilder.build();
}
It works for me
spring.batch.schema=classpath:org/springframework/batch/core/schema-mysql.sql
My solution was this, you have to add the jdbcUrl
Properties file example:
spring.datasource.url=jdbc:mysql://localhost:3306/udemy-springbatch-chunks
spring.datasource.jdbcUrl=${spring.datasource.url}
spring.datasource.username=____
spring.datasource.password=____
spring.datasource.platform=mysql
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#alternate datasource for db input for reader
spring.universitydatasource.url=jdbc:mysql://localhost:3306/university
spring.universitydatasource.jdbcUrl=${spring.universitydatasource.url}
spring.universitydatasource.username=____
spring.universitydatasource.password=____
spring.universitydatasource.platform=mysql
spring.universitydatasource.driverClassName=com.mysql.cj.jdbc.Driver
Regards.

How to Configure Two Data Sources JDBC in a Spring Boot Application?

JPA is not used.
project structure: each database has its own class-configurator.
file application.properties is
app.datasource.h2.jdbc-url=jdbc:h2:~/database/tester
app.datasource.h2.username=usr
app.datasource.h2.password=pwd
app.datasource.pg.jdbc-url=jdbc:postgresql://localhost:5432/tester
app.datasource.pg.username=usr
app.datasource.pg.password=pwd
config db H2 is DataSourcesConfigurationH2:
#Configuration
#EnableTransactionManagement
public class DataSourcesConfigurationH2 {
#Bean
#Primary
#ConfigurationProperties(prefix="app.datasource.h2")
public HikariDataSource dataSourceH2(DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean
#Primary
public NamedParameterJdbcTemplate jdbcH2(HikariDataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
#Bean
#Primary
TransactionManager transactionManagerH2(HikariDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
config db postgres is DataSourcesConfigurationPg:
#Configuration
#EnableTransactionManagement
public class DataSourcesConfigurationPg {
#Bean
#ConfigurationProperties(prefix="app.datasource.pg")
public HikariDataSource dataSourcePg(DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean
public NamedParameterJdbcTemplate jdbcPg(HikariDataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
#Bean
TransactionManager transactionManagerPg(HikariDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
however, when the application starts, the dataSourcePg value is not initialized.
dataSourceH2.getDriverClassName() is "org.h2.Driver"
and
dataSourcePg.getDriverClassName() is "org.h2.Driver"
how to initialize the value of dataSourcePg correctly ?
Just use three application.properties files. First one is to select the correct properties file. The other two is to have the two different data sourses.
the solution works for the environment:
JDK 11, Spring Boot 2.5.4
fragment application.yml
app:
datasourceh2:
jdbcUrl: jdbc:h2:~/database/tester
driverClassname: org.h2.Driver
username: usr
password: pwd
datasourcepg:
jdbcUrl: jdbc:postgresql://localhost:5432/tester
driverClassname: org.postgresql.Driver
username: usr
password: pwd
I repeat, each database has its own class-configurator.
config db H2 is DataSourcesConfigurationH2:
#Configuration
public class DataSourcesConfigurationH2 {
#Primary
#Bean
#ConfigurationProperties("app.datasourceh2")
public DataSourceProperties dataSourcePropertiesH2() {
return new DataSourceProperties();
}
#Primary
#Bean("dataSourceH2")
#ConfigurationProperties(prefix = "app.datasourceh2")
public HikariDataSource dataSourceH2() {
return dataSourcePropertiesH2()
.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Primary
#Bean
public NamedParameterJdbcTemplate jdbcTemplateH2()
{
DataSource ds = dataSourceH2();
return new NamedParameterJdbcTemplate(ds);
}
// JdbcRepository - is my class for data manipulation
#Primary
#Bean
JdbcRepository jdbcRepositoryH2() {
NamedParameterJdbcTemplate jdbc = jdbcTemplateH2();
return new JdbcRepository(jdbc);
};
}
config db postgres is DataSourcesConfigurationPg:
#Configuration
public class DataSourcesConfigurationPg {
#Bean
#ConfigurationProperties("app.datasourcepg")
public DataSourceProperties dataSourcePropertiesPg() {
return new DataSourceProperties();
}
#Bean("dataSourcePg")
#ConfigurationProperties(prefix = "app.datasourcepg")
public HikariDataSource dataSourcePg() {
return dataSourcePropertiesPg()
.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean("jdbcTemplatePg")
public NamedParameterJdbcTemplate jdbcTemplatePg()
{
HikariDataSource ds = dataSourcePg();
return new NamedParameterJdbcTemplate(ds);
}
#Bean("jdbcRepositoryPg")
JdbcRepository jdbcRepositoryPg() {
NamedParameterJdbcTemplate jdbc = jdbcTemplatePg();
return new JdbcRepository(jdbc);
};
}
the dependency injection should be as follows:
for db H2 Service:
#Service
public class DataAccessServiceH2 {
#Autowired
#Qualifier("jdbcRepositoryH2")
private JdbcRepository jdbcRepository;
...
}
for db Pg Service:
#Service
public class DataAccessServicePg {
#Autowired
#Qualifier("jdbcRepositoryPg")
private JdbcRepository jdbcRepository;
...
}
next you can call the db H2 methods from DataAccessServiceH2 or postgres methods from DataAccessServicePg.
to find the answer, I used:
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.data-access.configure-two-datasources

Spring boot batch Spring data jpa

i am using Spring boot + Spring Batch + JPA + Mysql. below are the follow i am following:
spring boot application
```
#SpringBootApplication(scanBasePackages = "com.xxx.xxxx.config, com.xxx.xxx.rest, com.xxx.xxx.domain, com.xxx.xxx.dataservice, com.xxx.xxx.batchconfiguration, com.xxx.xxx.steps")
#EnableAutoConfiguration
#EnableConfigurationProperties(Properties.class)
#EnableEncryptableProperties
public class SampleApplication
{
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
```
Created #Entity classes based on table structure
created reposity interface like below
```
#Component
public interface ExampleRepository extends JpaRepository<tableClass, Long> {
Page<tableClass> findTop10ByStatus(tableClassStatus status,
Pageable pageable);
}
```
Batch configuration:
```
#Configuration
#EnableScheduling
public class BatchScheduler {
#Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
#Bean
public JobExplorer jobExplorer() throws Exception {
MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(
mapJobRepositoryFactory());
jobExplorerFactory.afterPropertiesSet();
return jobExplorerFactory.getObject();
}
#Bean
public MapJobRepositoryFactoryBean mapJobRepositoryFactory() throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(transactionManager());
return factory;
}
#Bean
public JobRepository jobRepository() throws Exception {
return mapJobRepositoryFactory().getObject();
}
#Bean
public JobLauncher jobLauncher() throws Exception {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
simpleJobLauncher.setJobRepository(jobRepository());
return simpleJobLauncher;
}
}
```
batch configuration
```
#Configuration
#EnableBatchProcessing
#Import({ BatchScheduler.class })
public class BatchConfiguration2 {
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
private SimpleJobLauncher jobLauncher;
#Autowired
public ExampleRepository exampleRepository ;
#Scheduled(cron = "0/5 * * * * ?")
public void perform() throws Exception {
System.out.println("Job Started at :" + new Date());
JobParameters param = new JobParametersBuilder()
.addString("JobID", String.valueOf(System.currentTimeMillis())).toJobParameters();
JobExecution execution = jobLauncher.run(job(), param);
System.out.println("Job finished with status :" + execution.getStatus());
}
#Bean
public RepositoryMetadata repositoryMetadata() {
return new DefaultRepositoryMetadata(ExampleRepository.class);
}
#Bean
public RepositoryItemReader<tableClass> reader() {
RepositoryItemReader<tableClass> fullfillment = new RepositoryItemReader<tableClass>();
fullfillment.setRepository(ExampleRepository);
fullfillment.setMethodName("findTop10ByStatus");
List<tableClassStatus> list = new ArrayList<tableClassStatus>();
list.add(tableClassStatus.FULFILLMENT_READY);
fullfillment.setArguments(list);
HashMap<String, Sort.Direction> sorts = new HashMap<>();
sorts.put("id", Direction.DESC);
fullfillment.setSort(sorts);
return fullfillment;
}
/* #Bean
public RepositoryItemWriter<tableClass> writer() {
System.out.println("BatchConfiguration.writer()");
RepositoryItemWriter<tableClass> itemWriter = new RepositoryItemWriter<tableClass>();
itemWriter.setRepository(ExampleRepository);
itemWriter.setMethodName("save");
return itemWriter;
}*/
#Bean
public RepositoryItemWriter<tableClass> writer() {
System.out.println("BatchConfiguration.writer()");
DefaultCrudMethods defaultCrudMethods = new DefaultCrudMethods(repositoryMetadata());
RepositoryItemWriter<tableClass> itemWriter = new RepositoryItemWriter<tableClass>();
itemWriter.setRepository(ExampleRepository);
itemWriter.setMethodName(defaultCrudMethods.getSaveMethod().getName());
return itemWriter;
}
#Bean
public Step step1() throws Exception {
return this.stepBuilderFactory.get("step1")
.<tableClass, tableClass> chunk(1).reader(reader())
.processor(new QuoteOfferFullfillmentSubmitionProcessor()).writer(writer()).build();
}
#Bean
public Job job() throws Exception {
return this.jobBuilderFactory.get("job").incrementer(new RunIdIncrementer()).start(step1())
.listener(new JobCompletionListener()).build();
}
}
```
QuoteOfferFullfillmentSubmitionProcessor.java
```
public class QuoteOfferFullfillmentSubmitionProcessor implements ItemProcessor<QuoteOfferFulfillment, QuoteOfferFulfillment> {
#Override
public tableClass process(tableClass item) throws Exception {
System.out.println("Processor.process() ==> ID " + item.getId());
System.out.println("Processor.process() ==> " + item.getLenderName());
System.out.println(
"QuoteOfferFullfillmentSubmitionProcessor.process() ==> source" + item.getStatus());
item.setStatus(QuoteOfferFulfillmentStatus.PROCESSING);
return item;
}
}
```
JobCompletionListener.java
```
public class JobCompletionListener extends JobExecutionListenerSupport {
#Override
public void afterJob(JobExecution jobExecution) {
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
System.out.println("BATCH JOB COMPLETED SUCCESSFULLY");
}
}
}
```
after all configuration, running the application every 5 sec the job is running fine, getting values and printing in process class, after that coming to writer class and printing all the values with out Errors.
the problem is: its not updating the values in the Database in write method.
with out BatchScheduler, scheduler and job launcher (commit the code) restarting the spring boot its all updating the values in database.
Can you guys suggest me what wrong i am doing.
I have resolve the issue. in the batch configuration if i use
```
#Bean
public ResourcelessTransactionManager resourcelessTransactionManager() {
return new ResourcelessTransactionManager();
}
#Bean
public JobRepository jobRepository() throws Exception {
return new MapJobRepositoryFactoryBean(resourcelessTransactionManager()).getObject();
}
```
it started working.
Thanks,
Bala.

Configurable Mongo database url and name in Spring Boot Application

I am trying to configure mongodb properties through application-{environment-name}.properties for connecting to mongodb.
Here's my code for making connection to mongo:
#Configuration
#EnableAutoConfiguration
public class SpringMongoConfig {
#Value("${db.connectionURL}")
private String databaseURL;
#Value("${db.name}")
private String databaseName;
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
System.out.println("database url: " + databaseURL + " db name: " + databaseName);
return new SimpleMongoDbFactory(new MongoClient(databaseURL), databaseName);
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
return mongoTemplate;
}
}
Here's my application-test.properties file:
db.connectionURL=localhost
db.name=rahab
I'm getting null values for databaseURL and databaseName. My idea is that the values are still not available during bean creation. But I don't have any idea to achieve this.
you can use PropertySource in the configuration to specify the location of the properties file which you have created. The example code is given below:
#Configuration
#EnableAutoConfiguration
#PropertySource("application-test.properties")
public class SpringMongoConfig {
#Value("${db.connectionURL}")
private String databaseURL;
#Value("${db.name}")
private String databaseName;
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
System.out.println("database url: " + databaseURL + " db name: " + databaseName);
return new SimpleMongoDbFactory(new MongoClient(databaseURL), databaseName);
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
return mongoTemplate;
}
}
Hope it helps to solve your issue.

Categories