How do i make my application restart every 5 minutes. I tried threads but it restarted only oncce - spring

#SpringBootApplication
public class CurdingApplication {
public static void main(String[] args) {
SpringApplication.run(CurdingApplication.class, args);
}
#Bean
CommandLineRunner runner(SnapshotsService SnapshotsService) {
return args -> {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
TypeReference<Snapshots> typeReference = new TypeReference<Snapshots>(){};
InputStream inputStream = TypeReference.class.getResourceAsStream("/json/snapshots.json");
try {
Snapshots indexs = mapper.readValue(inputStream,typeReference);
SnapshotsService.saveIndex(indexs);
System.out.println("Users Saved!");
} catch (IOException e){
System.out.println("Unable to save users: " + e.getMessage());
}
};
}
}
The application runs the command line runner when the application starts. I basically want the commandline runner to run every 5 mins

Related

Is there a way to do a spring batch processor next page?

I set the chunk size to 15 and the page size to 15 at the time of programming, and made the batch program run every minute and 1 second. The result I want is, for example, when I have 30 data, I process 15 data in the first second and then 15 data in the immediately following page. But the way it works now is that it processes 15 data in the first second, then another 15 in the next second, and so on. Is there a way to do an action until the end of the page when executed once?
#Bean
public Job ConfirmJob() throws Exception {
Job exampleJob = jobBuilderFactory.get("ConfirmJob")
.start(Step())
.build();
return exampleJob;
}
#Bean
#JobScope
public Step Step() throws Exception {
return stepBuilderFactory.get("Step")
.<UserOrder,UserOrder>chunk(15)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
#Bean
#StepScope
public JpaPagingItemReader<UserOrder> reader() throws Exception {
Map<String,Object> parameterValues = new HashMap<>();
parameterValues.put("beforeDay", LocalDateTime.now().minusDays(14));
parameterValues.put("od", OrderStatus.ship);
return new JpaPagingItemReaderBuilder<UserOrder>()
.pageSize(15)
.parameterValues(parameterValues)
.queryString("SELECT uo FROM UserOrder uo where uo.standardfinishAt <: beforeDay And uo.orderStatus =: od ORDER BY id ASC")
.entityManagerFactory(entityManagerFactory)
.name("JpaPagingItemReader")
.build();
}
#Bean
#StepScope
public ItemProcessor<UserOrder, UserOrder> processor(){
return new ItemProcessor<UserOrder, UserOrder>() {
#Override
public UserOrder process(UserOrder us) throws Exception {
us.batchConfirm(LocalDateTime.now());
return us;
}
};
}
#Bean
#StepScope
public JpaItemWriter<UserOrder> writer(){
return new JpaItemWriterBuilder<UserOrder>()
.entityManagerFactory(entityManagerFactory)
.build();
}
}
this is scheduler code
#Autowired
private ResignConfiguration resignConfiguration;
#Scheduled(cron = "1 * * * * ?")
public void runConfirmJob() {
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(jobConfiguration.ConfirmJob(), jobParameters);
} catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {
log.error(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
It's a paging problem
JpaPagingItemReader<UserOrder> reader = new JpaPagingItemReader<UserOrder>() {
#Override
public int getPage() {
return 0;
}
};
reader.setParameterValues(parameterValues);
reader.setQueryString("SELECT uo FROM UserOrder uo where uo.createdAt <: limitDay And uo.orderStatus =: od ORDER BY id ASC");
reader.setPageSize(100);
reader.setEntityManagerFactory(entityManagerFactory);
reader.setName("JpaPagingItemReader");

Stop RabbitMQ-Connection in Spring-Boot

I have a spring-boot application that pulls all the messages from a RabbitMQ-queue and then terminates. I use rabbitTemplate from the package spring-boot-starter-amqp (version 2.4.0), namely receiveAndConvert(). Somehow, I cannot get my application to start and stop again. When the rabbitConnectionFactory is created, it will never stop.
According to Google and other stackoverflow-questions, calling stop() or destroy() on the rabbitTemplate should do the job, but that doesn't work.
The rabbitTemplate is injected in the constructor.
Here is some code:
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
Object msg = getMessage();
while (msg != null) {
try {
String name = ((LinkedHashMap) msg).get(propertyName).toString();
//business logic
logger.debug("added_" + name);
} catch (Exception e) {
logger.error("" + e.getMessage());
}
msg = getMessage();
}
rabbitTemplate.stop();
private Object getMessage() {
try {
return rabbitTemplate.receiveAndConvert(queueName);
} catch (Exception e) {
logger.error("" + e.getMessage());
return null;
}
}
So, how do you terminate the connection to RabbitMQ properly?
Thanks for your inquiry.
You can call resetConnection() on the CachingConnectionFactory to close the connection.
Or close() the application context.
If I were to do it , I would use #RabbitListener to receive the messages and RabbitListenerEndpointRegistry to start and stop the listener. Sample Code is given below
#EnableScheduling
#SpringBootApplication
public class Application implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static final String queueName = "Hello";
#Bean
public Queue hello() {
return new Queue(queueName);
}
#Autowired
private RabbitTemplate template;
#Scheduled(fixedDelay = 1000, initialDelay = 500)
public void send() {
String message = "Hello World!";
this.template.convertAndSend(queueName, message);
System.out.println(" [x] Sent '" + message + "'");
}
#Autowired
RabbitListenerEndpointRegistry registry;
#Override
public void run(ApplicationArguments args) throws Exception {
registry.getListenerContainer( Application.queueName).start();
Thread.sleep(10000L);
registry.getListenerContainer( Application.queueName).stop();
}
}
#Component
class Receiver {
#RabbitListener(id= Application.queueName,queues = Application.queueName)
public void receive(String in) {
System.out.println(" [x] Received '" + in + "'");
}
}

Spring Batch Not reading from DB nor writing to file

I want to use multiple datasources, one for the Spring Batch Metadata and the other for the business data. My batch job just runs and does not even try to connect to the secondaryDataSource. can someone point out what is wrong with my configuration?
#Configuration
#EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {
#Override
#Autowired
public void setDataSource(
#Qualifier("batchDataSource") DataSource batchDataSource) {
super.setDataSource(batchDataSource);
}
}
public class SpringBatchConfig {
#Autowired
private JobBuilderFactory jobs;
#Autowired
private StepBuilderFactory steps;
private static final String QUERY_FIND_STUDENTS = "select * from ...";
#Bean
ItemReader<DotDetailsDTO> reader(
#Qualifier("secondaryDataSource") DataSource dataSource)
throws SQLException {
JdbcCursorItemReader<DotDetailsDTO> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql(QUERY_FIND_STUDENTS);
databaseReader.setRowMapper(new DOTRowMapper());
return databaseReader;
}
#Bean
public ItemProcessor<DotDetailsDTO, DotDetailsDTO> itemProcessor() {
return new CustomItemProcessor();
}
#Bean
public ItemWriter<DotDetailsDTO> writer() throws Exception {
FlatFileItemWriter<DotDetailsDTO> writer = new FlatFileItemWriter<DotDetailsDTO>();
writer.setResource(new ClassPathResource("file:test.csv"));
DelimitedLineAggregator<DotDetailsDTO> delLineAgg = new DelimitedLineAggregator<DotDetailsDTO>();
delLineAgg.setDelimiter(",");
BeanWrapperFieldExtractor<DotDetailsDTO> fieldExtractor = new BeanWrapperFieldExtractor<DotDetailsDTO>();
fieldExtractor.setNames(new String[] { "airwayBillNumber",
"outboundDate", "orig", "dest", "lotNumber",
"lotFlightNumber", "lotOrig", "lotDest", "lotPcs", "lotWt",
"lotFlightDepartDate", "iataCode" });
delLineAgg.setFieldExtractor(fieldExtractor);
writer.setLineAggregator(delLineAgg);
writer.afterPropertiesSet();
return writer;
}
#Bean
protected Step step1(ItemReader<DotDetailsDTO> reader,
ItemProcessor<DotDetailsDTO, DotDetailsDTO> processor,
ItemWriter<DotDetailsDTO> writer) throws SQLException {
return steps.get("step1").<DotDetailsDTO, DotDetailsDTO> chunk(10)
.reader(reader).processor(processor).writer(writer).build();
}
#Bean(name = "firstBatchJob")
public Job job(#Qualifier("step1") Step step1) {
return jobs.get("firstBatchJob").start(step1).build();
}
}
public class DataSourceConfiguration {
#Bean(name="batchDataSource")
public DataSource dataSource() throws SQLException {
BasicDataSource dataSource = new BasicDataSource();
...
return dataSource;
}
#Bean
public JdbcTemplate jdbcTemplate(
#Qualifier("batchDataSource") final DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
#Primary
#Bean(name="secondaryDataSource")
public DataSource secondaryDataSource() throws SQLException {
OracleDataSource secondaryDataSource = new OracleDataSource();
...
return secondaryDataSource;
}
#Bean
public JdbcTemplate secondaryJdbcTemplate(
#Qualifier("secondaryDataSource") final DataSource secondaryDataSource) {
return new JdbcTemplate(secondaryDataSource);
}
}
public static void main(String[] args) {
// Spring Java config
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(DataSourceConfiguration.class);
context.register(BatchConfiguration.class);
context.register(SpringBatchConfig.class);
context.refresh();
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("firstBatchJob");
System.out.println("Starting the batch job");
try {
JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Job Status : " + execution.getStatus());
System.out.println("Job completed");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Job failed");
}
}
Wow after 2 days I figured out what the issue was. I was not providing new JobParameters because of which I was running the same old broken job over and over.
Below is the fix in the main method.
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(DataSourceConfiguration.class);
context.register(BatchConfiguration.class);
context.register(SpringBatchConfig.class);
context.refresh();
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("firstBatchJob");
System.out.println("Starting the batch job");
try {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
JobParameters jobParam =
new JobParametersBuilder().addString("jobDate",dateFormat.format(date)).toJobParameters();
JobExecution execution = jobLauncher.run(job, jobParam);
System.out.println("Job Status : " + execution.getStatus());
System.out.println("Job completed : " + execution.getJobId());
} catch (Exception e) {
e.printStackTrace();
System.out.println("Job failed");
}
}

How to send email asynchronously using spring 4 #Async

I know this question has been asked but I am not able to send email using configuration. I don't know what I am doing wrong and why I am not getting the email. Here is my Spring configuration.
#Configuration
#PropertySource(value = {
"classpath:autoalert.properties"
})
#EnableAsync
#Import({PersistenceConfig.class, EmailConfig.class, VelocityConfig.class})
#ComponentScan(basePackageClasses = {
ServiceMarker.class,
RepositoryMarker.class }
)
public class AutoAlertAppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Here is my email config
#Configuration
#PropertySources({
#PropertySource("classpath:email/email.properties")
})
public class EmailConfig {
#Autowired
private Environment env;
#Bean
public JavaMailSender mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setSession(getEmailSession());
return mailSender;
}
#Bean
public MailMessage mailSettings() {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setFrom(env.getProperty("mail.from"));
...
mailMessage.setText(env.getProperty("mail.body"));
return mailMessage;
}
private Session getEmailSession() {
Properties emailProperties = SpringUtil.loadPropertiesFileFromClassPath("email" + File.separator + "general-mail-settings.properties");
final String userName = emailProperties.getProperty("user");
final String password = emailProperties.getProperty("password");
Session session = null;
try {
session = Session.getInstance(emailProperties, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password);
}
}); //end of anonymous class
} catch (Exception e) {
e.printStackTrace();
}
return session;
} //end of getEmailSession()
}
Here is my class
public static void main(String[] args) {
try (GenericApplicationContext springContext = new AnnotationConfigApplicationContext(AutoAlertAppConfig.class)) {
AutoAlertService autoAlertService = springContext.getBean(AutoAlertServiceImpl.class);
try {
autoAlertService.handleProcess(fromDate, toDate);
} catch (Exception e) {
logger.error("Exception occurs", e);
autoAlertService.handleException(fromDate, toDate, e);
}
} catch (Exception e) {
logger.error("Exception occurs in loading Spring context: ", e);
}
#Service
public class AutoAlertServiceImpl implements AutoAlertService {
#Inject
private AsyncEmailService asyncEmailService;
#Override
public void handleProcess(String fromDate, String toDate) {
logger.info("Start process");
try {
..
//Sending email
asyncEmailService.sendMailWithFileAttachment(fromDate, toDate, file);
} catch (Exception e) {
handleException(fromDate, toDate, e);
}
logger.info("Finish process");
}
}
here is my email service
#Component
public class AsyncEmailServiceImpl implements AsyncEmailService {
#Resource(name="mailSender")
private JavaMailSender mailSender;
#Resource(name="mailSettings")
private SimpleMailMessage simpleMailMessage;
#Async
#Override
public void sendMailWithFileAttachment(String from, String to, String attachFile) {
logger.info("Start execution of async. Sending email with file attachment");
MimeMessage message = mailSender.createMimeMessage();
try{
MimeMessageHelper helper = new MimeMessageHelper(message, true);
....
helper.setText(String.format(simpleMailMessage.getText(), from, to));
FileSystemResource file = new FileSystemResource(attachFile);
helper.addAttachment(file.getFilename(), file);
mailSender.send(message);
} catch (MessagingException e) {
logger.error("Exception occurs in sending email with file attachment: " + attachFile, e);
throw new MailParseException(e);
}
logger.info("Complete execution of async. Email with file attachment " + attachFile + " send successfully.");
}
}
When I run the code it comes to method. This is printed on the console
13:59:43.004 [main] INFO com.softech.vu360.autoalert.service.impl.AutoAlertServiceImpl - Finish process
13:59:43.005 [SimpleAsyncTaskExecutor-1] INFO com.softech.vu360.autoalert.service.impl.AsyncEmailServiceImpl - Start execution of async. Sending email with file attachment
13:59:43.007 [main] INFO com.softech.vu360.autoalert.AutoAlert - Exiting application.
But I get no email. In case of Synchronous calling I get the email. Why I am not getting email ? Am I doing something wrong ?
Thanks
I think this is better approach. Create a file AsyncConfig.java
#Configuration
#EnableAsync(proxyTargetClass = true)
#EnableScheduling
public class AsyncConfig implements SchedulingConfigurer, AsyncConfigurer {
private static final Logger log = LogManager.getLogger();
private static final Logger schedulingLogger = LogManager.getLogger(log.getName() + ".[scheduling]");
#Bean
public ThreadPoolTaskScheduler taskScheduler() {
log.info("Setting up thread pool task scheduler with 20 threads.");
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(2);
scheduler.setThreadNamePrefix("task-");
scheduler.setAwaitTerminationSeconds(1200); // 20 minutes
scheduler.setWaitForTasksToCompleteOnShutdown(true);
scheduler.setErrorHandler(t -> schedulingLogger.error("Unknown error occurred while executing task.", t));
scheduler.setRejectedExecutionHandler((r, e) -> schedulingLogger.error("Execution of task {} was rejected for unknown reasons.", r));
return scheduler;
}
#Override
public Executor getAsyncExecutor() {
Executor executor = this.taskScheduler();
log.info("Configuring asynchronous method executor {}.", executor);
return executor;
}
#Override
public void configureTasks(ScheduledTaskRegistrar registrar) {
TaskScheduler scheduler = this.taskScheduler();
log.info("Configuring scheduled method executor {}.", scheduler);
registrar.setTaskScheduler(scheduler);
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}
Now import it into your main configuration like this
#Configuration
#PropertySource(value = {
"classpath:autoalert.properties"
})
#Import({AsyncConfig.class, PersistenceConfig.class, EmailConfig.class, VelocityConfig.class})
#ComponentScan(basePackageClasses = {
ServiceMarker.class,
RepositoryMarker.class }
)
public class AutoAlertAppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Change return type from void to Future
#Service
public class AsyncEmailServiceImpl implements AsyncEmailService {
#Resource(name="mailSender")
private JavaMailSender mailSender;
#Resource(name="mailSettings")
private SimpleMailMessage simpleMailMessage;
#Async
#Override
public Future<String> sendMailWithFileAttachment(String from, String to, String attachFile) {
....
return new AsyncResult<String>("Attachment File successfully send: " + attachFile);
}
#Async
#Override
public Future<String> sendMail(String from, String to, String emailBody) {
....
return new AsyncResult<String>("Email send successfully");
}
}
and in my service class just do this
logger.info("Start process");
try {
....
//Sending email
Future<String> result = asyncEmailService.sendMailWithFileAttachment(fromDate, toDate, file);
} catch (Exception e) {
handleException(fromDate, toDate, e);
}
logger.info("Finish process");
See no need to check result.get(). Now when new Thread starts and application starts to finish. I configured the scheduler.setAwaitTerminationSeconds(1200); // 20 minutes in AsyncConfig.java. This will ensure that all the pending threads must complete before the application shuts down. Ofcourse this can be change according to any ones need.
Now when I run the application it prints these on the console
12:55:33.879 [main] INFO com.softech.vu360.autoalert.service.impl.AutoAlertServiceImpl - Finish process
12:55:33.895 [task-1] INFO com.softech.vu360.autoalert.service.impl.AsyncEmailServiceImpl - Start execution of async. Sending email with file attachment
12:58:09.030 [task-1] INFO com.softech.vu360.autoalert.service.impl.AsyncEmailServiceImpl - Complete execution of async. Email with file attachment D:\projects\AutoAlerts\marketo\autoalert 2015-08-24 to 2015-08-30.csv send successfully.
12:58:09.033 [main] INFO com.softech.vu360.autoalert.AutoAlert - Exiting application.
See starts new thread, but before application shuts down make sure, the thread completes and then exits the application. I configured 20 minutes for email, but as soon as thread completes, application get shut down. This is happy ending :)

