1

有一个使用 Play 执行此操作的示例!v2.0但我正在尝试对 v1.2.4 做同样的事情

我尝试遵循相同的通用方法,即让Heroku 调度程序使用初始化 Play 环境的类显式启动 JVM,然后在该环境中执行所需的任务。我的具体任务是使用 JPA 从数据库中检索一些数据,然后使用 Mailer 使用该数据生成电子邮件。最初的方法只是在初始化 Play 后直接执行逻辑,但我遇到了一个异常,即“JPA 上下文未初始化”。

档案:

web: play run --http.port=$PORT $PLAY_OPTS
reports: java -Dapplication.path=./ -Dplay.id=staging -Dprecompiled=true -DlogLevel=INFO -cp "precompiled/java:lib/*:conf:.play/framework/play-1.2.4.jar:.play/framework/lib/*:modules/mailerPlus-0.1/lib/*:modules/fastergt-1.7/lib/*" jobs.Reports .

报告.java:

public class Reports {

    private Reports() {
        super();
    }

    public static void main(String[] args) {
        File root = new File(System.getProperty("application.path"));

        if (System.getProperty("precompiled", "false").equals("true")) {
            Play.usePrecompiled = true;
        }

        try {
            Play.init(root, System.getProperty("play.id", ""));

            Mails.itjbSurveyReport();
        } catch (Exception e) {
            Logger.error(e, "");
        } finally {
            Play.stop();
        }
    }
}

日志:

2012-06-20T21:58:27+00:00 app[run.1]: play.exceptions.JPAException: The JPA context is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the @javax.persistence.Entity annotation are found in the application.
2012-06-20T21:58:27+00:00 app[run.1]:   at play.db.jpa.JPA.get(JPA.java:22)
2012-06-20T21:58:27+00:00 app[run.1]:   at play.db.jpa.JPA.em(JPA.java:51)
2012-06-20T21:58:27+00:00 app[run.1]:   at play.db.jpa.JPQL.em(JPQL.java:18)
2012-06-20T21:58:27+00:00 app[run.1]:   at play.db.jpa.JPQL.count(JPQL.java:26)
2012-06-20T21:58:27+00:00 app[run.1]:   at models.User.count(User.java)
2012-06-20T21:58:27+00:00 app[run.1]:   at notifiers.Mails.itjbSurveyReport(Mails.java:246)
2012-06-20T21:58:27+00:00 app[run.1]:   at jobs.Reports.main(Reports.java:35)

然后决定将逻辑包装在“作业”中以确保 JPA 上下文已初始化,但随后我遇到了从 JPA 查询返回的对象的类加载问题:

报告.java:

public class Reports extends Job {

    private Reports() {
        super();
    }

    @Override
    public void doJob() throws Exception {
        Mails.itjbSurveyReport();
    }

    public static void main(String[] args) {
        File root = new File(System.getProperty("application.path"));

        if (System.getProperty("precompiled", "false").equals("true")) {
            Play.usePrecompiled = true;
        }

        try {
            Play.init(root, System.getProperty("play.id", ""));

            Reports reports = new Reports();
            reports.now().get();
        } catch (Exception e) {
            Logger.error(e, "");
        } finally {
            Play.stop();
        }
    }
}

日志:

2012-06-20T19:04:24+00:00 app[run.1]: ClassCastException occured : securesocial.provider.ProviderType cannot be cast to securesocial.provider.ProviderType
2012-06-20T19:04:24+00:00 app[run.1]: 
2012-06-20T19:04:24+00:00 app[run.1]: play.exceptions.JavaExecutionException: securesocial.provider.ProviderType cannot be cast to securesocial.provider.ProviderType
2012-06-20T19:04:24+00:00 app[run.1]:   at play.jobs.Job.call(Job.java:155)
2012-06-20T19:04:24+00:00 app[run.1]:   at play.jobs.Job$1.call(Job.java:66)
2012-06-20T19:04:24+00:00 app[run.1]:   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
2012-06-20T19:04:24+00:00 app[run.1]:   at java.util.concurrent.FutureTask.run(FutureTask.java:166)
2012-06-20T19:04:24+00:00 app[run.1]:   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:165)
2012-06-20T19:04:24+00:00 app[run.1]:   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:266)
2012-06-20T19:04:24+00:00 app[run.1]:   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
2012-06-20T19:04:24+00:00 app[run.1]:   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
2012-06-20T19:04:24+00:00 app[run.1]:   at java.lang.Thread.run(Thread.java:636)
2012-06-20T19:04:24+00:00 app[run.1]: Caused by: java.lang.ClassCastException: securesocial.provider.ProviderType cannot be cast to securesocial.provider.ProviderType
2012-06-20T19:04:24+00:00 app[run.1]:   at notifiers.Mails.itjbSurveyReport(Mails.java:259)
2012-06-20T19:04:24+00:00 app[run.1]:   at jobs.Reports.doJob(Reports.java:36)
2012-06-20T19:04:24+00:00 app[run.1]:   at play.jobs.Job.doJobWithResult(Job.java:50)
2012-06-20T19:04:24+00:00 app[run.1]:   at play.jobs.Job.call(Job.java:146)
2012-06-20T19:04:24+00:00 app[run.1]:   ... 8 more

有趣的是,在上面提到的 v2.0 版本中,看起来本地类加载器被传递到 Play 环境中,这可能解决了这个问题。不确定如何在 v1.2.4 中完成

不知道下一步该怎么做...

4

2 回答 2

2

这是一个工作示例应用程序:
https ://github.com/jamesward/play1-scheduled-job-demo

诀窍是从 Play 的类加载器(来自HelloJob.java)加载作业:

Class c = Play.classloader.loadClass("jobs.HelloJob");
Job s = (Job) c.newInstance();
s.run();
于 2012-06-25T02:32:38.027 回答
0

为什么不直接添加

@Every("5min")
public class Reports extends Job {
  ...
}

我不确定你想做什么。

如果你使用@Every 表示法,你不需要对 Heroku 做任何特别的事情。

于 2012-06-21T00:58:04.680 回答