JpaRepository无法在自定义RichSinkFunction中自动装配

时间:2018-10-11 00:12:31

标签: java spring spring-data-jpa apache-flink flink-streaming

我创建了一个自定义Flink RichSinkFunction,并尝试在此自定义类中自动连接JpaRepository,但是我一直在获取NullPointerException。 如果我在构造函数中对其进行自动布线,则可以看到已经找到了JpaRepo-但是当调用invoke方法时,我会收到一个NullPointerException

public interface MessageRepo extends JpaRepository<Message, Long> {
}


@Component
public class MessageSink extends RichSinkFunction<Message> {

    private final transient MessageRepo messageRepo; //if i don't make this transient, i get the error message "The implementation of the RichSinkFunction is not serializable"

    @Autowired
    public MessageSink(MessageRepo messageRepo){
        this.messageRepo = messageRepo;
        messageRepo.save(new Message()); //no issues when i do this
    }

    @Override
    public void invoke(Message message, Context context) {
         // the message is not null
         messageRepo.save(message); // NPE
    }

有人曾经遇到过这个问题吗?看起来MessageSink的invoke方法是在单独的线程中被调用的,这就是messageRepo始终为null的原因? 除了拥有自己的自定义接收器外,代码的其他部分还可以使用MessageRepo。

2 个答案:

答案 0 :(得分:1)

我不清楚原因,但是我认为Spring Boot在注入bean时会优先考虑您的服务类。当我尝试为Entity类编写侦听器时,我遇到了类似的问题。这就是我解决的方法。 创建一个实现ApplicationContextAware接口的组件类,并重写setApplicationContext方法。在名为getBean的类中有一个静态方法,该方法将在您的第一个请求时自动装配。示例代码---

@Component
public class SpringBeansUtil implements ApplicationContextAware {
private static ApplicationContext context;

    @SuppressWarnings("static-access")
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) 
    throws BeansException {
    this.context = applicationContext;
}

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
}

然后在代码中添加bean ------- >>     ClassName referenceName =(ClassName)SpringBeansUtil.getBean(ClassName.class);

答案 1 :(得分:1)

我认为这里的问题是flink需要在自定义接收器函数分发给其工作程序之前对其进行序列化。

通过标记MessageRepo传输,这意味着当工作程序节点反序列化此功能时,该字段将为null。通常,您可以在open函数中初始化传输依赖关系,该函数将在反序列化对象后调用。