Task has started,but nerver executed ,Anyone know what's problem there?
Now the Problem is every time i run the code it gives me only The output
Here's the final log
2020-11-02 17:03:30.852 DEBUG 9264 --- [nio-8089-exec-7] c.z.t.c.quartz.QuartzScheduleManager : addNewCronJob() called with: jobInfo = [JobInfo(className=class com.zx.tzgl.cronJob.YearPlanJob, identifier=25ddaab4-3e3b-45e9-84a3-77ff7ca4c049, groupName=zx, cornExpr=00 18 17 02 11 ? 2020, params={PLAY_YEAR_SWITCH_PARAMS={"planType":"1","isOpen":"1","enable":"1","annual":"2020至2025","closeTime":1604307810844,"id":"1"}})]
2020-11-02 17:03:30.852 INFO 9264 --- [nio-8089-exec-7] org.quartz.core.QuartzScheduler : Scheduler SchedulerFactory_$_NON_CLUSTERED started.
Here's my using quartz' version
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
Here's the quartz.properties file content
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 100
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
org.quartz.jobStore.misfireThreshold = 5000
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = myQuartzDB
org.quartz.dataSource.myQuartzDB.driver:oracle.jdbc.OracleDriver
#org.quartz.dataSource.myQuartzDB.URL:jdbc:oracle:thin:#//xx.xx.xx.xx:xxxx/cdb1
#org.quartz.dataSource.myQuartzDB.user:xxxx
#org.quartz.dataSource.myQuartzDB.password:xxxx
org.quartz.dataSource.myQuartzDB.URL:jdbc:oracle:thin:#//xx.xx.x.xx:xxxx/szorcl
org.quartz.dataSource.myQuartzDB.user:xxxx
org.quartz.dataSource.myQuartzDB.password:xxxx
org.quartz.dataSource.myQuartzDB.maxConnections:10
org.quartz.jobStore.isClustered=false
Here's Configuartion
#Configuration
public class QuartzConfig {
#Resource
private MyJobFactory myJobFactory;
#Bean(name = "SchedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setQuartzProperties(quartzProperties());
factory.setJobFactory(myJobFactory);
return factory;
}
#Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("config/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
#Bean
public QuartzInitializerListener executorListener() {
return new QuartzInitializerListener();
}
#Bean(name = "quartzScheduler")
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}
}
#Component
public class MyJobFactory extends AdaptableJobFactory {
#Autowired
private AutowireCapableBeanFactory capableBeanFactory;
#Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
Here's the schduler manager
#Component
#Slf4j
public class QuartzScheduleManager implements QuartzScheduleI {
#Resource(name = "quartzScheduler")
private Scheduler scheduler;
#Override #SneakyThrows
public void checkAndAddCornJob(JobInfo jobInfo) {
if (isExistJob(jobInfo)) {
resumeJob(jobInfo);
} else {
addNewCronJob(jobInfo);
}
}
#Override #SneakyThrows
public boolean isExistJob(JobInfo jobInfo) {
return scheduler.checkExists(new JobKey(jobInfo.getIdentifier(), jobInfo.getGroupName()));
}
#Override #SneakyThrows
public boolean isExistJob2(JobInfo jobInfo) {
boolean isExist = false;
JobKey jobKey1 = new JobKey(jobInfo.getIdentifier(), jobInfo.getGroupName());
List<? extends Trigger> triggers1 = scheduler.getTriggersOfJob(jobKey1);
if (triggers1.size() > 0) {
for (Trigger tg : triggers1) {
if ((tg instanceof CronTrigger) || (tg instanceof SimpleTrigger)) {
isExist = true;
}
}
}
return isExist;
}
private void addNewCronJob(JobInfo jobInfo) throws Exception {
scheduler.start();
//build job info
JobDetail jobDetail = JobBuilder.newJob(jobInfo.getClassName()).
withIdentity(jobInfo.getIdentifier(), jobInfo.getGroupName())
.build();
//add params to job
if (ObjectUtil.isNotNull(jobInfo.getParams()) && !jobInfo.getParams().isEmpty()) {
jobInfo.getParams().forEach((key, value) -> jobDetail.getJobDataMap().put(key, value));
}
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getCornExpr());
CronTrigger trigger = TriggerBuilder.newTrigger().
withIdentity(jobInfo.getIdentifier(), jobInfo.getGroupName())
.forJob(jobDetail)
.withSchedule(scheduleBuilder)
.build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new CustomException(ResultCode.PARAM_ERROR.getCode(), e.getMessage());
}
}
Here's the job listener
public class YearPlanJob implements Job {
#Override public void execute(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap;
if (!jobDetail.getJobDataMap().isEmpty()) {
jobDataMap = jobDetail.getJobDataMap();
} else {
jobDataMap = jobExecutionContext.getTrigger().getJobDataMap();
}
}
}
Here's my test code
public String testQuartzTask() {
Date date = DateUtil.parse("2020-11-02 17:18:00", "yyyy-MM-dd HH:mm:ss");
PlanapplyYear planapplyYear = new PlanapplyYear();
planapplyYear.setCloseTime(new Date());
String jsonParams = JSONUtil.toJsonStr(planapplyYear);
JobInfo jobInfo = new JobInfo();
jobInfo.setClassName(YearPlanJob.class);
jobInfo.setIdentifier(UUID.randomUUID().toString());
jobInfo.setGroupName("zx");
jobInfo.setCornExpr(CronDateUtils.getCron(date));
jobInfo.setParams(ImmutableMap.of(PLAN_YEAR_SWITCH, jsonParams));
mQuartzScheduleManager.checkAndAddCornJob(jobInfo);
}
Related
I have next JobSchedulerService:
#Slf4j
#Service
#RequiredArgsConstructor
public class QuartzServiceImpl implements JobSchedulerService {
private final SchedulerFactoryBean schedulerFactoryBean;
#Override
public void scheduleJob(LocalDateTime date, Class jobClass, boolean repeatUntilManuallyStopped, Map<String, Object> jobDataMap) {
String expirationDate = date.toString();
String name = jobClass.getName() + "_";;
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(name + expirationDate)
.storeDurably().build();
if(jobDataMap != null){
jobDetail.getJobDataMap().putAll(jobDataMap);
}
jobDetail.getJobDataMap().put("expirationDate", expirationDate);
ZonedDateTime zonedDateTime = date.atZone(ZoneId.systemDefault());
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name + expirationDate)
.startAt(Date.from(zonedDateTime.toInstant()))
.endAt(Date.from(zonedDateTime.plusMinutes(2).toInstant()))
.withSchedule(repeatUntilManuallyStopped ?
SimpleScheduleBuilder.repeatMinutelyForever().withMisfireHandlingInstructionFireNow() : SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow())
.build();
schedule(jobDetail, trigger, false);
}
#Override
public void scheduleJob(LocalDateTime date, int intervalInMinutes, int count, Class jobClass, Map<String, Object> jobDataMap) {
String expirationDate = date.toString();
String name = jobClass.getName() + "_";
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(name + expirationDate)
.storeDurably().build();
jobDetail.getJobDataMap().putAll(jobDataMap);
jobDetail.getJobDataMap().put("expirationDate", expirationDate);
LocalDateTime currentTime = LocalDateTime.now();
LocalDateTime startDateTime = date;
int decrement = count;
while (decrement != 0) {
startDateTime = startDateTime.minusMinutes(intervalInMinutes);
decrement --;
if(currentTime.compareTo(startDateTime) >= 0) {
startDateTime = currentTime;
break;
}
}
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name + expirationDate)
.startAt(Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()))
.withSchedule(SimpleScheduleBuilder.repeatMinutelyForTotalCount(count - decrement, intervalInMinutes)
.withMisfireHandlingInstructionFireNow())
.build();
schedule(jobDetail, trigger, false);
}
public Date schedule(JobDetail jobDetail, SimpleTrigger trigger, boolean isUnique) {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
try {
boolean alreadyExists = scheduler.checkExists(jobDetail.getKey());
if(isUnique && alreadyExists) {
throw new ApiException(ApiError.RESOURCE_EXISTS);
} else if(!alreadyExists){
Date date = scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
return date;
} else {
return trigger.getStartTime();
}
} catch (ObjectAlreadyExistsException e) {
if(isUnique) {
ExceptionTracker.captureException(e);
log.error("Could not schedule job with key {} and description {}. Job already exists", jobDetail.getKey().getName(), jobDetail.getDescription());
throw new ApiException(ApiError.INTERNAL_SERVER_ERROR);
} else {
return trigger.getStartTime();
}
} catch (Exception e){
ExceptionTracker.captureException(e);
log.error("Could not schedule job with key {} and description {}. Localized message => {}", jobDetail.getKey().getName(), jobDetail.getDescription(), e.getLocalizedMessage());
throw new ApiException(ApiError.INTERNAL_SERVER_ERROR);
}
}
}
Here I am setting time for expiration after 2 minutes
.endAt(Date.from(zonedDateTime.plusMinutes(2).toInstant()))
And I shutdown the application right after it creates job and trigger. But when I startup again it runs expired trigger, even if the time has passed in table qrtz_triggers.end_time.
My properties file for Quartz:
org.quartz.scheduler.instanceName=PostcreditService
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.tablePrefix=postcredit.qrtz_
org.quartz.jobStore.isClustered=true
org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown=TRUE
Configs:
#Configuration
public class QuartzConfig {
#Autowired
private ApplicationContext applicationContext;
#Autowired
private DataSource dataSource;
#Bean
public JobFactory jobFactory() {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setQuartzProperties(quartzProperties());
schedulerFactory.setWaitForJobsToCompleteOnShutdown(true);
schedulerFactory.setAutoStartup(true);
schedulerFactory.setJobFactory(jobFactory());
schedulerFactory.setDataSource(dataSource);
return schedulerFactory;
}
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
}
Please, help!
You are setting trigger's expire time correctly using TriggerBuilder.endAt()
And I shutdown the application right after it creates job and trigger.
But when I startup again it runs expired trigger, even if the time has
passed in table qrtz_triggers.end_time.
This happens because on restart quartz checks for misfired triggers and try to rerun those based on the configured mirefire instruction which in your case is withMisfireHandlingInstructionFireNow. Now the thing is that this particluar instruction does not consider the trigger's endAt() time and always set a new nextFireTime and rerun it.
For your case, there are other misfire instructions that you may want to consider like withMisfireHandlingInstructionNowWithExistingCount
quick question
So in the FTP inbound channel adapter how to log for example every 10 minutes to the remote FTP, is the poller fixed rate what does this? the poller is for polling but it keeps logged into the remote server?
I have this:
#Bean
#InboundChannelAdapter(value = "stream", poller = #Poller(fixedRate = "1000"))
public MessageSource<InputStream> ftpMessageSource() {
FtpStreamingMessageSource messageSource = new FtpStreamingMessageSource(template(), null);
messageSource.setRemoteDirectory(remotedirectory);
messageSource.setFilter(filter());
return messageSource;
}
or the poller METADATA trigger:
#Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata defaultPoller() {
PollerMetadata pollerMetadata = new PollerMetadata();
pollerMetadata.setTrigger(new PeriodicTrigger(5000));
return pollerMetadata;
}
or how to log every 10 minutes and then poll all new files, setting a Thread.sleep() ?
_______EDIT___
public static void main(String[] args) {
SpringApplication.run(FtpinboundApp.class, args);
}
#Bean
public SessionFactory<FTPFile> ftpSessionFactory() {
DefaultFtpSessionFactory sf = new DefaultFtpSessionFactory();
sf.setHost(remotehost);
sf.setPort(remoteport);
sf.setUsername(remoteuser);
sf.setPassword(remotepassword);
return new CachingSessionFactory<FTPFile>(sf);
}
#Bean
#ServiceActivator(inputChannel = "data", adviceChain = "after")
public MessageHandler handler() {
return new MessageHandler() {
#Override
public void handleMessage(Message<?> message) throws MessagingException {
try {
httpposthgfiles.getHGFilesfromRestful(message.getPayload().toString());
httppost990.get990fromRestful(message.getPayload().toString());
} catch (IOException e) {
logger.error(e);
} catch (Exception e) {
logger.error(e);
}
}
};
}
#Bean
public ExpressionEvaluatingRequestHandlerAdvice after() {
ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
advice.setOnSuccessExpression("#template.remove(headers['file_remoteDirectory'] + headers['file_remoteFile'])");
advice.setPropagateEvaluationFailures(true);
return advice;
}
#Bean
#InboundChannelAdapter(value = "stream", poller = #Poller(fixedRate = "1000"))
public MessageSource<InputStream> ftpMessageSource() {
FtpStreamingMessageSource messageSource = new FtpStreamingMessageSource(template(), null);
messageSource.setRemoteDirectory(remotedirectory);
messageSource.setFilter(filter());
return messageSource;
}
public FileListFilter<FTPFile> filter() {
CompositeFileListFilter<FTPFile> filter = new CompositeFileListFilter<>();
filter.addFilter(new FtpSimplePatternFileListFilter("xxxx_aaa204*"));
filter.addFilter(acceptOnceFilter());
return filter;
}
#Bean
public FtpPersistentAcceptOnceFileListFilter acceptOnceFilter() {
FtpPersistentAcceptOnceFileListFilter filter = new FtpPersistentAcceptOnceFileListFilter(meta(), "xxxx_aaa204");
filter.setFlushOnUpdate(true);
return filter;
}
#Bean
public ConcurrentMetadataStore meta() {
PropertiesPersistingMetadataStore meta = new PropertiesPersistingMetadataStore();
meta.setBaseDirectory("/tmp/foo");
meta.setFileName("ftpStream.properties");
return meta;
}
#Bean
#Transformer(inputChannel = "stream", outputChannel = "data")
public org.springframework.integration.transformer.Transformer transformer() {
return new StreamTransformer("UTF-8");
}
#Bean
public FtpRemoteFileTemplate template() {
return new FtpRemoteFileTemplate(ftpSessionFactory());
}
#Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata defaultPoller() {
PollerMetadata pollerMetadata = new PollerMetadata();
pollerMetadata.setTrigger(new PeriodicTrigger(5000));
return pollerMetadata;
}
It will only stay logged in if you use a CachingSessionFactory.
It's better not to sleep and tie up a thread like that, but use the task scheduler (which is what the poller does).
new PeriodicTrigger(600_000) will schedule a task to log in and check for files once every 10 minutes.
I can't get my #Autowired/#Value populated in Spring, I have the following code:
#Configuration
#SpringBootApplication
#ComponentScan({"com.ftpoutbound990"})
#IntegrationComponentScan
public class Ftpoutbound990Application {
public static MyGateway classGateway;
#Autowired
private static MonitorDirectory monitor;
public static void main(String[] args) throws IOException, InterruptedException {
// SpringApplication.run(Ftpoutbound990Application.class, args);
ConfigurableApplicationContext context = new SpringApplicationBuilder(Ftpoutbound990Application.class)
.web(false).run(args);
MyGateway gateway = context.getBean(MyGateway.class);
classGateway = gateway;
monitor.startMonitoring();
}
#Bean
public SessionFactory<FTPFile> ftpSessionFactory() {
DefaultFtpSessionFactory sf = new DefaultFtpSessionFactory();
sf.setHost("X.X.X.X");
sf.setPort(21);
sf.setUsername("x");
sf.setPassword("X");
return new CachingSessionFactory<FTPFile>(sf);
}
#Bean
#ServiceActivator(inputChannel = "ftpChannel")
public MessageHandler handler() {
FtpMessageHandler handler = new FtpMessageHandler(ftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression("/X/x/"));
handler.setFileNameGenerator(new FileNameGenerator() {
#Override
public String generateFileName(Message<?> message) {
String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
String time = new SimpleDateFormat("HHmmssss").format(new Date());
return "XXX." + date + time;
}
});
return handler;
}
#MessagingGateway
public interface MyGateway {
#Gateway(requestChannel = "ftpChannel")
void sendToFtp(File file);
}
}
And this is the monitor:
#Component
public class MonitorDirectory {
//#Autowired
//Ftpoutbound990Application ftpoutbound99application;
public void startMonitoring() throws IOException, InterruptedException {
Path faxFolder = Paths.get("/X/x/x/");
WatchService watchService = FileSystems.getDefault().newWatchService();
faxFolder.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
boolean valid = true;
do {
WatchKey watchKey = watchService.take();
for (WatchEvent event : watchKey.pollEvents()) {
WatchEvent.Kind kind = event.kind();
if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
String fileName = event.context().toString();
System.out.println("File Created:" + fileName);
//ftpoutbound99application.classGateway.sendToFtp(getFile(fileName));
}
}
valid = watchKey.reset();
Thread.sleep(1000 * 10);
} while (valid);
}
public File getFile(String fileName) throws IOException {
File file = new File("/X/x/x" + fileName);
return file;
}
}
The monitor Injection is NULL and if I try to get #Values from properties they are NULL as well, what am I missing?
Thanks in advance
I would like understand how to a job, start new job after of finished with quartz in java.
My Jobs Bean:
#Bean
public JobDetailFactoryBean jobDownload() {
JobDetailFactoryBean j = new JobDetailFactoryBean();
j.setJobClass(DownloadJob.class);
j.setName("jobDownload");
j.setGroup("group1");
return j;
}
#Bean
public JobDetailFactoryBean jobRegex() {
JobDetailFactoryBean j = new JobDetailFactoryBean();
j.setJobClass(RegexJob.class);
j.setName("jobRegex");
j.setGroup("group1");
return j;
}
My Trigger Bean:
#Bean
public CronTriggerFactoryBean triggerDownload() {
CronTriggerFactoryBean cron = new CronTriggerFactoryBean();
cron.setName("triggerDownload");
cron.setGroup("group1");
cron.setCronExpression("0 15 17 * * ?");
cron.setJobDetail(jobConfiguration.jobDownload().getObject());
return cron;
}
My Scheduler:
#Bean
public SchedulerFactoryBean sched() {
SchedulerFactoryBean sched = new SchedulerFactoryBean();
try {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
sched.setJobFactory(jobFactory);
// Agendando execução das triggers
sched.setTriggers(triggerConfiguration.triggerDownload()
.getObject());
sched.start();
} catch (Exception e) {
e.printStackTrace();
}
return sched;
}
My Job Executer:
#Service
#Transactional
public class DownloadJob implements Job {
#Autowired
private RegexService service;
#Override
public void execute(JobExecutionContext j) throws JobExecutionException {
try {
DownloadService t = new DownloadService();
File file = t
.fazerDownload(
"nameFile",
"urlName");
service.aplicaTreeRegex(3L, file, 789L);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I would like jobDownload to start jobRegex after finish. How to do that?
Camel http component does not close connections properly?
Having below route I have observed that connections are being created on the server, but not terminated.
After a while this is causing a problem
java.io.IOException: Too many open files
route:
from("seda:testSeda?concurrentConsumers=20")
.setHeader("Connection", constant("Close"))
.to("http://testServer/testFile.xml?authMethod=Basic&throwExceptionOnFailure=false&authUsername=user&authPassword=password")
.to("file://abc")
.end();
connections are in Close_Wait state any ideas?
I am using camel-http lib in version 2.14
You can override default HttpClient used by Apache Camel and define a custom Keep Alive Strategy.
https://howtodoinjava.com/spring-boot2/resttemplate/resttemplate-httpclient-java-config/
The code bellow resolved my issue in production:
#Configuration
public class AppConfiguration {
#Autowired
private PoolingHttpClientConnectionManager poolingConnectionManager;
#Autowired
private ConnectionKeepAliveStrategy connectionKeepAliveStrategy;
#Autowired
private SSLConnectionSocketFactory sslContext;
#Bean
CamelContextConfiguration contextConfiguration() {
return new CamelContextConfiguration() {
#Override
public void beforeApplicationStart(CamelContext context) {
HttpComponent httpComponent = context.getComponent("https4", HttpComponent.class);
httpComponent.setHttpClientConfigurer(new HttpClientConfigurer() {
#Override
public void configureHttpClient(HttpClientBuilder builder) {
builder.setSSLSocketFactory(sslContext);
RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslContext).build();
builder.setConnectionManager(poolingConnectionManager);
builder.setKeepAliveStrategy(connectionKeepAliveStrategy);
}
});
}
#Override
public void afterApplicationStart(CamelContext arg0) {
}
};
}
}
#Configuration
public class HttpClientConfig {
private static final int DEFAULT_KEEP_ALIVE_TIME_MILLIS = 20 * 1000;
private static final int CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS = 30;
#Value("${pathCertificado}")
private String pathCertificado;
private Logger logger = LoggerFactory.getLogger(HttpClientConfig.class);
#Bean
public PoolingHttpClientConnectionManager poolingConnectionManager() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(200);
connectionManager.setDefaultMaxPerRoute(20);
return connectionManager;
}
#Bean
public CloseableHttpClient httpClient() {
RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(5000).setConnectTimeout(5000)
.setSocketTimeout(15000).build();
return HttpClientBuilder.create().setSSLSocketFactory(this.getSSLContext())
.setConnectionManager(this.poolingConnectionManager()).setDefaultRequestConfig(config)
.setKeepAliveStrategy(this.connectionKeepAliveStrategy()).build();
}
#Bean
public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
return new ConnectionKeepAliveStrategy() {
#Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
HeaderElementIterator it = new BasicHeaderElementIterator(
response.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
HeaderElement he = it.nextElement();
String param = he.getName();
String value = he.getValue();
if (value != null && param.equalsIgnoreCase("timeout")) {
return Long.parseLong(value) * 1000;
}
}
return DEFAULT_KEEP_ALIVE_TIME_MILLIS;
}
};
}
#Bean
public Runnable idleConnectionMonitor(final PoolingHttpClientConnectionManager connectionManager) {
return new Runnable() {
#Override
#Scheduled(fixedDelay = 10000)
public void run() {
if (connectionManager != null) {
connectionManager.closeExpiredConnections();
connectionManager.closeIdleConnections(CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS, TimeUnit.SECONDS);
}
}
};
}
#Bean
public SSLConnectionSocketFactory getSSLContext() {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (FileInputStream jksFile = new FileInputStream(this.pathCertificado)) {
keyStore.load(jksFile, "xxxxxx".toCharArray());
}
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(keyStore, acceptingTrustStrategy).build();
return new SSLConnectionSocketFactory(sslContext);
} catch (Exception e) {
logger.error("Keystore load failed: " + this.pathCertificado, e);
return null;
}
}
}