Non-persistence timer creation on WAS Liberty 17.0.0.3 - java

During migration application to latest Liberty I have some problem with Timer creation. The Timer is created in the #Singleton annotated class in the initialize() method (#PostConstruct). The code is enough easy:
ScheduleExpression schedule = new ScheduleExpression();
setScheduleExpressionTime(schedule);
TimerConfig timerConfig = new TimerConfig();
timerConfig.setPersistent(false);
timerScheduled = timerService.createCalendarTimer(schedule, timerConfig);
When I deploy the application I get the exception with proposal to create datasource for my persistence Timer. I know - a timer is persistence by default and requires datasource and table to keep it's state, but I ask to create non-persistence.
I was trying to remove persistence timers support from server features (I changed Java EE 7 Full Platform features to Java™ EE 7 Web Profile, so no more ejb-3.2). And now I have exception: CNTR4019E: Persistent timers cannot be created or accessed. Persistent EJB timers are not supported by any of the features configured in the server.xml file.
So, It looks like server ignores my requirement to create non-persistence timer and always trying to create persistence. This code worked before with some old WAS (JEE6), but now I couldn't deploy it.
Someone had this problem? May be I do something wrong?
Thank you in advance.

I've tested this out locally and it works OK for me. Here is the full EJB and server.xml configuration that I've used for your comparison.
If this does not work for you, you will need to provide more details on how you are creating/submitting your timer as well as more details on server configuration.
EJB class:
#Singleton
#Startup
public class MyEJB {
#Resource
TimerService timerService;
#PostConstruct
#Timeout
public void doThing() {
System.out.println("starting EJB post-construct");
ScheduleExpression schedule = new ScheduleExpression();
schedule.second(5);
TimerConfig timerConfig = new TimerConfig();
timerConfig.setPersistent(false);
Timer timerScheduled = timerService.createCalendarTimer(schedule, timerConfig);
System.out.println("Is persistent: " + timerScheduled.isPersistent());
}
}
Server configuration:
<server>
<featureManager>
<feature>webProfile-7.0</feature>
</featureManager>
<application location="app1.war"/>
</server>

I found out the reason. It is really my fault. I missed one place with timer creation. The timerService is used twice to create timers. First time in the place which I described above and second time inside an event. And second time it looks like:
timerService.createTimer(NB_OF_MILLISECONDS_UNTIL_FIRST_START, null);
Possible for some old WAS versions this code was creating a non-persistence timer, but for now it should be changed to something like:
TimerConfig timerConfig = new TimerConfig();
timerConfig.setPersistent(false);
timer = timerService.createSingleActionTimer(NB_OF_MILLISECONDS_UNTIL_FIRST_START, timerConfig);
Be careful while creating timers. :-)
Thank you for help.

Related

How to auto configure programmatically?

I have a spring boot kafka application. My brokers are recycled every few days. The old brokers are deprovisioned and new brokers are provisioned.
I have a scheduler which is checking for brokers every few hours. I would like to make sure as soon as the we have new brokers,
we should reload all the Spring Kafka related beans. Very similar to KafkaAutoConfiguration except I want a trigger on broker value change and load the auto configuration programmatically.
How do I call the auto configure programmatically whenever the old brokers are replaced with new one ?
Your requirements sounds like Config Server in Spring Cloud:https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/multi/multi__spring_cloud_config_2.html#_spring_cloud_config_2 with its #RefreshScope feature: https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/multi/multi__spring_cloud_context_application_context_services.html#refresh-scope.
So, you need to specify your own beans and mark them with that annotation:
#Bean
#RefreshScope
public ConsumerFactory<?, ?> kafkaConsumerFactory() {
return new DefaultKafkaConsumerFactory<>(this.properties.buildConsumerProperties());
}
#Bean
#RefreshScope
public ProducerFactory<?, ?> kafkaProducerFactory() {
DefaultKafkaProducerFactory<?, ?> factory = new DefaultKafkaProducerFactory<>(
this.properties.buildProducerProperties());
String transactionIdPrefix = this.properties.getProducer().getTransactionIdPrefix();
if (transactionIdPrefix != null) {
factory.setTransactionIdPrefix(transactionIdPrefix);
}
return factory;
}
These two beans rely on the configuration properties for connection to Apache Kafka broker and that is really fully enough to have them refreshable. Whenever a ContextRefreshedEvent happens these beans are going to be re-initialized with a fresh configuration properties.
I think the ConsumerFactory consumers (MessageListenerContainer and KafkaListenerEndpointRegistry) have to be restarted on that event as well. The point is that MessageListenerContainer starts a long-living process and therefore caches a KafkaConsumer instance for the poll purposes.
All the ProducerFactory consumers don't need to be restarted. Even if KafkaProducer is cached in the DefaultKafkaProducerFactory it is going to be reinitialized during #RefreshScope phase.
UPDATE
I don’t use config server. I get the new hosts from consul catalog service.
Right, I didn't say that you use a Config Server. That just looks for me similar way. So, from big height I would really take a look into a Config Client implementation for your Consul catalog solution.
Nevertheless you still can emit a RefreshEvent which will trigger all your #RefreshScope'd beans to be reloaded. For that purpose you need to implement an ApplicationEventPublisherAware and emit that event whenever you have update from Consul. Remember: Kafka listener containers must be restarted. For that purpose you can listen for the RefreshScopeRefreshedEvent since you really are interested in the restart only when all the #RefreshScope have been refreshed.
More about refresh scope: https://gist.github.com/dsyer/a43fe5f74427b371519af68c5c4904c7

