= JPA Component
:doctitle: JPA
:shortname: jpa
:artifactid: camel-jpa
:description: Store and retrieve Java objects from databases using Java Persistence API (JPA).
:since: 1.0
:supportlevel: Stable
:component-header: Both producer and consumer are supported
//Manually maintained attributes
:camel-spring-boot-name: jpa

*Since Camel {since}*

*{component-header}*

The JPA component enables you to store and retrieve Java objects from
persistent storage using EJB 3's Java Persistence Architecture (JPA),
which is a standard interface layer that wraps Object/Relational Mapping
(ORM) products such as OpenJPA, Hibernate, TopLink, and so on.

Maven users will need to add the following dependency to their `pom.xml`
for this component:

[source,xml]
------------------------------------------------------------
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jpa</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>
------------------------------------------------------------

== Sending to the endpoint

You can store a Java entity bean in a database by sending it to a JPA
producer endpoint. The body of the _In_ message is assumed to be an
entity bean (that is, a POJO with an
http://java.sun.com/javaee/5/docs/api/javax/persistence/Entity.html[@Entity]
annotation on it) or a collection or array of entity beans.

If the body is a List of entities, make sure to use
*entityType=java.util.List* as a configuration passed to the
producer endpoint.

If the body does not contain one of the previous listed types, put a
Message Translator in front of the
endpoint to perform the necessary conversion first.

You can use `query`, `namedQuery` or `nativeQuery`
for the producer as well. Also in the value of the `parameters`, you can use
Simple expression which allows you to retrieve parameter values from Message body, header
and etc. Those query can be used for retrieving a set of data with using `SELECT`
JPQL/SQL statement as well as executing bulk update/delete with using `UPDATE`/`DELETE`
JPQL/SQL statement. Please note that you need to specify `useExecuteUpdate` to `true`
if you execute `UPDATE`/`DELETE` with `namedQuery` as camel don't look into the
named query unlike `query` and `nativeQuery`.


== Consuming from the endpoint

Consuming messages from a JPA consumer endpoint removes (or updates)
entity beans in the database. This allows you to use a database table as
a logical queue: consumers take messages from the queue and then
delete/update them to logically remove them from the queue.

If you do not wish to delete the entity bean when it has been processed
(and when routing is done), you can specify `consumeDelete=false` on the
URI. This will result in the entity being processed each poll.

If you would rather perform some update on the entity to mark it as
processed (such as to exclude it from a future query) then you can
annotate a method with
https://www.javadoc.io/doc/org.apache.camel/camel-jpa/current/org/apache/camel/component/jpa/Consumed.html[@Consumed]
which will be invoked on your entity bean when the entity bean when it
has been processed (and when routing is done).

You can use https://www.javadoc.io/doc/org.apache.camel/camel-jpa/current/org/apache/camel/component/jpa/PreConsumed.html[@PreConsumed]
which will be invoked on your entity bean before it has been processed
(before routing).

If you are consuming a lot (100K+) of rows and experience OutOfMemory
problems you should set the maximumResults to sensible value.

== URI format

-----------------------------
jpa:entityClassName[?options]
-----------------------------

For sending to the endpoint, the _entityClassName_ is optional. If
specified, it helps the http://camel.apache.org/type-converter.html[Type Converter] to
ensure the body is of the correct type.

For consuming, the _entityClassName_ is mandatory.


// component-configure options: START

// component-configure options: END

// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
// component options: END

// endpoint options: START

// endpoint options: END


== Message Headers

Camel adds the following message headers to the exchange:

