ludc
2025-01-16 986aa62ed00bee39363bab41b4eeb8259d446efd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jbpm.pvm.internal.cmd;
 
import java.util.Date;
 
import org.jbpm.api.JbpmException;
import org.jbpm.api.cmd.Environment;
import org.jbpm.api.job.Job;
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.env.JobContext;
import org.jbpm.pvm.internal.job.JobImpl;
import org.jbpm.pvm.internal.jobexecutor.JobExceptionHandler;
import org.jbpm.pvm.internal.session.DbSession;
import org.jbpm.pvm.internal.tx.Transaction;
 
 
 
/**
 * @author Tom Baeyens
 */
public class ExecuteJobCmd extends AbstractCommand<Job> {
 
  private static final long serialVersionUID = 1L;
 
  private static final Log log = Log.getLog(ExecuteJobCmd.class.getName());
  
  protected Long jobDbid;
 
  public ExecuteJobCmd(String jobId) {
    if (jobId==null) {
      throw new JbpmException("jobId is null");
    }
    jobDbid = Long.parseLong(jobId);
  }
 
  public ExecuteJobCmd(Long jobDbid) {
    this.jobDbid = jobDbid;
  }
 
  public Job execute(Environment environmentInterface) throws Exception {
    EnvironmentImpl environment = (EnvironmentImpl) environmentInterface;
      DbSession dbSession = environment.get(DbSession.class);
      if (dbSession==null) {
        throw new JbpmException("no db-session configured");
      }
    JobImpl<?> job = (JobImpl<?>) dbSession.get(JobImpl.class, jobDbid);
 
      // in case of decision jobs, the job might have been deleted
      // before we execute it (they are in a list)
      if (job != null) {
          JobContext jobContext = new JobContext(job);
        environment.setContext(jobContext);
        try {
          log.debug("executing job "+job+"...");
          job.execute(environment);
          log.debug("executed job "+job);
 
          // if this job is locked too long, it could be unlocked by the lockmonitor and 
          // executed by another thread.
          Date lockExpirationDate = job.getLockExpirationTime();
          // can be null if it was rescheduled
          if (lockExpirationDate != null) {
              long lockExpiration = lockExpirationDate.getTime();
              long currentTime = System.currentTimeMillis();
              if (currentTime>lockExpiration) {
                throw new JbpmException("job took too long: lock expired "+(currentTime-lockExpiration)+"ms ago");
              }
          }
        } catch (Exception exception) {
          log.error("exception while executing '"+job+"'", exception);
          handleJobExecutionException(environment, job, exception);
        } finally {
          environment.removeContext(jobContext);
        }
 
      } else {
          log.debug("job " + jobDbid + " no longer exists");
      }
    return job;
  }
 
  /** This transaction will be marked for rollback.  A command will be associated with the 
   * Transaction.EVENT_AFTERCOMPLETION (after the job locks of the current transaction are 
   * released).  Then the command will update the job with the exception details in a separate 
   * transaction. */
  protected void handleJobExecutionException(Environment environment, JobImpl<?> job, Exception exception) {
    Transaction transaction = environment.get(Transaction.class);
    CommandService commandService = (CommandService) environment.get(CommandService.NAME_NEW_TX_REQUIRED_COMMAND_SERVICE);
    JobExceptionHandler jobExceptionHandler = new JobExceptionHandler(job.getDbid(), exception, commandService);
    transaction.registerSynchronization(jobExceptionHandler);
    
    if (exception instanceof RuntimeException) {
      throw (RuntimeException) exception;
    }
    throw new JbpmException("job failed: "+exception.getMessage(), exception);
  }
}