001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.oozie; 019 020import java.io.DataInput; 021import java.io.DataOutput; 022import java.io.IOException; 023import java.sql.Timestamp; 024import java.text.MessageFormat; 025import java.util.Date; 026import java.util.List; 027import java.util.Properties; 028 029import javax.persistence.Basic; 030import javax.persistence.Column; 031import javax.persistence.Entity; 032import javax.persistence.Id; 033import javax.persistence.Lob; 034import javax.persistence.NamedQueries; 035import javax.persistence.NamedQuery; 036import javax.persistence.Table; 037 038import org.apache.hadoop.io.Writable; 039import org.apache.oozie.client.WorkflowAction; 040import org.apache.oozie.client.rest.JsonBean; 041import org.apache.oozie.client.rest.JsonTags; 042import org.apache.oozie.client.rest.JsonUtils; 043import org.apache.oozie.util.DateUtils; 044import org.apache.oozie.util.ParamChecker; 045import org.apache.oozie.util.PropertiesUtils; 046import org.apache.oozie.util.WritableUtils; 047import org.apache.openjpa.persistence.jdbc.Index; 048import org.apache.openjpa.persistence.jdbc.Strategy; 049 050import org.json.simple.JSONArray; 051import org.json.simple.JSONObject; 052 053/** 054 * Bean that contains all the information to start an action for a workflow 055 * node. 056 */ 057@Entity 058@NamedQueries({ 059 060 @NamedQuery(name = "UPDATE_ACTION", query = "update WorkflowActionBean a set a.conf = :conf, a.consoleUrl = :consoleUrl, a.data = :data, a.stats = :stats, a.externalChildIDs = :externalChildIDs, a.errorCode = :errorCode, a.errorMessage = :errorMessage, a.externalId = :externalId, a.externalStatus = :externalStatus, a.name = :name, a.cred = :cred , a.retries = :retries, a.trackerUri = :trackerUri, a.transition = :transition, a.type = :type, a.endTimestamp = :endTime, a.executionPath = :executionPath, a.lastCheckTimestamp = :lastCheckTime, a.logToken = :logToken, a.pending = :pending, a.pendingAgeTimestamp = :pendingAge, a.signalValue = :signalValue, a.slaXml = :slaXml, a.startTimestamp = :startTime, a.statusStr = :status, a.wfId=:wfId where a.id = :id"), 061 062 @NamedQuery(name = "UPDATE_ACTION_FOR_LAST_CHECKED_TIME", query = "update WorkflowActionBean a set a.lastCheckTimestamp = :lastCheckTime where a.id = :id"), 063 064 @NamedQuery(name = "UPDATE_ACTION_START", query = "update WorkflowActionBean a set a.startTimestamp = :startTime, a.externalChildIDs = :externalChildIDs, a.conf = :conf, a.errorCode = :errorCode, a.errorMessage = :errorMessage, a.startTimestamp = :startTime, a.externalId = :externalId, a.trackerUri = :trackerUri, a.consoleUrl = :consoleUrl, a.lastCheckTimestamp = :lastCheckTime, a.statusStr = :status, a.externalStatus = :externalStatus, a.data = :data, a.retries = :retries, a.pending = :pending, a.pendingAgeTimestamp = :pendingAge, a.userRetryCount = :userRetryCount where a.id = :id"), 065 066 @NamedQuery(name = "UPDATE_ACTION_CHECK", query = "update WorkflowActionBean a set a.userRetryCount = :userRetryCount, a.stats = :stats, a.externalChildIDs = :externalChildIDs, a.externalStatus = :externalStatus, a.statusStr = :status, a.data = :data, a.pending = :pending, a.errorCode = :errorCode, a.errorMessage = :errorMessage, a.lastCheckTimestamp = :lastCheckTime, a.retries = :retries, a.pendingAgeTimestamp = :pendingAge, a.startTimestamp = :startTime where a.id = :id"), 067 068 @NamedQuery(name = "UPDATE_ACTION_END", query = "update WorkflowActionBean a set a.stats = :stats, a.errorCode = :errorCode, a.errorMessage = :errorMessage, a.retries = :retries, a.endTimestamp = :endTime, a.statusStr = :status, a.pending = :pending, a.pendingAgeTimestamp = :pendingAge, a.signalValue = :signalValue, a.userRetryCount = :userRetryCount, a.externalStatus = :externalStatus where a.id = :id"), 069 070 @NamedQuery(name = "UPDATE_ACTION_PENDING", query = "update WorkflowActionBean a set a.pending = :pending, a.pendingAgeTimestamp = :pendingAge where a.id = :id"), 071 072 @NamedQuery(name = "UPDATE_ACTION_STATUS_PENDING", query = "update WorkflowActionBean a set a.statusStr = :status, a.pending = :pending, a.pendingAgeTimestamp = :pendingAge where a.id = :id"), 073 074 @NamedQuery(name = "UPDATE_ACTION_PENDING_TRANS", query = "update WorkflowActionBean a set a.pending = :pending, a.pendingAgeTimestamp = :pendingAge, a.transition = :transition where a.id = :id"), 075 076 @NamedQuery(name = "UPDATE_ACTION_PENDING_TRANS_ERROR", query = "update WorkflowActionBean a set a.pending = :pending, a.pendingAgeTimestamp = :pendingAge, a.transition = :transition, a.errorCode = :errorCode, a.errorMessage = :errorMessage where a.id = :id"), 077 078 @NamedQuery(name = "DELETE_ACTION", query = "delete from WorkflowActionBean a where a.id = :id"), 079 080 @NamedQuery(name = "DELETE_ACTIONS_FOR_WORKFLOW", query = "delete from WorkflowActionBean a where a.wfId = :wfId"), 081 082 @NamedQuery(name = "GET_ACTIONS", query = "select OBJECT(a) from WorkflowActionBean a"), 083 084 @NamedQuery(name = "GET_ACTION", query = "select OBJECT(a) from WorkflowActionBean a where a.id = :id"), 085 086 @NamedQuery(name = "GET_ACTION_ID_TYPE_LASTCHECK", query = "select a.id, a.type, a.lastCheckTimestamp from WorkflowActionBean a where a.id = :id"), 087 088 @NamedQuery(name = "GET_ACTION_FAIL", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.type, a.logToken, a.transition, a.errorCode, a.errorMessage from WorkflowActionBean a where a.id = :id"), 089 090 @NamedQuery(name = "GET_ACTION_SIGNAL", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.pendingAgeTimestamp, a.type, a.logToken, a.transition, a.errorCode, a.errorMessage, a.executionPath, a.signalValue, a.slaXml from WorkflowActionBean a where a.id = :id"), 091 092 @NamedQuery(name = "GET_ACTION_CHECK", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.pendingAgeTimestamp, a.type, a.logToken, a.transition, a.retries, a.userRetryCount, a.userRetryMax, a.userRetryInterval, a.trackerUri, a.startTimestamp, a.endTimestamp, a.lastCheckTimestamp, a.errorCode, a.errorMessage, a.externalId, a.externalStatus, a.externalChildIDs, a.conf from WorkflowActionBean a where a.id = :id"), 093 094 @NamedQuery(name = "GET_ACTION_END", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.pendingAgeTimestamp, a.type, a.logToken, a.transition, a.retries, a.trackerUri, a.userRetryCount, a.userRetryMax, a.userRetryInterval, a.startTimestamp, a.endTimestamp, a.errorCode, a.errorMessage, a.externalId, a.externalStatus, a.externalChildIDs, a.conf, a.data, a.stats from WorkflowActionBean a where a.id = :id"), 095 096 @NamedQuery(name = "GET_ACTION_COMPLETED", query = "select a.id, a.wfId, a.statusStr, a.type, a.logToken from WorkflowActionBean a where a.id = :id"), 097 098 @NamedQuery(name = "GET_ACTION_FOR_UPDATE", query = "select OBJECT(a) from WorkflowActionBean a where a.id = :id"), 099 100 @NamedQuery(name = "GET_ACTION_FOR_SLA", query = "select a.id, a.statusStr, a.startTimestamp, a.endTimestamp from WorkflowActionBean a where a.id = :id"), 101 102 @NamedQuery(name = "GET_ACTIONS_FOR_WORKFLOW", query = "select OBJECT(a) from WorkflowActionBean a where a.wfId = :wfId order by a.startTimestamp"), 103 104 @NamedQuery(name = "GET_ACTIONS_OF_WORKFLOW_FOR_UPDATE", query = "select OBJECT(a) from WorkflowActionBean a where a.wfId = :wfId order by a.startTimestamp"), 105 106 @NamedQuery(name = "GET_PENDING_ACTIONS", query = "select a.id, a.wfId, a.statusStr, a.type, a.pendingAgeTimestamp from WorkflowActionBean a where a.pending = 1 AND a.pendingAgeTimestamp < :pendingAge AND a.statusStr <> 'RUNNING'"), 107 108 @NamedQuery(name = "GET_RUNNING_ACTIONS", query = "select a.id from WorkflowActionBean a where a.pending = 1 AND a.statusStr = 'RUNNING' AND a.lastCheckTimestamp < :lastCheckTime"), 109 110 @NamedQuery(name = "GET_RETRY_MANUAL_ACTIONS", query = "select OBJECT(a) from WorkflowActionBean a where a.wfId = :wfId AND (a.statusStr = 'START_RETRY' OR a.statusStr = 'START_MANUAL' OR a.statusStr = 'END_RETRY' OR a.statusStr = 'END_MANUAL')"), 111 112 @NamedQuery(name = "GET_ACTIONS_FOR_WORKFLOW_RERUN", query = "select a.id, a.name, a.statusStr, a.endTimestamp from WorkflowActionBean a where a.wfId = :wfId order by a.startTimestamp") }) 113@Table(name = "WF_ACTIONS") 114public class WorkflowActionBean implements Writable, WorkflowAction, JsonBean { 115 @Id 116 private String id; 117 118 @Basic 119 @Index 120 @Column(name = "wf_id") 121 private String wfId = null; 122 123 @Basic 124 @Column(name = "created_time") 125 private Timestamp createdTimeTS = null; 126 127 @Basic 128 @Index 129 @Column(name = "status") 130 private String statusStr = WorkflowAction.Status.PREP.toString(); 131 132 @Basic 133 @Column(name = "last_check_time") 134 private Timestamp lastCheckTimestamp; 135 136 @Basic 137 @Column(name = "end_time") 138 private Timestamp endTimestamp = null; 139 140 @Basic 141 @Column(name = "start_time") 142 private Timestamp startTimestamp = null; 143 144 @Basic 145 @Column(name = "execution_path", length = 1024) 146 private String executionPath = null; 147 148 @Basic 149 @Column(name = "pending") 150 private int pending = 0; 151 152 @Basic 153 @Index 154 @Column(name = "pending_age") 155 private Timestamp pendingAgeTimestamp = null; 156 157 @Basic 158 @Column(name = "signal_value") 159 private String signalValue = null; 160 161 @Basic 162 @Column(name = "log_token") 163 private String logToken = null; 164 165 @Basic 166 @Column(name = "sla_xml") 167 @Lob 168 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 169 private StringBlob slaXml; 170 171 @Basic 172 @Column(name = "name") 173 private String name = null; 174 175 @Basic 176 @Column(name = "cred") 177 private String cred = null; 178 179 @Basic 180 @Column(name = "type") 181 private String type = null; 182 183 @Basic 184 @Column(name = "conf") 185 @Lob 186 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 187 private StringBlob conf; 188 189 @Basic 190 @Column(name = "retries") 191 private int retries; 192 193 @Basic 194 @Column(name = "user_retry_count") 195 private int userRetryCount; 196 197 @Basic 198 @Column(name = "user_retry_max") 199 private int userRetryMax; 200 201 @Basic 202 @Column(name = "user_retry_interval") 203 private int userRetryInterval; 204 205 @Basic 206 @Column(name = "transition") 207 private String transition = null; 208 209 @Basic 210 @Column(name = "data") 211 @Lob 212 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 213 private StringBlob data; 214 215 @Basic 216 @Column(name = "stats") 217 @Lob 218 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 219 private StringBlob stats; 220 221 @Basic 222 @Column(name = "external_child_ids") 223 @Lob 224 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 225 private StringBlob externalChildIDs; 226 227 @Basic 228 @Column(name = "external_id") 229 private String externalId = null; 230 231 @Basic 232 @Column(name = "external_status") 233 private String externalStatus = null; 234 235 @Basic 236 @Column(name = "tracker_uri") 237 private String trackerUri = null; 238 239 @Basic 240 @Column(name = "console_url") 241 private String consoleUrl = null; 242 243 @Basic 244 @Column(name = "error_code") 245 private String errorCode = null; 246 247 @Column(name = "error_message", length = 500) 248 private String errorMessage = null; 249 250 /** 251 * Default constructor. 252 */ 253 public WorkflowActionBean() { 254 } 255 256 /** 257 * Serialize the action bean to a data output. 258 * 259 * @param dataOutput data output. 260 * @throws IOException thrown if the action bean could not be serialized. 261 */ 262 263 public void write(DataOutput dataOutput) throws IOException { 264 WritableUtils.writeStr(dataOutput, getId()); 265 WritableUtils.writeStr(dataOutput, getName()); 266 WritableUtils.writeStr(dataOutput, getCred()); 267 WritableUtils.writeStr(dataOutput, getType()); 268 WritableUtils.writeStr(dataOutput, getConf()); 269 WritableUtils.writeStr(dataOutput, getStatusStr()); 270 dataOutput.writeInt(getRetries()); 271 dataOutput.writeLong((getStartTime() != null) ? getStartTime().getTime() : -1); 272 dataOutput.writeLong((getEndTime() != null) ? getEndTime().getTime() : -1); 273 dataOutput.writeLong((getLastCheckTime() != null) ? getLastCheckTime().getTime() : -1); 274 WritableUtils.writeStr(dataOutput, getTransition()); 275 WritableUtils.writeStr(dataOutput, getData()); 276 WritableUtils.writeStr(dataOutput, getStats()); 277 WritableUtils.writeStr(dataOutput, getExternalChildIDs()); 278 WritableUtils.writeStr(dataOutput, getExternalId()); 279 WritableUtils.writeStr(dataOutput, getExternalStatus()); 280 WritableUtils.writeStr(dataOutput, getTrackerUri()); 281 WritableUtils.writeStr(dataOutput, getConsoleUrl()); 282 WritableUtils.writeStr(dataOutput, getErrorCode()); 283 WritableUtils.writeStr(dataOutput, getErrorMessage()); 284 WritableUtils.writeStr(dataOutput, wfId); 285 WritableUtils.writeStr(dataOutput, executionPath); 286 dataOutput.writeInt(pending); 287 dataOutput.writeLong((getPendingAge() != null) ? getPendingAge().getTime() : -1); 288 WritableUtils.writeStr(dataOutput, signalValue); 289 WritableUtils.writeStr(dataOutput, logToken); 290 dataOutput.writeInt(getUserRetryCount()); 291 dataOutput.writeInt(getUserRetryInterval()); 292 dataOutput.writeInt(getUserRetryMax()); 293 } 294 295 /** 296 * Deserialize an action bean from a data input. 297 * 298 * @param dataInput data input. 299 * @throws IOException thrown if the action bean could not be deserialized. 300 */ 301 public void readFields(DataInput dataInput) throws IOException { 302 setId(WritableUtils.readStr(dataInput)); 303 setName(WritableUtils.readStr(dataInput)); 304 setCred(WritableUtils.readStr(dataInput)); 305 setType(WritableUtils.readStr(dataInput)); 306 setConf(WritableUtils.readStr(dataInput)); 307 setStatus(WorkflowAction.Status.valueOf(WritableUtils.readStr(dataInput))); 308 setRetries(dataInput.readInt()); 309 long d = dataInput.readLong(); 310 if (d != -1) { 311 setStartTime(new Date(d)); 312 } 313 d = dataInput.readLong(); 314 if (d != -1) { 315 setEndTime(new Date(d)); 316 } 317 d = dataInput.readLong(); 318 if (d != -1) { 319 setLastCheckTime(new Date(d)); 320 } 321 setTransition(WritableUtils.readStr(dataInput)); 322 setData(WritableUtils.readStr(dataInput)); 323 setStats(WritableUtils.readStr(dataInput)); 324 setExternalChildIDs(WritableUtils.readStr(dataInput)); 325 setExternalId(WritableUtils.readStr(dataInput)); 326 setExternalStatus(WritableUtils.readStr(dataInput)); 327 setTrackerUri(WritableUtils.readStr(dataInput)); 328 setConsoleUrl(WritableUtils.readStr(dataInput)); 329 setErrorInfo(WritableUtils.readStr(dataInput), WritableUtils.readStr(dataInput)); 330 wfId = WritableUtils.readStr(dataInput); 331 executionPath = WritableUtils.readStr(dataInput); 332 pending = dataInput.readInt(); 333 d = dataInput.readLong(); 334 if (d != -1) { 335 pendingAgeTimestamp = DateUtils.convertDateToTimestamp(new Date(d)); 336 } 337 signalValue = WritableUtils.readStr(dataInput); 338 logToken = WritableUtils.readStr(dataInput); 339 setUserRetryCount(dataInput.readInt()); 340 setUserRetryInterval(dataInput.readInt()); 341 setUserRetryMax(dataInput.readInt()); 342 } 343 344 /** 345 * Return whether workflow action in terminal state or not 346 * 347 * @return 348 */ 349 public boolean inTerminalState() { 350 boolean isTerminalState = false; 351 switch (WorkflowAction.Status.valueOf(statusStr)) { 352 case ERROR: 353 case FAILED: 354 case KILLED: 355 case OK: 356 isTerminalState = true; 357 break; 358 default: 359 break; 360 } 361 return isTerminalState; 362 } 363 364 /** 365 * Return if the action execution is complete. 366 * 367 * @return if the action start is complete. 368 */ 369 public boolean isExecutionComplete() { 370 return getStatus() == WorkflowAction.Status.DONE; 371 } 372 373 /** 374 * Return if the action is START_RETRY or START_MANUAL or END_RETRY or 375 * END_MANUAL. 376 * 377 * @return boolean true if status is START_RETRY or START_MANUAL or 378 * END_RETRY or END_MANUAL 379 */ 380 public boolean isRetryOrManual() { 381 return (getStatus() == WorkflowAction.Status.START_RETRY || getStatus() == WorkflowAction.Status.START_MANUAL 382 || getStatus() == WorkflowAction.Status.END_RETRY || getStatus() == WorkflowAction.Status.END_MANUAL); 383 } 384 385 /** 386 * Return true if the action is USER_RETRY 387 * 388 * @return boolean true if status is USER_RETRY 389 */ 390 public boolean isUserRetry() { 391 return (getStatus() == WorkflowAction.Status.USER_RETRY); 392 } 393 394 /** 395 * Return if the action is complete. 396 * 397 * @return if the action is complete. 398 */ 399 public boolean isComplete() { 400 return getStatus() == WorkflowAction.Status.OK || getStatus() == WorkflowAction.Status.KILLED 401 || getStatus() == WorkflowAction.Status.ERROR; 402 } 403 404 /** 405 * Return if the action is complete with failure. 406 * 407 * @return if the action is complete with failure. 408 */ 409 public boolean isTerminalWithFailure() { 410 boolean result = false; 411 switch (getStatus()) { 412 case FAILED: 413 case KILLED: 414 case ERROR: 415 result = true; 416 } 417 return result; 418 } 419 420 /** 421 * Set the action pending flag to true. 422 */ 423 public void setPendingOnly() { 424 pending = 1; 425 } 426 427 /** 428 * Set the action as pending and the current time as pending. 429 */ 430 public void setPending() { 431 pending = 1; 432 pendingAgeTimestamp = DateUtils.convertDateToTimestamp(new Date()); 433 } 434 435 /** 436 * Set pending flag 437 */ 438 public void setPending(int i) { 439 pending = i; 440 } 441 442 /** 443 * Set a time when the action will be pending, normally a time in the 444 * future. 445 * 446 * @param pendingAge the time when the action will be pending. 447 */ 448 public void setPendingAge(Date pendingAge) { 449 this.pendingAgeTimestamp = DateUtils.convertDateToTimestamp(pendingAge); 450 } 451 452 /** 453 * Return the pending age of the action. 454 * 455 * @return the pending age of the action, <code>null</code> if the action is 456 * not pending. 457 */ 458 public Date getPendingAge() { 459 return DateUtils.toDate(pendingAgeTimestamp); 460 } 461 462 /** 463 * Return if the action is pending. 464 * 465 * @return if the action is pending. 466 */ 467 public boolean isPending() { 468 return pending == 1 ? true : false; 469 } 470 471 /** 472 * Removes the pending flag and pendingAge from the action. 473 */ 474 public void resetPending() { 475 pending = 0; 476 pendingAgeTimestamp = null; 477 } 478 479 /** 480 * Removes the pending flag from the action. 481 */ 482 public void resetPendingOnly() { 483 pending = 0; 484 } 485 486 /** 487 * Increments the number of retries for the action. 488 */ 489 public void incRetries() { 490 setRetries(getRetries() + 1); 491 } 492 493 /** 494 * Set a tracking information for an action, and set the action status to 495 * {@link Action.Status#DONE} 496 * 497 * @param externalId external ID for the action. 498 * @param trackerUri tracker URI for the action. 499 * @param consoleUrl console URL for the action. 500 */ 501 public void setStartData(String externalId, String trackerUri, String consoleUrl) { 502 setExternalId(ParamChecker.notEmpty(externalId, "externalId")); 503 setTrackerUri(ParamChecker.notEmpty(trackerUri, "trackerUri")); 504 setConsoleUrl(ParamChecker.notEmpty(consoleUrl, "consoleUrl")); 505 Date now = new Date(); 506 if (this.startTimestamp == null) { 507 setStartTime(now); 508 } 509 setLastCheckTime(now); 510 setStatus(Status.RUNNING); 511 } 512 513 /** 514 * Set the completion information for an action start. Sets the Action 515 * status to {@link Action.Status#DONE} 516 * 517 * @param externalStatus action external end status. 518 * @param actionData action output data, <code>null</code> if there is no 519 * action output data. 520 */ 521 public void setExecutionData(String externalStatus, Properties actionData) { 522 setStatus(Status.DONE); 523 setExternalStatus(ParamChecker.notEmpty(externalStatus, "externalStatus")); 524 if (actionData != null) { 525 setData(PropertiesUtils.propertiesToString(actionData)); 526 } 527 } 528 529 /** 530 * Return the action statistics info. 531 * 532 * @return Json representation of the stats. 533 */ 534 public String getExecutionStats() { 535 return getStats(); 536 } 537 538 /** 539 * Set the action statistics info for the workflow action. 540 * 541 * @param Json representation of the stats. 542 */ 543 public void setExecutionStats(String jsonStats) { 544 setStats(jsonStats); 545 } 546 547 /** 548 * Return the external child IDs. 549 * 550 * @return externalChildIDs as a string. 551 */ 552 @Override 553 public String getExternalChildIDs() { 554 return externalChildIDs == null ? null : externalChildIDs.getString(); 555 } 556 557 /** 558 * Set the external child IDs for the workflow action. 559 * 560 * @param externalChildIDs as a string. 561 */ 562 public void setExternalChildIDs(String externalChildIDs) { 563 if (this.externalChildIDs == null) { 564 this.externalChildIDs = new StringBlob(externalChildIDs); 565 } 566 else { 567 this.externalChildIDs.setString(externalChildIDs); 568 } 569 } 570 571 /** 572 * Set external child ids 573 * 574 * @param externalChildIds 575 */ 576 public void setExternalChildIDsBlob(StringBlob externalChildIDs) { 577 this.externalChildIDs = externalChildIDs; 578 } 579 580 /** 581 * Get external ChildIds 582 * 583 * @return 584 */ 585 public StringBlob getExternalChildIDsBlob() { 586 return externalChildIDs; 587 } 588 589 /** 590 * Set the completion information for an action end. 591 * 592 * @param status action status, {@link Action.Status#OK} or 593 * {@link Action.Status#ERROR} or {@link Action.Status#KILLED} 594 * @param signalValue the signal value. In most cases, the value should be 595 * OK or ERROR. 596 */ 597 public void setEndData(Status status, String signalValue) { 598 if (status == null || (status != Status.OK && status != Status.ERROR && status != Status.KILLED)) { 599 throw new IllegalArgumentException("Action status must be OK, ERROR or KILLED. Received [" 600 + status.toString() + "]"); 601 } 602 if (status == Status.OK) { 603 setErrorInfo(null, null); 604 } 605 setStatus(status); 606 setSignalValue(ParamChecker.notEmpty(signalValue, "signalValue")); 607 } 608 609 /** 610 * Return the job Id. 611 * 612 * @return the job Id. 613 */ 614 public String getJobId() { 615 return wfId; 616 } 617 618 /** 619 * Return the job Id. 620 * 621 * @return the job Id. 622 */ 623 public String getWfId() { 624 return wfId; 625 } 626 627 /** 628 * Set the job id. 629 * 630 * @param id jobId; 631 */ 632 public void setJobId(String id) { 633 this.wfId = id; 634 } 635 636 public void setSlaXml(String slaXmlStr) { 637 if (this.slaXml == null) { 638 this.slaXml = new StringBlob(slaXmlStr); 639 } 640 else { 641 this.slaXml.setString(slaXmlStr); 642 } 643 } 644 645 public String getSlaXml() { 646 return slaXml == null ? null : slaXml.getString(); 647 } 648 649 public void setSlaXmlBlob(StringBlob slaXml) { 650 this.slaXml = slaXml; 651 } 652 653 public StringBlob getSlaXmlBlob() { 654 return slaXml; 655 } 656 657 /** 658 * Set status of job 659 * 660 * @param val 661 */ 662 public void setStatus(Status val) { 663 this.statusStr = val.toString(); 664 } 665 666 @Override 667 public Status getStatus() { 668 return Status.valueOf(this.statusStr); 669 } 670 671 /** 672 * Set status 673 * 674 * @param statusStr 675 */ 676 public void setStatusStr(String statusStr) { 677 this.statusStr = statusStr; 678 } 679 680 /** 681 * Get status 682 * 683 * @return 684 */ 685 public String getStatusStr() { 686 return statusStr; 687 } 688 689 /** 690 * Return the node execution path. 691 * 692 * @return the node execution path. 693 */ 694 public String getExecutionPath() { 695 return executionPath; 696 } 697 698 /** 699 * Set the node execution path. 700 * 701 * @param executionPath the node execution path. 702 */ 703 public void setExecutionPath(String executionPath) { 704 this.executionPath = executionPath; 705 } 706 707 /** 708 * Return the signal value for the action. 709 * <p/> 710 * For decision nodes it is the choosen transition, for actions it is OK or 711 * ERROR. 712 * 713 * @return the action signal value. 714 */ 715 public String getSignalValue() { 716 return signalValue; 717 } 718 719 /** 720 * Set the signal value for the action. 721 * <p/> 722 * For decision nodes it is the choosen transition, for actions it is OK or 723 * ERROR. 724 * 725 * @param signalValue the action signal value. 726 */ 727 public void setSignalValue(String signalValue) { 728 this.signalValue = signalValue; 729 } 730 731 /** 732 * Return the job log token. 733 * 734 * @return the job log token. 735 */ 736 public String getLogToken() { 737 return logToken; 738 } 739 740 /** 741 * Set the job log token. 742 * 743 * @param logToken the job log token. 744 */ 745 public void setLogToken(String logToken) { 746 this.logToken = logToken; 747 } 748 749 /** 750 * Return the action last check time 751 * 752 * @return the last check time 753 */ 754 public Date getLastCheckTime() { 755 return DateUtils.toDate(lastCheckTimestamp); 756 } 757 758 /** 759 * Return the action last check time 760 * 761 * @return the last check time 762 */ 763 public Timestamp getLastCheckTimestamp() { 764 return lastCheckTimestamp; 765 } 766 767 /** 768 * Return the action last check time 769 * 770 * @return the last check time 771 */ 772 public Timestamp getStartTimestamp() { 773 return startTimestamp; 774 } 775 776 /** 777 * Return the action last check time 778 * 779 * @return the last check time 780 */ 781 public Timestamp getEndTimestamp() { 782 return endTimestamp; 783 } 784 785 /** 786 * Return the action last check time 787 * 788 * @return the last check time 789 */ 790 public Timestamp getPendingAgeTimestamp() { 791 return pendingAgeTimestamp; 792 } 793 794 /** 795 * Sets the action last check time 796 * 797 * @param lastCheckTime the last check time to set. 798 */ 799 public void setLastCheckTime(Date lastCheckTime) { 800 this.lastCheckTimestamp = DateUtils.convertDateToTimestamp(lastCheckTime); 801 } 802 803 public int getPending() { 804 return this.pending; 805 } 806 807 @Override 808 public Date getStartTime() { 809 return DateUtils.toDate(startTimestamp); 810 } 811 812 /** 813 * Set start time 814 * 815 * @param startTime 816 */ 817 public void setStartTime(Date startTime) { 818 this.startTimestamp = DateUtils.convertDateToTimestamp(startTime); 819 } 820 821 @Override 822 public Date getEndTime() { 823 return DateUtils.toDate(endTimestamp); 824 } 825 826 /** 827 * Set end time 828 * 829 * @param endTime 830 */ 831 public void setEndTime(Date endTime) { 832 this.endTimestamp = DateUtils.convertDateToTimestamp(endTime); 833 } 834 835 @SuppressWarnings("unchecked") 836 public JSONObject toJSONObject() { 837 return toJSONObject("GMT"); 838 } 839 840 @SuppressWarnings("unchecked") 841 public JSONObject toJSONObject(String timeZoneId) { 842 JSONObject json = new JSONObject(); 843 json.put(JsonTags.WORKFLOW_ACTION_ID, id); 844 json.put(JsonTags.WORKFLOW_ACTION_NAME, name); 845 json.put(JsonTags.WORKFLOW_ACTION_AUTH, cred); 846 json.put(JsonTags.WORKFLOW_ACTION_TYPE, type); 847 json.put(JsonTags.WORKFLOW_ACTION_CONF, getConf()); 848 json.put(JsonTags.WORKFLOW_ACTION_STATUS, statusStr); 849 json.put(JsonTags.WORKFLOW_ACTION_RETRIES, (long) retries); 850 json.put(JsonTags.WORKFLOW_ACTION_START_TIME, JsonUtils.formatDateRfc822(getStartTime(), timeZoneId)); 851 json.put(JsonTags.WORKFLOW_ACTION_END_TIME, JsonUtils.formatDateRfc822(getEndTime(), timeZoneId)); 852 json.put(JsonTags.WORKFLOW_ACTION_TRANSITION, transition); 853 json.put(JsonTags.WORKFLOW_ACTION_DATA, getData()); 854 json.put(JsonTags.WORKFLOW_ACTION_STATS, getStats()); 855 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_CHILD_IDS, getExternalChildIDs()); 856 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_ID, externalId); 857 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_STATUS, externalStatus); 858 json.put(JsonTags.WORKFLOW_ACTION_TRACKER_URI, trackerUri); 859 json.put(JsonTags.WORKFLOW_ACTION_CONSOLE_URL, consoleUrl); 860 json.put(JsonTags.WORKFLOW_ACTION_ERROR_CODE, errorCode); 861 json.put(JsonTags.WORKFLOW_ACTION_ERROR_MESSAGE, errorMessage); 862 json.put(JsonTags.TO_STRING, toString()); 863 return json; 864 } 865 866 @Override 867 public String getId() { 868 return id; 869 } 870 871 public void setId(String id) { 872 this.id = id; 873 } 874 875 public Timestamp getCreatedTimestamp() { 876 return createdTimeTS; 877 } 878 879 public Date getCreatedTime() { 880 return DateUtils.toDate(createdTimeTS); 881 } 882 883 public void setCreatedTime(Date createdTime) { 884 this.createdTimeTS = DateUtils.convertDateToTimestamp(createdTime); 885 } 886 887 @Override 888 public String getName() { 889 return name; 890 } 891 892 public void setName(String name) { 893 this.name = name; 894 } 895 896 @Override 897 public String getCred() { 898 return cred; 899 } 900 901 public void setCred(String cred) { 902 this.cred = cred; 903 } 904 905 @Override 906 public String getType() { 907 return type; 908 } 909 910 public void setType(String type) { 911 this.type = type; 912 } 913 914 @Override 915 public String getConf() { 916 return conf == null ? null : conf.getString(); 917 } 918 919 public void setConf(String conf) { 920 if (this.conf == null) { 921 this.conf = new StringBlob(conf); 922 } 923 else { 924 this.conf.setString(conf); 925 } 926 } 927 928 public void setConfBlob(StringBlob conf) { 929 this.conf = conf; 930 } 931 932 public StringBlob getConfBlob() { 933 return conf; 934 } 935 936 @Override 937 public int getRetries() { 938 return retries; 939 } 940 941 public void setRetries(int retries) { 942 this.retries = retries; 943 } 944 945 @Override 946 public int getUserRetryCount() { 947 return userRetryCount; 948 } 949 950 public void setUserRetryCount(int retryCount) { 951 this.userRetryCount = retryCount; 952 } 953 954 public void incrmentUserRetryCount() { 955 this.userRetryCount++; 956 } 957 958 @Override 959 public int getUserRetryMax() { 960 return userRetryMax; 961 } 962 963 /** 964 * Set user retry max 965 * 966 * @param retryMax 967 */ 968 public void setUserRetryMax(int retryMax) { 969 this.userRetryMax = retryMax; 970 } 971 972 @Override 973 public int getUserRetryInterval() { 974 return userRetryInterval; 975 } 976 977 public void setUserRetryInterval(int retryInterval) { 978 this.userRetryInterval = retryInterval; 979 } 980 981 @Override 982 public String getTransition() { 983 return transition; 984 } 985 986 /** 987 * Set transition 988 * 989 * @param transition 990 */ 991 public void setTransition(String transition) { 992 this.transition = transition; 993 } 994 995 @Override 996 public String getData() { 997 return data == null ? null : data.getString(); 998 } 999 1000 /** 1001 * Set data 1002 * 1003 * @param data 1004 */ 1005 public void setData(String data) { 1006 if (this.data == null) { 1007 this.data = new StringBlob(data); 1008 } 1009 else { 1010 this.data.setString(data); 1011 } 1012 } 1013 1014 public void setDataBlob(StringBlob data) { 1015 this.data = data; 1016 } 1017 1018 public StringBlob getDataBlob() { 1019 return data; 1020 } 1021 1022 @Override 1023 public String getStats() { 1024 return stats == null ? null : stats.getString(); 1025 } 1026 1027 /** 1028 * Set stats 1029 * 1030 * @param stats 1031 */ 1032 public void setStats(String stats) { 1033 if (this.stats == null) { 1034 this.stats = new StringBlob(stats); 1035 } 1036 else { 1037 this.stats.setString(stats); 1038 } 1039 } 1040 1041 public void setStatsBlob(StringBlob stats) { 1042 this.stats = stats; 1043 } 1044 1045 public StringBlob getStatsBlob() { 1046 return this.stats; 1047 } 1048 1049 @Override 1050 public String getExternalId() { 1051 return externalId; 1052 } 1053 1054 /** 1055 * Set external Id 1056 * 1057 * @param externalId 1058 */ 1059 public void setExternalId(String externalId) { 1060 this.externalId = externalId; 1061 } 1062 1063 @Override 1064 public String getExternalStatus() { 1065 return externalStatus; 1066 } 1067 1068 /** 1069 * Set external status 1070 * 1071 * @param externalStatus 1072 */ 1073 public void setExternalStatus(String externalStatus) { 1074 this.externalStatus = externalStatus; 1075 } 1076 1077 @Override 1078 public String getTrackerUri() { 1079 return trackerUri; 1080 } 1081 1082 /** 1083 * Set tracker uri 1084 * 1085 * @param trackerUri 1086 */ 1087 public void setTrackerUri(String trackerUri) { 1088 this.trackerUri = trackerUri; 1089 } 1090 1091 @Override 1092 public String getConsoleUrl() { 1093 return consoleUrl; 1094 } 1095 1096 /** 1097 * Set console URL 1098 * 1099 * @param consoleUrl 1100 */ 1101 public void setConsoleUrl(String consoleUrl) { 1102 this.consoleUrl = consoleUrl; 1103 } 1104 1105 @Override 1106 public String getErrorCode() { 1107 return errorCode; 1108 } 1109 1110 @Override 1111 public String getErrorMessage() { 1112 return errorMessage; 1113 } 1114 1115 /** 1116 * Set the error Info 1117 * 1118 * @param errorCode 1119 * @param errorMessage 1120 */ 1121 public void setErrorInfo(String errorCode, String errorMessage) { 1122 this.errorCode = errorCode; 1123 if (errorMessage != null && errorMessage.length() > 500) { 1124 errorMessage = errorMessage.substring(0, 500); 1125 } 1126 this.errorMessage = errorMessage; 1127 } 1128 1129 @Override 1130 public String toString() { 1131 return MessageFormat.format("Action name[{0}] status[{1}]", getName(), getStatus()); 1132 } 1133 1134 /** 1135 * Convert a nodes list into a JSONArray. 1136 * 1137 * @param nodes nodes list. 1138 * @param timeZoneId time zone to use for dates in the JSON array. 1139 * @return the corresponding JSON array. 1140 */ 1141 @SuppressWarnings("unchecked") 1142 public static JSONArray toJSONArray(List<WorkflowActionBean> nodes, String timeZoneId) { 1143 JSONArray array = new JSONArray(); 1144 for (WorkflowActionBean node : nodes) { 1145 array.add(node.toJSONObject(timeZoneId)); 1146 } 1147 return array; 1148 } 1149 1150}