SLAM Operations Service - Domain-Driven Design
Overview
The SLAM Operations Service manages the final quality gate operations: Scan, Label, Apply, and Manifest. It is the last step before packages are handed off to transportation carriers.
| Attribute |
Value |
| Port |
8086 |
| Package |
com.paklog.wms.slam |
| Database |
MongoDB |
| Messaging |
Apache Kafka |
Domain Model
Aggregates
SLAMSession (Root Aggregate)
Represents a package going through the SLAM quality gate process.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| public class SLAMSession {
private String sessionId;
private String orderId;
private String shipmentId;
private String packageId;
private SessionStatus status;
private String scannedBarcode;
private WeightVerification weightVerification;
private ShippingLabel shippingLabel;
private String manifestId;
private LocalDateTime createdAt;
private LocalDateTime scannedAt;
private LocalDateTime labeledAt;
private LocalDateTime manifestedAt;
}
|
State Machine:
stateDiagram-v2
[*] --> CREATED
CREATED --> SCANNED: scanPackage()
SCANNED --> WEIGHT_EXCEPTION: weightOutOfTolerance
SCANNED --> LABELED: generateLabel()
LABELED --> LABEL_APPLIED: applyLabel()
LABEL_APPLIED --> MANIFESTED: manifest()
WEIGHT_EXCEPTION --> EXCEPTION: escalate()
SCANNED --> EXCEPTION: escalate()
LABELED --> EXCEPTION: escalate()
Business Rules:
- Session must be in CREATED status to scan
- Weight verification is performed during scan
- Session must be SCANNED to generate label
- Session must be LABELED to apply label
- Session must have LABEL_APPLIED to add to manifest
Manifest
Represents a carrier manifest containing multiple packages.
1
2
3
4
5
6
7
8
9
| public class Manifest {
private String manifestId;
private String carrier;
private ManifestStatus status;
private List<String> packageIds;
private int packageCount;
private LocalDateTime createdAt;
private LocalDateTime closedAt;
}
|
Value Objects
WeightVerification
1
2
3
4
5
6
7
8
9
10
11
| public class WeightVerification {
private double scannedWeight;
private double expectedWeight;
private double variance;
private double variancePercent;
private VerificationResult result;
public boolean isWithinTolerance() {
return variancePercent <= 10.0;
}
}
|
ShippingLabel
1
2
3
4
5
6
7
| public record ShippingLabel(
String carrier,
String trackingNumber,
String routingCode,
String serviceLevel,
LocalDateTime generatedAt
) {}
|
Domain Events
Events Published
| Event |
Type |
Description |
| PackageScannedEvent |
com.paklog.wes.slam.package-scanned.v1 |
Package barcode scanned |
| WeightVerifiedEvent |
com.paklog.wes.slam.weight-verified.v1 |
Weight verification passed |
| WeightDiscrepancyEvent |
com.paklog.wes.slam.weight-discrepancy.v1 |
Weight verification failed |
| LabelGeneratedEvent |
com.paklog.wes.slam.label-generated.v1 |
Shipping label generated |
| PackageManifestedEvent |
com.paklog.wes.slam.package-manifested.v1 |
Package added to manifest |
| SLAMCompletedEvent |
com.paklog.wes.slam.completed.v1 |
SLAM process completed |
| SLAMExceptionEvent |
com.paklog.wes.slam.exception.v1 |
SLAM exception occurred |
Events Consumed
| Source |
Topic |
Event |
Handler |
| AFE Path Service |
process-path.afe.v1.events |
RebinCompletedEvent |
RebinCompletedEventConsumer |
| Batch Flow Path Service |
process-path.batch.v1.events |
OrderConsolidatedEvent |
OrderConsolidatedEventConsumer |
| Singles Path Service |
process-path.singles.v1.events |
SinglesPackCompletedEvent |
SinglesPackCompletedEventConsumer |
Domain Services
SLAMSessionService
1
2
3
4
5
6
7
8
9
| public interface SLAMSessionService {
SLAMSession createSession(String orderId, String shipmentId, String packageId);
SLAMSession scanPackage(String sessionId, String barcode, double scannedWeight, double expectedWeight);
SLAMSession generateLabel(String sessionId, String carrier, String trackingNumber, String routingCode);
SLAMSession applyLabel(String sessionId);
SLAMSession manifest(String sessionId, String manifestId);
SLAMSession escalateException(String sessionId, String reason);
SLAMSession getSession(String sessionId);
}
|
ManifestService
1
2
3
4
5
6
7
| public interface ManifestService {
Manifest createManifest(String carrier);
Manifest addPackage(String manifestId, String packageId);
Manifest closeManifest(String manifestId);
Manifest getManifest(String manifestId);
List<Manifest> getOpenManifests(String carrier);
}
|
API Endpoints
SLAM Sessions
| Method |
Endpoint |
Description |
| POST |
/api/v1/slam-sessions |
Create SLAM session |
| PUT |
/api/v1/slam-sessions/{sessionId}/scan |
Scan and verify weight |
| PUT |
/api/v1/slam-sessions/{sessionId}/generate-label |
Generate shipping label |
| PUT |
/api/v1/slam-sessions/{sessionId}/apply-label |
Confirm label applied |
| PUT |
/api/v1/slam-sessions/{sessionId}/manifest |
Add to manifest |
| PUT |
/api/v1/slam-sessions/{sessionId}/escalate |
Escalate exception |
| GET |
/api/v1/slam-sessions/{sessionId} |
Get session details |
Manifests
| Method |
Endpoint |
Description |
| POST |
/api/v1/manifests |
Create new manifest |
| PUT |
/api/v1/manifests/{manifestId}/add-package |
Add package to manifest |
| PUT |
/api/v1/manifests/{manifestId}/close |
Close manifest |
| GET |
/api/v1/manifests/{manifestId} |
Get manifest details |
| GET |
/api/v1/manifests/carrier/{carrier}/open |
Get open manifests for carrier |
Workflow
sequenceDiagram
participant PATH as Path Services
participant SLAM as SLAM Service
participant CARRIER as Carrier API
participant TRANSPORT as Transportation
PATH->>SLAM: Pack Completed Event
SLAM->>SLAM: Create session
SLAM->>SLAM: Scan package
SLAM->>SLAM: Verify weight (ACW)
alt Weight OK
SLAM-->>SLAM: WeightVerifiedEvent
else Weight Discrepancy
SLAM-->>SLAM: WeightDiscrepancyEvent
SLAM->>SLAM: Escalate
end
SLAM->>CARRIER: Request label
CARRIER-->>SLAM: Tracking number
SLAM-->>SLAM: LabelGeneratedEvent
SLAM->>SLAM: Apply label
SLAM->>SLAM: Add to manifest
SLAM-->>SLAM: PackageManifestedEvent
SLAM-->>TRANSPORT: SLAMCompletedEvent
Weight Verification Rules
| Outcome |
Variance |
Action |
| PASS |
≤10% |
Continue to label |
| FLAG |
10-25% |
Manager review |
| FAIL |
>25% |
Divert to problem solve |
Repository Interfaces
1
2
3
4
5
6
7
8
9
10
11
12
| public interface SLAMSessionRepository {
SLAMSession save(SLAMSession session);
Optional<SLAMSession> findById(String sessionId);
List<SLAMSession> findByStatus(SessionStatus status);
List<SLAMSession> findByShipmentId(String shipmentId);
}
public interface ManifestRepository {
Manifest save(Manifest manifest);
Optional<Manifest> findById(String manifestId);
List<Manifest> findOpenByCarrier(String carrier);
}
|
Integration Patterns
Customer-Supplier
- Upstream: All path services (Singles, AFE, Batch Flow) supply pack completion events
- Downstream: Transportation services consume SLAM completion events
Open Host Service
- Provides standardized SLAM completion events to downstream consumers
Technology Stack
| Component |
Technology |
| Language |
Java 21 |
| Framework |
Spring Boot 3.3.3 |
| Database |
MongoDB 7.0 |
| Messaging |
Apache Kafka 7.5.0 |
| Event Format |
CloudEvents 2.5.0 |
References