I am doing data format conversion between POJO to CSV and vice versa. In this while converting CSV to Object file(Unmarshalling) i am getting illegal argument exception for int data type. Only for string its working fine.
Below is my POJO
#CsvRecord(separator="//|",crlf="UNIX",generateHeaderColumns=false)
public class EmployeeVO implements Serializable{
private static final long serialVersionUID = -663135747565879908L;
#DataField(pos=1)
private String name;
#DataField(pos=3)
private Integer age;
#DataField(pos=2)
private String grade;
// getter setter
}
csv data
sumit|4th standrad|22
the above csv is generated from the above POJO. But at the time of converting CSV to POJO i am getting folloing exception
java.lang.IllegalArgumentException: Parsing error detected for field defined at the position: 3, line: 1
following are my camel - context file for your reference
marshal
<route>
<from uri="cxf:bean:rtoemplyeeService"/>
<convertBodyTo type="java.lang.String" id="stringInput"/>
<bean ref="govtEmpBean" method="getEmployeeCSV" beanType="govtEmpBean" id="govtEmp"/>
<log message="before marshalling ================== ${body}"/>
<marshal ref="bindyDataformat">
<bindy type="Csv" packages="com.mycompany.converter.vo"/>
</marshal>
<log message="after marshalling ================== ${body}"/>
<to uri="file://D:/JATO_WORK/repo_bkp/csv/"/>
<setBody>
<simple>CSV output is generated at file system </simple>
</setBody>
</route>
un marshal
<route id="csvtoobject">
<from uri="file://D:/JATO_WORK/repo_bkp/csv?delay=10000&initialDelay=10"/>
<log message="csv string ============= ${body}"/>
<unmarshal ref="bindyDataformat"/>
<log message="${body}"/>
<bean ref="govtEmpBean" method="printCSVObject" beanType="govtEmpBean" id="govtEmp"/>
</route>
You need to specify the csv record as follows
#CsvRecord(separator = "\\|")
Related
I am migrating from camle 2 to camel 3 as below configuration
<onException>
<exception>com.sample</exception>
<redeliveryPolicy disableRedelivery="true"/>
<handled>
<constant>true</constant>
</handled>
<log message="got here, before predict, ${exchangeProperty.firstCall}" loggingLevel="INFO"/>
<choice>
<when>
<method>operation</method>
<bean ref="Procs" method="SampleCommentRequestForError"/>
<setProperty propertyName="firstCall">
<constant>false</constant>
</setProperty>
<log message="got here, after predict, ${exchangeProperty.firstCallOf}" loggingLevel="INFO"/>
<to uri="direct:sample-comment"/>
</when>
</choice>
<bean ref="abc_errorhandler" method="abcException"/>
</onException>
and getting below exception :
Failed to create route route-nsm-client-call at: >>> OnException[[com.sample] -> [Log[got here, before predict, ${exchangeProperty.firstCall], Choice[[When[bean{abc} [From[direct:bbc-call ->... because of Bean language requires bean, beanType, or ref argument
Caused by: java.lang.IllegalArgumentException: Bean language requires bean, beanType, or ref argument
Any idea on this?
This will work camel 2.x operation but if you try to upgrade camel 3.x for existing code. So, in that case you need to change this code to like below sample . but rather than myBean provide whole class package path.
Try below sample code..
for more details, please check below official website..
https://camel.apache.org/components/3.17.x/languages/bean-language.html
what is the difference to refer a processor using process tag or using to tag?
<route id="sample"><from uri="" /><to uri="bean:mqResponseProcessor" /></route>
<route id="sample"><from uri="" /><process ref="mqResponseProcessor"/></route>
If your bean is an implementation of org.apache.camel.Processor then there is no practical difference. However, using bean binding offers you much greater flexibility. Among others the bean
does not have to implement org.apache.camel.Processor
can offer any number of methods to invoke
with an arbitrary method signature
method parameter values can be transferred from the exchange using annotations like org.apache.camel.Body or org.apache.camel.Header
Using beans and bean binding is sort of like processors on steroids.
There is no differences, both do the same job.
With the java DSL, you have the possibility to put annonymous inner class with process syntax.
from("direct:demo").process(new Processor() {
public void process(Exchange exchange) throws Exception {
// some stuff
}
}).to("mock:demoEnd");
The process syntax can also improve the readability of code :
<route id="sample">
<from uri="direct:demo"/>
<process ref="firstProcessor"/>
<to uri="mock:otherRoute"/>
<process ref="secondProcessor"/>
<to uri="mock:endTest"/>
</route>
Vs
<route id="sample">
<from uri="direct:demo"/>
<to uri="bean:firstProcessor"/>
<to uri="mock:otherRoute"/>
<to uri="bean:secondProcessor"/>
<to uri="mock:endTest"/>
</route>
I am trying move few files from location A to location B on same server based on the name and number of files present in that folder. To achieve this I am using processStrategy option and extended GenericFileDeleteProcessStrategy to check for the batchsize. The files get moved to the destination but I also wanted to move the processed files to the .done folder and any failed files to the .failed location.
If I noticed that move, premove, moveFailed options are not working when used along with processStrategy
below is the code snippet I have used.
Please let me know your suggestions. I need to have the files available in the backup.
public class CustomTestProcessStrategy extends GenericFileDeleteProcessStrategy<File>{
static Logger logger = Logger.getLogger(CustomTestProcessStrategy.class);
#Override
public boolean begin(GenericFileOperations<File> operations,
GenericFileEndpoint<File> endpoint, Exchange exchange,
GenericFile<File> file) throws Exception {
boolean begin = super.begin(operations, endpoint, exchange, file);
if(!begin){
return false;
}
int batchSize = (int) exchange.getProperty("CamelBatchSize");
if(batchSize != 2){
logger.info("[OUT] CustomTestProcessStrategy Stopped. batch size is not met.");
return false;
}
return true;
}
beans.xml
<bean id="testStrategy" class="com.camel.CustomTestProcessStrategy">
cameljob.properties
file.testmove.properties=?idempotent=true&processStrategy=#testStrategy&readLock=rename&readLockMinLength=0&initialDelay=10000&delay=5000&moveFailed=.failed&preMove=order&move=.done&scheduler=quartz2&scheduler.cron={{testmove.Schedule}}
folder.source=C:/readfiles/source
folder.destination =C:/readfiles/destination
camel-context.xml
<route id="FileTestMoveRoute">
<from uri="file:{{folder.source}}{{file.testmove.properties}}"/>
<bean ref="cifProcessor" method="startFinalProcess"/>
<log message="*****************Moving file ${header.CamelFileName} to the final desitnation folder *********" />
<choice>
<when>
<simple>${header.CamelFileName} regex '^.*(fileA).*(CSV|csv)'</simple>
<to uri="file:{{folder.destination}/FileA}"/>
</when>
<when>
<simple>${header.CamelFileName} regex '^.*(fileB).*(CSV|csv)'</simple>
<to uri="file:{{folder.destination}}/FileB"/>
</when>
</choice>
</when>
</route>
I have a task to handle all incoming messages within the route and save them to database.
My route starts with webservice (camel-cxf), and then process to ejb and return soap response.
I've decided to use camel-sql component. As far as I don't have any problems with logging incoming message:
<camelContext id="InstitutionContext" xmlns="http://camel.apache.org/schema/spring">
<onException>
<exception>org.example.MyException</exception>
<continued><constant>true</constant></continued>
<to uri="bean:myExceptionHandler?method=handle" />
</onException>
<route id="InstitutionRoute" >
<from uri="direct:start" />
<to uri="sql:insert into translog(id,type,data) values(2,'IN',#)" />
<split>
<tokenize token="\n" />
<unmarshal>
<csv delimiter=";" />
</unmarshal>
<process ref="InstitutionProcessorTest" />
</split>
<to uri="bean:myExceptionHandler?method=checkErrors" />
</route>
</camelContext>
but I don't have idea how to handle exceptions and save them in the form of SOAP message.
<onCompletion onFailureOnly="true">
<to uri="sql:insert into translog(id,type,data) values(2,'ERROR',#)" />
</onCompletion>
but it saves original message in data column. Is there any body who can help?
I might be misunderstanding the question but it looks you are trying to save the SOAP message in XML format if there is a exception.
By default the dataFormat for CXF is POJO meaning it sends a POJO around the camel route i.e. the SOAP XML is converted to a POJO.
Two options come to mind:
Set the dataformat to message or payload. This will send the XML message across the camel route instead of a POJO
Marshall the POJO into a XML message and save it.
How can i call a SOAP web service with an empty message body using Apache Camel?
For example, the final endpoint on a route would be the invocation of a method on my proxy that takes 0 arguments.
EDIT:
example xml configuration:
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<to uri="cxf:bean:someWS"/>
</route>
...
<cxf:cxfEndpoint id="someWS" address="${ws.address}"
serviceClass="com.example.ws.SomeWS"
The problem is that the method 'invoke' on the WS takes 0 arguments, and an exception is thrown stating that 1 argument is being received. Is there a way for me to specify to ignore this received input?
You can set the message body to be null, if the invocation just take 0 argument. null simple expression is added since camel 2.12.3.
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setBody>
<simple>null</simple>
</setBody>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<to uri="cxf:bean:someWS"/>
</route>
I also needed to set an empty body to Apache Camel xml and the solution below worked for me.
<setBody id="set-empty-body">
<constant/>
</setBody>
Hope this helps to whoever need it.
The xml configuration will fail if the content of the body is not with the correct type of the class required by the method of your bean. By default, it could be an Object and not a String. When the method recieves the body in an incorrect format, it would process a null value, instead of the body of the route. To solve this problem, you will need to convert the body into the expected class of the method of your bean. For example, if the method's argument of the bean is a String, then you could do something like:
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<convertBodyTo type="String"/>
<to uri="cxf:bean:someWS"/>
</route>
For more information about body conversion, you can check the docs: https://camel.apache.org/components/3.14.x/eips/convertBodyTo-eip.html