使用Camel路由读取文件插入MongoDB时遇InvalidPayloadException报错求助
Hey there! Let's break down the org.apache.camel.InvalidPayloadException: No body available of type: com.mongodb.DBObject error you're hitting. This is a common mismatch issue—your file endpoint is reading raw text (or an InputStream) from files, but the MongoDB Camel component expects a body in a format it can serialize to MongoDB documents (like DBObject, Map, POJO, or BsonDocument).
Let's Start with the Root Cause
By default, Camel's file component returns the file content as a String or InputStream in the message body. The MongoDB component can't directly convert that to a MongoDB document, hence the error. We need to add a step to transform the file content into a compatible type.
Step-by-Step Fixes Based on Your File Format
1. If Your Files Contain Single JSON Objects
If each file holds a single JSON document (e.g., {"id": 1, "content": "test data"}), use Camel's Jackson JSON component to unmarshal the string into a Map or BasicDBObject:
First, ensure you have the Jackson dependency (Maven example):
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jackson</artifactId> <version>your-camel-version</version> </dependency>
Then update your route to convert the JSON string:
from("file:/path/to/your/files") // Convert JSON string to a Map (MongoDB supports Map directly) .unmarshal().json(JsonLibrary.Jackson, Map.class) // Or convert to BasicDBObject if you prefer the native MongoDB type // .unmarshal().json(JsonLibrary.Jackson, BasicDBObject.class) .to("mongodb:mongoConnection?database=yourDb&collection=yourColl&operation=insert");
2. If Your Files Contain Multi-Line JSON (One Document Per Line)
For files with multiple JSON entries (each on a new line), split the file content by lines first, then convert each line:
from("file:/path/to/your/files") // Split file content into individual lines .split(body().tokenize("\n")) // Skip empty lines to avoid errors .filter(body().isNotEmpty()) // Convert each line to a Map .unmarshal().json(JsonLibrary.Jackson, Map.class) .to("mongodb:mongoConnection?database=yourDb&collection=yourColl&operation=insert");
3. If Your Files Use a Custom Format (e.g., CSV)
For non-JSON formats like CSV, first parse the content into a structured format, then map it to a Map or POJO. Here's an example using Camel's CSV component:
Add the CSV dependency:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-csv</artifactId> <version>your-camel-version</version> </dependency>
Then build the route to parse and transform:
from("file:/path/to/your/files") // Parse CSV (configure headers if your file has them) .unmarshal().csv().setHeader(Exchange.CSV_HEADER, constant("id,content,createdDate")) // Convert parsed rows to Maps .process(exchange -> { List<Map<String, String>> csvRows = exchange.getIn().getBody(List.class); List<Map<String, Object>> mongoDocuments = new ArrayList<>(); for (Map<String, String> row : csvRows) { Map<String, Object> doc = new HashMap<>(row); // Optional: Convert data types (e.g., string date to LocalDateTime) doc.put("createdDate", LocalDateTime.parse(row.get("createdDate"))); mongoDocuments.add(doc); } exchange.getIn().setBody(mongoDocuments); }) .to("mongodb:mongoConnection?database=yourDb&collection=yourColl&operation=insert");
Additional Debugging Tips
- Add a log step to verify the body type before and after transformation:
from("file:/path/to/your/files") .log("Original body type: ${body.class} | Content: ${body}") .unmarshal().json(JsonLibrary.Jackson, Map.class) .log("Transformed body type: ${body.class} | Content: ${body}") .to("mongodb:..."); - Ensure your Camel and MongoDB component versions are compatible (e.g., use
mongodb4component for MongoDB 4.x+ instead of the oldermongodbcomponent).
内容的提问来源于stack exchange,提问作者Shamim Ahmad

