Skip to main content

Overview

The Blackjack API uses MongoDB as a reactive NoSQL database to store game state. MongoDB is ideal for storing the dynamic game documents that include player cards, dealer cards, deck state, and game status.

Dependencies

The project uses Spring Data MongoDB Reactive, configured in pom.xml:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>

Connection Configuration

Local Development

For local development, configure MongoDB connection in application-local.yml:
spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/blackjack

Docker Environment

For Docker deployments, use service names in application-docker.yml:
spring:
  data:
    mongodb:
      uri: mongodb://mongo:27017/blackjack

Production Environment

For production, use environment variables in application-prod.yml:
spring:
  data:
    mongodb:
      uri: ${SPRING_DATA_MONGODB_URI}

Configuration Properties

PropertyDescriptionExample
spring.data.mongodb.uriMongoDB connection stringmongodb://localhost:27017/blackjack

Connection String Format

mongodb://[username:password@]host[:port]/database[?options]
For production deployments with authentication:
mongodb://username:password@host:27017/blackjack?authSource=admin

Document Model

Games are stored as MongoDB documents with the following structure:
@Document("games")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class MongoGameDocument {

    @Id
    private String id;

    private String playerId;
    private List<CardDoc> playerCards;
    private List<CardDoc> dealerCards;
    private List<CardDoc> deckCards;
    private String status;
}

Document Fields

  • id: Unique game identifier (MongoDB ObjectId)
  • playerId: Reference to the player (external UUID)
  • playerCards: Cards held by the player
  • dealerCards: Cards held by the dealer
  • deckCards: Remaining cards in the deck
  • status: Game status (IN_PROGRESS, PLAYER_WIN, DEALER_WIN, TIE)

Reactive MongoDB Repository

The application uses Spring Data’s ReactiveMongoRepository for reactive database operations:
public interface SpringDataMongoGameRepository 
    extends ReactiveMongoRepository<MongoGameDocument, String> {
}

Repository Adapter

The adapter pattern connects the MongoDB repository to the domain layer:
@Component
public class MongoGameRepositoryAdapter implements GameRepositoryPort {

    private final SpringDataMongoGameRepository repo;

    public MongoGameRepositoryAdapter(SpringDataMongoGameRepository repo) {
        this.repo = repo;
    }

    @Override
    public Mono<Game> save(Game game) {
        MongoGameDocument doc = MongoGameMapper.toDocument(game);
        return repo.save(doc).thenReturn(game);
    }

    @Override
    public Mono<Game> findById(GameId id) {
        return repo.findById(id.value())
                .map(MongoGameMapper::toDomain);
    }

    @Override
    public Mono<Void> deleteById(GameId id) {
        return repo.findById(id.value())
                .switchIfEmpty(Mono.error(new GameNotFoundException(id.value())))
                .flatMap(doc -> repo.deleteById(id.value()));
    }
}

Reactive Operations

All MongoDB operations return reactive types:
  • Mono<Game> - Single game or empty
  • Mono<Void> - Completion signal for delete operations
  • Flux<Game> - Stream of multiple games (if needed)

Example Operations

Save a game:
Mono<Game> savedGame = gameRepository.save(game);
Find a game by ID:
Mono<Game> game = gameRepository.findById(gameId);
Delete a game:
Mono<Void> result = gameRepository.deleteById(gameId);

MongoDB Setup

Local Development with Docker

docker run -d \
  --name blackjack-mongo \
  -p 27017:27017 \
  mongo:latest

Verify Connection

Connect using MongoDB shell:
mongosh mongodb://localhost:27017/blackjack
View stored games:
db.games.find().pretty()

Best Practices

  1. Use Connection Pooling: Spring Data MongoDB handles connection pooling automatically
  2. Reactive Streams: Always use Mono and Flux for non-blocking operations
  3. Document Design: Keep game documents denormalized for fast reads
  4. Indexing: Add indexes on frequently queried fields like playerId
  5. Error Handling: Use reactive error handling with onErrorResume and switchIfEmpty

Troubleshooting

Connection Issues

If MongoDB connection fails:
  1. Verify MongoDB is running: docker ps | grep mongo
  2. Check connection string format
  3. Ensure network connectivity between application and MongoDB
  4. Review application logs for connection errors

Performance Tuning

For production deployments:
spring:
  data:
    mongodb:
      uri: mongodb://host:27017/blackjack?maxPoolSize=50&minPoolSize=10

Build docs developers (and LLMs) love