I have this Spring Boot app. using Quartz (a richly featured, open source job scheduling library that can be integrated within virtually any Java application ) to execute a Job the 10th day of the month
#EnableScheduling
#SpringBootApplication
public class IberiaUtilsApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(IberiaUtilsApplication.class);
app.run(args);
}
#Override
public void run(String... args) throws Exception {
..
}
}
and inside the config package:
#Configuration
public class JobConfig {
#Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(MonthlyIberiaMetrics.class).withIdentity("iberiaJob")
.usingJobData("iberiaMetrics", "fleet").storeDurably().build();
}
#Bean
public Trigger sampleJobTrigger() {
return newTrigger()
.forJob(sampleJobDetail())
.withIdentity("iberiaTrigger")
.withSchedule(cronSchedule("0 0 10 10 * ?"))
.build();
}
}
I run the app. from the command line, using mvn spring-boot:run but it seems that the Quartz is not initialised:
...
017-10-31 15:11 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
2017-10-31 15:11 [main] WARN c.z.hikari.util.DriverDataSource - Registered driver with driverClassName=oracle.jdbc.driver.OracleDriver was not found, trying direct instantiation.
2017-10-31 15:12 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
2017-10-31 15:12 [main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
2017-10-31 15:12 [main] INFO o.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2017-10-31 15:12 [main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
2017-10-31 15:12 [main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
2017-10-31 15:12 [main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'quartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2017-10-31 15:12 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'quartzScheduler' initialized from an externally provided properties instance.
2017-10-31 15:12 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
2017-10-31 15:12 [main] INFO org.quartz.core.QuartzScheduler - JobFactory set to: org.springframework.boot.autoconfigure.quartz.AutowireCapableBeanJobFactory#64ea8964
2017-10-31 15:12 [main] INFO o.s.j.e.a.AnnotationMBeanExporter - Registering beans for JMX exposure on startup
2017-10-31 15:12 [main] INFO o.s.j.e.a.AnnotationMBeanExporter - Bean with name 'dataSource' has been autodetected for JMX exposure
2017-10-31 15:12 [main] INFO o.s.j.e.a.AnnotationMBeanExporter - Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2017-10-31 15:12 [main] INFO o.s.c.s.DefaultLifecycleProcessor - Starting beans in phase 2147483647
2017-10-31 15:12 [main] INFO o.s.s.quartz.SchedulerFactoryBean - Starting Quartz Scheduler now
2017-10-31 15:12 [main] INFO org.quartz.core.QuartzScheduler - Scheduler quartzScheduler_$_NON_CLUSTERED started.
2017-10-31 15:12 [Thread-3] INFO o.s.c.a.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#589ebb: startup date [Tue Oct 31 15:11:56 CET 2017]; root of context hierarchy
2017-10-31 15:12 [Thread-3] INFO o.s.c.s.DefaultLifecycleProcessor - Stopping beans in phase 2147483647
2017-10-31 15:12 [Thread-3] INFO org.quartz.core.QuartzScheduler - Scheduler quartzScheduler_$_NON_CLUSTERED paused.
2017-10-31 15:12 [Thread-3] INFO o.s.s.quartz.SchedulerFactoryBean - Shutting down Quartz Scheduler
2017-10-31 15:12 [Thread-3] INFO org.quartz.core.QuartzScheduler - Scheduler quartzScheduler_$_NON_CLUSTERED shutting down.
2017-10-31 15:12 [Thread-3] INFO org.quartz.core.QuartzScheduler - Scheduler quartzScheduler_$_NON_CLUSTERED paused.
2017-10-31 15:12 [Thread-3] INFO org.quartz.core.QuartzScheduler - Scheduler quartzScheduler_$_NON_CLUSTERED shutdown complete.
2017-10-31 15:12 [Thread-3] INFO o.s.j.e.a.AnnotationMBeanExporter - Unregistering JMX-exposed beans on shutdown
2017-10-31 15:12 [Thread-3] INFO o.s.j.e.a.AnnotationMBeanExporter - Unregistering JMX-exposed beans
2017-10-31 15:12 [Thread-3] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
2017-10-31 15:12 [Thread-3] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.
MacBook-Pro-de-lopes:iberiaUtils lopes$
I also tried changing the expression to 0 * * * * ? (every minute) with the same result
and also created this other class with the same result:
public class ScheduledTasks1 {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
#Scheduled(cron = "0 * * * * ?")
public void reportCurrentTime() {
System.out.println("The time is now {}" +
dateFormat.format(new Date()));
}
}
for your information, I have another similar application without Quartz properties and its working fine:
#SpringBootApplication
public class IberiaReservationsApplication {
public static void main(String[] args) {
SpringApplication.run(IberiaReservationsApplication.class, args);
}
#Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(CheckDBJobExecution.class).withIdentity("sampleJob")
.usingJobData("name", "World").storeDurably().build();
}
#Bean
public Trigger sampleJobTrigger() {
return newTrigger()
.forJob(sampleJobDetail())
.withIdentity("sampleTrigger")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
.build();
}
}
Have you considered using Springs own scheduler, it's easy to configure and I've always found it to work well.
https://spring.io/guides/gs/scheduling-tasks/
You are missing various configuration for Quartz here like
Quartz properties
SchedulerFactoryBean
Follow below examples for complete implementation:
https://chynten.wordpress.com/2016/06/17/quartz-with-databse-and-spring-4/
http://www.baeldung.com/spring-quartz-schedule
Related
I'm setting up a Quartz Scheduler in Spring Boot. I want the scheduled Jobs to be able to inject Beans from the Application Context. For that I created my own Quartz Job Factory:
public final class MyQuartzJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
#Override
public void setApplicationContext(final ApplicationContext context) throws BeansException {
beanFactory = context.getAutowireCapableBeanFactory();
}
#Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
For keeping a reference to the Scheduler, I have a SchedulerManager Bean that initializes the Scheduler:
public void initScheduler() {
try (InputStream propsInputStream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("my-quartz.properties")) {
log.info("Creating Quartz scheduler...");
Properties myQuartzProperties = new Properties();
myQuartzProperties.load(propsInputStream);
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setQuartzProperties(myQuartzProperties);
schedulerFactory.afterPropertiesSet();
schedulerFactory.setJobFactory(quartzJobFactory);
this.scheduler = schedulerFactory.getScheduler();
this.schedulingConfigMap = new HashMap<>();
log.info("Quartz scheduler created.");
} catch (Exception e) {
log.error("Unable to create Quartz scheduler", e);
throw new RuntimeException("Scheduler extension initialization error", e);
}
}
I do the initialization of the Scheduler once the context has been initialized:
public class MyLifecycleListener implements ServletContextListener {
private final SchedulerManager schedulerManager;
#Override
public void contextInitialized(ServletContextEvent sce) {
schedulerManager.initScheduler();
}
}
The quartz configuration file is as follows:
org.quartz.scheduler.instanceName=MyQuartzScheduler
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=12
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
org.quartz.jobStore.misfireThreshold=60000
When starting the application I see my Quartz Scheduler is initialized, but the problem is that I see a second Quartz Scheduler initialized (maybe a Spring default one?).
Mine: 'MyQuartzScheduler' with 12 threads
2022-08-23 14:13:03.239 INFO 24788 --- [ main] org.quartz.core.QuartzScheduler : Quartz Scheduler v.2.3.2 created.
2022-08-23 14:13:03.240 INFO 24788 --- [ main] org.quartz.simpl.RAMJobStore : RAMJobStore initialized.
2022-08-23 14:13:03.241 INFO 24788 --- [ main] org.quartz.core.QuartzScheduler : Scheduler meta-data: Quartz Scheduler (v2.3.2) 'MyQuartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 12 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2022-08-23 14:13:03.241 INFO 24788 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler 'MyQuartzScheduler' initialized from an externally provided properties instance.
Some milliseconds later, another one called 'quartzScheduler' with 10 threads.
2022-08-23 14:13:03.713 INFO 24788 --- [ main] org.quartz.core.QuartzScheduler : Quartz Scheduler v.2.3.2 created.
2022-08-23 14:13:03.713 INFO 24788 --- [ main] org.quartz.simpl.RAMJobStore : RAMJobStore initialized.
2022-08-23 14:13:03.713 INFO 24788 --- [ main] org.quartz.core.QuartzScheduler : Scheduler meta-data: Quartz Scheduler (v2.3.2) 'quartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2022-08-23 14:13:03.713 INFO 24788 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler 'quartzScheduler' initialized from an externally provided properties instance.
How can I disable this second one?
Sample project can be found here: https://github.com/dajoropo/spring-quartz-demo/tree/stackoverflow_question_73459083
The easiest way is to use the Spring configured scheduler instead of doing it yourself. Move the quartz.properties to the spring.quartz namespace in the application.properties.
spring.quartz.scheduler-name=MyQuartzScheduler
spring.quartz.properties.org.quartz.threadPool.threadCount=12
spring.quartz.properties.org.quartz.threadPool.threadPriority=5
spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000
To configure your own JobFactory write a SchedulerFactoryBeanCustomizer to configure it on the SchedulerFactoryBean.
#Component
class MySchedulerFactoryBeanCustomizer implements SchedulerFactoryBeanCustomizer {
void customize(SchedulerFactoryBean schedulerFactoryBean) {
schedulerFactoryBean.setJobFactory(new MyQuartzJobFactory());
}
}
Now ditch the quartz.properties, MyLifecycleListener and the SchedulerManager and let Spring handle all that for you.
I want to get a file from a SFTP server, transform the JSON content into an array of instances of one of my classes.
Therfore I have thought to use Spring Integration within a Spring Boot application and would be happy to have one of the IntegrationFlows fluently programmed to achieve that.
I dived into many articles, questions and answers here in SO so far, but nothing really helped. I am struggling with it since weeks. The Spring Integration documentation is itself hard to understand. It comes with a whole lot of different aspects depending of Spring versions and different programming paradigmas (XML, Java Configuration, and Java DSL), which brings more complexity into the matter, makes it even harder to decide, which of the rare examples to follow, and is eventually no help for a newbee. A newbee wants to find his problem and wants being recommended and guided to the currently best way to solve his problem, being explained the whys and odds and evens. If he is happy enough, he will be able to find his problem in one of the examples (getting a file from SFTP to further process it, is not an exotic task) and the solution is quite in an example, he can copy&paste with minimal adaptations. I was not so lucky until now.
One question here in SO was near to what I probably need: there was an sftpInboundFileSynchonizer configured, together with a MessageSource and a MassageHandler. The asking person wanted to do roughly the same as I. The answer was "That code is doing the reverse (sending to SFTP)." which left me flabbergasted and thinking, did I mixed up basically the understanding of inbound and outbound?
I think I have to use an InboundAdapter based on a SftpSessionFactory. I put the SessionFactory into an extra configuration because I plan to use it with other adapters as well:
#Configuration
#ConfigurationProperties("test.job.common")
public class JobCommonConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(JobCommonConfiguration.class);
private String hostname;
private int port;
private String username;
private String password;
#Bean
public SessionFactory<LsEntry> sftpTest3SessionFactory() {
DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();
sf.setHost(hostname);
sf.setPort(port);
sf.setUser(username);
sf.setPassword(password);
// factory.setTestSession(true);
return new CachingSessionFactory<LsEntry>(sf);
}
/* getters & setters */
}
The second configuration is to configure an SftpInboundAdapter, assuming my understanding of "inbound" is correct, which comes with a SI Transformer to convert JSON into an array of my Event instances. In the end the instances should be send by request to an HTTP REST service, which I could as well include into the adapter? It is as follows:
#Configuration
#ConfigurationProperties("test.job.transfer3")
#Import({ JobCommonConfiguration.class })
public class Job3Configuration {
private static final Logger LOG = LoggerFactory.getLogger(Job3Configuration.class);
private boolean enabled = false;
private String remoteDir;
private String remoteFile;
private String remoteFilePattern;
private boolean remoteRemove;
private String localDir;
private String localFile;
#Autowired
private SessionFactory<LsEntry> sftpTest3SessionFactory;
#Bean
public FireOnceTrigger fireOnceTest3Trigger() {
return new FireOnceTrigger();
}
#Bean
public IntegrationFlow test3SftpInboundFlow() {
return IntegrationFlows
.from(Sftp.inboundAdapter(sftpTest3SessionFactory)
.preserveTimestamp(true)
.remoteDirectory(remoteDir)
.regexFilter(remoteFilePattern)
.localFilenameExpression(localFile)
.localDirectory(new File(localDir)),
e -> e.id("sftpTest3InboundAdapter")
.autoStartup(true)
.poller(Pollers.trigger(fireOnceTest3Trigger()))
)
.transform(Transformers.fromJson(Event[].class))
.handle(m -> System.out.println(m.getPayload()))
.get();
}
/* getters & setters */
}
My entity Event is quite simple:
public class Event {
private Integer crmId;
private String eventType;
private LocalDateTime dateFrom;
private LocalDateTime dateTo;
/* getters & setter & toString() */
}
My Test is not testing anything yet, because nothing happened so far. It then should assert that I received the correct number of Events. It looks as following:
#RunWith(SpringRunner.class)
#SpringBootTest
#ContextConfiguration(classes=SftpTransferTestApplication.class)
#Import(Job3Configuration.class)
public class GetFileIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(GetFileIntegrationTest.class);
#Test
public void testGetFile() throws Exception {
LOG.info("GetIntegrationTest testgetFile");
// assertThat(fileReceived, is(sb.toString()));
}
}
The Test application is straight forward:
#SpringBootApplication
#EnableIntegration
#IntegrationComponentScan
public class SftpTransferTestApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SftpTransferTestApplication.class).web(
NONE).run(args);
}
}
My project has as parent spring-boot-starter-parent with version 2.3.0.RELEASE and uses spring-integration-sftp with version 5.3.0.RELEASE.
Please help me to bring this test case alive. What do I wrong?
How can I include the Logger features into the IntegrationFlow to see more of what is (or is not) happening?
EDIT 1
I tried to strip my code a bit to avoid configuration proplems:
#Configuration
public class JobConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(JobConfiguration.class);
#Bean
public TransferChannel getTransferChannel() {
TransferChannel channel = new TransferChannel();
channel.setHost("myHost");
channel.setPort(0);
channel.setUser("test");
channel.setPassword("xxx");
return channel;
}
#Bean
public TransferContext getTransferContext() {
TransferContext context = new TransferContext();
context.setEnabled(false);
context.setChannel(getTransferChannel());
context.setRemoteDir("data");
context.setRemoteFilename("GetMessage3.json");
context.setRemoteFilenameFilter("GetMessage\\.json$");
context.setLocalDir("sftp-inbound");
context.setLocalFile("GetMessage3.json");
return context;
}
#Bean
public SessionFactory<LsEntry> getSftpTestSessionFactory(TransferChannel transferChannel) {
DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();
sf.setHost(transferChannel.getHost());
sf.setPort(transferChannel.getPort());
sf.setUser(transferChannel.getUser());
sf.setPassword(transferChannel.getPassword());
// factory.setTestSession(true);
return new CachingSessionFactory<LsEntry>(sf);
}
#Bean
public FireOnceTrigger fireOnceTestTrigger() {
return new FireOnceTrigger();
}
#Bean
public IntegrationFlow testSftpInboundFlow(TransferContext context) {
return IntegrationFlows
.from(Sftp.inboundAdapter(getSftpTestSessionFactory(context.getChannel()))
.preserveTimestamp(true)
.remoteDirectory(context.getRemoteDir())
.regexFilter(context.getRemoteFilenameFilter())
.localFilenameExpression(context.getLocalFile())
.localDirectory(new File(context.getLocalDir())),
e -> e.id("sftpTestInboundAdapter")
.autoStartup(true)
.poller(Pollers.trigger(fireOnceTestTrigger()))
// .poller(Pollers.fixedDelay(5000))
)
.transform(Transformers.fromJson(Event[].class))
.channel("sftpTestMessageChannel")
// .logAndReply(Level.DEBUG);
// .handle(m -> System.out.println("myHandler: " + m.getPayload().toString()))
.get();
}
#Bean("someService.handler")
#EndpointId("someService")
#ServiceActivator(inputChannel = "sftpTestMessageChannel")
public MessageHandler someHandler() {
return new MessageHandler() {
#Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println("myThirdHandler: " + message.getPayload());
System.out.println("myThirdHandler: " + message.getHeaders());
Event ev = ((Event[]) message.getPayload())[1];
System.out.println("myThirdHandler: " + ev);
throw new IllegalStateException("Want to see the next MessageHandler");
}
};
}
}
To let the ftp implementation Jsch speak a bit more, I have a configuration "application-junit.yaml":
logging:
level:
org.springframework.integration: debug
### filter warning
### org.springframework.integration.expression.ExpressionUtils:
### Creating EvaluationContext with no beanFactory
org.springframework.integration.expression.ExpressionUtils: error
### filter info
### because jsch is very talkative
com.jcraft.jsch: debug
com.harry.potter: debug
com.harry.potter.filetransfer: trace
I can't get it to work. Logging output is:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.0.RELEASE)
2021-08-22 23:29:27.958 INFO 9916 --- [ main] c.l.c.f.service.GetFileIntegrationTest : Starting GetFileIntegrationTest on myClient with PID 9916 (started by test in C:\Users\test\git\tis\sftp-client)
2021-08-22 23:29:27.959 DEBUG 9916 --- [ main] c.l.c.f.service.GetFileIntegrationTest : Running with Spring Boot v2.3.0.RELEASE, Spring v5.2.6.RELEASE
2021-08-22 23:29:27.959 INFO 9916 --- [ main] c.l.c.f.service.GetFileIntegrationTest : No active profile set, falling back to default profiles: default
2021-08-22 23:29:28.752 INFO 9916 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.
2021-08-22 23:29:28.759 INFO 9916 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.
2021-08-22 23:29:28.763 DEBUG 9916 --- [ main] faultConfiguringBeanFactoryPostProcessor : SpEL function '#xpath' isn't registered: there is no spring-integration-xml.jar on the classpath.
2021-08-22 23:29:28.766 INFO 9916 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.
2021-08-22 23:29:28.837 INFO 9916 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationChannelResolver' of type [org.springframework.integration.support.channel.BeanFactoryChannelResolver] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2021-08-22 23:29:28.841 INFO 9916 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationDisposableAutoCreatedBeans' of type [org.springframework.integration.config.annotation.Disposables] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2021-08-22 23:29:28.873 INFO 9916 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.integration.config.IntegrationManagementConfiguration' of type [org.springframework.integration.config.IntegrationManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2021-08-22 23:29:30.298 INFO 9916 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2021-08-22 23:29:30.802 INFO 9916 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler'
2021-08-22 23:29:30.894 DEBUG 9916 --- [ main] faultConfiguringBeanFactoryPostProcessor :
Spring Integration global properties:
spring.integration.endpoints.noAutoStartup=
spring.integration.taskScheduler.poolSize=10
spring.integration.channels.maxUnicastSubscribers=0x7fffffff
spring.integration.channels.autoCreate=true
spring.integration.channels.maxBroadcastSubscribers=0x7fffffff
spring.integration.readOnly.headers=
spring.integration.messagingTemplate.throwExceptionOnLateReply=false
2021-08-22 23:29:30.901 DEBUG 9916 --- [ main] .s.i.c.GlobalChannelInterceptorProcessor : No global channel interceptors.
2021-08-22 23:29:30.904 INFO 9916 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2021-08-22 23:29:30.904 INFO 9916 --- [ main] o.s.i.channel.PublishSubscribeChannel : Channel 'application.errorChannel' has 1 subscriber(s).
2021-08-22 23:29:30.904 INFO 9916 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started bean '_org.springframework.integration.errorLogger'
2021-08-22 23:29:30.905 INFO 9916 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {json-to-object-transformer} as a subscriber to the 'testSftpInboundFlow.channel#0' channel
2021-08-22 23:29:30.905 INFO 9916 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application.testSftpInboundFlow.channel#0' has 1 subscriber(s).
2021-08-22 23:29:30.905 INFO 9916 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started bean 'testSftpInboundFlow.org.springframework.integration.config.ConsumerEndpointFactoryBean#0'; defined in: 'class path resource [com/harry/potter/filetransfer/config/JobConfiguration.class]'; from source: 'bean method testSftpInboundFlow'
2021-08-22 23:29:30.905 INFO 9916 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {message-handler:someService} as a subscriber to the 'sftpTestMessageChannel' channel
2021-08-22 23:29:30.905 INFO 9916 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application.sftpTestMessageChannel' has 1 subscriber(s).
2021-08-22 23:29:30.905 INFO 9916 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started bean 'someService'
2021-08-22 23:29:30.910 INFO 9916 --- [ main] o.s.i.e.SourcePollingChannelAdapter : started bean 'sftpTestInboundAdapter'; defined in: 'class path resource [com/harry/potter/filetransfer/config/JobConfiguration.class]'; from source: 'bean method testSftpInboundFlow'
2021-08-22 23:29:30.922 INFO 9916 --- [ main] c.l.c.f.service.GetFileIntegrationTest : Started GetFileIntegrationTest in 3.323 seconds (JVM running for 4.13)
2021-08-22 23:29:30.935 INFO 9916 --- [ask-scheduler-1] com.jcraft.jsch : Connecting to myHost port 22
2021-08-22 23:29:30.968 INFO 9916 --- [ask-scheduler-1] com.jcraft.jsch : Connection established
2021-08-22 23:29:31.041 INFO 9916 --- [ask-scheduler-1] com.jcraft.jsch : Remote version string: SSH-2.0-OpenSSH_for_Windows_8.1
2021-08-22 23:29:31.042 INFO 9916 --- [ask-scheduler-1] com.jcraft.jsch : Local version string: SSH-2.0-JSCH-0.1.54
2021-08-22 23:29:31.042 INFO 9916 --- [ask-scheduler-1] com.jcraft.jsch : CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
2021-08-22 23:29:31.216 INFO 9916 --- [ main] c.l.c.f.service.GetFileIntegrationTest : GetIntegrationTest testgetFile
2021-08-22 23:29:31.226 INFO 9916 --- [extShutdownHook] o.s.i.e.SourcePollingChannelAdapter : stopped bean 'sftpTestInboundAdapter'; defined in: 'class path resource [com/harry/potter/filetransfer/config/JobConfiguration.class]'; from source: 'bean method testSftpInboundFlow'
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer : Removing {json-to-object-transformer} as a subscriber to the 'testSftpInboundFlow.channel#0' channel
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.integration.channel.DirectChannel : Channel 'application.testSftpInboundFlow.channel#0' has 0 subscriber(s).
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer : stopped bean 'testSftpInboundFlow.org.springframework.integration.config.ConsumerEndpointFactoryBean#0'; defined in: 'class path resource [com/harry/potter/filetransfer/config/JobConfiguration.class]'; from source: 'bean method testSftpInboundFlow'
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.i.channel.PublishSubscribeChannel : Channel 'application.errorChannel' has 0 subscriber(s).
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer : stopped bean '_org.springframework.integration.errorLogger'
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer : Removing {message-handler:someService} as a subscriber to the 'sftpTestMessageChannel' channel
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.integration.channel.DirectChannel : Channel 'application.sftpTestMessageChannel' has 0 subscriber(s).
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.i.endpoint.EventDrivenConsumer : stopped bean 'someService'
2021-08-22 23:29:31.227 INFO 9916 --- [extShutdownHook] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler'
2021-08-22 23:29:31.228 INFO 9916 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
I replaced the FireOnceTestTrigger with Pollers.fixedDelay(5000), nothing.
What do I wrong?
The test is exiting and the JVM shut down before the fetch is completed.
You need to wait for the file to be fetched. One way would be to add a channel interceptor in your test. Something like this:
public class GetFileIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(GetFileIntegrationTest.class);
#Autowired
AbstractMessageChannel sftpTestMessageChannel;
#Test
public void testGetFile() throws Exception {
LOG.info("GetIntegrationTest testgetFile");
CountDownLatch latch = new CountDownLatch(1);
this.sftpTestMessageChannel.addInterceptor(new ChannelInterceptor() {
// override preSend and/or postSend, capture the message and
// count down the latch.
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
// assertThat(fileReceived, is(sb.toString()));
}
}
situation
I have a spring boot application that run a simple REST Service. I want to test this service. Since I love Spock Framework I'd love to use it here but I can't get pass the issue with the Spring Configuration.
problem
The test itself does run but is throwing a java.net.ConnectException: Connection refused: connect exception. The issue here is that the actual application I want to test against is not running - therefore there is not REST interface available. How can I assure that the actual application is running before the test runs? Using JUnit this concern was kinda trivial since Spring has its annotations for that. But what about Spock?
Edit: I tried to use the following article: http://henningpetersen.com/post/18/testing-spring-mvc-controllers-with-spock
RestHandler.java
#RestController
public class RestHandler {
private #Autowired ExecutionService executionService;
public RestHandler(ExecutionService executionService) {
this.executionService = executionService;
}
#RequestMapping(value = "/toolbox/exec", method = POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.TEXT_PLAIN_VALUE)
public String executeTool(#RequestBody Tool tool) {
executionService.execute(tool);
return "thanks";
}
}
ToolExecutor.java
#SpringBootApplication
public class ToolExecutor {
public static void main(String[] args) {
SpringApplication.run(ToolExecutor.class, args);
}
}
RestHandlerTest.groovy
#SpringBootTest
class RestHandlerTest extends Specification {
def someService = Mock(ExecutionService)
def underTest = new RestHandler(someService);
def mockMvc = MockMvcBuilders.standaloneSetup(underTest).build()
#Shared
def client = new RESTClient("http://localhost:603/toolbox/exec")
def "ExecuteToolTest"() {
when: "If POST has valid JSON format"
Closure object = { "{\"name\":\"test\",\"parameters\":[\"abc\",\"def\"]}" }
def response = client.request(Method.POST, object);
then:
with(response){
data.text == "thanks"
status == 200
}
}
}
LOG
15:22:07.601 [main] DEBUG org.springframework.core.env.StandardEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
15:22:07.605 [main] DEBUG org.springframework.core.env.StandardEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
15:22:07.605 [main] DEBUG org.springframework.core.env.StandardEnvironment - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment]
15:22:07.855 [main] DEBUG org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - Looking for request mappings in application context: org.springframework.test.web.servlet.setup.StubWebApplicationContext#17f9d882
15:22:07.897 [main] DEBUG org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - 2 request handler methods found on class com.company.toolbox.components.executor.RestHandler: {public void com.company.toolbox.components.executor.RestHandler.isAlive()={[/toolbox/exec],methods=[GET]}, public java.lang.String com.company.toolbox.components.executor.RestHandler.executeTool(com.company.toolbox.commons.Tool)={[/toolbox/exec],methods=[POST],consumes=[application/json],produces=[text/plain]}}
15:22:07.900 [main] INFO org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - Mapped "{[/toolbox/exec],methods=[GET]}" onto public void com.company.toolbox.components.executor.RestHandler.isAlive()
15:22:07.907 [main] INFO org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - Mapped "{[/toolbox/exec],methods=[POST],consumes=[application/json],produces=[text/plain]}" onto public java.lang.String com.company.toolbox.components.executor.RestHandler.executeTool(com.company.toolbox.commons.Tool)
15:22:08.285 [main] DEBUG org.jboss.logging - Logging Provider: org.jboss.logging.Slf4jLoggerProvider
15:22:08.286 [main] INFO org.hibernate.validator.internal.util.Version - HV000001: Hibernate Validator 5.3.4.Final
15:22:08.307 [main] DEBUG org.hibernate.validator.internal.engine.resolver.DefaultTraversableResolver - Cannot find javax.persistence.Persistence on classpath. Assuming non JPA 2 environment. All properties will per default be traversable.
15:22:08.317 [main] DEBUG org.hibernate.validator.internal.engine.ConfigurationImpl - Setting custom MessageInterpolator of type org.springframework.validation.beanvalidation.LocaleContextMessageInterpolator
15:22:08.318 [main] DEBUG org.hibernate.validator.internal.engine.ConfigurationImpl - Setting custom ParameterNameProvider of type com.sun.proxy.$Proxy26
15:22:08.320 [main] DEBUG org.hibernate.validator.internal.xml.ValidationXmlParser - Trying to load META-INF/validation.xml for XML based Validator configuration.
15:22:08.323 [main] DEBUG org.hibernate.validator.internal.xml.ResourceLoaderHelper - Trying to load META-INF/validation.xml via TCCL
15:22:08.324 [main] DEBUG org.hibernate.validator.internal.xml.ResourceLoaderHelper - Trying to load META-INF/validation.xml via Hibernate Validator's class loader
15:22:08.324 [main] DEBUG org.hibernate.validator.internal.xml.ValidationXmlParser - No META-INF/validation.xml found. Using annotation based configuration only.
15:22:08.386 [main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for #ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext#17f9d882
15:22:08.422 [main] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Looking for exception mappings: org.springframework.test.web.servlet.setup.StubWebApplicationContext#17f9d882
15:22:08.442 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Initializing servlet ''
15:22:08.452 [main] DEBUG org.springframework.web.context.support.StandardServletEnvironment - Adding [servletConfigInitParams] PropertySource with lowest search precedence
15:22:08.452 [main] DEBUG org.springframework.web.context.support.StandardServletEnvironment - Adding [servletContextInitParams] PropertySource with lowest search precedence
15:22:08.455 [main] DEBUG org.springframework.web.context.support.StandardServletEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
15:22:08.455 [main] DEBUG org.springframework.web.context.support.StandardServletEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
15:22:08.455 [main] DEBUG org.springframework.web.context.support.StandardServletEnvironment - Initialized StandardServletEnvironment with PropertySources [servletConfigInitParams,servletContextInitParams,systemProperties,systemEnvironment]
15:22:08.455 [main] INFO org.springframework.mock.web.MockServletContext - Initializing Spring FrameworkServlet ''
15:22:08.455 [main] INFO org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization started
15:22:08.457 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided
15:22:08.458 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using LocaleResolver [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver#267f474e]
15:22:08.458 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using ThemeResolver [org.springframework.web.servlet.theme.FixedThemeResolver#7a7471ce]
15:22:08.458 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using RequestToViewNameTranslator [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator#28276e50]
15:22:08.458 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using FlashMapManager [org.springframework.web.servlet.support.SessionFlashMapManager#62e70ea3]
15:22:08.458 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Published WebApplicationContext of servlet '' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.]
15:22:08.458 [main] INFO org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization completed in 3 ms
15:22:08.458 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Servlet '' configured successfully
15:22:08.476 [main] DEBUG groovyx.net.http.RESTClient - POST http://localhost:603/toolbox/exec
15:22:08.728 [main] DEBUG org.apache.http.impl.conn.BasicClientConnectionManager - Get connection for route {}->http://localhost:603
15:22:08.742 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnectionOperator - Connecting to localhost:603
15:22:09.744 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnectionOperator - Connect to localhost:603 timed out. Connection will be retried using another IP address
15:22:09.745 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnectionOperator - Connecting to localhost:603
15:22:10.745 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnection - Connection org.apache.http.impl.conn.DefaultClientConnection#21362712 closed
15:22:10.745 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnection - Connection org.apache.http.impl.conn.DefaultClientConnection#21362712 shut down
15:22:10.746 [main] DEBUG org.apache.http.impl.conn.BasicClientConnectionManager - Releasing connection org.apache.http.impl.conn.ManagedClientConnectionImpl#27eb3298
EXCEPTION
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:120)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:179)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:328)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:612)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:447)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:884)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:476)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:441)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:373)
at com.xetra11.toolbox.components.executor.RestHandlerTest.ExecuteToolTest(RestHandlerTest.groovy:26)
Process finished with exit code -1
This is what you need
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RestHandlerTest extends Specification {
#Autowired
TestRestTemplate testRestTemplate
And then you use testRestTemplate instead of client. You also need to add spock-spring dependency.
New to Apache camel, I have a requirement that I need to look for a folder and move the files from source to destination every five minutes. I wrote the below code, but when I run the Job it is copying the files to destination irrespective of time when I copy the files to source, Please help me in understanding this :
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.routepolicy.quartz.CronScheduledRoutePolicy;
public class App1 {
public static void main(final String[] arguments) {
final CamelContext camelContext = new DefaultCamelContext();
try {
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
CronScheduledRoutePolicy startPolicy = new CronScheduledRoutePolicy();
startPolicy.setRouteStartTime("0 0/5 * 1/1 * ? *");
from("file:E:\\TestingWatch1\\input")
.routeId("testRoute").routePolicy(startPolicy)
.to("file:E:\\TestingWatch1\\output");
}
});
camelContext.start();
Thread.sleep(10000);
//camelContext.stop();
} catch (Exception camelException) {
}
}
}
In order to schedule a route I have been using the CAMEL QUARTZ component. I believe Claus has been alluding to this option as well:
from("quartz://scheduler_name?cron={{cron.schedule}}")
.routeId("cron-scheduler")
cron.schedule value is set in params as:
00+00+*/2+1/1+*+?+*
I.e to run every two hours.
So to run every 5 minutes that would be something like:
00+*/5+*+1/1+*+?+*
As Claus Ibsen said, you can use cron directly:
public class CopyTest {
public static void main(final String[] arguments) {
final CamelContext camelContext = new DefaultCamelContext();
try {
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("file://c:/test/input?scheduler=quartz2&scheduler.cron=00+*/5+*+1/1+*+?+*")
.routeId("testRoute")
.log(LoggingLevel.INFO, "File name : ${header.CamelFileName}")
.to("file://c:/test/output");
}
});
camelContext.start();
Thread.sleep(10*60*1000);
//camelContext.stop();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
More info can be found here:
http://www.davsclaus.com/2013/08/apache-camel-212-even-easier-cron.html
or here:
http://camel.apache.org/file2.html URI options->Consumer->scheduler
or here:
http://camel.apache.org/quartz2.html Using QuartzScheduledPollConsumerScheduler
Here is my log:
2016-12-23 21:52:24,440 [main ] INFO DefaultCamelContext - Apache Camel 2.15.2 (CamelContext: camel-1) is starting
2016-12-23 21:52:24,440 [main ] INFO ManagedManagementStrategy - JMX is enabled
2016-12-23 21:52:25,329 [main ] INFO DefaultTypeConverter - Loaded 200 type converters
2016-12-23 21:52:25,985 [main ] INFO DefaultCamelContext - AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn this option off as it may improve performance.
2016-12-23 21:52:25,985 [main ] INFO DefaultCamelContext - StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
2016-12-23 21:52:26,187 [main ] INFO QuartzComponent - Create and initializing scheduler.
2016-12-23 21:52:26,187 [main ] INFO QuartzComponent - Setting org.quartz.scheduler.jmx.export=true to ensure QuartzScheduler(s) will be enlisted in JMX.
2016-12-23 21:52:26,312 [main ] INFO StdSchedulerFactory - Using default implementation for ThreadExecutor
2016-12-23 21:52:26,312 [main ] INFO SimpleThreadPool - Job execution threads will use class loader of thread: main
2016-12-23 21:52:26,359 [main ] INFO SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2016-12-23 21:52:26,359 [main ] INFO QuartzScheduler - Quartz Scheduler v.2.2.1 created.
2016-12-23 21:52:26,390 [main ] INFO RAMJobStore - RAMJobStore initialized.
2016-12-23 21:52:26,421 [main ] INFO QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.1) 'DefaultQuartzScheduler-camel-1' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
2016-12-23 21:52:26,421 [main ] INFO StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler-camel-1' initialized from an externally provided properties instance.
2016-12-23 21:52:26,421 [main ] INFO StdSchedulerFactory - Quartz scheduler version: 2.2.1
2016-12-23 21:52:26,999 [main ] INFO DefaultCamelContext - Route: testRoute started and consuming from: Endpoint[file://c:/test/input?scheduler=quartz2&scheduler.cron=00+*%2F5+*+1%2F1+*+%3F+*]
2016-12-23 21:52:26,999 [main ] INFO QuartzComponent - Starting scheduler.
2016-12-23 21:52:26,999 [main ] INFO QuartzScheduler - Scheduler DefaultQuartzScheduler-camel-1_$_NON_CLUSTERED started.
2016-12-23 21:52:26,999 [main ] INFO DefaultCamelContext - Total 1 routes, of which 1 is started.
2016-12-23 21:52:26,999 [main ] INFO DefaultCamelContext - Apache Camel 2.15.2 (CamelContext: camel-1) started in 2.574 seconds
2016-12-23 21:55:00,052 [amel-1_Worker-1] INFO testRoute - File name : client.log
You'll need the dependency:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-quartz2</artifactId>
<version>${camel.version}</version>
</dependency>
I set following properties in my quartz.properties file:
org.quartz.threadPool.threadCount = 60
org.quartz.scheduler.batchTriggerAcquisitionMaxCount = 60
, however, for some reason, apparently it doesn't take effect. because when I start my application, the log shows that it still uses 1 thread in the pool:
[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.1.1 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.1.1) 'QuartzScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0
Using **thread pool 'org.quartz.simpl.SimpleThreadPool' - with 1 threads.**
I know, the quartz.properties needs to be at class path to be found. and I just did it.
any other reason why this file is not detected? or it is detected but number of threads is not set correctly?
Thanks
For those who are using Spring + Quartz and quartz.properties file is not working (i.e. gets ignored while starting the application):
Quartz Scheduler (org.quartz.Scheduler) instantiated by Spring Factory Bean (org.springframework.scheduling.quartz.SchedulerFactoryBean) won't read quartz.properties file from the classpath by default as it's said in Quartz docs - you need to set the reference manually:
[in case of Java config]:
#Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
// ...
}
[in case of XML config]:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="configLocation" value="classpath:quartz.properties" />
// ...
</bean>
oops, I found the problem, actually the code was overriding the properties file config by creating an instance of Properties class in the code. so the answer is this line:
sf = new StdSchedulerFactory("conf/quartz.properties");
If someone still looking for answer, they can use the below snippet
#Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setTriggers(jobOneTrigger());
scheduler.setQuartzProperties(quartzProperties());
scheduler.setJobDetails(jobOneDetail());
return scheduler;
}
#Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}