Hi,

I don't think this approach is the good one.

Quartz is an implementation of the Karaf Scheduler, but we can imagine
other implementations.

That's why the Quartz packages are not directly exported by the Karaf
Scheduler (it's private package). That's really my main concern: Karaf
scheduler should not export or be tight to Quartz.

If you want to create your own scheduler, than you can directly use the
Quartz bundle, like camel-quartz for instance.
Is it not what you need ?

On the other hand, I think we can improve/extend the Karaf scheduler
API. I already changed it in Karaf 4.2.x but I think we can move forward
on this.

Regards
JB

On 11/09/2018 09:09, Miroslav Beranič wrote:
> 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
> 
> 

-- 
Jean-Baptiste Onofré
jbono...@apache.org
http://blog.nanthrax.net
Talend - http://www.talend.com

Reply via email to