Wicket应用程序、序列化和Java计时器

Wicket应用程序、序列化和Java计时器,java,serialization,timer,wicket,Java,Serialization,Timer,Wicket,因此,我在序列化、Wicket和多线程项目方面的经验有限,所以请耐心等待 从本质上说,我的web应用程序类实例化了一个POJ(parentObject),它创建了一个新的计时器,并实例化了几个也包含计时器的ChildObject。这些子对象存储在parentObject类的列表中。wicket应用程序中的页面需要访问parentObject,因此我将其设置为可访问: public Object getParentObject { return this.parentObject; } 在

因此,我在序列化、Wicket和多线程项目方面的经验有限,所以请耐心等待

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

public Object getParentObject
{
   return this.parentObject;
}
在每个页面中检索,如下所示:

((MyApplication)Application.get()).getParentObject()
目前的问题是parentObject和ChildObject的timertask不再像应该的那样每分钟都被调用一次。我的日志会拾取parentObject的第一个开始,但是日志消息不会再次输出,表明父对象的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);
    }
}
公共类childObject实现可序列化
{
私有瞬态名称参数jdbctemplate njt;
专用瞬态定时器;
公共子对象(数据源ds)
{
this.njt=新名称参数JDBCTemplate(ds);
}
公开作废开始()
{
定时器=新定时器();
timer.schedule(新TimerTask(){
公开募捐
{
//做一些从未发生过的事情
}
}, 0, 60000);
}
}
公共类ParentObject实现了可序列化
{
私有数据源ds;
私有列表对象;
专用瞬态定时器;
公共ParentObject(数据源ds)
{
这是1.ds=ds;
//向childObjects添加一些内容
定时器=新定时器();
timer.schedule(新TimerTask(){
公开募捐
{
为了(某些条件)
{
//做点什么
如果(/*条件满足*/)
{
get(i).start();
}
}
}
}, 0, 60000);
}
}
公共MyApplication扩展了WebApplication
{
私有父对象;
私有数据源ds;
公共void init()
{
super.init();
ApplicationContext context=new ClassPathXmlApplicationContext(“/ApplicationContext.xml”);
ds=(DataSource)context.getBean(“DataSource”);
parentObject=新的parentObject(ds);
}
}

根据您的问题描述,我认为您可以将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();
    }
}
公共类ParentObjectModel扩展了LoadableDetachableModel{
@重写公共父对象加载(){
return((MyApplication)Application.get()).getParentObject();
}
}

请参阅。

WicketApplication是Singleton,不会被序列化为页面或会话。感谢您的评论。我明白这一点,但我的计时器仍然没有按预期工作。我添加了一些伪代码来显示这种情况,你是说我应该将parentObject变量作为公共变量存储在应用程序中?这与使用访问器方法将其存储为私有变量有什么不同吗,因为这是我目前正在做的事情。我从来没有说过。Wicket足够聪明,可以使用私有字段和/或访问器。这就是房产模型的工作原理。谢谢你的建议。我编辑了这个问题,添加了一些更详细的代码。