Hello,
I've spent a long time with this so this request is a bit of a last
resort.
I have a very simple route:
@Component
public class IngestRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("seda:ingest_database_queue?concurrentConsumers={{seda.ingest.concurrent.consumers}}")
.routeId("ingest-database-persisting")
.to("jpa:esac.archive.p2sa.ingest.entity.ingest.IngestLog")
.log(LoggingLevel.INFO, "Finished Inserting IngestLog")
.bean(MessageBodySetterBean.class)
.recipientList(simple("file://${headers.FileDestination}/?fileName=${headers.Filename}"))
.log(LoggingLevel.INFO, "Finished Ingesting File:
${headers.Filename}}");
}
}
Which persists an entity to the database and moves a file somewhere.
My idea was to make use of @DataJpaTest which loads up all the in memory
database etc for unit tests and it nearly works.
This is my test (sorry to paste large code):
@RunWith(SpringRunner.class)
@DataJpaTest
//@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class IngestRouteBuilderTest extends CamelTestSupport {
@Autowired
private TestEntityManager entityManager;
private static final String TARGET_DIR = "target/repository";
@Override
public void setUp() throws Exception {
deleteDirectory(TARGET_DIR);
super.setUp();
}
@Override
public void tearDown() throws Exception {
deleteDirectory(TARGET_DIR);
super.tearDown();
}
@Override
public String isMockEndpoints() {
// override this method and return the pattern for which
endpoints to mock.
return "file:" + TARGET_DIR + "*";
}
@Test
public void testDeadLetterChannel() throws Exception {
// This is a notify wait condition
NotifyBuilder notify = new
NotifyBuilder(context).from("seda:*").whenDone(1).create();
// notice we have automatic mocked all endpoints and the name of
the endpoints is "mock:uri"
MockEndpoint mock = getMockEndpoint("mock:file:" + TARGET_DIR +
"/");
mock.expectedMessageCount(1);
// Mock the headers
Map<String, Object> headers = new HashMap<>();
headers.put(Constants.FILE_NAME_HEADER,
"lyra_20160708-000000_lev1_met.fits");
headers.put(Constants.FILE_CONTENT_HEADER,
TestUtils.getFile("/data/lyra/level1/lyra_20160708-000000_lev1_met.fits"));
// Setup the exchange
Exchange exchange = new DefaultExchange(context);
exchange.getOut().setHeaders(headers);
exchange.getIn().setBody(createIngestLog());
// Send the message
template.send("seda:ingest_database_queue", exchange);
//unwrap.getSession().beginTransaction().begin();
// Verify the outcome
assertMockEndpointsSatisfied(5, TimeUnit.SECONDS);
boolean done = notify.matches(5, TimeUnit.SECONDS);
assertTrue("Should be done", done);
assertTrue("File should exist", new
File("target/failed-test/lyra_20160708-000000_lev1_met.fits").exists());
}
@Override
protected Properties useOverridePropertiesWithPropertiesComponent()
{
Properties extra = new Properties();
extra.put("seda.ingest.concurrent.consumers", "1");
return extra;
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
JpaComponent component =
(JpaComponent)context.getComponent("jpa");
component.setEntityManagerFactory(entityManager.getEntityManager().getEntityManagerFactory());
//Map<String, Object> properties =
entityManager.getEntityManager().getProperties();
//EntityManagerFactory createEntityManagerFactory =
javax.persistence.Persistence.createEntityManagerFactory("camel",
properties);
//component.setEntityManagerFactory(createEntityManagerFactory);
IngestRouteBuilder route = new IngestRouteBuilder();
//ReflectionTestUtils.setField(route, "failed",
"file:target/failed-test");
return route;
}
private IngestLog createIngestLog() {
IngestLog ingestLog = new IngestLog();
ingestLog.setStatus(IngestStatus.INGEST_DONE.name());
ingestLog.setDataType(DataType.SCIENCE.name());
Instant ingested =
Instant.from(Instant.now().atOffset(ZoneOffset.UTC));
ingestLog.setDateIngested(Date.from(ingested));
ingestLog.setFileFormat(FileExtension.FITS.name());
ingestLog.setFileName("filename");
ingestLog.setFileSize(500);
ingestLog.setPathStage("/stage/path");
ingestLog.setPathRepository("/final/path");
return ingestLog;
}
}
It fails with the following error:
2018-04-10 17:37:19 WARN o.a.c.component.seda.SedaConsumer - Error
processing exchange. Exchange[]. Caused by:
[javax.persistence.TransactionRequiredException - no transaction is in
progress]
javax.persistence.TransactionRequiredException: no transaction is in
progress
at
org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3430)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1397)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1393)
at
org.apache.camel.component.jpa.JpaProducer$2.doInTransaction(JpaProducer.java:247)
at
org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at
org.apache.camel.component.jpa.JpaProducer.processEntity(JpaProducer.java:210)
at
org.apache.camel.component.jpa.JpaProducer.process(JpaProducer.java:162)
at
org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
...
I'm not really interested in transactions, however if I uncomment this
at the top //@Transactional(propagation = Propagation.NOT_SUPPORTED)
then I get a different failure - java.lang.IllegalStateException: No
transactional EntityManager found.
If I remove the test entity manager then I get the following error:\
endpoint: jpa://esac.archive.p2sa.ingest.entity.ingest.IngestLog.
Reason: javax.persistence.PersistenceException: No Persistence provider
for EntityManager named camel
I looked at some of the tests in the component and I don't see what I'm
doing differently really.
Thanks
Jonathan