Camel on Google App Engine Tutorial
This tutorial will be updated whenever new features are added to the Camel Components for Google App Engine.
Overview
Goal of this tutorial is to get a non-trivial Camel application running on Google App Engine (GAE). For developing that application the Camel Components for Google App Engine will be used. The application allows the user to enter the name of a city and an email adsress in an HTML form. The form data are submitted by the user to a Camel application, running on GAE, which retrieves weather data for the given city. It then sends a weather report to the user-defined email address. The following figure gives an overview.
POSTed form data are dispatched to the Camel application via the ghttp component. Then the application queues the message with the gtask component for further background processing. This includes retrieval of weather data from the Google Weather Service, transforming the data to generate a report and sending that report by email via the gmail component.
Prerequisites
- Sign up for a Google App Engine account if you don't have already.
- Create a new application via the admin console or reuse an existing one for uploading the example.
- Install the Google App Engine SDK for Java. This tutorial has been tested with version 1.2.6.
Deployment
To deploy the example application, first checkout the sources with
svn co http://svn.apache.org/repos/asf/camel/trunk/examples/camel-example-gae camel-example-gae
Open the camel-example-gae/src/main/webapp/WEB-INF/application-web.xml
file in an editor and replace the template application name replaceme
with the name of the application that you created in the previous section.
<?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <!-- use your own application name here --> <application>replaceme</application> <version>1</version> <!-- Configure java.util.logging --> <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties> </appengine-web-app>
Open camel-example-gae/src/main/resources/context.xml
file and change the sender
property value to the email address of your Google App Engine account.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> ... <bean id="tutorialRouteBuilder" class="org.apache.camel.example.gae.TutorialRouteBuilder"> <!-- use your own GAE admin email address here --> <property name="sender" value="replaceme@gmail.com" /> </bean> </beans>
Then go to the camel-example-gae
directory and enter
mvn install
This will create the application war
file in the target directory. Finally use the appcfg
command-line tool of the App Engine SDK to deploy the application.
appcfg update target/camel-example-gae-<version>
where version
needs to be replaced with the version of Camel you're using. You will be prompted for the email address and password of your Google App Engine account. After deployment the example application is ready to use.
Usage
Go to http://replaceme.appspot.com
where replaceme
must be replaced with the application name you entered in appengine-web.xml
. The following form should now appear.
Enter the name of a city and your email address, for example:
Then press Submit
. The immediate response is
Weather report will be sent to you@yourprovider.com
In the background, the current weather conditions for the user-defined city will be obtained from the Google weather service and a formatted weather report will be send by email. Submitting the form the first time initializes the application on Google App Engine which can take several seconds. Subsequent submissions are served much faster. Check your emails and you should now see a new email with subject Wheather report
and content similar to this one:
Weather report for: London, England Current condition: Klar Current temperature: 12 (Celsius)
The report is partly internationalized, depending on the language settings of your browser.
Route builder walkthrough
package org.apache.camel.example.gae; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.gae.mail.GMailBinding; public class TutorialRouteBuilder extends RouteBuilder { private String sender; public void setSender(String sender) { this.sender = sender; } @Override public void configure() throws Exception { from("ghttp:///weather") .to("gtask://default") .setHeader(Exchange.CONTENT_TYPE, constant("text/plain")) .transform(constant("Weather report will be sent to ").append(header("mailto"))); from("gtask://default") .setHeader(Exchange.HTTP_QUERY, constant("weather=").append(header("city"))) .to("ghttp://www.google.com/ig/api") .process(new WeatherProcessor()) .setHeader(GMailBinding.GMAIL_SUBJECT, constant("Weather report")) .setHeader(GMailBinding.GMAIL_TO, header("mailto")) .to("gmail://" + sender); } }
Form data are received via the ghttp component. After receiving the request it is added to the default
queue for background processing. Queueing messages on GAE is done with the gtask component. After queueing the request a response is generated for being displayed in the browser. The value of the mailto
header is the email address the user entered in the form.
Background processing of the queued messages starts from("gtask://default")
. The first step is the construction of the Google weather service URL followed by the weather service invocation using the ghttp component. For example, if the user entered London
in the city field of the form the resulting URL is http://www.google.com/ig/api?weather=London
. The resulting XML data are processed by the WeatherProcessor
:
package org.apache.camel.example.gae; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.w3c.dom.Document; public class WeatherProcessor implements Processor { @Override public void process(Exchange exchange) throws Exception { // convert XML body to DOM tree Document doc = exchange.getIn().getBody(Document.class); XPathFactory xpfactory = XPathFactory.newInstance(); XPath xpath = xpfactory.newXPath(); // Extract result values via XPath String city = xpath.evaluate("//forecast_information/city/@data", doc); String cond = xpath.evaluate("//current_conditions/condition/@data", doc); String temp = xpath.evaluate("//current_conditions/temp_c/@data", doc); String msg = null; if (city != null && city.length() > 0) { msg = new StringBuffer() .append("\n").append("Weather report for: ").append(city) .append("\n").append("Current condition: ").append(cond) .append("\n").append("Current temperature: ").append(temp).append(" (Celsius)").toString(); } else { // create an error message msg = "Error getting weather report for " + exchange.getIn().getHeader("city", String.class); } exchange.getIn().setBody(msg); } }
This processor extracts data from the XML result with XPath expressions and creates a simple text-based report for being sent by email. For sending the email the gmail component is used. The recipient is derived from the user-defined mailto
header value.