apache-camelbindycamel-jdbc

camel jdbc and outputClass option


I want to read from DB and create a CSV file. In order to do that I am using camel-jdbc and camel-bindy.

First I set the body with the SELECT statement.

SELECT  [vendor],
        [ean],
        [itemid] AS itemId,
        [quantity]
FROM [dbo].[ElectronicDeliveryNotes]

then I call the jdbc component

<to uri="jdbc:dataSource?outputType=SelectList&amp;outputClass=com.xxx.Model"/> 

This will return a List of Model. Model class is

@CsvRecord(separator = ";", generateHeaderColumns = true, crlf = "UNIX")
public class Model2 {

    @DataField(pos = 1, columnName = "A_Liererant")
    private String vendor;
    @DataField(pos = 2, columnName = "F_EAN")
    private String ean;
    @DataField(pos = 3, columnName = "G_Lief. Artikelnummer")
    private String itemId;
    @DataField(pos = 4, columnName = "H_Menge")
    private BigDecimal quantity;

    //getters setters 

I am getting the following error:

java.lang.IllegalArgumentException: Cannot map all properties to bean of type class com.xxx.Model2. There are 1 unmapped properties. {itemid=11.0441-5402.2}

From my understanding the problem is in the naming of model properties. One solution that I tried and worked is to rename the Model itemId => itemid. This will work, but i am not using Java naming conventions.

Do you know how to overcome this without renaming properties?

I also tried the following but it didn't work.

 @DataField(pos = 3, columnName = "G_Lief. Artikelnummer", name = "itemid")
    private String itemId;

Solution

  • I didn't see anything wrong with your code structure.

    If what you want to accomplish is retrieving from a table and export its results to a CSV based on your Model2 class, I may suggest using camel-sql. Could be something like:

    @Override
    protected RoutesBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
    
            @Override
            public void configure() throws Exception {
                getContext().getComponent("sql", SqlComponent.class).setDataSource(db);
                BindyCsvDataFormat camelDataFormat = new BindyCsvDataFormat(Model2.class);
    
                from("sql:select vendor, ean, itemid as itemId, quantity from ElectronicDeliveryNotes?outputType=SelectList&outputClass=com....model.Model2")
                        .marshal(camelDataFormat)
                        .log("the body:\n${body}")
                        .to("mock:result");
            }
        };
    }
    

    You poll the data from the table, marshall it and then send the message to other queue. I've run some tests to make sure that the query results could be transformed into a CSV and as long as you keep the fields' name equals to your property, nothing seems to go wrong. (side note: in my tests even without the alias everything went fine).

    But, testing your code, I went in the same error. Maybe you need to implement the beanRowMapper:

    To use a custom org.apache.camel.component.jdbc.BeanRowMapper when using outputClass. The default implementation will lower case the row names and skip underscores, and dashes. For example "CUST_ID" is mapped as "custId".

    My guess this is the reason why you are stuck in this error:

    java.lang.IllegalArgumentException: Cannot map all properties to bean of type class com.xxx.Model2. There are 1 unmapped properties. {itemid=11.0441-5402.2}
    

    Try renaming your alias to ITEM_ID.