2

I apologies if this has been answered already; my search did not revealed any one.

I have a play application deployed on Heroku. I also have another Worker class with main method in the same build. I want to run that class as a worker and not web. When I try to run it it gives me ClassDefNotFound exception which is obvious because I am not providing classpath for this process.

How do I figure out what should be the classpath (jars and classes both)? Or is there any other way of doing this?

Reason to put that class separate worker process is to scale it independent of web application.

Here is more detail. My Procfile has following entries,

web: target/start -Dhttp.port=$PORT -DapplyEvolutions.default=true -DapplyDownEvolutions.default=true -Ddb.default.url=$DATABASE_URL ${JAVA_OPTS}
worker: target/start com/company/test/worker/WorkerApplication ${JAVA_OPTS}

worker entry has only the name of the class "WorkerApplication" which needs to be run but Heroku is unable to find these class files and other dependencies.

dylanfm
  • 6,292
  • 5
  • 28
  • 29

3 Answers3

3

You need to create multiple Global objects in your project with different names for each entry point. Then in your Procfile, you specify which one you are starting with the application.global property, like this:

web:     target/start -Dhttp.port=${PORT} ${JAVA_OPTS} -Dapplication.global=Web
worker:  target/start -Dhttp.port=${PORT} ${JAVA_OPTS} -Dapplication.global=Worker

I haven't tried this with a Play project, but you might also be able to get it to work with the sbt-start-script plugin to create a custom target/start script with the correct classpath.

ryanbrainard
  • 5,918
  • 35
  • 41
  • By using the same ${PORT} twice don't we have a conflict on the port? Does Heroku run the worker process using a different port setting? – anfuerer Nov 13 '13 at 12:21
  • Each line the the Procfile is run in its own dyno (i.e. container) with their own port, so there is not port conflict. – ryanbrainard Nov 13 '13 at 16:47
  • In my version of Play (2.0.4) this is -Dglobal=..., not -Dapplication.global=... -- note that the docs are incorrect: http://www.playframework.com/documentation/2.0.4/ScalaGlobal – jsalvata Dec 12 '13 at 02:09
2

Ok, I figured it out. target/start is for web not for worker. I found all the jars in target/stage folder. Changing worker to following works fine.

worker: java -cp "target/staged/*" com/company/test/worker/WorkerApplication

0

We've recently open-source our delayed job framework, Moonlight, for Playframework on Heroku.

A delayed job usually requires some sort of coordination. For example, you might need a queue, so that a worker can fetch a job from the queue and process it. Moonlight handles that for you.

For your specific question around Procfile, we have a working example here: https://github.com/GIVESocialMovement/moonlight/blob/master/test-project/Procfile

Your classpath shouldn't contain /, and I think you need the argument -main.

Tanin
  • 1,853
  • 1
  • 15
  • 20