karaf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Miroslav Beranič <miroslav.bera...@mibesis.si>
Subject Scheduler Service to support/expose native Quartz
Date Tue, 11 Sep 2018 07:09:49 GMT
Hi guys,

I am porting multiple existing production backend/middlware systems from
Tomcat/JBoss to Karaf.

At first I had issues with JPA+Hibernate, seems to be work now. Now I have
task to migrate existing Quartz 1.8.x code to 2.2.x. At first look I
thought all is done in Karaf, also Quartz was a dependency - and example
looked really simple.

Here I do not know what is a common guideline in Karaf : Is it good to
support "native" API or is more in favor to implement "common" API. My
decision was, to move to support native Quartz API , as it is really "well
done" and has all and more any one should need.

So here I will explain why I've decided to update Scheduler service and how
( in general ) I did it. I am working on last few changes, before I push to
forked github repository.
Repository & branch is already online and anyone can check it out, but it
is not final - I have few more errors needed to be fixed. Repository&branch
location is:

https://github.com/mibesis/karaf/tree/karaf-4.2.2-scheduler-quartz-api

What I've changed:

1.) in existing scheduler/pom.xml I've changed so no Quartz package is
private package - stored inside a Scheduler bundle, but all Quartz
dependencies are pulled from existing ServiceMix Quartz bundle:

mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.quartz/2.2.4-SNAPSHOT

2.) I extracted interfaces for QuartzScheduler ( Karaf's Scheduler Quartz
wrapper ) so it can be exposed, also for other exposed classes.

3.) Exporting all the packages inside Scheduler bundle. This is not
something I am really happy about, but when I was trying to go around this,
I had more problems than benefits.

4.) Made all data passed to "datamap" as Serializable, as Quartz as RAM
Storage most of the time only for fun, I guess most of the real usage is
using some kind of persistence - SQL DB - as this is also my case, I had to
support this.

5.) I bypass almost all existing "wrapping" code as this introduced
complexity at only additional cost -- when I talk about support for "native
Quartz API".

So now I can write Quartz producer as :

@Component
public class KarafSchedulerQuartzJobProducer {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference
    private Scheduler scheduler;

    @Activate
    public void start() {
        JobDataMap data = new JobDataMap();
        data.put("message", "Hello Karaf user from Quartz Job.");
        final QuartzScheduler quartzScheduler =
(QuartzScheduler)this.scheduler;
        JobDetail job =
JobBuilder.newJob(KarafSchedulerComplexJobService.class)
                .withIdentity("KarafSchedulerComplexJobService",
"NativeQuartz")
                .usingJobData(data)
                .build();

        Date runTime = DateBuilder.evenMinuteDate(new Date());

        // Trigger the job to run on the next round minute
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("KarafSchedulerComplexJobServiceTrigger",
"NativeQuartz")
                .startAt(runTime)
                .withSchedule(sb.withIntervalInMilliseconds(period * 1000))
                .build();

        try {
            quartzScheduler.scheduleJob(job, trigger);
        } catch (Exception e) {
            log.warn(e.getLocalizedMessage(), e);
        }
    }
}

and Quartz job as any already existing Quartz job -- without any change to
existing code:

import org.quartz.Job;
public class KarafSchedulerComplexJobService implements Job {

    private final Logger log = LoggerFactory.getLogger(getClass());

    public KarafSchedulerComplexJobService() {
        super();
    }

    @Override
    public void execute(final JobExecutionContext context) {
        final JobDataMap jobDataMap =
context.getJobDetail().getJobDataMap();

        message = jobDataMap.getString("message");
        log.info(message);

    }

}

So to me this is great solution , as I can now quite easy migrate existing
source. What I am asking now is: how good solution would this be for Karaf
- as this makes Scheduler service "bound" to Quartz API, but this is only
if you need it -- all existing API is still working and was not changes -
API not, but in the section where data is passed to Quartz any
non-serializable data was moved to temporary storage and than before
calling Runnable task re-attached back again, so producer and consumer do
not really know for any change.


But all is not all that good, at it might seem. To me this perfect
solution, but I know it can be made better - more robust/general.

What are the problems:

1.) Quartz is loading classes - so it needs to know where they are. I
needed quite some time, knocks at the wall and coffee cups to figure this
out. ( I am not OSGi expert ). So my solution was, to agree on a common
package, where all Quartz Jobs must be. To me this is issue, but issue I
can handle - for now.

Package I've decided for is: org.apache.karaf.scheduler.quartz.job

a.) To make this work, I have to update ServiceMix Quartz bundle:
mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.quartz/2.2.4-SNAPSHOT
was updated to import package org.apache.karaf.scheduler.quartz.job

b.) Karaf Scheduler Core imports package
org.apache.karaf.scheduler.quartz.job

c.) Quartz producer exports org.apache.karaf.scheduler.quartz.job - but I
also scan for sub-packages, so I guess jobs should be in sub-packages, to
avoid conflicts.

This is one part of my changes, I would really like better one, but for
what I need, this is ok -- and after all the headaches I am quite happy
with this.

Example code is located at:
https://github.com/mibesis/karaf/tree/karaf-4.2.2-scheduler-quartz-api/examples/karaf-scheduler-example/karaf-scheduler-example-quartz

but ( again ) this is not yet final commit, as I have few more errors to
fix, but I think not a show stoppers ( I hope ).

So my final thoughts/questions:

1.) Is such a change welcome at Karaf - is this something that would
benefit Karaf?

2.) Is there any other existing solution, I should know of?

3.) How can I implement "dynamic" package - so that Quartz job can be in
any package, but just pre-defined ones.

Kind regards,
Miroslav


-- 
Miroslav Beranič
MIBESIS
+386(0)40/814-843
miroslav.beranic@mibesis.si
http://www.mibesis.si

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message