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