Apache Camel: How to look inside body to determine file format - java

We receive .csv files (both via ftp and email) each of which can be one of a few different formats (that can be determined by looking at the top line of the file). I am fairly new to Apache Camel but want to implement a content based router and unmarshal each to the relevant class.
My current solution is to break down the files to a lists of strings, manually use the first line to determine the type of file, and then use the rest of the strings to create relevant entity instances.
Are there a cleaner and better way?

You could use a POJO to implement the type check in whatever way works best for your files.
public String checkFileType(#Body File file) {
return determineFileType(file);
}
private String determineFileType(File file) {...}
Like this you can keep your route clean by separating the filetype check and any other part of processing. Because the filetype check is just metadata enrichment.
For example you could just set the return value as a message header by calling the bean)
.setHeader("fileType", method(fileTypeChecker))
Then you can route the files according to type easily by using the message header.
.choice()
.when(header("fileType").isEqualTo("foo"))
...

Related

Send HTML file in Apache Camel RouteBuilder

I am having HTML file which I want to send as a response for the rest call inside Apache camel RouteBuilder. The code looks like below
public class RestEndpointRouteBuilder extends RouteBuilder {
#Override
public void configure() {
rest("/form")
.post()
.produces(MediaType.TEXT_HTML_VALUE)
.to("file:target/classes/static/form.html");
}
But, I am getting below error when I call the API
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot write null body to file: target\classes\static\form.html\ID-*****-***-****
at org.apache.camel.component.file.FileOperations.storeFile(FileOperations.java:245)
at org.apache.camel.component.file.GenericFileProducer.writeFile(GenericFileProducer.java:277)
at org.apache.camel.component.file.GenericFileProducer.processExchange(GenericFileProducer.java:165)
at org.apache.camel.component.file.GenericFileProducer.process(GenericFileProducer.java:79)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
Basically, I want to return an HTML file, which is a ReactJS application, alongwith JS minified files. Could someone please help me with this?
There are several problems in your code:
The more appropriate HTTP method is rather GET instead of POST
The file component here is a to endpoint so it is used as a producer, in other words, it will save into the file instead of reading it as you expect.
The URI of the file component is incorrect, the URI format is file:directoryName[?options] which means that target/classes/static/form.html is supposed to be a directory, not a file.
What you try to achieve could be done as follow:
rest("/form")
// Fix #1: Use "get" instead of "post"
.get()
.produces(MediaType.TEXT_HTML)
.to("direct:fileContent");
from("direct:fileContent")
// Fix #2: Use "pollEnrich" to use the file component as a
// consumer to read the file
// Fix #3: Fix the URI to have the directory name on one side
// and the file name on the other side
.pollEnrich("file:target/classes/static?fileName=form.html");
NB: Even if what I described above will work, please note that a rest endpoint is not meant to be used for static content, you are supposed to use a reverse proxy instead.

Send and receive data with XML

I have 2 programs : Agent.java & Simulator.java (don't worry about names, you can call them A & B respectively). Now, I want to send job object from Agent to Simulator using XML format. The job class looks like:
public class job {
int JobID;
job(int JobID){
this.JobID=JobID;
}
public int getJobID(){
//get JobID variable value from here
}
public void setJobID(int temp_JobID){
//change variable JobID here
}
}
Now I store it in a XML format and send to Simulator. I know that I can use other ways to send object job but this XML file format is standard to be followed in my project.
On the other hand , I receive job object, get data from it and use them in program.
So my Q. is: How do I send data using XML? I saw many Q. related to this but they refer to an XML file on hard drive, convert to String, send it and then receive in other program. I think this is not going to work in my case because I have many jobs are coming continuously, and I will receive them on real-time. So, its bad idea to store them on my compute. Isn't there any XML file sender and receiver?
Maybe look at JAXB. You can create xsd-files from your specified format, generate annotated job class from it and also use the generated object factories. Then you have your jobs in memory and you can create a queue of them.
In one of the projects, I used JDOM for exchanging data between files in xml.
Class A constructs xml document from the object's fields and send that document to class B. Class B can create object from that received document.
No need of any file for posting jobs. You can use in-memory objects.
Try using JIBX to Marshall/Unmarshall you job object and have it in memory instead of in file. Once you have that Job object marshall to XML in string format send it to Simulator. On the Simulator side unmashall the XML to Job object again.
If you are using any JMS service for posting jobs to Simulator make that XML string part of you Message.

How can I get content from Exchange.In:Body object from a ProcessDefinition in Camel

I am integrating data between two systems using Apache Camel. I want the resulting xml to be written to an xml file. I want to base the name of that file on some data which is unknown when the integration chain starts.
When I have done the first enrich step the data necessary is in the Exchange object.
So the question is how can I get data from the exchange.getIn().getBody() method outside of the process chain in order to generate a desirable filename for my output file and as a final step, write the xml to this file? Or is there some other way to accomplish this?
Here is my current Process chain from the routebuilders configuration method:
from("test_main", "jetty:server")
.process(new PiProgramCommonProcessor())
.enrich("piProgrammeEnricher", new PiProgrammeEnricher())
// after this step I have the data available in exchange.in.body
.to(freeMarkerXMLGenerator)
.to(xmlFileDestination)
.end();
best regards
RythmiC
The file component takes the file name from a header (if present). So you can just add a header to your message with the desired file name.
The header should use the key "CamelFileName" which is also defined from Exchange.FILE_NAME.
See more details at: http://camel.apache.org/file2

Reading Java property groups from a file

Is it possible to read different property groups from a Java file, without manual processing?
By "manual" I mean reading the file line by line, detecting where the start of a property group is and then extracting the corresponding key-value pairs. In practice, this means reinventing (most of) the wheel that the Properties.load() method constitutes.
Essentially, what I am looking for is an easy way of reading, from a single file, multiple groups of properties, with each group being identifiable, so that it can be loaded in its own Java Properties object.
I you want to use java.util.Properties you can use prefixes. In .properties file:
group1.key1=valgroup1key1
group2.key1=valgroup2key1
group2.key2=valgroup2key2
and read them like this:
class PrefixedProperty extends Properties {
public String getProperty(String group, String key) {
return getProperty(group + '.' + key);
}
}
and using:
/* loading, initialization like for java.util.Properties */
String val = prefixedProperty.getProperty("group1", "key1");
You can also use ini4j with windows ini files.
Another, better way is using own, custom structured file (for example XML).

JSP: Get MIME Type on File Upload

I'm doing a file upload, and I want to get the Mime type from the uploaded file.
I was trying to use the request.getContentType(), but when I call:
String contentType = req.getContentType();
It will return:
multipart/form-data; boundary=---------------------------310662768914663
How can I get the correct value?
Thanks in advance
It sounds like as if you're homegrowing a multipart/form-data parser. I wouldn't recommend to do that. Rather use a decent one like Apache Commons FileUpload. For uploaded files, it offers a FileItem#getContentType() to extract the client-specified content type, if any.
String contentType = item.getContentType();
If it returns null (just because the client didn't specify it), then you can take benefit of ServletContext#getMimeType() based on the file name.
String filename = FilenameUtils.getName(item.getName());
String contentType = getServletContext().getMimeType(filename);
This will be resolved based on <mime-mapping> entries in servletcontainer's default web.xml (in case of for example Tomcat, it's present in /conf/web.xml) and also on the web.xml of your webapp, if any, which can expand/override the servletcontainer's default mappings.
You however need to keep in mind that the value of the multipart content type is fully controlled by the client and also that the client-provided file extension does not necessarily need to represent the actual file content. For instance, the client could just edit the file extension. Be careful when using this information in business logic.
Related:
How to upload files in JSP/Servlet?
How to check whether an uploaded file is an image?
just use:
public String ServletContext.getMimeType(String file)
You could use MimetypesFileTypeMap
String contentType = new MimetypesFileTypeMap().getContentType(fileName)); // gets mime type
However, you would encounter the overhead of editing the mime.types file, if the file type is not already listed. (Sorry, I take that back, as you could add instances to the map programmatically and that would be the first place that it checks)

Categories

Resources