Flink快速构建项目quickstart - 自定义UDF函数

官方推荐两种构建方式,第一

mvn archetype:generate -DarchetypeGroupId=org.apache.flink -DarchetypeArtifactId=flink-quickstart-java  -DarchetypeVersion=1.12.0

创建flink的UDF需要Flink-table的jar包,ScalarFunction在table的依赖中

通过quickstart构建后,在pom.xml中加入依赖

        <dependency>
            <groupId>org.apache.flink</groupId>
            <!--<artifactId>flink-table_${scala.binary.version}</artifactId>-->
            <artifactId>flink-table_2.11</artifactId>
            <version>${flink.version}</version>
        </dependency>

创建java类

 

package department.jr;

import org.apache.flink.table.functions.ScalarFunction;

public class HashCode extends ScalarFunction {

    /**
     * udf的这个方法必须是public的
     * @param s
     * @return
     */
    public int eval(String s){
        return s.hashCode();
    }
    
//    public static void main(String[] args) {
//        HashCode hashCode = new HashCode();
//        System.out.println(hashCode.eval("abc"));
//    }
}

 

 

package department.jr;

import org.apache.flink.table.functions.ScalarFunction;

/**
 * 给一个数值乘以一个因子
 */
public class Multiply extends ScalarFunction {
    public Integer factor;

    public Multiply() {
    }
    public Multiply(int factor) {
        this.factor = factor;
    }
    public int eval(Integer s){
        return s * factor;
    }
}

 

 

 

 

运行一下试试,发现报错

java.lang.NoClassDefFoundError: org/apache/flink/api/common/functions/InvalidTypesException
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
    at java.lang.Class.getMethod0(Class.java:3018)
    at java.lang.Class.getMethod(Class.java:1784)
    at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: org.apache.flink.api.common.functions.InvalidTypesException
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    ... 7 more
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" 
Process finished with exit code 1

原因:pom.xml中的核心包都是<provided>的,调试时候注释掉<provieded>,采用默认值。

成功!

注释掉main方法,打包UDF类:

jr-flinkudf-0.1.jar

 上传 jr-flinkudf-0.1.jar 到Flink的lib目录下。

修改 Flink的conf的目录下的 sql-client-defaults.yaml 文件

 

 启动Flink-sql-client

./sql-client.sh embedded

发现报错:

Exception in thread "main" org.apache.flink.table.client.SqlClientException: Unexpected exception. This is a bug. Please consider filing an issue.
        at org.apache.flink.table.client.SqlClient.main(SqlClient.java:208)
Caused by: org.apache.flink.table.client.gateway.SqlExecutionException: Could not create execution context.
        at org.apache.flink.table.client.gateway.local.ExecutionContext$Builder.build(ExecutionContext.java:878)
        at org.apache.flink.table.client.gateway.local.LocalExecutor.openSession(LocalExecutor.java:226)
        at org.apache.flink.table.client.SqlClient.start(SqlClient.java:108)
        at org.apache.flink.table.client.SqlClient.main(SqlClient.java:196)
Caused by: org.apache.flink.table.api.ValidationException: Cannot find a public constructor with parameter types 'java.lang.Integer' for 'department.jr.Multiply'.
        at org.apache.flink.table.functions.FunctionService.generateInstance(FunctionService.java:205)
        at org.apache.flink.table.functions.FunctionService.createFunction(FunctionService.java:115)
        at org.apache.flink.table.client.gateway.local.ExecutionContext.lambda$registerFunctions$10(ExecutionContext.java:704)
        at java.util.HashMap.forEach(HashMap.java:1288)
        at org.apache.flink.table.client.gateway.local.ExecutionContext.registerFunctions(ExecutionContext.java:703)
        at org.apache.flink.table.client.gateway.local.ExecutionContext.initializeTableEnvironment(ExecutionContext.java:523)
        at org.apache.flink.table.client.gateway.local.ExecutionContext.<init>(ExecutionContext.java:185)
        at org.apache.flink.table.client.gateway.local.ExecutionContext.<init>(ExecutionContext.java:138)
        at org.apache.flink.table.client.gateway.local.ExecutionContext$Builder.build(ExecutionContext.java:867)
        ... 3 more

原因:Multiply 类的构造器是int类型的参数,但是FlinkSQL只允许是Interger类型,见官方文档

ref: https://ci.apache.org/projects/flink/flink-docs-release-1.12/zh/dev/table/sqlClient.html

 

修改 Multiply 类的构造器 参数为Integer,重新打包上传。

成功启动sql-client端。使用两个自定义UDF函数,没问题!

 

posted @ 2021-04-16 18:32  cknds  阅读(1124)  评论(0编辑  收藏  举报