Jetty shuts down program

I am trying to create a GUI interface to start and stop a Jetty server with different return strings. Currently I have a start and stop button programmed and it returns "Hello World" into localhost:8080. My code is posted below, yes I have imports, removed to simplify it.
public class JettyGUI extends AbstractHandler{
private static Server server = new Server(8080);
private static boolean running = false;
private static void gui() {
JFrame frame = new JFrame("Jetty");
JButton start_button = new JButton("Start");
JButton stop_button = new JButton("Stop");
JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
panel.add(start_button);
panel.add(stop_button);
frame.add(panel);
frame.setSize(300, 150);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
start_button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Start pressed.");
startServer();
}
});
stop_button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Stop pressed.");
JettyGUI.stopServer();
}
});
}
private static void stopServer() {
if(running == false){
System.err.println("Server is already running!");
}
else{
try {
server.stop();
}
catch (Exception ex) {
System.out.println(ex);
}
}
System.out.println("Server stopped!");
}
private static void startServer() {
if(running == true){
System.err.println("Server is already running!");
}
else{
try{
server.setHandler(new JettyGUI());
server.start();
server.join();
}
catch(Exception ex){
System.out.println(ex);
}
System.out.println("Server started!");
}
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType("text;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
response.getWriter().println("Hello World!"); //print this text
}
public static void main(String[] args) {
gui();
}
}
When I press the "start" button, Jetty API seems to take over my application and I can no longer press the "stop" button. Could anyone tell me a way to navigate around this or program this differently?
Thanks! :)
-Henry Harris
The server.join(); will make the current thread wait until the server is stopped.
Comment it out, as a GUI program you don't need it.

Resources