Announcement Announcement Module
Collapse
No announcement yet.
Create Quartz Jobs as Prototypes Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Create Quartz Jobs as Prototypes

    Hello.

    I would like to configure Spring so that it creates a new Quartz job instance every time a trigger fires (i.e. prototype instead of singleton). I'm using MethodInvokingJobDetailFactoryBean, CronTriggerBean, and SchedulerFactoryBean. I've looked in the forum, the API, and the code, but I couldn't find an example that demonstrates this. Does anyone know how to get Spring do this, or if it's possible?

    Thank you!

  • #2
    What is the reason you want this behavior?

    Comment


    • #3
      Create Quartz Jobs as Prototypes

      I want to make sure that my jobs are thread-safe, as Quartz ensures, and set Spring so that the second job will not have to wait until first job has finished, as does the "concurrent" property of MethodInvokingJobDetailFactoryBean.

      Comment


      • #4
        Originally posted by rpepersack View Post
        I want to make sure that my jobs are thread-safe, as Quartz ensures, and set Spring so that the second job will not have to wait until first job has finished, as does the "concurrent" property of MethodInvokingJobDetailFactoryBean.
        I don't understand what you want.

        So by creating multiple jobs (each job executed by a different thread) you want to make it threadsafe? (isolation/confinement is a very valuable technique for concurrency control). But do you jobs have state?

        Personally I prefer making quartz (or any other threading engine) as stupid as possible. If I need to maintain some kind of context(state) for a Job, I make it part of the call.

        Code:
        class FireService{
           void fireThemAll(){
              FireThemAllContext context = new FireThemAllContext();
              ... now pass the context to the locations needed (could also use a threadlocal for this but making it explicit is less vague).
           }
        }
        And now the FireService.fireThemAll Service can be called by the same instance of the QuartzJob (MethodInvoking.... for example) by multiple Quartz-threads.
        Last edited by Alarmnummer; Mar 3rd, 2008, 09:36 AM.

        Comment


        • #5
          Yes, my jobs have state. Some also take a long time to finish. That's why I want each job to have its own instance. I'm new to Spring, so please bear with me. Are you suggesting that I should create a factory class that creates a new Job instance?

          Comment


          • #6
            Originally posted by rpepersack View Post
            Yes, my jobs have state. Some also take a long time to finish. That's why I want each job to have its own instance. I'm new to Spring, so please bear with me. Are you suggesting that I should create a factory class that creates a new Job instance?
            Nope.. suggest that you make the calling context (a location where you can store state) part of your design. See the example I have provided.

            If you make it part of your design, you don't need to add this logic to the QuartzJob..

            In essence you are moving the responsibility of creating 'a context per thread' from quarts to your service. Maybe the name context is a little bit confusing; maybe it would be better to call it job (the job contains the context of the call).

            Code:
            class FireService{
                void fireAll(){
                    FireAllJob job = new FireAllJob();
                    job.setStartTime(new Date()); //some data specific to this call
                    ... now do calls and you can pass the job to these calls.
                }
            }

            Comment


            • #7
              So, would I configure my Spring XML file so that all of my job details would call FireService, which would, in turn, call FireAllJob? Would FireAllJob create instances of my jobs, or is it just for storing state?

              Comment


              • #8
                Originally posted by rpepersack View Post
                So, would I configure my Spring XML file so that all of my job details would call FireService
                Correct.

                You just need to hook up a Quartz scheduler (or any other mechanism) to that fire method of the FireService.

                which would, in turn, call FireAllJob?
                Correct.

                Would FireAllJob create instances of my jobs, or is it just for storing state?
                The FireAllJob is the Job you are executing. So I don't think you need to create additional jobs (unless you are splitting up the FireAllJob in smaller Jobs.. but that depends on the situation again).

                Comment


                • #9
                  I assume that the "service class" would be a singleton, and the jobs would be prototypes. If my "service" class acts as a "job instance creator", then how do I tell it which job to create? Or, does each "job prototype" have its own "singleton creator"?

                  Comment


                  • #10
                    Originally posted by rpepersack View Post
                    I assume that the "service class" would be a singleton, and the jobs would be prototypes.
                    Correct

                    If my "service" class acts as a "job instance creator", then how do I tell it which job to create? Or, does each "job prototype" have its own "singleton creator"?
                    That depends on your requirements/taste. I don't know anything about the requirements to help you in a good direction. I don't know how complex the tasks are.. if logic should be added to the job... or if the job should be a 'state container'.. it all depends. There are many different ways to design it.

                    Comment


                    • #11
                      I have several different jobs. I would like to create a single service class that can create an instance of whichever job I need, when the job's trigger fires. I know how to create classes using design patterns. It sounds like the service class can follow the Factory Method pattern. So, assuming that I create a "job factory singleton bean" class, how would I get Spring IOC tell it which job to create and run when a trigger fires?

                      Comment


                      • #12
                        Each trigger, could call a different method on a service. And each service method can create a different job.

                        Code:
                        class SomeService{
                        
                            void foo(){
                                  FooJob job = new FooJob(...);
                                  ....
                             }
                        
                             void bar(){
                                  BarJob job = new BarJob(...);
                                  ...
                              }
                        }

                        Comment


                        • #13
                          I like it. Short and sweet, but I have more questions.

                          If I create my jobs with the "new" operator (e.g. FooJob job = new FooJob()), then how would I get the Spring IOC container to inject the dependencies into FooJob and BarJob? For example, FooJob needs FooDao injected into it.

                          Also, would I inject SomeService into the "targetObject" property of MethodInvokingJobDetailFactoryBean? This seems a little cumbersome, so is there a better way?

                          Thanks.

                          Comment


                          • #14
                            Originally posted by rpepersack View Post
                            If I create my jobs with the "new" operator (e.g. FooJob job = new FooJob()), then how would I get the Spring IOC container to inject the dependencies into FooJob and BarJob? For example, FooJob needs FooDao injected into it.
                            It depends on the situation. If there are not resources, I inject them in the Service and when the job is created, the service can inject them in the Job. If there are more dependencies, I create a Factory..

                            Code:
                            void foo(){
                               FooJob job = fooJobFactory.create();
                               ....
                            }
                            Also, would I inject SomeService into the "targetObject" property of MethodInvokingJobDetailFactoryBean? This seems a little cumbersome, so is there a better way?
                            Why is it cumbersome (apart from the large amount of XML stuff).

                            Code:
                            <!-- A Trigger for the fileSystemMontitor -->
                                <bean id="fileSystemMonitorTrigger"
                                      class="org.springframework.scheduling.quartz.CronTriggerBean">
                                    <property name="jobDetail">
                                        <bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                                            <property name="targetObject"
                                                      ref="fileSystemMonitor"/>
                                            <property name="targetMethod"
                                                      value="check"/>
                                            <!-- we don't want concurrent executions-->
                                            <property name="concurrent"
                                                      value="false"/>
                                        </bean>
                                    </property>
                                    <property name="cronExpression"
                                              value="${intake.uploadDirectoryCronExpression}"/>
                                </bean>
                            
                                <!-- the scheduler that triggers the FileSystemMonitor -->
                                <bean id="fileSystemMonitorScheduler"
                                      class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
                                    <property name="quartzProperties">
                                        <props>
                                            <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                                            <prop key="org.quartz.threadPool.threadCount">1</prop>
                                            <prop key="org.quartz.threadPool.threadPriority">1</prop>
                                        </props>
                                    </property>
                            
                                    <property name="triggers">
                                        <list>
                                            <ref bean="fileSystemMonitorTrigger"/>
                                        </list>
                                    </property>
                                </bean>

                            Comment


                            • #15
                              Create Quartz Jobs as Prototypes

                              You could also use ObjectFactoryCreatingFactoryBean for that

                              Comment

                              Working...
                              X