Skip to main content

Overview

pn-address-manager provides address normalisation and deduplication services. Paper Channel calls Address Manager during the prepare phase whenever it needs to compare two addresses (e.g., a first-attempt postman address versus a second-attempt National Registry address) and obtain a normalised canonical form. The core operation is deduplicates, which takes two addresses, determines whether they are equivalent, and returns a normalised version of the target address.

When Paper Channel calls Address Manager

Address Manager is invoked from SecondAttemptFlowService.handleSecondAttempt(...) — the abstract base class for all second-attempt prepare flows. Concrete subclasses include the postman flow and the National Registry flow. The call sequence is:
SecondAttemptFlowService.handleSecondAttempt(pnDeliveryRequest, secondAttemptAddress, firstAttemptAddress)
  └─▶ callDeduplica(correlationId, ...)
        └─▶ AddressManagerClient.deduplicates(correlationId, base, target)
              └─▶ DeduplicatesAddressServiceApi.deduplicates(cxId, apiKey, requestDto)
  ├─▶ checkAndHandleErrors(...)       — inspect DeduplicatesResponseDto.error
  ├─▶ checkAndHandleSameAddresses(...) — inspect DeduplicatesResponseDto.equalityResult
  └─▶ checkAndParseNormalizedAddress(...) — extract normalizedAddress

Client interface

// AddressManagerClient.java
public interface AddressManagerClient {
    Mono<DeduplicatesResponseDto> deduplicates(
        String correlationId,
        Address base,
        Address target
    );
}

Implementation — AddressManagerClientImpl

// AddressManagerClientImpl.java
public Mono<DeduplicatesResponseDto> deduplicates(
    String correlationId,
    Address base,
    Address target
) {
    DeduplicatesRequestDto requestDto = new DeduplicatesRequestDto();
    requestDto.setBaseAddress(AddressMapper.toAnalogAddressManager(base));
    requestDto.setTargetAddress(AddressMapper.toAnalogAddressManager(target));
    requestDto.setCorrelationId(correlationId);
    return this.apiService.deduplicates(
            this.pnPaperChannelConfig.getAddressManagerCxId(),
            this.pnPaperChannelConfig.getAddressManagerApiKey(),
            requestDto
        )
        .retryWhen(
            Retry.backoff(2, Duration.ofMillis(500))
                .filter(t -> t instanceof TimeoutException || t instanceof ConnectException)
        );
}
  • Calls DeduplicatesAddressServiceApi.deduplicates with cxId and apiKey headers.
  • Retries up to 2 times with 500 ms backoff on transient TimeoutException or ConnectException.
  • Maps both addresses via AddressMapper.toAnalogAddressManager(...) before sending.

Request fields — DeduplicatesRequestDto

correlationId
string
required
Correlation identifier for tracing the request across services.
baseAddress
object
required
The reference address (first-attempt address). Mapped from Address via AddressMapper.toAnalogAddressManager.
targetAddress
object
required
The candidate address to normalise and compare (second-attempt address).

Response fields — DeduplicatesResponseDto

normalizedAddress
AnalogAddressDto
The normalised canonical form of the target address. null if Address Manager could not normalise the address.
equalityResult
boolean
true if the base and target addresses are considered equivalent after normalisation.
error
string
An error code string if normalisation failed. Known codes are defined in DeduplicateErrorConst.

Error codes — DeduplicateErrorConst

CodeMeaningcontinueFlow flag
PNADDR001Address differs after normalisation — variant 1Controlled by pn.paper-channel.pnaddr001continue-flow (default: true)
PNADDR002Address differs after normalisation — variant 2Controlled by pn.paper-channel.pnaddr002continue-flow (default: false)
PNADDR003Address differs after normalisation — variant 3Always stops the flow (continueFlow = false)
PNADDR999Unrecoverable Address Manager errorThrows PnAddressFlowException(ADDRESS_MANAGER_ERROR)
When continueFlow is true for an error code, the prepare flow continues using the original first-attempt address (via throwExceptionToContinueFlowAfterError). When false, the flow stops and a StopFlowSecondAttemptException is thrown with the error code and geokey.
// SecondAttemptFlowService.java
if (PNADDR001.equals(errorCode)) {
    isContinueFlow = config.isPnaddr001continueFlow();
} else if (PNADDR002.equals(errorCode)) {
    isContinueFlow = config.isPnaddr002continueFlow();
} else { // PNADDR003
    isContinueFlow = false;
}
If normalizedAddress is null in the response, Paper Channel throws RESPONSE_NULL_FROM_DEDUPLICATION. This is treated as a fatal error — the prepare flow cannot continue without a valid normalised address.

Configuration

PropertyDescriptionExample
pn.paper-channel.client-address-manager-basepathBase URL of the Address Manager servicehttp://localhost:1080
pn.paper-channel.address-manager-cx-idClient identity header (x-pagopa-pn-cx-id)pn-paper-channel
pn.paper-channel.address-manager-api-keyAPI key header for Address Manager_
pn.paper-channel.attempt-queue-address-managerMax SQS consumer retry attempts3
pn.paper-channel.pnaddr001continue-flowWhether PNADDR001 allows the flow to continuetrue
pn.paper-channel.pnaddr002continue-flowWhether PNADDR002 allows the flow to continuefalse

Error handling

ExceptionCauseBehaviour
ADDRESS_MANAGER_ERROR (via PnAddressFlowException)PNADDR999 error code in response, or any unrecoverable exception from deduplicatesPropagated upstream; prepare flow fails
RESPONSE_NULL_FROM_DEDUPLICATIONnormalizedAddress is null in responseFatal — prepare flow terminates
RESPONSE_ERROR_NOT_HANDLED_FROM_DEDUPLICATIONerror code is not PNADDR001/002/003/999PnGenericException thrown
StopFlowSecondAttemptExceptionPNADDR002 or PNADDR003 with continueFlow = falseFlow stops; outcome reported to Delivery Push
TimeoutException / ConnectExceptionTransient connectivity issueRetried 2 times with 500 ms backoff; PnAddressFlowException thrown if all fail
Setting pn.paper-channel.pnaddr002continue-flow=true in production will cause Paper Channel to proceed with the first-attempt address when normalisation returns a PNADDR002 error, potentially delivering to an unverified address. Change this setting only after understanding the legal implications.

Build docs developers (and LLMs) love