How to InitialContext.lookup instance of EJB by Class<?>

I am trying to create an EJB class using it's class type. My function gets this class type as parameter. This class has it's own dependencies and i want those dependencies to be created as well.
addToUploadQueue(Class<? extends ICallback> callbackClazz)
how can i create an ejb instance of this class?
Edit: i am uploading videos to youtube on a ManagedExecutorService thread.This is a generic module. i want this to run on every project. Http requests call my function, i create another thread and return immediately. When upload finishes i need to inform this callback function to update statusses of those videos on db (or do whatever they want).
Given the extra information that you have provided, it looks a little like you're trying to reinvent the Observer Pattern.
Fortunately, Java EE 6 and newer provides us with a CDI framework that implements this for us.
Adam Bien shows an example at JAVA EE 6 OBSERVER PATTERN / EVENTS WITH CDI (JSR-299/JSR-330) AND EJB 3.1.
you have to get a ejb instance using the lookup method, you can do something like that
addToUploadQueue(Class<? extends ICallback> callbackClazz) {
InitialContext ic = new InitialContext();
MyEjb myEjb = (MyEjb)ic.lookup("java:comp/env/ejb/" + callbackClazz.getName());
}

How to launch a Spring Batch job after startup?

How can I run a job configured using Spring-Batch right after application startup?
Currently I'm specifying an exact time using cron job, but that requires to change the cron every time I restart the application:
#JobRegistry, #Joblauncher and a Job.
I execute the job as follows:
#Scheduled(cron = "${my.cron}")
public void launch() {
launcher.run(job, params);
}
Checking aroud Spring code I have found SmartLifecycle
An extension of the Lifecycle interface for those objects that require
to be started upon ApplicationContext refresh and/or shutdown in a
particular order. The isAutoStartup() return value indicates whether
this object should be started at the time of a context refresh.
Try creating a custom bean implementing SmartLifecycle and setting autoStartup; when this custom bean start method is invoked launch your job.
A few options that I can think of on the places to put your startup logic:
.1. In a bean #PostConstruct annotated method, reference is here - http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-postconstruct-and-predestroy-annotations
.2. By implementing an ApplicationListener, specifically for either ContextStartedEvent or ContextRefreshedEvent. Reference here - http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#context-functionality-events

Sidekiq-like queue using java tools?

I want to have a work queue that behaves almost exactly like ruby's sidekiq(it doesn't need to use Redis, but it can - I just can't use ruby - not even Jruby). Basically I want to be able to create jobs that runs with some parameters and a worker pool executes the jobs. The workers are going to use hibernate to do some work, so I think that Spring integration could make things easier.
Spring Integration has Redis Queue inbound and outbound channel adapters.
The inbound message-driven adapter doesn't currently support concurrency; we worked around that in Spring XD with a composite adapter that wraps a collection of RedisQueueMessageDrivenEndpoint.
Or you could use RabbitMQ; the Spring Integration adapter for it does support concurrency.
EDIT
The bus was extracted to a sub project within that repo.
Spring Framework has ThreadPoolTaskExecutor. You could use it in your class as follows.
#Autowired
ThreadPoolTaskExecutor executor;
ThreadPoolTaskExecutor has properties needed to be set before it is put to use. PostConstruct will be executed after the dependency injections, so we can set the properities of ThreadPoolExecutor there.
#PostConstruct
public void init() {
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
}
Then you can start using executor as follow
executor.execute(new EmailtoCustomerTask("zhw#gmail.com"));
The only requirement needed to become a task is to implement the Runnable interface.
private class EmailtoCustomerTask implements Runnable

