flapdoodle-oss / de.flapdoodle.embed.mongo.spring

embedded mongo spring integration
Apache License 2.0
32 stars 7 forks source link

Cant get flapdoodle to run with transaction support #39

Closed Tobbers closed 6 months ago

Tobbers commented 11 months ago

Hi,

i am currently trying to get flapdoodle to run with transaction support but so far i have failed. I tried to follow this guide as well as other sources i could find online / in my company. My current setup (tried different setups as well) is as follows:

application-test.yaml:

de:
  flapdoodle:
    mongodb:
      embedded:
        version: 5.0.5
spring:
  data:
    mongodb:
      port: 0
      database: test
      uri:

EmbededMongoConfiguration:

@Data
@Profile("test")
@Configuration
public class EmbedMongoConfiguration {

    private static final String DOWNLOAD_LOCATION = "... link to local location ...";

    private final MongoTemplate mongoTemplate;

    @Lazy
    public EmbedMongoConfiguration(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @Bean
    MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
        var transactionManager = new MongoTransactionManager(dbFactory);
        transactionManager.setOptions(TransactionOptions.builder()
                .readConcern(ReadConcern.MAJORITY)
                .writeConcern(WriteConcern.MAJORITY)
                .build());

        return transactionManager;
    }

    @Bean
    MongodArguments mongodArguments() {
        return MongodArguments.builder()
                .replication(Storage.of("rs0", 5000))
                .build();
    }

    @Bean
    Mongod customGod(Net net) {
        return new Mongod() {
            @Override
            public Transition<DistributionBaseUrl> distributionBaseUrl() {
                return Start.to(DistributionBaseUrl.class)
                        .initializedWith(DistributionBaseUrl.of(DOWNLOAD_LOCATION));
            }

            @Override
            public Transition<PersistentDir> persistentBaseDir() {
                String tmpdir = System.getProperty("java.io.tmpdir");

                return Start.to(PersistentDir.class)
                        .initializedWith(PersistentDir.of(Path.of(tmpdir)));
            }

            @Override
            public Transition<Net> net() {
                return Start.to(Net.class)
                        .providedBy(() -> net);
            }

        };
    }

    @SneakyThrows
    @Bean
    public MongoClientSettings mongoClient(Net net) {
        return MongoClientSettings.builder()
                .applyConnectionString(new ConnectionString("mongodb://localhost:" + net.getPort()))
                .uuidRepresentation(UuidRepresentation.STANDARD)
                .build();
    }

    @Bean
    public Object mongoIndexInitializer() {
        return new MongoIndexInitializer(mongoTemplate);
    }
}

Very basic test:

@ActiveProfiles(profiles = "test")
@AutoConfigureDataMongo
@EnableAutoConfiguration
@SpringBootTest
class EurServiceTest {

    @Autowired
    EurService sut;

    @Test
    void upsertEur() {

        sut.upsertEur(null);
    }
}

Service that´s being tested:

@Component
@Slf4j
public class EurService {

    private final EusHelper eusHelper;
    private final EusRepository eusRepository;

    public EurService(EusHelper eusHelper, EusRepository eusRepository) {
        this.eusHelper = eusHelper;
        this.eusRepository = eusRepository;
    }

    @Transactional
    public void upsertEur(SdKafkaEvent sdEvent) {
        eusRepository.save(EusEntity.builder()
                .name("saved in db")
                .build());
    }
}

With this setup I get the following error:

