Na verdade não, pois o Mongo Java Driver já expõe o último erro como uma String construída:
writeResult.getLastError().get("err")
retorna algo como:insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.person.$username dup key: { : "joe" }
Isso também é verdade para o shell e todos os drivers, imagino.
Uma solução razoável, eu acho, é analisar essa exceção de chave duplicada usando uma exceção personalizada:
public class DetailedDuplicateKeyException extends DuplicateKeyException {
public DetailedDuplicateKeyException(String msg) {
// Instead of just calling super parse the message here.
super(msg);
}
}
... um tradutor de exceção personalizado:
public class DetailedDuplicateKeyExceptionTransaltor extends MongoExceptionTranslator {
@Override
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
if (ex instanceof MongoException.DuplicateKey) {
return new DetailedDuplicateKeyException(ex.getMessage());
}
return super.translateExceptionIfPossible(ex);
}
}
... e definindo a configuração do Spring corretamente:
@Bean
public MongoFactoryBean mongo() {
MongoFactoryBean mongo = new MongoFactoryBean();
mongo.setExceptionTranslator(new DetailedDuplicateKeyExceptionTransaltor());
mongo.setHost("localhost");
return mongo;
}
EDITAR
Após inspecionar
MongoTemplate
code (1.4.1.RELEASE), parece que internamente um SimpleMongoDbFactory
é usado para recuperar um padrão MongoExceptionTranslator
, então aquele criado com MongoFactoryBean
está sombreado. Tinha perdido essa parte. A solução é substituir
SimpleMongoDbFactory
(esqueça sobre MongoFactoryBean
, é inútil neste contexto):public class MySimpleMongoDbFactory extends SimpleMongoDbFactory {
PersistenceExceptionTranslator translator = new
DetailedDuplicateKeyExceptionTransaltor();
public MySimpleMongoDbFactory(Mongo mongo, String databaseName) {
super(mongo, databaseName);
}
@Override
public PersistenceExceptionTranslator getExceptionTranslator() {
return translator;
}
}
Agora você pode construir um modelo usando o
MongoDbFactory
personalizado :template = new MongoTemplate
(new MySimpleMongoDbFactory(new MongoClient(), "test"));
Tinha tentado, e este funciona para mim.