Using Cloud Foundry Workers with Spring
You've no doubt read Jennifer Hickey's amazing blog posts introducing Cloud Foundry workers, their application in setting up Ruby Resque background jobs, and today's post introducing the Spring support.
Key Takeaways for Spring Developers
- You need to update your version of
vmcwithgem update vmc. - Cloud Foundry workers let you run
public static void mainjobs. That is, a Cloud Foundry worker is basically a process, lower level than a web application, which maps naturally to many so-called back-office jobs. - You need to provide the command that Cloud Foundry will run. You could provide the
javaincantation you'd like it to use, but it's far simpler to ship a shell script, and have Cloud Foundry run that shell script for you, instead. The command you provide should employ$JAVA_OPTS, which Cloud Foundry has already provided to ensure consistent memory usage and JVM settings. - There are various ways to automate the creation of a Cloud Foundry deployable application. If you're using Maven, then the
org.codehaus.mojo:appassembler-maven-pluginplugin will help you create a startup script and package your.jarsfor easy deployment, as well as specifying an entry point class. - Everything else is basically the same. When you do
vmc pushon a Java.jarproject, Cloud Foundry will ask you whether the application is a standalone application. Confirm, and it'll walk you through the setup from there.
So, let's look at a few common architectures and arrangements that are easier and more natural with Cloud Foundry workers. We'll look at these patterns in terms of the Spring framework and two surrounding projects, Spring Integration and Spring Batch, both of which thrive in, and outside of, web applications. As we'll see, both of these frameworks support decoupling and improved composability. We'll disconnect what happens from when it happens, and we'll disconnect what happens from where it happens, both in the name of freeing up capacity on the front end.
I've got a Schedule to Keep!
One common question I get is: How do I do job scheduling on Cloud Foundry? Cloud Foundry supports Spring applications, and Spring of course has always supported enterprise grade scheduling abstractions like Quartz and Spring 3.0's @Scheduled annotation. @Scheduled is really nice because it is super easy to add into an existing application. In the simplest case, you add @EnableScheduling to your Java configuration or <task:annotation-driven/> to your XML, and then use the @Scheduled annotation in your code. This is a very natural thing to do in an enterprise application - perhaps you have an analytics or reporting process that needs to run? Some long running batch process? I've put together an example that demonstrates using @Scheduled to run a Spring Batch Job. The Spring Batch job itself is a worker thread that works with a web service whose poor SLA make it unfit for realtime use. It's safer, and cleaner, to handle the work in Spring Batch, where its recovery and retry capabilities pick up the slack of any network outages, network latency, etc. I'll refer you to the code example for most of the details, we'll just look at the the entry point and then look at deploying the application to Cloud Foundry.
// set to every 10s for testing.
@Scheduled(fixedRate = 10 * 1000)
public void runNightlyStockPriceRecorder() throws Throwable {
JobParameters params = new JobParametersBuilder()
.addDate("date", new Date())
.toJobParameters();
JobExecution jobExecution = jobLauncher.run(job, params);
BatchStatus batchStatus = jobExecution.getStatus();
while (batchStatus.isRunning()) {
logger.info("Still running...");
Thread.sleep(1000);
}
logger.info(String.format("Exit status: %s", jobExecution.getExitStatus().getExitCode()));
JobInstance jobInstance = jobExecution.getJobInstance…