Caused by: com.mongodb.MongoCommandException: Command failed with error 76 (NoReplicationEnabled): 'This node was not started with the replSet option' on server vmware-plugin:3843. The full response is {"ok": 0.0, "errmsg": "This node was not started with the replSet option", "code": 76, "codeName": "NoReplicationEnabled"}
    at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:205)
    at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:443)
    at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:365)
    at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:114)
    at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:643)
    at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:73)
    at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:204)
    at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:122)
    at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:87)
    at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:76)
    at com.mongodb.internal.connection.DefaultServer$OperationCountTrackingConnection.command(DefaultServer.java:288)
    at com.mongodb.internal.operation.CommandOperationHelper.createReadCommandAndExecute(CommandOperationHelper.java:239)
    at com.mongodb.internal.operation.CommandOperationHelper.lambda$executeRetryableRead$4(CommandOperationHelper.java:220)
    at com.mongodb.internal.operation.OperationHelper.lambda$withSourceAndConnection$0(OperationHelper.java:358)
    at com.mongodb.internal.operation.OperationHelper.withSuppliedResource(OperationHelper.java:383)
    at com.mongodb.internal.operation.OperationHelper.lambda$withSourceAndConnection$1(OperationHelper.java:357)
    at com.mongodb.internal.operation.OperationHelper.withSuppliedResource(OperationHelper.java:383)
    at com.mongodb.internal.operation.OperationHelper.withSourceAndConnection(OperationHelper.java:356)
    at com.mongodb.internal.operation.CommandOperationHelper.lambda$executeRetryableRead$5(CommandOperationHelper.java:218)
    at com.mongodb.internal.async.function.RetryingSyncSupplier.get(RetryingSyncSupplier.java:67)
    at com.mongodb.internal.operation.CommandOperationHelper.executeRetryableRead(CommandOperationHelper.java:223)
    at com.mongodb.internal.operation.CommandOperationHelper.executeRetryableRead(CommandOperationHelper.java:204)
    at com.mongodb.internal.operation.CommandReadOperation.execute(CommandReadOperation.java:48)
    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:185)
    at com.mongodb.client.internal.MongoDatabaseImpl.executeCommand(MongoDatabaseImpl.java:196)
    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:165)
    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:160)
    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:150)
    at de.flapdoodle.embed.mongo.spring.autoconfigure.SyncClientServerFactory.resultOfAction(SyncClientServerFactory.java:68)
    at de.flapdoodle.embed.mongo.spring.autoconfigure.SyncClientServerFactory.resultOfAction(SyncClientServerFactory.java:47)
    at de.flapdoodle.embed.mongo.spring.autoconfigure.AbstractServerFactory.executeClientAction(AbstractServerFactory.java:155)
    ... 185 common frames omitted

Do you have any suggestions that I could try to resolve the issue?

michaelmosmann commented 11 months ago

@Tobbers hmm.. interesting .. you could fork this project (https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo.canary) and apply these changes until it breaks/works.. then i have to look into this..

Tobbers commented 11 months ago

Thanks, I will try that as soon as I can but it could take a while

Tobbers commented 11 months ago

Hey @michaelmosmann .

I was able to reproduce the problem in the canary project https://github.com/Tobbers/de.flapdoodle.embed.mongo.canary

A few comments:

michaelmosmann commented 11 months ago

@Tobbers cool.. thanks.. i will have a look into that.

michaelmosmann commented 11 months ago

@Tobbers .. hmm.. may i miss something. None of these cases did run on my machine (reverted the local-artifactory-url) .. after setting useNoJournal to false (yes.. it should be useJournal=true) it failed with this error message: ommand failed with error 13436 (NotPrimaryOrSecondary): 'node is not in primary or recovering state'

Tobbers commented 11 months ago

@michaelmosmann hm that is weird. I wasn't at work for a week but when I came back ConfigurationA still ran. One thing that I didn't mention is that since we have no internet access and ConfigurationA doesn't specify the download location I had to install the local mongo manually. For this I followed the instructions printed on the first test run. Something like "Download zip manually and put it at "%userprofile%/.embededmongo/archives/....". Don't know if you did the same.

If this Information doesn't help you locating the problem I think I´ll have to bite the bullet and refrain from testing transactions with flapdoodle.

michaelmosmann commented 6 months ago

@Tobbers is this still an issue? i would close this.. reopen if needed.