'MongoDB Lifecycle event access to MongoTemplate

I'm trying to implement a versioning system for my mongodb documents with Spring Data Mongodb. I thought i'd take advantage of the Mongo lifecycle events

Mongo Lifecycle Events in Spring

What I wanted to do was listen to onBeforeSave and fetch the pristine version of the document, and get the diff between the two.

@Override
public void onBeforeSave(Table table, DBObject dbo) {

    if (table.getId() != null) {
        TableChange change = new TableChange();

        Table beforeTable = mongoOperations.findById(table.getId(), Table.class);

        if (!beforeTable.getName().equals(table.getName())) {
            change.setName(table.getName());
        }

        MapDifference<String, Column> diff = Maps.difference(beforeTable.getColumns(), table.getColumns());

        logger.debug(diff.entriesInCommon().toString());
        logger.debug(diff.entriesDiffering().toString());
        logger.debug(diff.entriesOnlyOnLeft().toString());
        logger.debug(diff.entriesOnlyOnRight().toString());         

        table.addChange(change);
    }
}

The problem I'm having is that i can't get a reference to mongoOperations. It keeps creating a circular reference. Whether i @Autowire:

Autowire Injection

Mongo config:

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
    <constructor-arg name="mongoConverter" ref="fooConverter" />
    <property name="writeResultChecking" value="EXCEPTION" />
</bean>

<bean class="com.example.listener.document.TableListener"></bean>

Listener:

public class TableListener extends AbstractMongoEventListener<Table> {

    private static final Logger logger = LoggerFactory.getLogger(TableListener.class);

    @Autowired MongoTemplate mongoTemplate;

    @Override
    public void onBeforeSave(Table table, DBObject dbo) {
        // .... 
    }
}

or use Setter Injection

Setter Injection

Mongo config:

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
    <constructor-arg name="mongoConverter" ref="fooConverter" />
    <property name="writeResultChecking" value="EXCEPTION" />
</bean>

<bean class="com.example.listener.document.TableListener">
    <property name="mongoTemplate" ref="mongoTemplate" />
</bean>

Listener:

public class TableListener extends AbstractMongoEventListener<Table> {

    private static final Logger logger = LoggerFactory.getLogger(TableListener.class);

    private MongoTemplate mongoTemplate;

    public void setMongoTemplate(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @Override
    public void onBeforeSave(Table table, DBObject dbo) {
        // .... 
    }
}

It makes sense to me to handle the Document versioning in the lifecycle events. I did a similar thing with PHP/Doctrine/Mongo

How I did it with Doctrine/PHP

In the case of Doctrine I get a reference to the Document Manager in the lifecycle callback. Any clues how i can do this same thing with Spring Data?



Solution 1:[1]

I've tried, few java based configurations

  1. With explicit parameter:

    @Configuration
    public static class ListenerConfiguration {
    
       @Bean
       public TableListener tableListener(MongoOperations mongoOperations) {
           return new TableListener(mongoOperations);
       }
    
    }
    
  2. With @Autowired

    @Configuration
    public static class ListenerConfiguration {
    
        @Bean
        public TableListener tableListener() {
            return new TableListener();
        }
    
    }
    

All of which worked perfectly.

  1. One option is - you just forgotten to add

    <context:annotation-config/>
    

    in your xml configurations, although this would not explain setter injection failure.

  2. You might have bean name overrides somewhere

And many more.

Anyway, the problem lies in how you use Spring, not in the spring configurations you provided, it's fine.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mavarazy