Issue
I am new to using Apache camel with Spring boot and try to implement a basic route in which, I want to filter out first whether the file has json contents or xml contents and based upon it, I want to save the file in some specific folder.
I make my service instance up and then hit its post endpoint using postman with JSON content. My service saves that file to some folder location with txt extension. I have created the route in the service which picks up the file and checks if it is not empty, it will transform the contents in to XML format and store it to some folder. Route for this thing is below:
public class OutboundRoute extends RouteBuilder {
Predicate p1=body().isNotNull();
Predicate p2=body().isNotEqualTo("");
Predicate predicateGroup=PredicateBuilder.and(p1,p2);
String inputFilePath="file:C:\\Users\\StorageFolder\\Input?noop=true";
String outputFilePathForJson="file:C:\\Users\\StorageFolder\\JsonFolderOutput?delete=true";
@Override
public void configure() throws Exception {
from(inputFilePath)
.routeId("readingJsonFromFile")
.choice()
.when(predicateGroup)
.log("Before converting to XML: ${body}")
.unmarshal().json(JsonLibrary.Jackson, Message.class)
.marshal().jacksonXml(true)
.log(LoggingLevel.INFO, "Payload after converting to xml = ${body}")
.to(outputFilePathForJson)
.otherwise()
.log("Body is Empty!!")
.end();
}
}
Now I want to implement this thing for xml also for better understanding. I want that I can hit my service using postman with either XML or JSON content. The route should pick the file and check it. If it has XML contents, route should convert its contents to JSON and store it to JSON folder but if it has JSON contents, route should convert its contents to XML and store it to XML folder. I need help with this thing.
Main thing is that when I hit the service using postman, service will always store the file with txt extension only. So, I need help with a way to find that content of file is of JSON format or XML format.
Also, I tried finding some content about learning apache camel but everywhere found basic tutorials only. Can someone recommend some platform where I can learn how to write complex routes?
Solution
I won't say its a good answer but an easy alternative I would say.
What I did is, I created a processor which will check first character of file and if its "{", then its json and if its "<", then its XML. So, after detecting, I would add a header to camel route exchange as "Type": json or xml or unknown
And using camel's "simple" language,I will check the header and based on that, in the route, I will do the processing. I am adding below files for better reference.
Predicates used in route:
private Predicate notNull=body().isNotNull();
private Predicate notEmpty=body().isNotEqualTo("");
private Predicate checkEmptyFile=PredicateBuilder.and(notNull,notEmpty);
private Predicate checkIfJsonContents=header("Type").isEqualTo("json");
private Predicate checkIfXmlContents=header("Type").isEqualTo("xml");
private Predicate checkIfFileHasJsonContents=PredicateBuilder.and(checkEmptyFile,checkIfJsonContents);
private Predicate checkIfFileHasXmlContents=PredicateBuilder.and(checkEmptyFile,checkIfXmlContents);
Route:
from(inputFilePath)
.routeId("readingJsonFromFile")
.routeDescription("This route will assign a file type to file based on contents and then save it in different folder based on contents.")
.process(fileTypeDetectionProcessor)
.log("Added file type to header as: ${header.Type}")
.choice()
.when(checkIfFileHasJsonContents)
.log("Payload before converting to XML: ${body}")
.unmarshal().json(JsonLibrary.Jackson, Message.class)
.marshal().jacksonXml(true)
.log(LoggingLevel.INFO, "Payload after converting to xml = ${body}")
.to(outputFilePathForXml)
.when(checkIfFileHasXmlContents)
.log("Payload before converting to JSON: ${body}")
.unmarshal().jacksonXml(Message.class,true)
.marshal().json(true)
.log(LoggingLevel.INFO, "Payload after converting to JSON = ${body}")
.to(outputFilePathForJson)
.otherwise()
.log("Unreadable format or empty file!!")
.to(outputFilePathForBadFile)
.end();
Processor:
public class FileTypeDetectionProcessor implements Processor {
@Override
public void process(Exchange exchange) throws Exception {
if(exchange.getIn().getBody(String.class).startsWith("{"))
exchange.getIn().setHeader("Type","json");
else if(exchange.getIn().getBody(String.class).startsWith("<"))
exchange.getIn().setHeader("Type","xml");
else
exchange.getIn().setHeader("Type","unknown");
}
}
Answered By - Prabhpreet Singh
Answer Checked By - Pedro (JavaFixing Volunteer)