[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Header |Type |Description

|`CamelEntityManager` |`EntityManager` |The JPA `EntityManager` object being used by `JpaConsumer` or `JpaProducer`.

|`CamelJpaParameters` |`Map<String, Object>` |Alternative way for passing query parameters as an Exchange header.

|=======================================================================

== Configuring EntityManagerFactory

Its strongly advised to configure the JPA component to use a specific
`EntityManagerFactory` instance. If failed to do so each `JpaEndpoint`
will auto create their own instance of `EntityManagerFactory` which most
often is not what you want.

For example, you can instantiate a JPA component that references the
`myEMFactory` entity manager factory, as follows:

[source,xml]
-------------------------------------------------------------------
<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
   <property name="entityManagerFactory" ref="myEMFactory"/>
</bean>
-------------------------------------------------------------------

The `JpaComponent` looks up automatically the
`EntityManagerFactory` from the Registry which means
you do not need to configure this on the `JpaComponent` as shown above.
You only need to do so if there is ambiguity, in which case Camel will
log a WARN.

== Configuring TransactionManager

The `JpaComponent` looks up automatically the
`TransactionManager` from the Registry. If Camel
won't find any `TransactionManager` instance registered, it will also
look up for the `TransactionTemplate` and try to
extract `TransactionManager` from it.

If none `TransactionTemplate` is available in the registry,
`JpaEndpoint` will auto create their own instance of
`TransactionManager` which most often is not what you want.

If more than single instance of the `TransactionManager` is found, Camel
will log a WARN. In such cases you might want to instantiate and
explicitly configure a JPA component that references the
`myTransactionManager` transaction manager, as follows:

[source,xml]
-------------------------------------------------------------------
<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
   <property name="entityManagerFactory" ref="myEMFactory"/>
   <property name="transactionManager" ref="myTransactionManager"/>
</bean>
-------------------------------------------------------------------

== Using a consumer with a named query

For consuming only selected entities, you can use the
`namedQuery` URI query option. First, you have to define the
named query in the JPA Entity class:

[source,java]
----------------------------------------------------------------------------------
@Entity
@NamedQuery(name = "step1", query = "select x from MultiSteps x where x.step = 1")
public class MultiSteps {
   ...
}
----------------------------------------------------------------------------------

After that you can define a consumer uri like this one:

[source,java]
----------------------------------------------------------------------------
from("jpa://org.apache.camel.examples.MultiSteps?namedQuery=step1")
.to("bean:myBusinessLogic");
----------------------------------------------------------------------------

== Using a consumer with a query

For consuming only selected entities, you can use the `query`
URI query option. You only have to define the query option:

[source,java]
---------------------------------------------------------------------------------------------------------------------------------------
from("jpa://org.apache.camel.examples.MultiSteps?query=select o from org.apache.camel.examples.MultiSteps o where o.step = 1")
.to("bean:myBusinessLogic");
---------------------------------------------------------------------------------------------------------------------------------------

== Using a consumer with a native query

For consuming only selected entities, you can use the
`nativeQuery` URI query option. You only have to define the
native query option:

[source,java]
---------------------------------------------------------------------------------------------------------------
from("jpa://org.apache.camel.examples.MultiSteps?nativeQuery=select * from MultiSteps where step = 1")
.to("bean:myBusinessLogic");
---------------------------------------------------------------------------------------------------------------

If you use the native query option, you will receive an object array in
the message body.


== Using a producer with a named query

For retrieving selected entities or execute bulk update/delete, you can use the
`namedQuery` URI query option. First, you have to define the
named query in the JPA Entity class:

[source,java]
----------------------------------------------------------------------------------
@Entity
@NamedQuery(name = "step1", query = "select x from MultiSteps x where x.step = 1")
public class MultiSteps {
   ...
}
----------------------------------------------------------------------------------

After that you can define a producer uri like this one:

[source,java]
----------------------------------------------------------------------------
from("direct:namedQuery")
.to("jpa://org.apache.camel.examples.MultiSteps?namedQuery=step1");
----------------------------------------------------------------------------

Note that you need to specify `useExecuteUpdate` option to `true` to execute `UPDATE`/`DELETE` statement
as a named query.

== Using a producer with a query

For retrieving selected entities or execute bulk update/delete, you can use the `query`
URI query option. You only have to define the query option:

[source,java]
---------------------------------------------------------------------------------------------------------------------------------------
from("direct:query")
.to("jpa://org.apache.camel.examples.MultiSteps?query=select o from org.apache.camel.examples.MultiSteps o where o.step = 1");
---------------------------------------------------------------------------------------------------------------------------------------

== Using a producer with a native query

For retrieving selected entities or execute bulk update/delete, you can use the
`nativeQuery` URI query option. You only have to define the
native query option:

[source,java]
---------------------------------------------------------------------------------------------------------------
from("direct:nativeQuery")
.to("jpa://org.apache.camel.examples.MultiSteps?resultClass=org.apache.camel.examples.MultiSteps&nativeQuery=select * from MultiSteps where step = 1");
---------------------------------------------------------------------------------------------------------------

If you use the native query option without specifying `resultClass`, you will receive an object array in
the message body.

== Using the JPA-Based Idempotent Repository

The Idempotent Consumer from the http://camel.apache.org/enterprise-integration-patterns.html[EIP patterns] is used to filter out duplicate messages. A JPA-based idempotent repository is provided.

To use the JPA based idempotent repository.

.Procedure

. Set up a `persistence-unit` in the persistence.xml file:

. Set up a `org.springframework.orm.jpa.JpaTemplate`
which is used by the
`org.apache.camel.processor.idempotent.jpa.JpaMessageIdRepository`:

. Configure the error formatting macro: snippet: java.lang.IndexOutOfBoundsException:
Index: 20, Size: 20

. Configure the idempotent repository:
`org.apache.camel.processor.idempotent.jpa.JpaMessageIdRepository`:

. Create the JPA idempotent repository in the Spring XML file:

[source,xml]
---------------------------------------------------------------
<camelContext xmlns="http://camel.apache.org/schema/spring">
    <route id="JpaMessageIdRepositoryTest">
        <from uri="direct:start" />
        <idempotentConsumer messageIdRepositoryRef="jpaStore">
            <header>messageId</header>
            <to uri="mock:result" />
        </idempotentConsumer>
    </route>
</camelContext>
---------------------------------------------------------------

*When running this Camel component tests inside your IDE*

If you run the
https://svn.apache.org/repos/asf/camel/trunk/components/camel-jpa/src/test[tests
of this component] directly inside your IDE, and not through
Maven, then you could see exceptions like these:

