Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

ComponentVersionNotes
Scala2.12.18Matches coop-scala version
Play Framework2.8.22Web framework
SBT1.xBuild tool
Melissa Datamdaddr 0.0.1Address validation library (JNI)
Guice5.1.0Dependency injection
ScalaTest(via scalatestplus-play 5.1.0)Testing framework

Dependencies (from coop-scala)

ArtifactPurpose
json-definitionsJSON model classes (AddressRequest, MDResponse, Cass)
commonShared utilities, JSON serialization
convertData conversion utilities

API

Endpoint

MethodPathDescription
POST/addressValidate 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"
  }
]
FieldRequiredDescription
idNoPass-through identifier for correlation
address1NoPrimary street address
address2NoSecondary address (apt, suite, etc.)
cityNoCity name
stateNoState abbreviation
zipNoZIP 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"
    }
  }
]
FieldDescription
address1Standardized primary address line (UPPERCASE)
address2Secondary address line if applicable
cityUSPS preferred city name (UPPERCASE)
stateState abbreviation (UPPERCASE)
zip5-digit ZIP code
plus4ZIP+4 extension
dpcDelivery Point Code
dpcdDelivery Point Check Digit
dpvDelivery Point Validation (Y=valid, N=invalid)
countryFipsCounty FIPS code
carrierRouteUSPS carrier route
dpvFootNoteDPV footnote codes
zipTypeZIP code type
recordTypeAddress type code (S=Street, R=Rural, etc.)

DPV Result Codes

The service interprets Melissa Data result codes to determine DPV status:

CodeMeaning
AS01Address fully validated (DPV=Y)
AS02Street address found but secondary missing
AS03Address not found
AS23Extra/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

VariablePurpose
LD_LIBRARY_PATHMust include /opt/melissadata/AddrObj
MDADDR_LICENSEMelissa Data license key (optional if in file)
CASS_DEBUGSet to t or true for debug logging

License Management

The Melissa Data license can be set via:

  1. MDADDR_LICENSE environment variable
  2. mdAddr.lic file in data directory
  3. SetLicenseString() 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

  1. Data Tools identifies files needing CASS processing
  2. Data Tools sends notification to SQS queue
  3. cass-spark picks up message, reads addresses from S3
  4. cass-spark calls cass-ws over HTTPS to validate addresses
  5. cass-spark writes results back to S3
  6. cass-spark sends completion message to SQS

SSL Configuration

cass-ws uses a self-signed certificate. Clients (cass-spark) must:

  1. Extract the certificate: openssl s_client -connect melissa.path2response.com:9443
  2. Configure TrustManager to accept the certificate
  3. 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 script
  • lib/ - Application JARs
  • scripts/ - 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

VariablePurpose
SESSION_SECPlay Framework session secret
CRT_PWKeystore password
LD_LIBRARY_PATHNative library path
CASS_DEBUGEnable debug logging

Processing Details

Input Sanitization

The service sanitizes input addresses by:

  1. Converting to uppercase
  2. Removing invalid characters: * . ( ) [ ] { } " ' , : ; & @ \
  3. Collapsing multiple spaces
  4. 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 names
  • SetSuiteParseMode(CombineSuite) - Combine suite into address
DocumentDescription
coop-scala OverviewCore data processing, includes CASS/NCOA extraction
Data Tools OverviewcassRunner triggers CASS processing
Path2Acquisition FlowCASS in overall data flow
GlossaryCASS and postal term definitions
ProjectDescription
cass-sparkSpark-based batch processor that calls cass-ws
coop-scala extract-ncoaCASS/NCOA data extraction from households

Source: cass-ws repository (README.txt, build.sbt, source files) Documentation created: 2026-01-24