目錄
本文以oozie-5.2.0.tar.gz爲例。
創建java項目
使用IDEA開發工具創建一個java項目,目錄結構如圖:
添加依賴
jdom-1.1.jar
oozie-client-5.2.0.jar
oozie-core-5.2.0.jar
這三個包在oozie安裝目錄的lib目錄下。
自定義action
代碼如下:
package com.leboop.www;
import org.apache.oozie.action.ActionExecutor;
import org.apache.oozie.action.ActionExecutorException;
import org.apache.oozie.client.WorkflowAction;
import org.apache.oozie.util.XmlUtils;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import java.io.PrintWriter;
import java.sql.*;
import java.util.HashSet;
import java.util.Set;
/**
* Created by leboop on 2020/6/21.
*/
public class SyncMysqlActionExecutor extends ActionExecutor {
// 自定義節點類型
private static final String ACTION_TYPE = "sync-mysql";
// 自定義節點命名空間
private static final String NAMESPACE = "uri:oozie:sync-mysql-action:0.1";
// 自定義節點的元素
private static final String JDBC_URL = "jdbc-url";
private static final String SQL = "sql";
private static final String SQL_OUTPUT_FILE_PATH = "sql-output-file-path";
// mysql驅動
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static Set<String> COMPLETED_STATUS = new HashSet<String>();
// 無參構造
public SyncMysqlActionExecutor() {
super(ACTION_TYPE);
}
// 靜態塊
static {
COMPLETED_STATUS.add("SUCCEEDED");
COMPLETED_STATUS.add("KILLED");
COMPLETED_STATUS.add("FAILED");
COMPLETED_STATUS.add("FAILED_KILLED");
}
@Override
public void initActionType() {
super.initActionType();
}
public void start(Context context, WorkflowAction workflowAction) throws ActionExecutorException {
Element actionXml = null;
try {
actionXml = XmlUtils.parseXml(workflowAction.getConf());
Namespace ns = Namespace.getNamespace(NAMESPACE);
String jdbcUrl = actionXml.getChildTextTrim(JDBC_URL, ns);
String sql = actionXml.getChildTextTrim(SQL, ns);
String sqlOutputFilePath = actionXml.getChildTextTrim(SQL_OUTPUT_FILE_PATH, ns);
runMysql(jdbcUrl, sql, sqlOutputFilePath);
context.setExecutionData("OK", null);
} catch (JDOMException e) {
e.printStackTrace();
}
}
public void end(Context context, WorkflowAction workflowAction) throws ActionExecutorException {
if (workflowAction.getExternalStatus().equals("OK")) {
context.setEndData(WorkflowAction.Status.OK, WorkflowAction.Status.OK.toString());
} else {
context.setEndData(WorkflowAction.Status.ERROR, WorkflowAction.Status.ERROR.toString());
}
}
public void check(Context context, WorkflowAction workflowAction) throws ActionExecutorException {
throw new UnsupportedOperationException();
}
public void kill(Context context, WorkflowAction workflowAction) throws ActionExecutorException {
context.setEndData(WorkflowAction.Status.KILLED, "ERROR");
}
public boolean isCompleted(String s) {
return COMPLETED_STATUS.contains(s);
}
private void runMysql(String jdbcUrl, String sql, String sqlOutputFilePath) throws ActionExecutorException {
Connection connect = null;
Statement statement = null;
ResultSet resultSet = null;
try {
Class.forName(DRIVER);
connect = DriverManager.getConnection(jdbcUrl);
statement = connect.createStatement();
resultSet = statement.executeQuery(sql);
writeResultSet(resultSet, sqlOutputFilePath);
} catch (Exception e) {
throw convertException(e);
} finally {
try {
if (resultSet != null)
resultSet.close();
if (statement != null)
statement.close();
if (connect != null)
connect.close();
} catch (Exception e) {
throw convertException(e);
}
}
}
private void writeResultSet(ResultSet resultSet, String sqlOutPutFilePath) throws Exception {
PrintWriter out;
if (sqlOutPutFilePath != null && sqlOutPutFilePath.length() > 0) {
out = new PrintWriter(sqlOutPutFilePath);
} else {
out = new PrintWriter(System.out);
}
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
for (int i = 1; i <= metaData.getColumnCount(); i++) {
out.println(metaData.getColumnName(i) + "=" + resultSet.getString(i));
}
}
out.close();
}
}
定義schema
sync_mysql-0.1.xsd 如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:sync-mysql="uri:oozie:sync-mysql-action:0.1" elementFormDefault="qualified"
targetNamespace="uri:oozie:sync-mysql-action:0.1">
<xs:element name="sync-mysql" type="sync-mysql:sync_mysql_type"/>
<xs:complexType name="sync_mysql_type">
<xs:sequence>
<xs:element name="jdbc-url" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="sql" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="sql-output-file-path" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
項目打包
打瘦包即可,如圖:
將包拷貝到oozie安裝目錄lib下。
oozie-site.xml添加配置
內容如下:
<property>
<name>oozie.service.ActionService.executor.ext.classes</name>
<value>com.leboop.www.SyncMysqlActionExecutor</value>
</property>
<property>
<name>oozie.service.SchemaService.wf.ext.schemas</name>
<value>sync_mysql-0.1.xsd</value>
</property>
重啓oozie server。
job.properties
nameNode=hdfs://single:9000
jobTracker=single:8032
queueName=default
examplesRoot=jobs
oozie.use.system.libpath=true
oozie.wf.application.path=${nameNode}/user/root/${examplesRoot}/sync-mysql
jdbcURL=jdbc:mysql://192.168.128.1:3306/oozie?user=root&password=root
sql=select * from oozie_sys;
SQL_OUTPUT_PATH=/out/result.txt
需要在Linux上創建/out/result.txt文件。
workflow.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<workflow-app xmlns="uri:oozie:workflow:0.5" name="sync-mysql-wf">
<start to="sync-mysql-node"/>
<action name="sync-mysql-node">
<sync-mysql xmlns="uri:oozie:sync-mysql-action:0.1">
<jdbc-url>${jdbcURL}</jdbc-url>
<sql>${sql}</sql>
<sql-output-file-path>${SQL_OUTPUT_PATH}</sql-output-file-path>
</sync-mysql>
<ok to="end"/>
<error to="fail"/>
</action>
<kill name="fail">
<message>syncMysql failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
</kill>
<end name="end"/>
</workflow-app>
需要將workflow.xml拷貝到job.properties配置的oozie.wf.application.path路徑下。
測試
oozie job -config job.properties -run
如圖:
查看日誌:
oozie job -info 0000004-200621162902099-oozie-root-W
如圖:
最後會將查詢oozie數據庫中oozie_sys表的內容:
輸出到/out/result.txt文件中,內容如下:
name=db.version
data=4
name=oozie.version
data=5.2.0