looking for persistent timers for a spring application

I'm looking for a lib that allow me to do
define a worker that will be invoked once on a specific time in the future (not need the re-schedule / cron like featrure) i.e. a Timer
The worker should accept a context which withe some parameters / inputs
all should be persistent in the DB (or file) the worker
worker should be managed by spring -- spring should instantiate the worker so it can be injected with dependencies
be able to create timers dynamically via API and not just statically via spring XML beans
nice to have:
support a cluster i.e. have several nodes that can host a worker. each store jobn in the DB will cause invokaction of ONE work on one of the nods
I've examined several alternatives none meets the requirements:
Quartz
when using org.springframework.scheduling.quartz.JobDetailBean makes quartz create your worker instance (and not by spring) so you can't get dependecy ijection, (which will lead me to use Service Locator which I want to avoid)
while using org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean you can't get a context. your Worker expose one public method that accepts no arguments.In addition when using MethodInvokingJobDetailFactoryBean you can't use persistence (form the Javadoc)
Note: JobDetails created via this FactoryBean are not serializable and thus not suitable for persistent job stores. You need to implement your own Quartz Job as a thin wrapper for each case where you want a persistent job to delegate to a specific service method.
Spring's Timer and simple JDK Timers does not support the persistence / cluster feature
I know I can impl thing myself using a DB and Spring (or even JDK) Timers but I prefer to use an a 3r party lib for that.
Any suggestions?
If you want to create the job details to generate triggers/job-details at runtime and still be able to use Spring DI on your beans you can refer to this blog post, it shows how to use SpringBeanJobFactory in conjunction with ObjectFactoryCreatingFactoryBean to create Quartz triggering objects at runtime with Spring injected beans.
For those interested in an alternative to Quartz, have a look at db-scheduler (https://github.com/kagkarlsson/db-scheduler). A persistent task/execution-schedule is kept in a single database table. It is guaranteed to be executed only once by a scheduler in the cluster.
Yes, see code example below.
Currently limited to a single string identifier for no format restriction. The scheduler will likely be extended in the future with better support for job-details/parameters.
The execution-time and context is persistent in the database. Binding a task-name to a worker is done when the Scheduler starts. The worker may be instantiated by Spring as long as it implements the ExecutionHandler interface.
See 3).
Yes, see code example below.
Code example:
private static void springWorkerExample(DataSource dataSource, MySpringWorker mySpringWorker) {
// instantiate and start the scheduler somewhere in your application
final Scheduler scheduler = Scheduler
.create(dataSource)
.threads(2)
.build();
scheduler.start();
// define a task and a handler that named task, MySpringWorker implements the ExecutionHandler interface
final OneTimeTask oneTimeTask = ComposableTask.onetimeTask("my-onetime-task", mySpringWorker);
// schedule a future execution for the task with a custom id (currently the only form for context supported)
scheduler.scheduleForExecution(LocalDateTime.now().plusDays(1), oneTimeTask.instance("1001"));
}
public static class MySpringWorker implements ExecutionHandler {
public MySpringWorker() {
// could be instantiated by Spring
}
#Override
public void execute(TaskInstance taskInstance, ExecutionContext executionContext) {
// called when the execution-time is reached
System.out.println("Executed task with id="+taskInstance.getId());
}
}
Your requirements 3 and 4 do not really make sense to me: how can you have the whole package (worker + work) serialized and have it wake up magically and do its work? Shouldn't something in your running system do this at the proper time? Shouldn't this be the worker in the first place?
My approach would be this: create a Timer that Spring can instantiate and inject dependencies to. This Timer would then load its work / tasks from persistent storage, schedule them for execution and execute them. Your class can be a wrapper around java.util.Timer and not deal with the scheduling stuff at all. You must implement the clustering-related logic yourself, so that only one Timer / Worker gets to execute the work / task.

Categories

Resources