AWDB Web Service Tutorial
Note: The following tutorial describes how to use a web service to access data in the Natural Resources Conservation Service (NRCS) National Water and Climate Center (NWCC) AWDB database. It is not meant to introduce general concepts and programming requirements relating to web services. Refer to the AWDB Web Service Reference for a complete listing of all Methods, Classes, Network Codes, and Element Codes.
The National Water and Climate Center maintains a large database of soil, water, and climate data known as AWDB (air and water database). This database includes data from NWCC’s extensive automated data collection system of snowpack and related climate data called SNOTEL (for SNOw TELemetry), its Soil Climate Analysis Network (SCAN) stations, as well as data from snow courses, streamflow stations, reservoirs, climate indices, National Weather Service COOP stations, 30-year normals, water supply forecasts, and more. All of this data can be accessed publicly through the AWDB Web Service.
A Web Service is a way to communicate between two devices over the Internet. A user (client) of a Web Service invokes remote procedure calls on a Web Service that provides some data or other services. The user of a Web Service is typically another application. The application can be written in any language and on any platform.
A Web Service provider will provide a WSDL (Web Services Description Language) file that fully describes the Web Service. The WSDL file is an XML document that has all of the information needed to access and use a Web Service.
The WSDL file describes all of the calls that can be made on the Web Service, the parameters and return values for each call, and the address of the service. Most programming languages provide a way to translate a WSDL file into code that can be used to make calls to the Web Service.
The AWDB Web Service is a SOAP (Simple Object Access Protocol) Web Service. The AWDB Web Service provides methods for accessing metadata (about elements, units, stations, etc.), data, 30-year normals, and water supply forecasts.
To access the AWDB Web Service from a Java project, you must create the Java stubs from the Web Services Description Language (WSDL) and include the classes in your project.
This tutorial describes how to:
- Generate the Java client stubs from the WSDL.
- Create an instance of the AwdbWebService object.
- Make calls to the AWDB database. Several “use cases” show examples of how to extract different types of data for different timeframes.
The URL for the Web Service Description Language (WSDL) for the AWDB Web Service is: https://wcc.sc.egov.usda.gov/awdbWebService/services?WSDL
The following conventions apply to the AWDB Web Service:
- Method parameters marked with an asterisk (*) are required.
- Several methods take a station triplet string or a list of triplets. These triplets identify a station and are composed of a three part string that contains the station id, the state code, and the network code of the station all delimited by a colon (‘:’), as follows:
[station id]:[state code]:[network code]
Example: "302:OR:SNTL"
Methods that request results for multiple stations will return an array holding the results in the same order the stations were given.
- Dates must be in the format YYYY-MM-DD. For example January 4, 2013 would be formatted as 2013-01-04.
wsimport is the utility to generate Java client stubs from a WSDL. It is supplied with the Java JDK and is located in the bin directory. If you do not have the JDK, you will need to download it first.
The wsimport utility simply needs to be given the desired package in which to put the new stubs and the WSDL address. From a command line, use the following command:
wsimport -p gov.usda.nrcs.wcc.awdbWebService -s . ‘https://www.wcc.nrcs.usda.gov/awdbWebService/services?WSDL’
This generates the stubs for the AWDB Web Service and places them in the package gov.usda.nrcs.wcc.awdbWebService. Once the client stubs are generated, they are imported and used just like any other Java package.
To make calls to the AWDB Web Service, you need an instance of the AwdbWebService class that is pointed to the Web Service. This can be done once prior to using the AWDB Web Service calls, such as on program start, and the instance can be reused repeatedly throughout the application.
To create this instance, use the following code:
import gov.usda.nrcs.wcc.awdbWebService.*; //The web service stubs
import javax.xml.namespace.QName;
import java.net.URL;
AwdbWebService m_webService = null;
try
{
URL wsURL = newURL("https://www.wcc.nrcs.usda.gov/awdbWebService/services?wsdl");
AwdbWebService_Service lookup = new AwdbWebService_Service(wsURL, new
QName("https://www.wcc.nrcs.usda.gov/ns/awdbWebService", "AwdbWebService"));
m_webService = lookup.getAwdbWebServiceImplPort();
}
catch (Exception e)
{
//On failure do...
}
Now you can use m_webService to make calls to the AWDB database. For example: m_webService.getElements() returns all elements in the AWDB database.
Following is an example java class that contains separate methods which demonstrate three common uses of the AWDB Web Service:
Use Case 1: Get an inventory of stations. The example gets an inventory of all SNOTEL stations in Oregon that have snow-water equivalent data (element code WTEQ) and returns a list of stations.
Use Case 2: Get period of record data. The example returns period of record data that are snow-water equivalent for a given station and date range.
Use Case 3: Get last seven days data. The example returns the last seven days of snow-water equivalent data, relative to today, for a given station.
The main method utilizes Use Case 1 and Use Case 3 by looping through the stations and returning each station’s metadata and values.
import gov.usda.nrcs.wcc.awdbWebService.*;
import javax.xml.namespace.QName;
import java.net.URL;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
public class WSUseCases
{
static final SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd");
AwdbWebService m_webService = null;
/**
* Constructor which initializes a web service instance.
*/
public WSUseCases()
{
initWebService();
}
/**
* Initialize the web service member variable m_webService.
*/
private void initWebService()
{
try
{
URL wsURL = new URL
"https://www.wcc.nrcs.usda.gov/awdbWebService/services?wsdl");
AwdbWebService_Service lookup = new AwdbWebService_Service(wsURL,
new QName("https://www.wcc.nrcs.usda.gov/ns/awdbWebService",
"AwdbWebService"));
m_webService = lookup.getAwdbWebServiceImplPort():
}
catch (Exception e)
{
System.out.println("Problem creating web service client: "
+ e.getMessage());
}
}
/**
* Example main program entry point which:
* 1 - instantiates this class and creates a web service object
* 2 - gets a list of stations, loop through the stations and print out each
* station's metadata
* 3 - uses Use Case 3 to get last 7 days data for each station
* and print out each day's date and values.
* @param args
*/
public static void main(String[] args){
WSUseCases useCase = new WSUseCases();
//Use Case 1: Get Inventory of Stations
// NOTE: For this tutorial, the selection criteria of
// network, state and element are hard-coded
// as ‘SNTL’, ’OR’ and ’WTEQ’ in the getData function.
// NOTE: The getStationMetadata* function
// may return some sites that do not have data
// the date range you are interested in.
// You can remove those stations by checking their
// begin and end dates before retrieving data.
List<StationMetaData> metadata = useCase.getStations();
String stationName, stationTriplet, beginDate, endDate, countyName,
huc, shefID, fipsCountryCode, fipsCountyCode, fipsStateNumber;
BigDecimal elevation, latitude, longitude, stationDataTimeZone;
// Loop through list of stations and retrieve and
// print out metadata for one station
for (StationMetaData metadatum : metadata)
{
stationName = metadatum.getName();
stationTriplet = metadatum.getStationTriplet();
beginDate = metadatum.getBeginDate();
endDate = metadatum.getEndDate();
countyName = metadatum.getCountyName();
elevation = metadatum.getElevation();
huc = metadatum.getHuc();
latitude = metadatum.getLatitude();
longitude = metadatum.getLongitude();
shefID = metadatum.getShefId();
stationDataTimeZone = metadatum.getStationDataTimeZone();
fipsCountryCode = metadatum.getFipsCountryCd();
fipsCountyCode = metadatum.getFipsCountyCd();
fipsStateNumber = metadatum.getFipsStateNumber();
System.out.println("Station Name: " + stationName + '\n' +
"Station Triplet: " + stationTriplet + '\n' +
"Begin Date: " + beginDate + '\n' +
"End Date: " + endDate + '\n' +
"County Name: " + countyName + '\n' +
"Elevation: " + elevation + '\n' +
"HUC: " + huc + '\n' +
"Latitude: " + latitude + '\n' +
"Longitude: " + longitude + '\n' +
"SHEF ID: " + shefID + '\n' +
"Station Time Zone: " + stationDataTimeZone + '\n' +
"Fips Country Code: " + fipsCountryCode + '\n' +
"Fips County Code: " + fipsCountyCode + '\n' +
"Fips State #: " + fipsStateNumber);
/*
* Use Case 3: Get Last 7 Days Data for One Station
* This will get DAILY data for each of the stations from
* Use Case 1.
* Note: To apply Use Case 2: Period of Record of Data for One Station,
* see example method getPeriodOfRecord().
*/
Data[] data = useCase.getLastSevenDaysData(stationTriplet);
String beginDt = data[0].getBeginDate();
String flags = data[0].getFlags().toString();
BigDecimal[] stationValues = data[0].getValues().toArray(
new BigDecimal[0]);
// Get values for current station
for (int i = 0; i <= stationValues.length; i++)
{
System.out.println("Date: Flags/Value: " + beginDt + ": "
+ flags + "/" + stationValues[i] + '\n');
}
}
}
Use Case 1: Get Inventory of Stations
/**
* Use Case 1: Get Inventory of Stations
* This example will get an inventory of all stations in Oregon
* for SNOTEL stations that have Snow Water Equivalent
* and return list of stations
*/
public List<StationMetaData> getStations(){
List<String> stationIds = null;
List<String> stateCds = null;
List<String> networkCds = Arrays.asList("SNTL");
List<String> hucs = null;
List<String> countyNames = null;
BigDecimal minLatitude = null;
BigDecimal maxLatitude = null;
BigDecimal minLongitude = null;
BigDecimal maxLongitude = null;
BigDecimal minElevation = null;
BigDecimal maxElevation = null;
List<String> elementCodes = Arrays.asList("WTEQ");
List<Integer> ordinals = Arrays.asList(1);
List<HeightDepth> heightDepths = null;
/*
* If (logicalAnd) is true, the getStations() call will return only
* stations that match ALL of the parameters passed in, otherwise it’ll
* return stations that match ANY of the parameters passed in.
*/
boolean logicalAnd = true;
List<String> stationTriplets = m_webService.getStations(stationIds,
stateCds, networkCds, hucs, countyNames, minLatitude,
maxLatitude, minLongitude, maxLongitude, minElevation,
maxElevation, elementCodes, ordinals, heightDepths, logicalAnd);
List<StationMetaData> stations = m_webService
.getStationMetadataMultiple(stationTriplets)
return stations;
}
Use Case 2: Get Period of Record for One Station
/**
* Use Case 2: Get period of record for one station.
* This will return period of Data that are SNOW WATER EQUIVALENT (element
* code = WTEQ) for a given station and date range.
* Note: Always use an ordinal of 1, and heightDepth of null
* (height depth is only used for soil sensors)
* @param p_stationTriplet The station to get data for, ex: "471:ID:SNTL"
* @param p_beginDate The begin date - a String format "yyyy-MM-dd"
* @param p_endDate The end date - a String format "yyyy-MM-dd"
* @return An Array of Data Objects
*/
public Data[] getPeriodOfRecord(String p_stationTriplet, String p_beginDate, String p_endDate){
Data[] values = m_webService.getData(Arrays.asList(p_stationTriplet),
"WTEQ", 1, null, Duration.DAILY, true, p_beginDate, p_endDate, true)
.toArray(new Data[0]);
return values;
}
Use Case 3: Get Last Seven Days of Data
/**
* Use Case 3: Get last seven days of data.
* This will return the last seven days of SNOW WATER EQUIVALENT (element
* code = WTEQ data, relative to today, for a given station.
* Note: Always use an ordinal of 1, and heightDepth of null
* (height depth is only used for soil sensors)
* @param p_stationTriplet The station to get data for, ex: "471:ID:SNTL"
* @return An Array of Data Objects
*/
public Data[] getLastSevenDaysData(String p_stationTriplet){
String today = dateFormat.format(new Date());
Calendar lastWeek = GregorianCalendar.getInstance();
lastWeek.add(Calendar.DAY_OF_YEAR, -7);
String sevenDaysAgo = dateFormat.format(lastWeek.getTime());
Data[] values = m_webService.getData(Arrays.asList(p_stationTriplet),
"WTEQ", 1, null, Duration.DAILY, true, sevenDaysAgo, today, ture)
.toArray(new Data[0]);
return values;
}
/* End class WSUseCases */
}