Why does Spring Data MongoDB not expose events for update…(…) methods?

后端 未结 3 1624
情话喂你
情话喂你 2021-01-07 09:37

It appears that the update for mongoOperations do not trigger the events in AbstractMongoEventListener.

This post indicates that wa

相关标签:
3条回答
  • 2021-01-07 09:46

    I know it's too late to answer this Question, I have the same situation with MongoTemplate.findAndModify method and the reason I needed events is for Auditing purpose. here is what i did.

    1.EventPublisher (which is ofc MongoTemplate's methods)

    public class CustomMongoTemplate extends MongoTemplate {
    
        private ApplicationEventPublisher applicationEventPublisher;
    
    
        @Autowired
        public void setApplicationEventPublisher(ApplicationEventPublisher
                                                             applicationEventPublisher) {
            this.applicationEventPublisher = applicationEventPublisher;
        }
    
       //Default Constructor here
    
        @Override
        public <T> T findAndModify(Query query, Update update, Class<T> entityClass) {
            T result = super.findAndModify(query, update, entityClass);
    
            //Publishing Custom Event on findAndModify
            if(result!=null && result instanceof Parent)//All of my Domain class extends Parent
                this.applicationEventPublisher.publishEvent(new AfterFindAndModify
                        (this,((Parent)result).getId(),
                                result.getClass().toString())
                );
    
            return result;
        } }
    

    2.Application Event

    public class AfterFindAndModify extends ApplicationEvent {
    
        private DocumentAuditLog documentAuditLog;
    
        public AfterFindAndModify(Object source, String documentId,
                                String documentObject) {
            super(source);
            this.documentAuditLog = new DocumentAuditLog(documentId,
                    documentObject,new Date(),"UPDATE");
        }
    
        public DocumentAuditLog getDocumentAuditLog() {
            return documentAuditLog;
        }
    }
    

    3.Application Listener

    public class FindandUpdateMongoEventListner implements ApplicationListener<AfterFindAndModify> {
    
        @Autowired
        MongoOperations mongoOperations;
    
        @Override
        public void onApplicationEvent(AfterFindAndModify event) {
            mongoOperations.save(event.getDocumentAuditLog());
        }
    }
    

    and then

    @Configuration
    @EnableMongoRepositories(basePackages = "my.pkg")
    @ComponentScan(basePackages = {"my.pkg"})
    public class MongoConfig extends AbstractMongoConfiguration {
    
        //.....
    
        @Bean
        public FindandUpdateMongoEventListner findandUpdateMongoEventListner(){
            return new FindandUpdateMongoEventListner();
        }   
    
    }
    
    0 讨论(0)
  • 2021-01-07 09:56

    You can listen to database changes, even the changes completely outside your program (MongoDB 4.2 and newer).

    (code is in kotlin language. same for java)

    @Autowired private lateinit var op: MongoTemplate
    
    @PostConstruct
    fun listenOnExternalChanges() {
        Thread {
            op.getCollection("Item").watch().onEach {
                if(it.updateDescription.updatedFields.containsKey("name")) {
                    println("name changed on a document: ${it.updateDescription.updatedFields["name"]}")
                }
            }
        }.start()
    }
    

    This code only works when replication is enabled. You can enable it even when you have a single node:

    Add the following replica set details to mongodb.conf (/etc/mongodb.conf or /usr/local/etc/mongod.conf or C:\Program Files\MongoDB\Server\4.0\bin\mongod.cfg) file

    replication:
      replSetName: "local"
    

    Restart mongo service, Then open mongo console and run this command:

    rs.initiate()
    
    0 讨论(0)
  • 2021-01-07 10:01

    This is no oversight. Events are designed around the lifecycle of a domain object or a document at least, which means they usually contain an instance of the domain object you're interested in.

    Updates on the other hand are completely handled in the database. So there are no documents or even domain objects handled in MongoTemplate. Consider this basically the same way JPA @EntityListeners are only triggered for entities that are loaded into the persistence context in the first place, but not triggered when a query is executed as the execution of the query is happening in the database.

    0 讨论(0)
提交回复
热议问题