详细报错信息
Exception in thread "main" org.apache.flink.api.common.typeutils.CompositeType$InvalidFieldReferenceException: Cannot reference field by field expression on GenericType<myflink.windows.Sensor>Field expressions are only supported on POJO types, tuples, and case classes. (See the Flink documentation on what is considered a POJO.)
at org.apache.flink.streaming.util.typeutils.FieldAccessorFactory.getAccessor(FieldAccessorFactory.java:193)
at org.apache.flink.streaming.api.functions.aggregation.SumAggregator.<init>(SumAggregator.java:55)
at org.apache.flink.streaming.api.datastream.KeyedStream.sum(KeyedStream.java:749)
at myflink.windows.TimeWindows.main(TimeWindows.java:42)
上述报错含义为:Flink sum算子只支持对POJO types, tuples, and case classes使用field进行声明,代码中自定义了类,但不是POJO types,因此报错。
错误代码如下:
package myflink.windows;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.datastream.WindowedStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows;
import org.apache.flink.streaming.api.windowing.assigners.WindowAssigner;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.streaming.api.windowing.windows.Window;
import org.apache.flink.util.Collector;
/**
* @projectName: my-flink-project
* @package: myflink.windows
* @className: TimeWindows
* @author: fangjiayueyuan
* @description: TODO
* @date: 2023/5/31 11:34 PM
* @version: 1.0
*/
public class TimeWindows {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStreamSource<String> ds = env.socketTextStream("localhost", 9000);
SingleOutputStreamOperator<Sensor> map = ds.map(new MapFunction<String, Sensor>() {
@Override
public Sensor map(String s) throws Exception {
String[] arr = s.split(",");
return new Sensor(arr[0], Integer.parseInt(arr[1]));
}
});
SingleOutputStreamOperator<Sensor> count = map.keyBy(Sensor::getSensorId).sum("count").returns(TypeInformation.of(Sensor.class));
count.print();
env.execute();
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Sensor {
private String sensorId;
private Integer count;
}
其中Sensor是内部类,不符合POJO types的定义。
什么是POJO types?
Flink 会分析那些不属于任何一类的数据类型,尝试将它们作为 POJO 类型进行处理。如果一个类型满足如下条件,Flink 就会将它们作为 POJO 数据类型:
POJOs 类必须是一个公有类,Public 修饰且独立定义,不能是内部类;
POJOs 类中必须包含一个 Public 修饰的无参构造器;
POJOs 类中所有的字段必须是 Public 或者具有 Public 修饰的 getter 和 setter 方法;
POJOs 类中的字段类型必须是 Flink 支持的。
如何修改
把Sensor类构建成public类即可