Scheduler Service to support/expose native Quartz

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Scheduler Service to support/expose native Quartz

Miroslav Beranič
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
[hidden email]
http://www.mibesis.si
Reply | Threaded
Open this post in threaded view
|

Re: Scheduler Service to support/expose native Quartz

jbonofre
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é
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Scheduler Service to support/expose native Quartz

Miroslav Beranič
Hi JB,

yes, I thought about this - and agree, this change is not all that
favorable for main-stream Karaf implementation.

I did not look at camel-quartz, will look it up - thanks.

One note though - in my "solution" Karaf imports Quartz, not exports, but
either way, I know what you mean.

Regards,
Miroslav



V V tor., 11. sep. 2018 ob 10:19 je oseba Jean-Baptiste Onofré <
[hidden email]> napisala:

> 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é
> [hidden email]
> http://blog.nanthrax.net
> Talend - http://www.talend.com
>


--
Miroslav Beranič
MIBESIS
+386(0)40/814-843
[hidden email]
http://www.mibesis.si
Reply | Threaded
Open this post in threaded view
|

Re: Scheduler Service to support/expose native Quartz

jbonofre
Hi,

So, I propose two actions:

1. Let me take a look on the PR and see how we can extend the Karaf
Scheduler API, still with Quartz "hidden"
2. I think in your case, you can create your own Scheduler using Quartz.
That would gives you complete control if (1) is not fully convenient for
you. I would be more than happy to help on this one.

Regards
JB

On 11/09/2018 10:27, Miroslav Beranič wrote:

> Hi JB,
>
> yes, I thought about this - and agree, this change is not all that
> favorable for main-stream Karaf implementation.
>
> I did not look at camel-quartz, will look it up - thanks.
>
> One note though - in my "solution" Karaf imports Quartz, not exports, but
> either way, I know what you mean.
>
> Regards,
> Miroslav
>
>
>
> V V tor., 11. sep. 2018 ob 10:19 je oseba Jean-Baptiste Onofré <
> [hidden email]> napisala:
>
>> 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é
>> [hidden email]
>> http://blog.nanthrax.net
>> Talend - http://www.talend.com
>>
>
>

--
Jean-Baptiste Onofré
[hidden email]
http://blog.nanthrax.net
Talend - http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Scheduler Service to support/expose native Quartz

Miroslav Beranič
Hi JB,

for now, I do not see other way, for me, than to go forward with my work.
As I am already weeks behind schedule regarding project schedule.
My main requirement ( right now ) is to migrate existing Quartz job classes
( this is about 600-700 classes , and with this my change to Scheduler - I
will not really have any work on the Job class ), I have to migrate from
Quartz 1.8.x to 2.2.x plus remove Spring Framework ( legacy spring ) +
Hibernate to JPA, etc. so less change - better for me.

With that said. I am missing what is "main guide line" for the Karaf
Scheduler: a.) to be "simple way" in to scheduling - that is perfect now,
b.) add full-working Scheduling service ( like Quartz ). I was looking at
different options, also implemented few. Current gihtub push is like third
implementation I did. I was working on one, where I basically rewrote
Quartz API -- end up dropping it as at the end I was adding extra code with
little benefits -- only benefit being that code was not inside Quartz
packages -- but for my specific usecase that also meant I have to rewrite
all the existing code -- not something I want.

Another thing was, that in current Karaf Scheduler job name is same as
tigger name -== trigger is job and vice versa. Well, this is not even close
to my usecase, as I have about two or three sometimes even more triggers
for one job class, so this is no go for me too. But I guess for some
"simple" scheduling tasks existing code is perfect - clean and easy to use.

So I would be glad to work on this, but for sure I need some "big picture"
puzzles to be put in - where Karaf Scheduler is trying to go.

Kind Regards,
Miroslav




V V tor., 11. sep. 2018 ob 10:38 je oseba Jean-Baptiste Onofré <
[hidden email]> napisala:

> Hi,
>
> So, I propose two actions:
>
> 1. Let me take a look on the PR and see how we can extend the Karaf
> Scheduler API, still with Quartz "hidden"
> 2. I think in your case, you can create your own Scheduler using Quartz.
> That would gives you complete control if (1) is not fully convenient for
> you. I would be more than happy to help on this one.
>
> Regards
> JB
>
> On 11/09/2018 10:27, Miroslav Beranič wrote:
> > Hi JB,
> >
> > yes, I thought about this - and agree, this change is not all that
> > favorable for main-stream Karaf implementation.
> >
> > I did not look at camel-quartz, will look it up - thanks.
> >
> > One note though - in my "solution" Karaf imports Quartz, not exports, but
> > either way, I know what you mean.
> >
> > Regards,
> > Miroslav
> >
> >
> >
> > V V tor., 11. sep. 2018 ob 10:19 je oseba Jean-Baptiste Onofré <
> > [hidden email]> napisala:
> >
> >> 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é
> >> [hidden email]
> >> http://blog.nanthrax.net
> >> Talend - http://www.talend.com
> >>
> >
> >
>
> --
> Jean-Baptiste Onofré
> [hidden email]
> http://blog.nanthrax.net
> Talend - http://www.talend.com
>


--
Miroslav Beranič
MIBESIS
+386(0)40/814-843
[hidden email]
http://www.mibesis.si