Wednesday, May 23, 2012

MongoDB "norepl" Exception

I was using MongoDB 2.0.4 (mongodb-win32-x86_64-2.0.4) with spring-data-mongodb-1.0.1-RELEASE and spring-framework-3.1.1-RELEASE to do a data insert.

The insert method was as follows:
 public static final String FOO_COLLECTION = "foos";

 @Autowired private MongoTemplate mongoTemplate;

 public void add(Foo foo) {
  mongoTemplate.save(foo, FOO_COLLECTION);
 }
It's supposed to be simple and yet I got the following error:
org.springframework.data.mongodb.UncategorizedMongoDbException: norepl; nested exception is com.mongodb.MongoException: norepl
 at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:70)
 at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:1538)
 at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:370)
 at org.springframework.data.mongodb.core.MongoTemplate.saveDBObject(MongoTemplate.java:784)
 at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:720)
 at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:707)
 ... ...
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
 at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
 at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
 at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: com.mongodb.MongoException: norepl
 at com.mongodb.CommandResult.getException(CommandResult.java:87)
 at com.mongodb.CommandResult.throwOnError(CommandResult.java:121)
 at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:131)
 at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:155)
 at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:138)
 at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:261)
 at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:211)
 at com.mongodb.DBCollection.insert(DBCollection.java:57)
 at com.mongodb.DBCollection.insert(DBCollection.java:87)
 at com.mongodb.DBCollection.save(DBCollection.java:728)
 at org.springframework.data.mongodb.core.MongoTemplate$11.doInCollection(MongoTemplate.java:792)
 at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:368)
 ... 33 more
The data got inserted into MongoDB, but the Exception still got thrown.

I look around and eventually found out that the way I define my "WriteConcern" in the mongoTemplate bean definition in applicationContext.xml caused the Exception.  It seems that anything other than the default will cause the Exception similar to above.

Here's how my mongoTemplate originally defined:
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
        <constructor-arg name="mongoConverter" ref="converter" />
        <property name="writeResultChecking" value="EXCEPTION" />
        <property name="writeConcern" value="NORMAL" />
    </bean>
Here's the changes that "fixed" the Exception:
<beans ...
xmlns:util="http://www.springframework.org/schema/util"
 ...
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
 ... >
     <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
        <constructor-arg name="mongoConverter" ref="converter" />
        <property name="writeResultChecking" value="EXCEPTION" />
        <property name="writeConcern">
          <util:constant static-field="com.mongodb.WriteConcern.NORMAL" />
        </property>
    </bean>
Apparently, changing:

<property name="writeConcern" value="SAFE">

to

<property name="writeConcern">
    <util:constant static-field="com.mongodb.WriteConcern.SAFE"></util:constant>
<property>

Seems to resolve the issue.

2 comments:

  1. Many thanks. You saved us lot of work! We faced this strange non-descriptive com.mongodb.MongoException: norepl error after upgrading from java mongodb driver from 2.6.5 to 2.8.0.
    Espinosa

    Minor fix:
    <property name="writeConcern">
    <util:constant static-field="com.mongodb.WriteConcern.SAFE"/>
    </property>

    Header definition:
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    ReplyDelete
    Replies
    1. Thanks for the correction. I updated the post accordingly.

      Delete