Maven by Example
7.4. The Simple Weather Module

The next module we’re going to examine could be considered something
of a “service.” The Simple Weather module is the module that contains
all of the logic necessary to retrieve and parse the data from the
Yahoo! Weather RSS feed. Although Simple Weather contains three Java
classes and one JUnit test, it is going to present a single component,
WeatherService, to both the Simple Web Application and the Simple
Command-line Utility. Very often an enterprise project will contain
several API modules that contain critical business logic or logic that
interacts with external systems. A banking system might have a module
that retrieves and parses data from a third-party data provider, and a
system to display sports scores might interact with an XML feed that
presents real-time scores for basketball or soccer. In
simple-weather Module POM, this module encapsulates all of
the network activity and XML parsing that is involved in the
interaction with Yahoo! Weather. Other modules can depend on this
module and simply call out to the <methodname
role="keep-together">retrieveForecast()+ method on WeatherService,
which takes a zip code as an argument and which returns a Weather
object.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook.multispring</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>simple-weather</artifactId>
<packaging>jar</packaging>
<name>Simple Weather API</name>
<dependencies>
<dependency>
<groupId>org.sonatype.mavenbook.multispring</groupId>
<artifactId>simple-model</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
The simple-weather POM extends the simple-parent POM, sets the
packaging to jar, and then adds the following dependencies:
-
org.sonatype.mavenbook.multispring:simple-model:1.0 -
simple-weatherparses the Yahoo! Weather RSS feed into aWeatherobject. It has a direct dependency onsimple-model. -
log4j:log4j:1.2.14 -
simple-weatheruses the Log4J library to print log messages. -
dom4j:dom4j:1.6.1 and jaxen:jaxen:1.1.1 - Both of these dependencies are used to parse the XML returned from Yahoo! Weather.
-
org.apache.commons:commons-io:1.3.2 (scope=test) -
This
test-scoped dependency is used by theYahooParserTest.
Next is the WeatherService class, shown in
WeatherService Class. This class is going to look very
similar to the WeatherService class from
The WeatherService Class. Although the WeatherService is the
same, there are some subtle differences in this chapter’s
example. This version’s retrieveForecast() method returns a
Weather object, and the formatting is going to be left to the
applications that call WeatherService. The other major change is
that the YahooRetriever and YahooParser are both bean properties
of the WeatherService bean.
package org.sonatype.mavenbook.weather;
import java.io.InputStream;
import org.sonatype.mavenbook.weather.model.Weather;
public class WeatherService {
private YahooRetriever yahooRetriever;
private YahooParser yahooParser;
public WeatherService() {
}
public Weather retrieveForecast(String zip) throws Exception {
// Retrieve Data
InputStream dataIn = yahooRetriever.retrieve(zip);
// Parse DataS
Weather weather = yahooParser.parse(zip, dataIn);
return weather;
}
public YahooRetriever getYahooRetriever() {
return yahooRetriever;
}
public void setYahooRetriever(YahooRetriever yahooRetriever) {
this.yahooRetriever = yahooRetriever;
}
public YahooParser getYahooParser() {
return yahooParser;
}
public void setYahooParser(YahooParser yahooParser) {
this.yahooParser = yahooParser;
}
}
Finally, in this project we have an XML file that is used by the
Spring Framework to create something called an
ApplicationContext. First, some explanation: both of our
applications, the web application and the command-line utility, need
to interact with the WeatherService class, and they both do so by
retrieving an instance of this class from a Spring
ApplicationContext using the name weatherService. Our web
application uses a Spring MVC controller that is associated with an
instance of WeatherService, and our command-line utility loads the
WeatherService from an ApplicationContext in a static main()
function. To encourage reuse, we’ve included an
applicationContext-weather.xml file in src/main/resources, which
is available on the classpath. Modules that depend on the
simple-weather module can load this application context using the
ClasspathXmlApplicationContext in the Spring Framework. They can
then reference a named instance of the WeatherService named
weatherService.
Spring Application Context for the simple-weather Module.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
default-lazy-init="true">
<bean id="weatherService"
class="org.sonatype.mavenbook.weather.WeatherService">
<property name="yahooRetriever" ref="yahooRetriever"/>
<property name="yahooParser" ref="yahooParser"/>
</bean>
<bean id="yahooRetriever"
class="org.sonatype.mavenbook.weather.YahooRetriever"/>
<bean id="yahooParser"
class="org.sonatype.mavenbook.weather.YahooParser"/>
</beans>
This document defines three beans: yahooParser, yahooRetriever,
and weatherService. The weatherService bean is an instance of
WeatherService, and this XML document populates the yahooParser
and yahooRetriever properties with references to the named instances
of the corresponding classes. Think of this
applicationContext-weather.xml file as defining the architecture of
a subsystem in this multi-module project. Projects like
simple-webapp and simple-command can reference this context and
retrieve an instance of WeatherService which already has
relationships to instances of YahooRetriever and YahooParser.
