1

I tried to update some of my sample codes to Spring Boot 3.0.5 from Spring Boot 2.7.

@Document(collection = "posts")
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Post implements Serializable {

    @Id
    private String id;

    @NotBlank
    private String title;

    @NotBlank
    private String content;

    @Builder.Default
    private Status status = DRAFT;

    @DocumentReference
    @Builder.Default
    List<Comment> comments = Collections.emptyList();

//    @Version
//    @Builder.Default
//    Long version = null;

    @CreatedDate
    private LocalDateTime createdDate;

    @CreatedBy
    private String createdBy;

    @LastModifiedDate
    private LocalDateTime lastModifiedDate;

    @LastModifiedBy
    private String lastModifiedBy;
}

I wrote a test for it like this.

@DataMongoTest
@Slf4j
@Testcontainers
public class PostRepositoryTest {

    @TestConfiguration
    @Import(MongoPostRepository.class)
    static class TestConfig {
    }

    @Container
    static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4");

    @DynamicPropertySource
    static void registerMongoProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getReplicaSetUrl());
    }

    @Autowired
    PostRepository postRepository;

    @Autowired
    ReactiveMongoTemplate reactiveMongoTemplate;

    @SneakyThrows
    @BeforeEach
    public void setup() {
        var latch = new CountDownLatch(1);
        this.reactiveMongoTemplate.remove(Post.class).all()
            .doOnTerminate(latch::countDown)
            .subscribe(
                r -> log.debug("delete all posts: " + r),
                e -> log.debug("error: " + e), () -> log.debug("done")
            );
        latch.await(5000, TimeUnit.MILLISECONDS);
    }


    @Test
    public void testSavePost() {
        var content = "my test content";
        var title = "my test title";
        var saved = this.postRepository.create(title, content);

        StepVerifier.create(saved)
            .consumeNextWith(p -> {
                log.debug("consuming:: {}", p);
                assertThat(p.getTitle()).isEqualTo(title);
            })
            .expectComplete()
            .verify();

        var id = saved.block().getId();

        this.postRepository.addComment(id, "comment1")
            .then(this.postRepository.findById(id))
            .as(StepVerifier::create)
            .consumeNextWith(p -> {
                log.debug("after add comments: {}", p);
                assertThat(p.getComments()).isNotNull();
            })
            .expectComplete()
            .verify();
    }


}

And the postRepository.addComment is a method using ReactiveMongoTemplate.

    @Override
    public Mono<Boolean> addComment(String id, String content) {
        var comment = mongoTemplate.insert(Comment.builder().content(content).build());
        return comment.flatMap(c -> mongoTemplate.update(Post.class)
                .matching(where("id").is(id))
                .apply(new Update().push("comments").value(c))
                .first().hasElement()
        );
    }

But the mongoTemplate.update throws an exception like this.


org.springframework.dao.DuplicateKeyException: Write operation error on server localhost:56524.
 Write error: WriteError{code=11000, message='E11000 duplicate key error collection: 
test.posts index: _id_ dup key: { _id: ObjectId('6428f50354bd273efaa52456') }', 
details={}}.

I have to make document Post to implement Persistable?

I am not sure why it determine an existing entity as new here.

Hantsy
  • 8,006
  • 7
  • 64
  • 109

0 Answers0