1

所以我在序列化、Wicket 和多线程项目方面的经验有些有限,所以请多多包涵。

本质上,我的 Web 应用程序类正在实例化一个 POJ(parentObject),它创建一个启动一个新计时器并实例化几个在其中也有计时器的子对象。这些子对象存储在 parentObject 类的列表中。我的 wicket 应用程序中的页面需要访问 parentObject,因此我将其设置为可访问:

public Object getParentObject
{
   return this.parentObject;
}

它在每个页面中被检索,如下所示:

((MyApplication)Application.get()).getParentObject()

当前的问题是 parentObject 和 childObjects 的 timertask 不再像应有的那样每分钟都被调用。我的日志记录了父对象的第一次启动,但日志消息永远不会再次输出,表明父对象的 timertask 的 run() 方法不是每分钟都在执行。

编辑:添加了更多代码以使问题更清楚

public class childObject implements Serializable
{
    private transient NamedParameterJdbcTemplate njt;
    private transient Timer timer;

    public childObject(DataSource ds)
    {
        this.njt = new NamedParamterJdbcTemplate(ds);
    }

    public void start()
    {
        timer = new Timer();

        timer.schedule(new TimerTask(){

            public void run()
            {
                //do some stuff that is never happening
            }

        }, 0, 60000);
    }
}

public class ParentObject implements Serializable
{
    private DataSource ds;
    private List<ChildObject> childObjects;
    private transient Timer;

    public ParentObject(DataSource ds)
    {
        this.ds = ds;
        //add some stuff to childObjects

        timer = new Timer();

        timer.schedule(new TimerTask(){

            public void run()
            {
                for(some condition)
                {
                    //Do some stuff

                    if(/*condition is met*/)
                    {
                        childObjects.get(i).start();
                    }
                }
            }

        }, 0, 60000);
    }
}

public MyApplication extends WebApplication
{
    private ParentObject object;
    private DataSource ds;

    public void init()
    {
        super.init();

        ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
        ds = (DataSource) context.getBean("dataSource");

        parentObject = new ParentObject(ds);
    }
}
4

1 回答 1

3

鉴于您的问题描述,我认为您将 ParentObject 直接绑定到您的组件,而不是绑定对 ParentObject 的引用。会话范围对象(实际上是所有页面、组件和模型)的序列化/反序列化会创建这些“新”实例(即使它们是原始父对象的反序列化副本)。

虽然您没有显示太多代码,但我怀疑您会执行以下操作:

public MyPage() {
    Object parentObject = ((MyApplication)Application.get()).getParentObject();
    add(new Label("timer", new PropertyModel(parentObject, "time")));
}

这将父对象绑定到属性模型,并将父对象绑定到页面(通过标签组件)。你应该做的是:

public MyPage() {
    add(new Label("timer", new PropertyModel(this, "application.parentObject.time")));
}

这将页面绑定到自身,并指示属性模型动态检索应用程序,并从应用程序获取父对象,并从该时间开始。这样您就不会将对象绑定到页面层次结构,而是动态检索它们。

另一种选择是使用 LoadableDetachableModel 从应用程序中检索父对象,并在呈现页面后将其分离。

public class ParentObjectModel extends LoadableDetachableModel<ParentObject> {
    @Override public ParentObject load() {
        return ((MyApplication)Application.get()).getParentObject();
    }
}

有关模型的更多信息,请参阅Wicket wiki

于 2012-04-17T09:49:07.693 回答