Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to implement a scheduled one-off process using Play! v1.2.4 and the Heroku Scheduler add-on
    text
    copied!<p>There is an <a href="https://github.com/jamesward/play2-scheduled-job-demo" rel="nofollow">example for doing this with Play! v2.0</a> but I'm trying to do the same for v1.2.4</p> <p>I've tried to follow the same general approach, which is to get the <a href="https://devcenter.heroku.com/articles/scheduler" rel="nofollow">Heroku Scheduler</a> to explicitly start the JVM with a class that initialises the Play environment and then executes the required task within that environment. My specific task was to retrieve some data from the database using JPA and then use the Mailer to generate an email using that data. The initial approach was just to execute the logic directly after initialising Play but I got an exception that the 'JPA context is not initialized'.</p> <p>Procfile:</p> <pre><code>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 . </code></pre> <p>Reports.java:</p> <pre><code>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(); } } } </code></pre> <p>Log:</p> <pre><code>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) </code></pre> <p>Then decided to wrap the logic in a 'Job' to ensure the JPA context was initialised but then I got a class loading issue with an object returned from the JPA query:</p> <p>Reports.java:</p> <pre><code>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(); } } } </code></pre> <p>Log:</p> <pre><code>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 </code></pre> <p>Interestingly in the v2.0 version, mentioned above, it looks like the local classloader is passed into the Play environment which probably resolves this issue. Not sure how this can be done in v1.2.4</p> <p>Not sure what to do next...</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload