Hi,
I have an issue with the camel sql-component.
I use the options outputHeader=myHeader and outputType=SelectOne. When the
query returns no result, the body of the Exchange is set to null instead of
preserved what I would expect when using outputHeader.
In my opinion the problem is in lines 175-185 of SqlProducer.java that does not
set the body in case the data is null (missing else block). As I am new to
Camel, I don't know if this was intended for a special case.
// Code section
if (data != null) { // <--- Missing the else
// for noop=true we still want to enrich with the row count header
if (getEndpoint().isNoop()) {
exchange.getOut().setBody(exchange.getIn().getBody());
} else if (getEndpoint().getOutputHeader() != null) {
exchange.getOut().setBody(exchange.getIn().getBody());
exchange.getOut().setHeader(getEndpoint().getOutputHeader(), data);
} else {
exchange.getOut().setBody(data);
}
exchange.getOut().setHeader(SqlConstants.SQL_ROW_COUNT, 1);
}
--------
following could be added (untested)
else { // if data == null
if (getEndpoint().isNoop()) {
exchange.getOut().setBody(exchange.getIn().getBody());
} else if (getEndpoint().getOutputHeader()
!= null) {
exchange.getOut().setBody(exchange.getIn().getBody());
}
exchange.getOut().setHeader(SqlConstants.SQL_ROW_COUNT, 0);
}
--------------------------
Following testcase:
import org.apache.camel.EndpointInject;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.spring.javaconfig.SingleRouteCamelConfiguration;
import org.apache.camel.test.spring.CamelSpringDelegatingTestContextLoader;
import org.apache.camel.test.spring.CamelSpringJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
@RunWith(CamelSpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { CamelSqlComponentTest.TestConfig.class },
loader = CamelSpringDelegatingTestContextLoader.class)
public class CamelSqlComponentTest {
@EndpointInject(uri = "mock:result")
protected MockEndpoint resultEndpoint;
@Produce(uri = "direct:start")
protected ProducerTemplate template;
@Test
@DirtiesContext
public void testSqlEndpoint() throws Exception {
String expectedBody = "body";
resultEndpoint.expectedBodiesReceived(expectedBody);
template.sendBody(expectedBody);
resultEndpoint.assertIsSatisfied();
}
@Configuration
public static class TestConfig extends SingleRouteCamelConfiguration {
@Bean(destroyMethod = "shutdown", name = "dataSource")
public EmbeddedDatabase dataSource() {
return new
EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
.addScript("db-camel-schema.sql").addScript("db-camel-data.sql").build();
}
@Bean
@Override
public RouteBuilder route() {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.to("sql:select id from
mytable where 1 =
2?dataSource=dataSource&outputHeader=myHeader&outputType=SelectOne")
.log("${body}").to("mock:result");
}
};
}
}
}
--------------------------
db-camel-data.sql
insert into MYTABLE (ID, SUBJECT) VALUES (1, 'subject');
--------------------------
db-camel-schema.sql
CREATE TABLE MYTABLE (
ID INT PRIMARY KEY,
SUBJECT VARCHAR(255)
);
Have a nice weekend.
Thomas