cass-ws Overview
Play Framework web service providing CASS (Coding Accuracy Support System) address validation via Melissa Data integration. This service is accessed by cass-spark for batch address processing.
Purpose
cass-ws is a lightweight REST API that validates and standardizes US postal addresses using the Melissa Data Address Object library. The service:
- Validates addresses against USPS standards using Melissa Data’s DPV (Delivery Point Validation)
- Standardizes address components (street, city, state, ZIP, ZIP+4)
- Enriches addresses with postal data (carrier route, FIPS code, address type)
- Supports batch processing by accepting JSON arrays of addresses
The service runs on dedicated servers (melissa.path2response.com, melissa-test.path2response.com, melissa-2.path2response.com) and is consumed by cass-spark for bulk CASS processing.
Architecture
System Context
┌─────────────────────┐
│ Data Tools │
│ (cassRunner) │
└──────────┬──────────┘
│ S3 + SQS
▼
┌─────────────────────┐ HTTPS (port 9443) ┌─────────────────────┐
│ cass-spark │ ──────────────────────▶ │ cass-ws │
│ (batch processor) │ │ (Play Framework) │
└─────────────────────┘ └──────────┬──────────┘
│ JNI
▼
┌─────────────────────┐
│ Melissa Data │
│ Address Object │
│ (/opt/melissadata) │
└─────────────────────┘
Directory Structure
cass-ws/
├── app/
│ ├── controllers/
│ │ └── AddressController.scala # HTTP endpoint for CASS requests
│ └── services/
│ └── com/path2response/coop/cass/
│ └── CassProcessor.scala # Melissa Data integration
├── conf/
│ ├── application.conf # Play configuration (allowed hosts)
│ └── routes # URL routing
├── project/
│ └── plugins.sbt # Play plugin
├── scripts/
│ ├── start-cass-ws.sh # Service start script
│ └── stop-cass-ws.sh # Service stop script
├── test/
│ └── com/path2response/coop/cass/
│ └── CassProcessorSpec.scala # Unit tests
├── build.sbt # SBT build configuration
├── build.sc # Mill build (alternative)
├── scalastyle-config.xml # Code style configuration
└── README.txt # Developer notes
Technology Stack
| Component | Version | Notes |
|---|---|---|
| Scala | 2.12.18 | Matches coop-scala version |
| Play Framework | 2.8.22 | Web framework |
| SBT | 1.x | Build tool |
| Melissa Data | mdaddr 0.0.1 | Address validation library (JNI) |
| Guice | 5.1.0 | Dependency injection |
| ScalaTest | (via scalatestplus-play 5.1.0) | Testing framework |
Dependencies (from coop-scala)
| Artifact | Purpose |
|---|---|
json-definitions | JSON model classes (AddressRequest, MDResponse, Cass) |
common | Shared utilities, JSON serialization |
convert | Data conversion utilities |
API
Endpoint
| Method | Path | Description |
|---|---|---|
| POST | /address | Validate and standardize addresses |
Request Format
The endpoint accepts a JSON array of address objects:
[
{
"id": "1",
"address1": "123 Main St",
"address2": "Apt 2",
"city": "Denver",
"state": "CO",
"zip": "80202"
}
]
| Field | Required | Description |
|---|---|---|
id | No | Pass-through identifier for correlation |
address1 | No | Primary street address |
address2 | No | Secondary address (apt, suite, etc.) |
city | No | City name |
state | No | State abbreviation |
zip | No | ZIP code (5 or 9 digit) |
Response Format
Returns a JSON array of validation results:
[
{
"id": "1",
"cass": {
"address1": "123 MAIN ST APT 2",
"address2": null,
"city": "DENVER",
"state": "CO",
"zip": "80202",
"plus4": "1234",
"dpc": "01",
"dpcd": "2",
"dpv": "Y",
"countryFips": "08031",
"carrierRoute": "C001",
"dpvFootNote": "AABB",
"zipType": " ",
"recordType": "S"
}
}
]
| Field | Description |
|---|---|
address1 | Standardized primary address line (UPPERCASE) |
address2 | Secondary address line if applicable |
city | USPS preferred city name (UPPERCASE) |
state | State abbreviation (UPPERCASE) |
zip | 5-digit ZIP code |
plus4 | ZIP+4 extension |
dpc | Delivery Point Code |
dpcd | Delivery Point Check Digit |
dpv | Delivery Point Validation (Y=valid, N=invalid) |
countryFips | County FIPS code |
carrierRoute | USPS carrier route |
dpvFootNote | DPV footnote codes |
zipType | ZIP code type |
recordType | Address type code (S=Street, R=Rural, etc.) |
DPV Result Codes
The service interprets Melissa Data result codes to determine DPV status:
| Code | Meaning |
|---|---|
AS01 | Address fully validated (DPV=Y) |
AS02 | Street address found but secondary missing |
AS03 | Address not found |
AS23 | Extra/garbage data in input |
Melissa Data Integration
Data Files
The service requires Melissa Data files installed at /opt/melissadata/:
/opt/melissadata/
├── data/
│ ├── mdAddr.dat # Main address database
│ ├── mdAddr.lic # License file
│ ├── mdAddr.nat # National database
│ └── mdAddr.str # Street database
└── AddrObj/
└── libmdAddr.so # Native library (JNI)
Required Environment Variables
| Variable | Purpose |
|---|---|
LD_LIBRARY_PATH | Must include /opt/melissadata/AddrObj |
MDADDR_LICENSE | Melissa Data license key (optional if in file) |
CASS_DEBUG | Set to t or true for debug logging |
License Management
The Melissa Data license can be set via:
MDADDR_LICENSEenvironment variablemdAddr.licfile in data directorySetLicenseString()call (defaults to “DEMO”)
Integration with cass-spark
Relationship
- cass-ws = Thin HTTP wrapper around Melissa Data library
- cass-spark = Spark-based batch processor that calls cass-ws
Communication Flow
- Data Tools identifies files needing CASS processing
- Data Tools sends notification to SQS queue
- cass-spark picks up message, reads addresses from S3
- cass-spark calls cass-ws over HTTPS to validate addresses
- cass-spark writes results back to S3
- cass-spark sends completion message to SQS
SSL Configuration
cass-ws uses a self-signed certificate. Clients (cass-spark) must:
- Extract the certificate:
openssl s_client -connect melissa.path2response.com:9443 - Configure TrustManager to accept the certificate
- Use custom SSLContext when connecting
Development
Building
# Development mode (with hot reload)
sbt run
# Run tests
sbt test
# Build distribution package
sbt dist
Build Output
The sbt dist command creates a zip file containing:
bin/cass-ws- Launch scriptlib/- Application JARsscripts/- Start/stop scripts
Build Troubleshooting
If dependencies are missing from the dist output:
rm -fr ~/.m2
rm -fr ~/.cache/coursier
rm -fr target
sbt stage dist
Deployment
Server Configuration
Hosted on dedicated servers:
melissa.path2response.com(production)melissa-test.path2response.com(test)melissa-2.path2response.com(secondary production)
Starting the Service
# Using start script
./scripts/start-cass-ws.sh
# Manual start
export LD_LIBRARY_PATH=/lib:/usr/lib:/opt/melissadata/AddrObj
bin/cass-ws \
-Dhttp.port=disabled \
-Dhttps.port=9443 \
-Dplay.http.secret.key="$SESSION_SEC" \
-Dplay.server.https.keyStore.password="$CRT_PW" \
-Dplay.server.https.keyStore.path=$HOME/keystore.keystore \
-Dpidfile.path=$HOME/play.pid
Stopping the Service
# Using stop script
./scripts/stop-cass-ws.sh
# Manual stop
kill `cat $HOME/play.pid`
SSL Certificate Setup
Generate a self-signed certificate for HTTPS:
keytool -genkeypair \
-alias melissa \
-validity 3650 \
-keysize 2048 \
-keyalg RSA \
-keystore keystore.keystore \
-storepass "<password>"
Note: Enter the full hostname (e.g., melissa.path2response.com) as the “First and Last Name” field.
Environment Variables
| Variable | Purpose |
|---|---|
SESSION_SEC | Play Framework session secret |
CRT_PW | Keystore password |
LD_LIBRARY_PATH | Native library path |
CASS_DEBUG | Enable debug logging |
Processing Details
Input Sanitization
The service sanitizes input addresses by:
- Converting to uppercase
- Removing invalid characters:
* . ( ) [ ] { } " ' , : ; & @ \ - Collapsing multiple spaces
- Combining address1 and address2 into single street field
Thread Pool
The service uses a fixed thread pool sized to the number of CPU cores:
- ThreadLocal mdAddr instances (one per thread)
- ArrayBlockingQueue for request handling
- 12-hour keep-alive for threads
Melissa Data Options
Configured options:
SetUseUSPSPreferredCityNames(1)- Use standardized city namesSetSuiteParseMode(CombineSuite)- Combine suite into address
Related Documentation
| Document | Description |
|---|---|
| coop-scala Overview | Core data processing, includes CASS/NCOA extraction |
| Data Tools Overview | cassRunner triggers CASS processing |
| Path2Acquisition Flow | CASS in overall data flow |
| Glossary | CASS and postal term definitions |
Related Projects
| Project | Description |
|---|---|
| cass-spark | Spark-based batch processor that calls cass-ws |
| coop-scala extract-ncoa | CASS/NCOA data extraction from households |
Source: cass-ws repository (README.txt, build.sbt, source files) Documentation created: 2026-01-24