'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
With explicit parameter:
@Configuration public static class ListenerConfiguration { @Bean public TableListener tableListener(MongoOperations mongoOperations) { return new TableListener(mongoOperations); } }With @Autowired
@Configuration public static class ListenerConfiguration { @Bean public TableListener tableListener() { return new TableListener(); } }
All of which worked perfectly.
One option is - you just forgotten to add
<context:annotation-config/>in your xml configurations, although this would not explain setter injection failure.
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 |
