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, a.statusStr = :status 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 isTerminalState Return whether workflow action in terminal state or not 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 * @param i the flag 439 */ 440 public void setPending(int i) { 441 pending = i; 442 } 443 444 /** 445 * Set a time when the action will be pending, normally a time in the 446 * future. 447 * 448 * @param pendingAge the time when the action will be pending. 449 */ 450 public void setPendingAge(Date pendingAge) { 451 this.pendingAgeTimestamp = DateUtils.convertDateToTimestamp(pendingAge); 452 } 453 454 /** 455 * Return the pending age of the action. 456 * 457 * @return the pending age of the action, <code>null</code> if the action is 458 * not pending. 459 */ 460 public Date getPendingAge() { 461 return DateUtils.toDate(pendingAgeTimestamp); 462 } 463 464 /** 465 * Return if the action is pending. 466 * 467 * @return if the action is pending. 468 */ 469 public boolean isPending() { 470 return pending == 1 ? true : false; 471 } 472 473 /** 474 * Removes the pending flag and pendingAge from the action. 475 */ 476 public void resetPending() { 477 pending = 0; 478 pendingAgeTimestamp = null; 479 } 480 481 /** 482 * Removes the pending flag from the action. 483 */ 484 public void resetPendingOnly() { 485 pending = 0; 486 } 487 488 /** 489 * Increments the number of retries for the action. 490 */ 491 public void incRetries() { 492 setRetries(getRetries() + 1); 493 } 494 495 /** 496 * Set a tracking information for an action, and set the action status to 497 * {@link org.apache.oozie.client.WorkflowAction.Status#DONE} 498 * 499 * @param externalId external ID for the action. 500 * @param trackerUri tracker URI for the action. 501 * @param consoleUrl console URL for the action. 502 */ 503 public void setStartData(String externalId, String trackerUri, String consoleUrl) { 504 setExternalId(ParamChecker.notEmpty(externalId, "externalId")); 505 setTrackerUri(ParamChecker.notEmpty(trackerUri, "trackerUri")); 506 setConsoleUrl(ParamChecker.notEmpty(consoleUrl, "consoleUrl")); 507 Date now = new Date(); 508 if (this.startTimestamp == null) { 509 setStartTime(now); 510 } 511 setLastCheckTime(now); 512 setStatus(Status.RUNNING); 513 } 514 515 /** 516 * Set the completion information for an action start. Sets the Action 517 * status to {@link org.apache.oozie.client.WorkflowAction.Status#DONE} 518 * 519 * @param externalStatus action external end status. 520 * @param actionData action output data, <code>null</code> if there is no 521 * action output data. 522 */ 523 public void setExecutionData(String externalStatus, Properties actionData) { 524 setStatus(Status.DONE); 525 setExternalStatus(ParamChecker.notEmpty(externalStatus, "externalStatus")); 526 if (actionData != null) { 527 setData(PropertiesUtils.propertiesToString(actionData)); 528 } 529 } 530 531 /** 532 * Return the action statistics info. 533 * 534 * @return Json representation of the stats. 535 */ 536 public String getExecutionStats() { 537 return getStats(); 538 } 539 540 /** 541 * Set the action statistics info for the workflow action. 542 * 543 * @param jsonStats representation of the stats. 544 */ 545 public void setExecutionStats(String jsonStats) { 546 setStats(jsonStats); 547 } 548 549 /** 550 * Return the external child IDs. 551 * 552 * @return externalChildIDs as a string. 553 */ 554 @Override 555 public String getExternalChildIDs() { 556 return externalChildIDs == null ? null : externalChildIDs.getString(); 557 } 558 559 /** 560 * Set the external child IDs for the workflow action. 561 * 562 * @param externalChildIDs as a string. 563 */ 564 public void setExternalChildIDs(String externalChildIDs) { 565 if (this.externalChildIDs == null) { 566 this.externalChildIDs = new StringBlob(externalChildIDs); 567 } 568 else { 569 this.externalChildIDs.setString(externalChildIDs); 570 } 571 } 572 573 /** 574 * Set external child ids 575 * 576 * @param externalChildIDs the external child ids 577 */ 578 public void setExternalChildIDsBlob(StringBlob externalChildIDs) { 579 this.externalChildIDs = externalChildIDs; 580 } 581 582 /** 583 * Get external ChildIds 584 * 585 * @return externalChildIDs Get external ChildIds 586 */ 587 public StringBlob getExternalChildIDsBlob() { 588 return externalChildIDs; 589 } 590 591 /** 592 * Set the completion information for an action end. 593 * 594 * @param status action status, {@link org.apache.oozie.client.WorkflowAction.Status#OK} or 595 * {@link org.apache.oozie.client.WorkflowAction.Status#ERROR} or 596 * {@link org.apache.oozie.client.WorkflowAction.Status#KILLED} 597 * @param signalValue the signal value. In most cases, the value should be 598 * OK or ERROR. 599 */ 600 public void setEndData(Status status, String signalValue) { 601 if (status == null || (status != Status.OK && status != Status.ERROR && status != Status.KILLED)) { 602 throw new IllegalArgumentException("Action status must be OK, ERROR or KILLED. Received [" 603 + (status == null ? "null" : status.toString()) + "]"); 604 } 605 if (status == Status.OK) { 606 setErrorInfo(null, null); 607 } 608 setStatus(status); 609 setSignalValue(ParamChecker.notEmpty(signalValue, "signalValue")); 610 } 611 612 /** 613 * Return the job Id. 614 * 615 * @return the job Id. 616 */ 617 public String getJobId() { 618 return wfId; 619 } 620 621 /** 622 * Return the job Id. 623 * 624 * @return the job Id. 625 */ 626 public String getWfId() { 627 return wfId; 628 } 629 630 /** 631 * Set the job id. 632 * 633 * @param id jobId; 634 */ 635 public void setJobId(String id) { 636 this.wfId = id; 637 } 638 639 public void setSlaXml(String slaXmlStr) { 640 if (this.slaXml == null) { 641 this.slaXml = new StringBlob(slaXmlStr); 642 } 643 else { 644 this.slaXml.setString(slaXmlStr); 645 } 646 } 647 648 public String getSlaXml() { 649 return slaXml == null ? null : slaXml.getString(); 650 } 651 652 public void setSlaXmlBlob(StringBlob slaXml) { 653 this.slaXml = slaXml; 654 } 655 656 public StringBlob getSlaXmlBlob() { 657 return slaXml; 658 } 659 660 /** 661 * Set status of job 662 * 663 * @param val the status 664 */ 665 public void setStatus(Status val) { 666 this.statusStr = val.toString(); 667 } 668 669 @Override 670 public Status getStatus() { 671 return Status.valueOf(this.statusStr); 672 } 673 674 /** 675 * Set status 676 * 677 * @param statusStr the status 678 */ 679 public void setStatusStr(String statusStr) { 680 this.statusStr = statusStr; 681 } 682 683 /** 684 * Get status 685 * 686 * @return statusStr Get status 687 */ 688 public String getStatusStr() { 689 return statusStr; 690 } 691 692 /** 693 * Return the node execution path. 694 * 695 * @return the node execution path. 696 */ 697 public String getExecutionPath() { 698 return executionPath; 699 } 700 701 /** 702 * Set the node execution path. 703 * 704 * @param executionPath the node execution path. 705 */ 706 public void setExecutionPath(String executionPath) { 707 this.executionPath = executionPath; 708 } 709 710 /** 711 * Return the signal value for the action. 712 * <p> 713 * For decision nodes it is the choosen transition, for actions it is OK or 714 * ERROR. 715 * 716 * @return the action signal value. 717 */ 718 public String getSignalValue() { 719 return signalValue; 720 } 721 722 /** 723 * Set the signal value for the action. 724 * <p> 725 * For decision nodes it is the choosen transition, for actions it is OK or 726 * ERROR. 727 * 728 * @param signalValue the action signal value. 729 */ 730 public void setSignalValue(String signalValue) { 731 this.signalValue = signalValue; 732 } 733 734 /** 735 * Return the job log token. 736 * 737 * @return the job log token. 738 */ 739 public String getLogToken() { 740 return logToken; 741 } 742 743 /** 744 * Set the job log token. 745 * 746 * @param logToken the job log token. 747 */ 748 public void setLogToken(String logToken) { 749 this.logToken = logToken; 750 } 751 752 /** 753 * Return the action last check time 754 * 755 * @return the last check time 756 */ 757 public Date getLastCheckTime() { 758 return DateUtils.toDate(lastCheckTimestamp); 759 } 760 761 /** 762 * Return the action last check time 763 * 764 * @return the last check time 765 */ 766 public Timestamp getLastCheckTimestamp() { 767 return lastCheckTimestamp; 768 } 769 770 /** 771 * Return the action last check time 772 * 773 * @return the last check time 774 */ 775 public Timestamp getStartTimestamp() { 776 return startTimestamp; 777 } 778 779 /** 780 * Return the action last check time 781 * 782 * @return the last check time 783 */ 784 public Timestamp getEndTimestamp() { 785 return endTimestamp; 786 } 787 788 /** 789 * Return the action last check time 790 * 791 * @return the last check time 792 */ 793 public Timestamp getPendingAgeTimestamp() { 794 return pendingAgeTimestamp; 795 } 796 797 /** 798 * Sets the action last check time 799 * 800 * @param lastCheckTime the last check time to set. 801 */ 802 public void setLastCheckTime(Date lastCheckTime) { 803 this.lastCheckTimestamp = DateUtils.convertDateToTimestamp(lastCheckTime); 804 } 805 806 public int getPending() { 807 return this.pending; 808 } 809 810 @Override 811 public Date getStartTime() { 812 return DateUtils.toDate(startTimestamp); 813 } 814 815 /** 816 * Set start time 817 * 818 * @param startTime the start time 819 */ 820 public void setStartTime(Date startTime) { 821 this.startTimestamp = DateUtils.convertDateToTimestamp(startTime); 822 } 823 824 @Override 825 public Date getEndTime() { 826 return DateUtils.toDate(endTimestamp); 827 } 828 829 /** 830 * Set end time 831 * 832 * @param endTime the end time 833 */ 834 public void setEndTime(Date endTime) { 835 this.endTimestamp = DateUtils.convertDateToTimestamp(endTime); 836 } 837 838 @SuppressWarnings("unchecked") 839 public JSONObject toJSONObject() { 840 return toJSONObject("GMT"); 841 } 842 843 @SuppressWarnings("unchecked") 844 public JSONObject toJSONObject(String timeZoneId) { 845 JSONObject json = new JSONObject(); 846 json.put(JsonTags.WORKFLOW_ACTION_ID, id); 847 json.put(JsonTags.WORKFLOW_ACTION_NAME, name); 848 json.put(JsonTags.WORKFLOW_ACTION_AUTH, cred); 849 json.put(JsonTags.WORKFLOW_ACTION_TYPE, type); 850 json.put(JsonTags.WORKFLOW_ACTION_CONF, getConf()); 851 json.put(JsonTags.WORKFLOW_ACTION_STATUS, statusStr); 852 json.put(JsonTags.WORKFLOW_ACTION_RETRIES, (long) retries); 853 json.put(JsonTags.WORKFLOW_ACTION_START_TIME, JsonUtils.formatDateRfc822(getStartTime(), timeZoneId)); 854 json.put(JsonTags.WORKFLOW_ACTION_END_TIME, JsonUtils.formatDateRfc822(getEndTime(), timeZoneId)); 855 json.put(JsonTags.WORKFLOW_ACTION_TRANSITION, transition); 856 json.put(JsonTags.WORKFLOW_ACTION_DATA, getData()); 857 json.put(JsonTags.WORKFLOW_ACTION_STATS, getStats()); 858 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_CHILD_IDS, getExternalChildIDs()); 859 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_ID, externalId); 860 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_STATUS, externalStatus); 861 json.put(JsonTags.WORKFLOW_ACTION_TRACKER_URI, trackerUri); 862 json.put(JsonTags.WORKFLOW_ACTION_CONSOLE_URL, consoleUrl); 863 json.put(JsonTags.WORKFLOW_ACTION_ERROR_CODE, errorCode); 864 json.put(JsonTags.WORKFLOW_ACTION_ERROR_MESSAGE, errorMessage); 865 json.put(JsonTags.TO_STRING, toString()); 866 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_INTERVAL, userRetryInterval); 867 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_COUNT, userRetryCount); 868 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_MAX, userRetryMax); 869 json.put(JsonTags.WORKFLOW_ACTION_CRED, cred); 870 return json; 871 } 872 873 @Override 874 public String getId() { 875 return id; 876 } 877 878 public void setId(String id) { 879 this.id = id; 880 } 881 882 public Timestamp getCreatedTimestamp() { 883 return createdTimeTS; 884 } 885 886 public Date getCreatedTime() { 887 return DateUtils.toDate(createdTimeTS); 888 } 889 890 public void setCreatedTime(Date createdTime) { 891 this.createdTimeTS = DateUtils.convertDateToTimestamp(createdTime); 892 } 893 894 @Override 895 public String getName() { 896 return name; 897 } 898 899 public void setName(String name) { 900 this.name = name; 901 } 902 903 @Override 904 public String getCred() { 905 return cred; 906 } 907 908 public void setCred(String cred) { 909 this.cred = cred; 910 } 911 912 @Override 913 public String getType() { 914 return type; 915 } 916 917 public void setType(String type) { 918 this.type = type; 919 } 920 921 @Override 922 public String getConf() { 923 return conf == null ? null : conf.getString(); 924 } 925 926 public void setConf(String conf) { 927 if (this.conf == null) { 928 this.conf = new StringBlob(conf); 929 } 930 else { 931 this.conf.setString(conf); 932 } 933 } 934 935 public void setConfBlob(StringBlob conf) { 936 this.conf = conf; 937 } 938 939 public StringBlob getConfBlob() { 940 return conf; 941 } 942 943 @Override 944 public int getRetries() { 945 return retries; 946 } 947 948 public void setRetries(int retries) { 949 this.retries = retries; 950 } 951 952 @Override 953 public int getUserRetryCount() { 954 return userRetryCount; 955 } 956 957 public void setUserRetryCount(int retryCount) { 958 this.userRetryCount = retryCount; 959 } 960 961 public void incrmentUserRetryCount() { 962 this.userRetryCount++; 963 } 964 965 @Override 966 public int getUserRetryMax() { 967 return userRetryMax; 968 } 969 970 /** 971 * Set user retry max 972 * 973 * @param retryMax the maximum retry count 974 */ 975 public void setUserRetryMax(int retryMax) { 976 this.userRetryMax = retryMax; 977 } 978 979 @Override 980 public int getUserRetryInterval() { 981 return userRetryInterval; 982 } 983 984 public void setUserRetryInterval(int retryInterval) { 985 this.userRetryInterval = retryInterval; 986 } 987 988 @Override 989 public String getTransition() { 990 return transition; 991 } 992 993 /** 994 * Set transition 995 * 996 * @param transition the transition 997 */ 998 public void setTransition(String transition) { 999 this.transition = transition; 1000 } 1001 1002 @Override 1003 public String getData() { 1004 return data == null ? null : data.getString(); 1005 } 1006 1007 /** 1008 * Set data 1009 * 1010 * @param data the data 1011 */ 1012 public void setData(String data) { 1013 if (this.data == null) { 1014 this.data = new StringBlob(data); 1015 } 1016 else { 1017 this.data.setString(data); 1018 } 1019 } 1020 1021 public void setDataBlob(StringBlob data) { 1022 this.data = data; 1023 } 1024 1025 public StringBlob getDataBlob() { 1026 return data; 1027 } 1028 1029 @Override 1030 public String getStats() { 1031 return stats == null ? null : stats.getString(); 1032 } 1033 1034 /** 1035 * Set stats 1036 * 1037 * @param stats the action stats 1038 */ 1039 public void setStats(String stats) { 1040 if (this.stats == null) { 1041 this.stats = new StringBlob(stats); 1042 } 1043 else { 1044 this.stats.setString(stats); 1045 } 1046 } 1047 1048 public void setStatsBlob(StringBlob stats) { 1049 this.stats = stats; 1050 } 1051 1052 public StringBlob getStatsBlob() { 1053 return this.stats; 1054 } 1055 1056 @Override 1057 public String getExternalId() { 1058 return externalId; 1059 } 1060 1061 /** 1062 * Set external Id 1063 * 1064 * @param externalId the id 1065 */ 1066 public void setExternalId(String externalId) { 1067 this.externalId = externalId; 1068 } 1069 1070 @Override 1071 public String getExternalStatus() { 1072 return externalStatus; 1073 } 1074 1075 /** 1076 * Set external status 1077 * 1078 * @param externalStatus the external status 1079 */ 1080 public void setExternalStatus(String externalStatus) { 1081 this.externalStatus = externalStatus; 1082 } 1083 1084 @Override 1085 public String getTrackerUri() { 1086 return trackerUri; 1087 } 1088 1089 /** 1090 * Set tracker uri 1091 * 1092 * @param trackerUri the URI 1093 */ 1094 public void setTrackerUri(String trackerUri) { 1095 this.trackerUri = trackerUri; 1096 } 1097 1098 @Override 1099 public String getConsoleUrl() { 1100 return consoleUrl; 1101 } 1102 1103 /** 1104 * Set console URL 1105 * 1106 * @param consoleUrl the URL 1107 */ 1108 public void setConsoleUrl(String consoleUrl) { 1109 this.consoleUrl = consoleUrl; 1110 } 1111 1112 @Override 1113 public String getErrorCode() { 1114 return errorCode; 1115 } 1116 1117 @Override 1118 public String getErrorMessage() { 1119 return errorMessage; 1120 } 1121 1122 /** 1123 * Set the error Info 1124 * 1125 * @param errorCode the error code 1126 * @param errorMessage the error message 1127 */ 1128 public void setErrorInfo(String errorCode, String errorMessage) { 1129 this.errorCode = errorCode; 1130 if (errorMessage != null && errorMessage.length() > 500) { 1131 errorMessage = errorMessage.substring(0, 500); 1132 } 1133 this.errorMessage = errorMessage; 1134 } 1135 1136 @Override 1137 public String toString() { 1138 return MessageFormat.format("Action name[{0}] status[{1}]", getName(), getStatus()); 1139 } 1140 1141 /** 1142 * Convert a nodes list into a JSONArray. 1143 * 1144 * @param nodes nodes list. 1145 * @param timeZoneId time zone to use for dates in the JSON array. 1146 * @return the corresponding JSON array. 1147 */ 1148 @SuppressWarnings("unchecked") 1149 public static JSONArray toJSONArray(List<WorkflowActionBean> nodes, String timeZoneId) { 1150 JSONArray array = new JSONArray(); 1151 for (WorkflowActionBean node : nodes) { 1152 array.add(node.toJSONObject(timeZoneId)); 1153 } 1154 return array; 1155 } 1156 1157}