--------------------------------------------------------------------------------------------------------------------------------------------------------
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is
<openjpa-2.2.1-r422266:1396819 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization,
but the following listed types were not enhanced at build time or at class load time with a javaagent: "org.apache.camel.examples.SendEmail".
    at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:427)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127)
    at org.apache.camel.processor.jpa.JpaRouteTest.cleanupRepository(JpaRouteTest.java:96)
    at org.apache.camel.processor.jpa.JpaRouteTest.createCamelContext(JpaRouteTest.java:67)
    at org.apache.camel.test.junit5.CamelTestSupport.doSetUp(CamelTestSupport.java:238)
    at org.apache.camel.test.junit5.CamelTestSupport.setUp(CamelTestSupport.java:208)
--------------------------------------------------------------------------------------------------------------------------------------------------------

The problem here is that the source has been compiled or recompiled through
your IDE and not through Maven, which would
https://svn.apache.org/repos/asf/camel/trunk/components/camel-jpa/pom.xml[enhance
the byte-code at build time]. To overcome this you need to enable
http://openjpa.apache.org/entity-enhancement.html#dynamic-enhancement[dynamic
byte-code enhancement of OpenJPA]. For example, assuming the current
OpenJPA version being used in Camel is 2.2.1, to run the
tests inside your IDE you would need to pass the following
argument to the JVM:

-------------------------------------------------------------------------------------------
-javaagent:<path_to_your_local_m2_cache>/org/apache/openjpa/openjpa/2.2.1/openjpa-2.2.1.jar
-------------------------------------------------------------------------------------------



include::spring-boot:partial$starter.adoc[]
