14 Replies Latest reply on Mar 4, 2019 1:24 PM by cfang

    How to get jboss eap 7.1 to execute scheduled jobs defined in xml?

    ncj

      I've managed to get a batchjob registered with the jboss eap 7.1 server. Thus I can start the job manually from the jboss eap 7.1 management web interface. I have kept it simple so far, only having the batchjob print out a simple text message I can view in the server log.

      What I have not been able to get working is scheduled repetitive execution by the jberet framework which is my objective.

       

      The server log outputs the following based on the xml file shown beneath.

      Server log:

      2019-03-03 13:42:09,400 INFO  [stdout] (Batch Thread - 2) This is an xml specified property!

      2019-03-03 13:42:09,403 INFO  [org.jberet.schedule-executor] (Batch Thread - 2) JBERET072500: Created JobScheduler: org.jberet.schedule.ExecutorSchedulerImpl{executorService=java.util.concurrent.Executors$DelegatedScheduledExecutorService@43f71b4c}, based on resource: null

      2019-03-03 13:42:09,421 INFO  [org.jberet.schedule-executor] (Batch Thread - 2) JBERET072502: The following job execution is scheduled to run after execution 2 ends: schedule id 1, JobScheduleInfo{jobName='dbCleanUpBatchJob', jobExecutionId=0, jobParameters={}, initialDelay=1, afterDelay=0, interval=0, persistent=true, scheduleExpression='null'}

      The xml file:

      <?xml version=1.0 encoding="UTF-8"?>
      
      <job id="dbCleanUpBatchJob" 
           xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemalocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd" 
           version="1.0" 
           restartable="true">
           
           <properties>
                <property name="interval" value="10"/>
           </properties>
      
           <listeners>
                <listener ref="org.jberet.schedule.SchedulingJobListeners">
                     <properties>
                          <property name="initialDelay" value="1"/>
                          <property name="afterDelay" value="1"/>
                          <property name="interval" value="1"/>
                          <property name="persistent" value="true"/>
                     </properties> 
                </listener> 
           </listeners>
           
           <step id="dbCleanUpBatchJob.step1" allow-start-if-complete="true">
                <properties>
                     <property name="printThisValue" value="This is an xml specified property!"/>
                </properties>
                <listeners>
                     <listener ref="org.jberet.schedule.SchedulingJobListeners">
                          <properties>
                               <property name="initialDelay" value="1"/>
                               <property name="afterDelay" value="1"/>
                               <property name="interval" value="1"/>
                          </properties>
                     </listener>
                </listeners>
                <batchlet ref="[packagename].DbCleanUpBatchJob"/>
           </step>
      </job>
      
      

       

      I would like to be able to define the schedule of the job in xml and just let the jberet subsystem handle the execution of the job.

      However, if it's not possible I would also like to know how else to get the job scheduled.

       

      I have looked at and read the jberet-user-guide as well as looked at a lot of the sample code on github. From there and the xsd I have come up with the above xml.

      Do I need changes to the above xml or am I missing something else or maybe both?

       

      The code which prints out the message from the xml file shown in the log from the server above:

      package [package name]
      
      import javax.batch.api.AbstractBatchlet;
      import javax.batch.runtime.context.StepContext;
      import javax.inject.Inject;
      
      public class DbCleanUpBatchJob extends AbstractBatchlet {
           @Inject
           StepContext stepContext;
      
           @Override
           public String process() {
                String say = stepContext.getProperties().getProperty("printThisValue");
                System.out.println(say);
                return "SUCCESS";
           }
      }
        • 1. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
          cfang

          what do you mean by repetitive execution scheduling not working?  What's the specific symptom?  Can you provide a reproducer test?

          • 2. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
            ncj

            I mean that with the xml I am able to get the JBoss EAP server to recognize that there is a batchjob. I can then start the job manually from the administrator interface by clicking the "Start" button. However, I need the JBeret subsystem to execute my java code on a schedule. For testing purposes it would be nice to e.g. have it scheduled to run every minute. In this scenario my goal for the test is to see in the server log that my text from the xml is outputtet in the log "[stdout]" every minute - and just goes on and on until I change the schedule or stop the job.

            Preferably I want the JBeret system to start executing the batchjob itself, such that I don't have to manually start it.

             

            The end goal is to have the batchjob code (Java) to execute every night. Either defined by a schedule or by a starting point and an interval from there.

            • 3. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
              cfang

              the log:

              JBERET072502: The following job execution is scheduled to run after execution 2 ends

               

              indicates the next job execution is already scheduled.  Did you see the scheduled job execution run?  Or is it that the job is scheduled but you did see it actually run?

               

              A similar test job definition and test is here, and it may help if you haven't seen it:

              jberet-wildfly-samples/timer-scheduler-job1.xml at master · jberet/jberet-wildfly-samples · GitHub

               

              If you are using org.jberet.schedule.SchedulingJobListener as the listener, it is a job listener, and should not be used as a step listener.

               

              If you can attach the test, I can look closer what's going on.

              • 4. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                ncj

                The symptom is that nothing happens in the server log unless I press the Start button in the JBoss EAP administrator console app. When I press the Start button, the server log shows a single output as shown in the original post, but then nothing more happens. Thus it seems I can currently only get the job executed manually.

                 

                Reproducer test:

                To reproduce you would need the server (JBoss EAP 7.1 with the profile "full-ha") and a batch module (that's what I have done).

                In the batch module I have the following structure:

                • batch-module
                  • src
                    • main
                      • java
                        • [package name] (e.g. com.company.project)
                          • batch
                            • DbCleanUpBatchJob.java
                      • resources
                        • META-INF.batch-jobs
                          • DbCleanUpBatchJob.xml
                      • webapp
                        • WEB-INF
                          • web.xml
                  • pom.xml

                 

                The contents of the DbCleanUpBatchJob.java file is the Java code shown in the original post.

                The contents of the DbCleanUpBatchJob.xml file is the xml shown in the original post.

                 

                The contents of the web.xml file:

                <?xml version="1.0" encoding="UTF-8"?>
                
                <web-app version="3.1"
                         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
                     <servlet-mapping>
                          <servlet-name>javax.ws.rs.core.Application</servlet-name>
                          <url-pattern>/api/*</url-pattern>
                     </servlet-mapping>
                </web-app>
                
                

                 

                The contents of the pom.xml file:

                <?xml version="1.0" encoding="UTF-8"?>
                
                <project xmlns="http://maven.apache.org/POM/4.0.0"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
                
                     <modelVersion>4.0.0</modelVersion>
                     <artifactId>[artifactId]</artifactId>
                     <packaging>war</packaging>
                
                     <parent>
                          <artifactId>[artifactId of parent]</artifactId>
                          <groupId>[groupId]</groupId>
                          <version>1.3</version>
                     </parent>
                
                     <repositories>
                          <repository>
                               <id>jboss-public-repository-group</id>
                               <name>JBoss Public Repository Group</name>
                               <url>http://repository.jboss.org/nexus/content/groups/public</url>
                          </repository>
                     </repositories>
                
                     <dependencies>
                          <dependency>
                               <groupId>org.jboss.spec.javax.batch</groupId>
                               <artifactId>jboss-batch-api_1.0_spec</artifactId>
                               <version>1.0.1.Final</version>
                          </dependency>
                ... the same structure for the following dependencies:
                javax.inject, javax.enterprise, org.jboss.spec.javax.transaction, org.jberet, org.jboss.marshalling, org.jboss.logging,
                org.jboss.weld, org.wildfly.security, com.google.guava, org.jboss.spec.javax.annotation, org.jboss.spec.javax.ejb
                </project>
                

                 

                And then add the produced war-file to the JBoss EAP server. Then I am able to start the batch job from the admin console.

                • 5. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                  cfang

                  I'll take a closer look.  Meanwhile If you have Red Hat JBoss EAP support contract, the best route is to report through the support channel so that your issue can be properly scheduled.

                  • 6. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                    ncj

                    Even though the log says that the job has been scheduled, the text does not get printed to the log again.

                    Only if I again start the job manually from the console, does the log show a new print.

                    • 7. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                      cfang

                      Can you add jberet-schedule-timer to your dependency list:

                       

                      <dependency>

                                  <groupId>org.jberet</groupId>

                                  <artifactId>jberet-schedule-timer</artifactId>

                              </dependency>

                       

                      It should have the same version as jberet-schedule-executor.

                       

                      This will allow jberet-schedule to use the scheduler based on ejb timer, which is the one you should use if you want your schedules to be persistent.

                       

                      It worked in my tests.

                      • 8. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                        ncj

                        Sorry, I missed to include that I have already inserted dependencies for jberet-schedule-timer as well as jberet-schedule-executor in the pom.xml.

                        These are inserted as follows in the dependency list (under the <dependencies> tag as shown in previous post):

                        <dependency>
                             <groupId>org.jberet</groupId>
                             <artifactId>jberet-schedule-executor</artifactId>
                             <version>1.4.0.Final</version>
                        </dependency>
                        <dependency>
                             <groupId>org.jberet</groupId>
                             <artifactId>jberet-schedule-timer</artifactId>
                             <version>1.4.0.Final</version>
                        </dependency>

                         

                        And it still does not result in the print of the message "This is an xml specified property!". It is still only when I press start manually in the admin console that the text is shown in the server log - and only once.

                         

                        Furthermore I cannot figure out why the log does not show the values

                        • afterDelay=1
                        • interval=1

                        even though I have specified those properties with the value 1 for each in the DbCleanUpBatchJob.xml file.

                         

                        JobScheduleInfo{jobName='dbCleanUpBatchJob', jobExecutionId=0, jobParameters={}, initialDelay=1, afterDelay=0, interval=0, persistent=true, scheduleExpression='null'

                         

                        Do you have any other idea as to what could cause this problem or be wrong?

                        • 9. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                          ncj

                          I have now succeeded in getting the job startet programatically and the job now also gets executed repeatedly. I got it working by intoducing a class "BatchStarter" annotated with @Singleton and @Startup and defining a public void onStartup method annotated with @PostConstruct:

                          package [packagename];
                          
                          import javax.annotation.PostConstruct;
                          import javax.batch.runtime.BatchRuntime;
                          import javax.ejb.Singleton;
                          import javax.ejb.Startup;
                          
                          @Singleton
                          @Startup
                          public class BatchStarter {
                               private final String jobID = "DbCleanUpBatchJob";
                               
                               @PostConstruct
                               public void onStartup() {
                                    BatchRuntime.getJobOperator().start(jobID, null);
                          }

                           

                          However, it seems like I can only get the initialDelay property set with a value (number os minutes). Thus I am able to get the job executed every minute (initialDelay=1), every 5 minutes (initialDelay=5) and so on.

                           

                          What I need is to provide a schedule such that I can pick a specific time of day and get the job executed at that time. E.g. every day at 11:00 AM. And should the need arise in the future it would of course also be relevant to be able to schedule the job to run only at every Tuesday at a specific time of the day or something like that.

                          As far as I can tell the JobScheduleInfo JSON object in the server log is where I need to fill this schedule in. There is a property called "scheduleExpression" with the value 'null'. I cannot find out how to get this value set.

                          Am I on the right track? Is it right that I need to set the "scheduleExpression" property? And if so, how do I do that?

                           

                          I can get a ScheduleExpression string into the jobParameters JSON object by instantiating a ScheduleExpression object and set e.g. the minute property in it, but the JBoss EAP server and JBeret subsystem does not seem to take notice of this. It still only reacts to the initialDelay value.

                           

                          As described I've got the server log to show repeated outputs:

                          2019-03-04 10:29:18,722 INFO  [stdout] (Batch Thread - 10) This is an xml specified property! @this time: 2019-03-04 11:29:18

                          2019-03-04 10:29:18,722 INFO  [org.jberet.schedule-executor] (Batch Thread - 10) JBERET072502: The following job execution is scheduled to run after execution 220 ends: schedule id 41184565-b359-4591-a60a-d9842ca74751, JobScheduleInfo{jobName='DbCleanUpBatchJob', jobExecutionId=0, jobParameters={}, initialDelay=1, afterDelay=0, interval=0, persistent=false, scheduleExpression='null'}

                          2019-03-04 10:30:18,727 INFO  [stdout] (Batch Thread - 1) This is an xml specified property! @this time: 2019-03-04 11:30:18

                          2019-03-04 10:30:18,727 INFO  [org.jberet.schedule-executor] (Batch Thread - 1) JBERET072502: The following job execution is scheduled to run after execution 221 ends: schedule id 3c0557c0-512c-4b96-8573-1b917e220700, JobScheduleInfo{jobName='DbCleanUpBatchJob', jobExecutionId=0, jobParameters={}, initialDelay=1, afterDelay=0, interval=0, persistent=false, scheduleExpression='null'}

                          2019-03-04 10:31:18,729 INFO  [stdout] (Batch Thread - 2) This is an xml specified property! @this time: 2019-03-04 11:31:18

                          2019-03-04 10:31:18,730 INFO  [org.jberet.schedule-executor] (Batch Thread - 2) JBERET072502: The following job execution is scheduled to run after execution 222 ends: schedule id 80b8443b-9f03-48ac-8900-2552ff46df43, JobScheduleInfo{jobName='DbCleanUpBatchJob', jobExecutionId=0, jobParameters={}, initialDelay=1, afterDelay=0, interval=0, persistent=false, scheduleExpression='null'}

                           

                          If I give the BatchRuntime.getJobOperator().start method a property object with a ScheduleExpression, I get the following output in the server log:

                          2019-03-04 10:40:03,294 INFO  [stdout] (Batch Thread - 1) This is an xml specified property! @this time: 2019-03-04 11:40:03

                          2019-03-04 10:40:03,295 INFO  [org.jberet.schedule-executor] (Batch Thread - 1) JBERET072502: The following job execution is scheduled to run after execution 231 ends: schedule id f4a69caf-bd47-4a0e-95f1-19b2d629c546, JobScheduleInfo{jobName='DbCleanUpBatchJob', jobExecutionId=0, jobParameters={scheduleExpression=ScheduleExpression[second=0 minute=*/3 hour=0 dayOfWeek=* dayOfMonth=* month=* year=* start=Mon Mar 04 10:39:03 GMT 2019 end=null timezone=]}, initialDelay=1, afterDelay=0, interval=0, persistent=false, scheduleExpression='null'}

                          2019-03-04 10:41:03,297 INFO  [stdout] (Batch Thread - 2) This is an xml specified property! @this time: 2019-03-04 11:41:03

                          2019-03-04 10:41:03,297 INFO  [org.jberet.schedule-executor] (Batch Thread - 2) JBERET072502: The following job execution is scheduled to run after execution 232 ends: schedule id c2d672a3-3f96-46aa-bda6-985e19951b15, JobScheduleInfo{jobName='DbCleanUpBatchJob', jobExecutionId=0, jobParameters={scheduleExpression=ScheduleExpression[second=0 minute=*/3 hour=0 dayOfWeek=* dayOfMonth=* month=* year=* start=Mon Mar 04 10:39:03 GMT 2019 end=null timezone=]}, initialDelay=1, afterDelay=0, interval=0, persistent=false, scheduleExpression='null'}

                          2019-03-04 10:42:03,301 INFO  [stdout] (Batch Thread - 3) This is an xml specified property! @this time: 2019-03-04 11:42:03

                          2019-03-04 10:42:03,304 INFO  [org.jberet.schedule-executor] (Batch Thread - 3) JBERET072502: The following job execution is scheduled to run after execution 233 ends: schedule id b020a1d3-7c66-4364-ae16-6058306b84f8, JobScheduleInfo{jobName='DbCleanUpBatchJob', jobExecutionId=0, jobParameters={scheduleExpression=ScheduleExpression[second=0 minute=*/3 hour=0 dayOfWeek=* dayOfMonth=* month=* year=* start=Mon Mar 04 10:39:03 GMT 2019 end=null timezone=]}, initialDelay=1, afterDelay=0, interval=0, persistent=false, scheduleExpression='null'}

                          • 10. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                            cfang

                            not exactly sure why the schedules are not executed in your case.  I suspect it could be caused by the fact that your original job was started from EAP web console.  I'll need to dig deeper.

                            • 11. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                              cfang

                              Since you already use ejb, you can directly use ejb's schedule and timer service:  in your @StartUp @Singleton ejb bean class, add an ejb @Schedule method to specify your calendar-based batch job execution schedule, roughtly like this:

                               

                              @Schedule(year="*", month="*", day="*", dayOfWeek="*", hour="9", persistent=true)

                              public void batchJobSchedule() {

                               

                              }

                               

                              then you can manage batch job schedules (ejb timers) just the way you manage ejb timers.

                              • 12. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                                cfang

                                to be able to use calendar based schedules (like every year every month on day 1 on 12:00PM), you'll need to use ejb timer, either directly write your @Singleton ejb with @Schedule method, or use jberet-schedule-timer library.

                                 

                                JBeret scheduling is separate from starting a batch job execution, so setting scheduleExpression on job parameters will simply be ignored.

                                 

                                The typical use, and also the primary way of my testing so far, is:

                                 

                                a REST client (browser, curl, postman, etc) ----- schedule ("jobName":"csv2db", "initialDelay":5...)---> EAP/WildFly JBeret REST service ---create---> jberet JobScheduler ---schedule(...)

                                See GitHub - jberet/intro-jberet: Introduction to batch processing with WildFly and JBeret  for example.

                                 

                                If you don't use REST, you can certainly programmatically do the similar (similar to jberet-rest/JobResource.java at master · jberet/jberet-rest · GitHub

                                and you it's pretty easy to create your own org.jberet.schedule.JobScheduleConfig (jberet-schedule/JobScheduleConfigBuilder.java at master · jberet/jberet-schedule · GitHub  and jberet-schedule/JobScheduleConfig.java at master · jberet/jberet-schedule · GitHub  )

                                • 13. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                                  ncj

                                  How do I then get the scheduleExpression applied to my batch job?

                                   

                                  @Singleton
                                  @Startup
                                  public class BatchStarter {
                                       private final String jobID = "DbCleanUpBatchJob";
                                  
                                       @PostConstruct
                                       public void onStartup() {
                                            Date startTime = new Date();
                                            ScheduleExpression scheduleExpression = new ScheduleExpression();
                                            scheduleExpression.start(startTime);
                                            scheduleExpression.minute("*/3");
                                            JobScheduleConfigBuilder jscb = JobScheduleConfigBuilder.newInstance();
                                  
                                            JobScheduleConfig jsc = jscb.jobName(jobID).initialDelay(1).afterDelay(2).interval(3)
                                                                     .scheduleExpression(scheduleExpression).build();
                                  
                                            Properties properties = new java.util.Properties();
                                            properties.setProperty("scheduleConfig", jsc.toString());
                                  
                                            BatchRuntime.getJobOperator().start(jobID, properties);
                                       }
                                  }

                                   

                                  I cannot find out other methods than the properties in the start-method to apply the schedule to the batch job, and it doesn't seem to work.

                                  Do you know how I get the JobScheduleConfig attached to the job, when I do not use rest and the BatchClient?

                                   

                                  I have just tried to use the @Schedule annotation on the whole class (just as the Singleton annotation is used). I am not allowed to do that it seems.

                                  • 14. Re: How to get jboss eap 7.1 to execute scheduled jobs defined in xml?
                                    cfang

                                    you can do something like this:

                                     

                                    @Singleton

                                    public class BatchStarterSingletonBean {

                                      private static final JobOperator jo = BatchRuntime.getJobOperator();

                                     

                                      @Schedule  (year="*", day="1", hour="9")

                                      public void scheduleBatchJob() {

                                        jo.start("myJob", props);

                                      }

                                    }

                                     

                                    so you have 1 ejb timer, and when it fires at your specified date/time, it will start the batch job execution. You don't even need the PostConstruct method to start it once.  After your war is deployed, the timer will start to tick.