我有一个使用工厂界面来创建它使用的工具的螺栓。它会在调用prepare
时创建这些工具。 Factory实现只有基本成员(字符串,整数),默认情况下应该是可序列化的。
当我运行我的拓扑时,我得到一个来自工厂实现的NotSerializableException
。我想知道如何为工厂注册序列化器。
这是一个例子:
public class Demo extends BaseRichBolt {
public static interface IExecutor
{
public void execute( Tuple tuple );
}
public static interface IExecutorCreator
{
public IExecutor create( Map map, TopologyContext tc, OutputCollector oc );
};
public static class DummyExecutor implements IExecutor
{
public void execute( Tuple tuple ) {}
};
public static class DummyExecutorCreator implements IExecutorCreator
{
String name_;
public DummyExecutorCreator(String name) { this.name_ = name;}
public IExecutor create(Map map, TopologyContext tc, OutputCollector oc) {
return new DummyExecutor();
}
};
public void declareOutputFields(OutputFieldsDeclarer ofd) {
}
private IExecutor executor_;
private IExecutorCreator creator_;
public Demo(IExecutorCreator creator)
{
this.creator_ = creator;
}
public void prepare(Map map, TopologyContext tc, OutputCollector oc) {
this.executor_ = this.creator_.create(map, tc, oc);
}
public void execute(Tuple tuple) {
this.executor_.execute(tuple);
}
}
当我尝试在拓扑中运行它时,我收到此错误:
java.io.NotSerializableException: Demo$DummyExecutorCreator
作为旁注,我开始怀疑,为什么暴风雨让你注册工厂而不是Bolts和Spouts。因为最终它们被序列化并在不同的线程中被复制,所以最好只给风暴一个意思来产生这些螺栓并分离关注点。
答案 0 :(得分:1)
不要在构造函数中设置任何值。在拓扑首次由驱动程序构建并在拓扑提交到集群之前调用构造函数。这就是为什么你设置的任何实例变量,无论是通过类初始化还是在构造函数中,都必须是可序列化的。
相反,只需将这些实例变量保留为null并在prepare()方法中设置它们。当你这样做时,你不需要序列化任何值,所以这也适用于不可序列化的实例变量。