Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
2.18.1
-
None
Description
I think there is a problem with multi-insert on MongoDB component as it fails to gracefully handle a BasicDBList. The logic below always sets the SingleInsert flag to true if the type converter is able to convert the exchange to a DBObject interface. This is implemented by BasicDBList and BasicDBObject.
Further details below :
I am trying to do a multiple insert using the camel mongo db component.
My Pojo representation is :
Person { String firstName; String lastName; }
I have a processor which constructs a valid List of Person pojo and is a valid json structure. When this list of Person is sent to the mongodb producer , on invocation of createDoInsert the type conversion to BasicDBObject fails. This piece of code below looks to be the problem. Should it have more fall backs / checks in place to attempt the list conversion down further below as it fails on the very first cast itself. Debugging the MongoDbProducer the exchange object being received is a BasicDBList which implements DBObject. This causes the singleInsert flag to remain set at true which fails the insertion below as we get a BasicDBList instead of a BasicDBObject :
if(singleInsert) { BasicDBObject insertObjects = (BasicDBObject)insert; dbCol.insertOne(insertObjects); exchange1.getIn().setHeader("CamelMongoOid", insertObjects.get("_id")); }
The Camel MongoDbProducer code fragment
private Function<Exchange, Object> createDoInsert() { return (exchange1) -> { MongoCollection dbCol = this.calculateCollection(exchange1); boolean singleInsert = true; Object insert = exchange1.getIn().getBody(DBObject.class); if(insert == null) { insert = exchange1.getIn().getBody(List.class); if(insert == null) { throw new CamelMongoDbException("MongoDB operation = insert, Body is not conversible to type DBObject nor List<DBObject>"); } singleInsert = false; insert = this.attemptConvertToList((List)insert, exchange1); } if(singleInsert) { BasicDBObject insertObjects = (BasicDBObject)insert; dbCol.insertOne(insertObjects); exchange1.getIn().setHeader("CamelMongoOid", insertObjects.get("_id")); } else { List insertObjects1 = (List)insert; dbCol.insertMany(insertObjects1); ArrayList objectIdentification = new ArrayList(insertObjects1.size()); objectIdentification.addAll((Collection)insertObjects1.stream().map((insertObject) -> { return insertObject.get("_id"); }).collect(Collectors.toList())); exchange1.getIn().setHeader("CamelMongoOid", objectIdentification); } return insert; }; }
My route is as below :
<route id="uploadFile"> <from uri="jetty://http://0.0.0.0:9886/test"/> <process ref="fileProcessor"/> <unmarshal> <csv> <header>fname</header> <header>lname</header> </csv> </unmarshal> <process ref="mongodbProcessor" /> <to uri="mongodb:mongoBean?database=axs175&collection=insurance&operation=insert" />
and the MongoDBProcessor constructing the List of Person Pojo
@Component public class MongodbProcessor implements Processor { @Override public void process(Exchange exchange) throws Exception { ArrayList<List<String>> personlist = (ArrayList) exchange.getIn().getBody(); ArrayList<Person> persons = new ArrayList<>(); for(List<String> records : personlist){ Person person = new Person(); person.setFname(records.get(0)); person.setLname(records.get(1)); persons.add(person); } exchange.getIn().setBody(persons); } }
Attachments
Issue Links
- links to