UDF не работает с внешней переменной [Java -spark] - PullRequest
1 голос
/ 07 апреля 2020

Я пытаюсь выполнить следующий код.

Я беру набор данных в качестве входных данных, выполняю некоторые операции с ним, используя Groovyshell, и добавляю этот результат в новый столбец в наборе данных.

private static Dataset<Row> addDebitCreditCol(SparkSession sparkSession,Dataset<Row> df,String code){
        Script script=new GroovyShell().parse(code);
        UDF3 rulesExecutingUDF = (UDF3<Double, String, String, String>) (val1, val2, val3) -> {
            Binding binding = new Binding();
            binding.setVariable("val1",val1);
            binding.setVariable("val2", val2);
            binding.setVariable("val3", val3);
            Object value = script.run();
            return value.toString();
        };
        sparkSession.udf().register("rulesExecutingUDF",rulesExecutingUDF,DataTypes.StringType);
        df=df.withColumn("NEW_COL",callUDF("rulesExecutingUDF",col("val1").,col("val2"),col("val3")));
        return df;
    }

Когда я выполняю этот код, выдается сообщение об ошибке:

Исключение класса пользователя: org. apache .spark.SparkException: Задача не сериализуема. Вызывается: java .io.NotSerializableException: Script1

Похоже, я не могу использовать внешнюю переменную (здесь это Script) внутри UDF. Какие у меня есть альтернативы?

Я пытался заставить эту внешнюю переменную как-то работать, но она не работала, и я не могу найти альтернативу UDF, которая могла бы это сделать.

1 Ответ

0 голосов
/ 07 апреля 2020

Простым способом решения этой проблемы может быть использование базового класса сценария , который реализует сам Serializable.

public static abstract class BaseClass extends Script implements Serializable {

}

И затем использование этого класса в качестве суперкласса вашего сценария :

CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass("stackoverflow.Main.BaseClass"); //use your FQCN
Script script = new GroovyShell(Main.class.getClassLoader(), config).parse(code);

Это сделает script Serializable экземпляр. Если вы протестируете script instanceof BaseClass и script instanceof Serializable, они оба вернут true.

...