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 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 org.apache.oozie.client.WorkflowAction.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 org.apache.oozie.client.WorkflowAction.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 jsonStats 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 org.apache.oozie.client.WorkflowAction.Status#OK} or 594 * {@link org.apache.oozie.client.WorkflowAction.Status#ERROR} or 595 * {@link org.apache.oozie.client.WorkflowAction.Status#KILLED} 596 * @param signalValue the signal value. In most cases, the value should be 597 * OK or ERROR. 598 */ 599 public void setEndData(Status status, String signalValue) { 600 if (status == null || (status != Status.OK && status != Status.ERROR && status != Status.KILLED)) { 601 throw new IllegalArgumentException("Action status must be OK, ERROR or KILLED. Received [" 602 + status.toString() + "]"); 603 } 604 if (status == Status.OK) { 605 setErrorInfo(null, null); 606 } 607 setStatus(status); 608 setSignalValue(ParamChecker.notEmpty(signalValue, "signalValue")); 609 } 610 611 /** 612 * Return the job Id. 613 * 614 * @return the job Id. 615 */ 616 public String getJobId() { 617 return wfId; 618 } 619 620 /** 621 * Return the job Id. 622 * 623 * @return the job Id. 624 */ 625 public String getWfId() { 626 return wfId; 627 } 628 629 /** 630 * Set the job id. 631 * 632 * @param id jobId; 633 */ 634 public void setJobId(String id) { 635 this.wfId = id; 636 } 637 638 public void setSlaXml(String slaXmlStr) { 639 if (this.slaXml == null) { 640 this.slaXml = new StringBlob(slaXmlStr); 641 } 642 else { 643 this.slaXml.setString(slaXmlStr); 644 } 645 } 646 647 public String getSlaXml() { 648 return slaXml == null ? null : slaXml.getString(); 649 } 650 651 public void setSlaXmlBlob(StringBlob slaXml) { 652 this.slaXml = slaXml; 653 } 654 655 public StringBlob getSlaXmlBlob() { 656 return slaXml; 657 } 658 659 /** 660 * Set status of job 661 * 662 * @param val 663 */ 664 public void setStatus(Status val) { 665 this.statusStr = val.toString(); 666 } 667 668 @Override 669 public Status getStatus() { 670 return Status.valueOf(this.statusStr); 671 } 672 673 /** 674 * Set status 675 * 676 * @param statusStr 677 */ 678 public void setStatusStr(String statusStr) { 679 this.statusStr = statusStr; 680 } 681 682 /** 683 * Get status 684 * 685 * @return 686 */ 687 public String getStatusStr() { 688 return statusStr; 689 } 690 691 /** 692 * Return the node execution path. 693 * 694 * @return the node execution path. 695 */ 696 public String getExecutionPath() { 697 return executionPath; 698 } 699 700 /** 701 * Set the node execution path. 702 * 703 * @param executionPath the node execution path. 704 */ 705 public void setExecutionPath(String executionPath) { 706 this.executionPath = executionPath; 707 } 708 709 /** 710 * Return the signal value for the action. 711 * <p> 712 * For decision nodes it is the choosen transition, for actions it is OK or 713 * ERROR. 714 * 715 * @return the action signal value. 716 */ 717 public String getSignalValue() { 718 return signalValue; 719 } 720 721 /** 722 * Set the signal value for the action. 723 * <p> 724 * For decision nodes it is the choosen transition, for actions it is OK or 725 * ERROR. 726 * 727 * @param signalValue the action signal value. 728 */ 729 public void setSignalValue(String signalValue) { 730 this.signalValue = signalValue; 731 } 732 733 /** 734 * Return the job log token. 735 * 736 * @return the job log token. 737 */ 738 public String getLogToken() { 739 return logToken; 740 } 741 742 /** 743 * Set the job log token. 744 * 745 * @param logToken the job log token. 746 */ 747 public void setLogToken(String logToken) { 748 this.logToken = logToken; 749 } 750 751 /** 752 * Return the action last check time 753 * 754 * @return the last check time 755 */ 756 public Date getLastCheckTime() { 757 return DateUtils.toDate(lastCheckTimestamp); 758 } 759 760 /** 761 * Return the action last check time 762 * 763 * @return the last check time 764 */ 765 public Timestamp getLastCheckTimestamp() { 766 return lastCheckTimestamp; 767 } 768 769 /** 770 * Return the action last check time 771 * 772 * @return the last check time 773 */ 774 public Timestamp getStartTimestamp() { 775 return startTimestamp; 776 } 777 778 /** 779 * Return the action last check time 780 * 781 * @return the last check time 782 */ 783 public Timestamp getEndTimestamp() { 784 return endTimestamp; 785 } 786 787 /** 788 * Return the action last check time 789 * 790 * @return the last check time 791 */ 792 public Timestamp getPendingAgeTimestamp() { 793 return pendingAgeTimestamp; 794 } 795 796 /** 797 * Sets the action last check time 798 * 799 * @param lastCheckTime the last check time to set. 800 */ 801 public void setLastCheckTime(Date lastCheckTime) { 802 this.lastCheckTimestamp = DateUtils.convertDateToTimestamp(lastCheckTime); 803 } 804 805 public int getPending() { 806 return this.pending; 807 } 808 809 @Override 810 public Date getStartTime() { 811 return DateUtils.toDate(startTimestamp); 812 } 813 814 /** 815 * Set start time 816 * 817 * @param startTime 818 */ 819 public void setStartTime(Date startTime) { 820 this.startTimestamp = DateUtils.convertDateToTimestamp(startTime); 821 } 822 823 @Override 824 public Date getEndTime() { 825 return DateUtils.toDate(endTimestamp); 826 } 827 828 /** 829 * Set end time 830 * 831 * @param endTime 832 */ 833 public void setEndTime(Date endTime) { 834 this.endTimestamp = DateUtils.convertDateToTimestamp(endTime); 835 } 836 837 @SuppressWarnings("unchecked") 838 public JSONObject toJSONObject() { 839 return toJSONObject("GMT"); 840 } 841 842 @SuppressWarnings("unchecked") 843 public JSONObject toJSONObject(String timeZoneId) { 844 JSONObject json = new JSONObject(); 845 json.put(JsonTags.WORKFLOW_ACTION_ID, id); 846 json.put(JsonTags.WORKFLOW_ACTION_NAME, name); 847 json.put(JsonTags.WORKFLOW_ACTION_AUTH, cred); 848 json.put(JsonTags.WORKFLOW_ACTION_TYPE, type); 849 json.put(JsonTags.WORKFLOW_ACTION_CONF, getConf()); 850 json.put(JsonTags.WORKFLOW_ACTION_STATUS, statusStr); 851 json.put(JsonTags.WORKFLOW_ACTION_RETRIES, (long) retries); 852 json.put(JsonTags.WORKFLOW_ACTION_START_TIME, JsonUtils.formatDateRfc822(getStartTime(), timeZoneId)); 853 json.put(JsonTags.WORKFLOW_ACTION_END_TIME, JsonUtils.formatDateRfc822(getEndTime(), timeZoneId)); 854 json.put(JsonTags.WORKFLOW_ACTION_TRANSITION, transition); 855 json.put(JsonTags.WORKFLOW_ACTION_DATA, getData()); 856 json.put(JsonTags.WORKFLOW_ACTION_STATS, getStats()); 857 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_CHILD_IDS, getExternalChildIDs()); 858 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_ID, externalId); 859 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_STATUS, externalStatus); 860 json.put(JsonTags.WORKFLOW_ACTION_TRACKER_URI, trackerUri); 861 json.put(JsonTags.WORKFLOW_ACTION_CONSOLE_URL, consoleUrl); 862 json.put(JsonTags.WORKFLOW_ACTION_ERROR_CODE, errorCode); 863 json.put(JsonTags.WORKFLOW_ACTION_ERROR_MESSAGE, errorMessage); 864 json.put(JsonTags.TO_STRING, toString()); 865 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_INTERVAL, userRetryInterval); 866 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_COUNT, userRetryCount); 867 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_MAX, userRetryMax); 868 json.put(JsonTags.WORKFLOW_ACTION_CRED, cred); 869 return json; 870 } 871 872 @Override 873 public String getId() { 874 return id; 875 } 876 877 public void setId(String id) { 878 this.id = id; 879 } 880 881 public Timestamp getCreatedTimestamp() { 882 return createdTimeTS; 883 } 884 885 public Date getCreatedTime() { 886 return DateUtils.toDate(createdTimeTS); 887 } 888 889 public void setCreatedTime(Date createdTime) { 890 this.createdTimeTS = DateUtils.convertDateToTimestamp(createdTime); 891 } 892 893 @Override 894 public String getName() { 895 return name; 896 } 897 898 public void setName(String name) { 899 this.name = name; 900 } 901 902 @Override 903 public String getCred() { 904 return cred; 905 } 906 907 public void setCred(String cred) { 908 this.cred = cred; 909 } 910 911 @Override 912 public String getType() { 913 return type; 914 } 915 916 public void setType(String type) { 917 this.type = type; 918 } 919 920 @Override 921 public String getConf() { 922 return conf == null ? null : conf.getString(); 923 } 924 925 public void setConf(String conf) { 926 if (this.conf == null) { 927 this.conf = new StringBlob(conf); 928 } 929 else { 930 this.conf.setString(conf); 931 } 932 } 933 934 public void setConfBlob(StringBlob conf) { 935 this.conf = conf; 936 } 937 938 public StringBlob getConfBlob() { 939 return conf; 940 } 941 942 @Override 943 public int getRetries() { 944 return retries; 945 } 946 947 public void setRetries(int retries) { 948 this.retries = retries; 949 } 950 951 @Override 952 public int getUserRetryCount() { 953 return userRetryCount; 954 } 955 956 public void setUserRetryCount(int retryCount) { 957 this.userRetryCount = retryCount; 958 } 959 960 public void incrmentUserRetryCount() { 961 this.userRetryCount++; 962 } 963 964 @Override 965 public int getUserRetryMax() { 966 return userRetryMax; 967 } 968 969 /** 970 * Set user retry max 971 * 972 * @param retryMax 973 */ 974 public void setUserRetryMax(int retryMax) { 975 this.userRetryMax = retryMax; 976 } 977 978 @Override 979 public int getUserRetryInterval() { 980 return userRetryInterval; 981 } 982 983 public void setUserRetryInterval(int retryInterval) { 984 this.userRetryInterval = retryInterval; 985 } 986 987 @Override 988 public String getTransition() { 989 return transition; 990 } 991 992 /** 993 * Set transition 994 * 995 * @param transition 996 */ 997 public void setTransition(String transition) { 998 this.transition = transition; 999 } 1000 1001 @Override 1002 public String getData() { 1003 return data == null ? null : data.getString(); 1004 } 1005 1006 /** 1007 * Set data 1008 * 1009 * @param data 1010 */ 1011 public void setData(String data) { 1012 if (this.data == null) { 1013 this.data = new StringBlob(data); 1014 } 1015 else { 1016 this.data.setString(data); 1017 } 1018 } 1019 1020 public void setDataBlob(StringBlob data) { 1021 this.data = data; 1022 } 1023 1024 public StringBlob getDataBlob() { 1025 return data; 1026 } 1027 1028 @Override 1029 public String getStats() { 1030 return stats == null ? null : stats.getString(); 1031 } 1032 1033 /** 1034 * Set stats 1035 * 1036 * @param stats 1037 */ 1038 public void setStats(String stats) { 1039 if (this.stats == null) { 1040 this.stats = new StringBlob(stats); 1041 } 1042 else { 1043 this.stats.setString(stats); 1044 } 1045 } 1046 1047 public void setStatsBlob(StringBlob stats) { 1048 this.stats = stats; 1049 } 1050 1051 public StringBlob getStatsBlob() { 1052 return this.stats; 1053 } 1054 1055 @Override 1056 public String getExternalId() { 1057 return externalId; 1058 } 1059 1060 /** 1061 * Set external Id 1062 * 1063 * @param externalId 1064 */ 1065 public void setExternalId(String externalId) { 1066 this.externalId = externalId; 1067 } 1068 1069 @Override 1070 public String getExternalStatus() { 1071 return externalStatus; 1072 } 1073 1074 /** 1075 * Set external status 1076 * 1077 * @param externalStatus 1078 */ 1079 public void setExternalStatus(String externalStatus) { 1080 this.externalStatus = externalStatus; 1081 } 1082 1083 @Override 1084 public String getTrackerUri() { 1085 return trackerUri; 1086 } 1087 1088 /** 1089 * Set tracker uri 1090 * 1091 * @param trackerUri 1092 */ 1093 public void setTrackerUri(String trackerUri) { 1094 this.trackerUri = trackerUri; 1095 } 1096 1097 @Override 1098 public String getConsoleUrl() { 1099 return consoleUrl; 1100 } 1101 1102 /** 1103 * Set console URL 1104 * 1105 * @param consoleUrl 1106 */ 1107 public void setConsoleUrl(String consoleUrl) { 1108 this.consoleUrl = consoleUrl; 1109 } 1110 1111 @Override 1112 public String getErrorCode() { 1113 return errorCode; 1114 } 1115 1116 @Override 1117 public String getErrorMessage() { 1118 return errorMessage; 1119 } 1120 1121 /** 1122 * Set the error Info 1123 * 1124 * @param errorCode 1125 * @param errorMessage 1126 */ 1127 public void setErrorInfo(String errorCode, String errorMessage) { 1128 this.errorCode = errorCode; 1129 if (errorMessage != null && errorMessage.length() > 500) { 1130 errorMessage = errorMessage.substring(0, 500); 1131 } 1132 this.errorMessage = errorMessage; 1133 } 1134 1135 @Override 1136 public String toString() { 1137 return MessageFormat.format("Action name[{0}] status[{1}]", getName(), getStatus()); 1138 } 1139 1140 /** 1141 * Convert a nodes list into a JSONArray. 1142 * 1143 * @param nodes nodes list. 1144 * @param timeZoneId time zone to use for dates in the JSON array. 1145 * @return the corresponding JSON array. 1146 */ 1147 @SuppressWarnings("unchecked") 1148 public static JSONArray toJSONArray(List<WorkflowActionBean> nodes, String timeZoneId) { 1149 JSONArray array = new JSONArray(); 1150 for (WorkflowActionBean node : nodes) { 1151 array.add(node.toJSONObject(timeZoneId)); 1152 } 1153 return array; 1154 } 1155 1156}