or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

inbound-adapter.mdindex.mdjpa-executor.mdjpa-operations.mdoutbound-adapter.mdparameter-sources.mdretrieving-gateway.mdupdating-gateway.mdxml-configuration.md
tile.json

xml-configuration.mddocs/

XML Configuration

Spring Integration JPA provides XML namespace support for declaring JPA components in Spring XML configuration files. The int-jpa namespace offers four main elements corresponding to the four primary JPA integration components.

Key Information for Agents

Required Dependencies:

  • spring-integration-jpa (this package)
  • spring-integration-core is required
  • EntityManagerFactory, EntityManager, or JpaOperations bean must be configured
  • XML namespace schema must be declared in Spring XML configuration

Default Behaviors:

  • All XML elements have same defaults as their Java DSL/programmatic equivalents
  • auto-startup="true" (components start automatically)
  • persist-mode="MERGE" (for outbound components)
  • flush="false", flush-size="0", clear-on-flush="false"
  • expect-single-result="false", max-results="0" (unlimited)
  • delete-after-poll="false", delete-in-batch="false"
  • use-payload-as-parameter-source="false"
  • reply-timeout="30000" (30 seconds for gateways)
  • requires-reply="true" (gateways require reply)

Threading Model:

  • Same threading model as Java DSL/programmatic configuration
  • Inbound adapters execute on poller thread
  • Outbound components execute on message processing thread
  • Thread-safe when using EntityManagerFactory

Lifecycle:

  • Components initialized when Spring context loads XML configuration
  • auto-startup="true" starts components automatically (default)
  • Components stop when context is destroyed
  • Poller lifecycle managed by Spring Integration poller infrastructure

Exceptions:

  • Same exceptions as Java DSL/programmatic configuration
  • XML parsing errors if namespace not declared correctly
  • Bean creation errors if referenced beans don't exist
  • Configuration errors if invalid attribute combinations used

Edge Cases:

  • Exactly one query type attribute must be set: entity-class, jpa-query, native-query, or named-query
  • Native queries require entity-class for result type mapping
  • Named queries must be defined on entity classes with @NamedQuery annotation
  • Poller must be configured for inbound adapters (via <int:poller> child element)
  • Transaction configuration via <int-jpa:transactional> child element
  • Parameter configuration via <int-jpa:parameter> child elements
  • Expression parameters use SpEL syntax (same as Java DSL)
  • Attribute values are strings (converted to appropriate types automatically)
  • Boolean attributes: "true" or "false" (case-sensitive)

Namespace Declaration

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/integration
           https://www.springframework.org/schema/integration/spring-integration.xsd
           http://www.springframework.org/schema/integration/jpa
           https://www.springframework.org/schema/integration/jpa/spring-integration-jpa.xsd">

    <!-- JPA components here -->

</beans>

XML Elements

Inbound Channel Adapter

<int-jpa:inbound-channel-adapter
    id="adapterId"
    channel="outputChannel"
    entity-manager-factory="entityManagerFactory"
    entity-manager="entityManager"
    jpa-operations="jpaOperations"
    entity-class="com.example.Student"
    jpa-query="SELECT s FROM Student s"
    native-query="SELECT * FROM students"
    named-query="Student.findAll"
    delete-after-poll="false"
    delete-in-batch="false"
    flush="false"
    expect-single-result="false"
    max-results="0"
    max-results-expression="headers.limit"
    parameter-source-factory="paramSourceFactory"
    auto-startup="true">

    <int-jpa:parameter name="paramName" value="staticValue"/>
    <int-jpa:parameter name="paramName" expression="payload.property"/>
    <int-jpa:transactional .../>
    <int:poller .../>
</int-jpa:inbound-channel-adapter>

Outbound Channel Adapter

<int-jpa:outbound-channel-adapter
    id="adapterId"
    channel="inputChannel"
    entity-manager-factory="entityManagerFactory"
    entity-manager="entityManager"
    jpa-operations="jpaOperations"
    entity-class="com.example.Student"
    jpa-query="UPDATE Student s SET s.status = :status"
    native-query="UPDATE students SET status = :status"
    named-query="Student.updateStatus"
    persist-mode="MERGE"
    flush="false"
    flush-size="0"
    clear-on-flush="false"
    parameter-source-factory="paramSourceFactory"
    use-payload-as-parameter-source="false"
    auto-startup="true"
    order="0">

    <int-jpa:parameter name="paramName" value="staticValue"/>
    <int-jpa:parameter name="paramName" expression="payload.property"/>
    <int-jpa:transactional .../>
</int-jpa:outbound-channel-adapter>

Retrieving Outbound Gateway

<int-jpa:retrieving-outbound-gateway
    id="gatewayId"
    request-channel="requestChannel"
    reply-channel="replyChannel"
    entity-manager-factory="entityManagerFactory"
    entity-manager="entityManager"
    jpa-operations="jpaOperations"
    entity-class="com.example.Student"
    jpa-query="SELECT s FROM Student s WHERE s.id = :id"
    native-query="SELECT * FROM students WHERE id = :id"
    named-query="Student.findById"
    id-expression="payload"
    expect-single-result="false"
    first-result="0"
    first-result-expression="payload.offset"
    max-results="0"
    max-results-expression="payload.limit"
    delete-after-poll="false"
    delete-in-batch="false"
    flush="false"
    parameter-source-factory="paramSourceFactory"
    use-payload-as-parameter-source="false"
    reply-timeout="30000"
    requires-reply="true"
    auto-startup="true"
    order="0">

    <int-jpa:parameter name="paramName" value="staticValue"/>
    <int-jpa:parameter name="paramName" expression="payload.property"/>
    <int-jpa:transactional .../>
</int-jpa:retrieving-outbound-gateway>

Updating Outbound Gateway

<int-jpa:updating-outbound-gateway
    id="gatewayId"
    request-channel="requestChannel"
    reply-channel="replyChannel"
    entity-manager-factory="entityManagerFactory"
    entity-manager="entityManager"
    jpa-operations="jpaOperations"
    entity-class="com.example.Student"
    jpa-query="UPDATE Student s SET s.status = :status WHERE s.id = :id"
    native-query="UPDATE students SET status = :status WHERE id = :id"
    named-query="Student.updateStatus"
    persist-mode="MERGE"
    flush="false"
    flush-size="0"
    clear-on-flush="false"
    parameter-source-factory="paramSourceFactory"
    use-payload-as-parameter-source="false"
    reply-timeout="30000"
    requires-reply="true"
    auto-startup="true"
    order="0">

    <int-jpa:parameter name="paramName" value="staticValue"/>
    <int-jpa:parameter name="paramName" expression="payload.property"/>
    <int-jpa:transactional .../>
</int-jpa:updating-outbound-gateway>

Complete Examples

Inbound Channel Adapter Examples

Poll All Entities

<int-jpa:inbound-channel-adapter
    id="studentInboundAdapter"
    entity-manager-factory="entityManagerFactory"
    channel="studentChannel"
    entity-class="com.example.Student"
    max-results="100">
    <int:poller fixed-delay="10000"/>
</int-jpa:inbound-channel-adapter>

Poll with JPQL Query

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="activeStudentChannel"
    jpa-query="SELECT s FROM Student s WHERE s.status = 'ACTIVE'"
    max-results="50">
    <int:poller fixed-rate="30000"/>
</int-jpa:inbound-channel-adapter>

Poll with Native Query

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="recentStudentChannel"
    native-query="SELECT * FROM students WHERE registration_date > CURRENT_DATE - 7"
    entity-class="com.example.Student">
    <int:poller fixed-delay="60000"/>
</int-jpa:inbound-channel-adapter>

Poll with Named Query

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="gradeAStudentChannel"
    named-query="Student.findByGrade">
    <int-jpa:parameter name="grade" value="A"/>
    <int:poller fixed-delay="15000"/>
</int-jpa:inbound-channel-adapter>

Poll and Delete

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="processedOrderChannel"
    jpa-query="SELECT o FROM ProcessedOrder o WHERE o.processed = true"
    delete-after-poll="true"
    delete-in-batch="true"
    flush="true"
    max-results="500">
    <int:poller fixed-delay="5000"/>
</int-jpa:inbound-channel-adapter>

Poll with Dynamic Parameters

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="dynamicPollChannel"
    jpa-query="SELECT t FROM Task t WHERE t.priority >= :minPriority"
    parameter-source-factory="taskParameterSourceFactory"
    max-results-expression="@config.batchSize">
    <int:poller fixed-delay="10000"/>
</int-jpa:inbound-channel-adapter>

<bean id="taskParameterSourceFactory"
      class="org.springframework.integration.jpa.support.parametersource.BeanPropertyParameterSourceFactory">
    <property name="staticParameters">
        <map>
            <entry key="minPriority" value="5"/>
        </map>
    </property>
</bean>

Outbound Channel Adapter Examples

Persist Entity

<int-jpa:outbound-channel-adapter
    channel="newStudentChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    persist-mode="PERSIST"/>

Merge Entity

<int-jpa:outbound-channel-adapter
    channel="updateStudentChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    persist-mode="MERGE"
    flush="true"/>

Delete Entity

<int-jpa:outbound-channel-adapter
    channel="deleteStudentChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    persist-mode="DELETE"/>

Execute Update Query

<int-jpa:outbound-channel-adapter
    channel="bulkUpdateChannel"
    entity-manager-factory="entityManagerFactory"
    jpa-query="UPDATE Student s SET s.status = :status WHERE s.year = :year">
    <int-jpa:parameter name="status" expression="payload.newStatus"/>
    <int-jpa:parameter name="year" expression="payload.year"/>
</int-jpa:outbound-channel-adapter>

Batch Processing

<int-jpa:outbound-channel-adapter
    channel="batchInsertChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.LogEntry"
    persist-mode="PERSIST"
    flush-size="100"
    clear-on-flush="true"/>

Retrieving Gateway Examples

Find by ID

<int-jpa:retrieving-outbound-gateway
    request-channel="findStudentChannel"
    reply-channel="studentResultChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    id-expression="payload"
    expect-single-result="true"/>

Query with JPQL

<int-jpa:retrieving-outbound-gateway
    request-channel="searchChannel"
    reply-channel="resultsChannel"
    entity-manager-factory="entityManagerFactory"
    jpa-query="SELECT s FROM Student s WHERE s.lastName = :lastName">
    <int-jpa:parameter name="lastName" expression="payload"/>
</int-jpa:retrieving-outbound-gateway>

Pagination

<int-jpa:retrieving-outbound-gateway
    request-channel="paginationChannel"
    reply-channel="pageResultsChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    first-result-expression="payload.offset"
    max-results-expression="payload.limit"/>

Complex Query

<int-jpa:retrieving-outbound-gateway
    request-channel="complexSearchChannel"
    reply-channel="searchResultsChannel"
    entity-manager-factory="entityManagerFactory"
    jpa-query="SELECT s FROM Student s WHERE s.department = :dept AND s.year = :year AND s.gpa >= :minGpa"
    parameter-source-factory="beanPropertyParameterSourceFactory"
    use-payload-as-parameter-source="true"
    max-results-expression="payload.limit"/>

Retrieve and Delete

<int-jpa:retrieving-outbound-gateway
    request-channel="retrieveAndDeleteChannel"
    reply-channel="retrievedChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Task"
    id-expression="payload"
    delete-after-poll="true"
    expect-single-result="true"/>

Updating Gateway Examples

Persist and Return

<int-jpa:updating-outbound-gateway
    request-channel="createChannel"
    reply-channel="createdChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    persist-mode="PERSIST"/>

Merge and Return

<int-jpa:updating-outbound-gateway
    request-channel="updateChannel"
    reply-channel="updatedChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    persist-mode="MERGE"
    flush="true"/>

Execute Update Query

<int-jpa:updating-outbound-gateway
    request-channel="bulkUpdateChannel"
    reply-channel="updateCountChannel"
    entity-manager-factory="entityManagerFactory"
    jpa-query="UPDATE Student s SET s.graduated = true WHERE s.credits >= :requiredCredits">
    <int-jpa:parameter name="requiredCredits" expression="payload"/>
</int-jpa:updating-outbound-gateway>

Named Update Query

<int-jpa:updating-outbound-gateway
    request-channel="namedUpdateChannel"
    reply-channel="updateResultChannel"
    entity-manager-factory="entityManagerFactory"
    named-query="Student.updateStatus"
    parameter-source-factory="beanPropertyParameterSourceFactory"
    use-payload-as-parameter-source="true"/>

Parameter Configuration

Static Parameters

<int-jpa:parameter name="status" value="ACTIVE"/>
<int-jpa:parameter name="year" value="2024"/>
<int-jpa:parameter name="minGpa" value="3.0"/>

Expression Parameters

<int-jpa:parameter name="studentId" expression="payload"/>
<int-jpa:parameter name="department" expression="payload.department"/>
<int-jpa:parameter name="year" expression="headers['academicYear']"/>
<int-jpa:parameter name="fullName" expression="payload.firstName + ' ' + payload.lastName"/>

Parameter Source Factory

<int-jpa:retrieving-outbound-gateway
    request-channel="searchChannel"
    reply-channel="resultsChannel"
    entity-manager-factory="entityManagerFactory"
    jpa-query="SELECT s FROM Student s WHERE s.lastName = :lastName AND s.department = :department"
    parameter-source-factory="paramSourceFactory"
    use-payload-as-parameter-source="true"/>

<bean id="paramSourceFactory"
      class="org.springframework.integration.jpa.support.parametersource.BeanPropertyParameterSourceFactory">
    <property name="staticParameters">
        <map>
            <entry key="status" value="ACTIVE"/>
        </map>
    </property>
</bean>

Expression-Based Parameter Source

<bean id="expressionParamFactory"
      class="org.springframework.integration.jpa.support.parametersource.ExpressionEvaluatingParameterSourceFactory">
    <constructor-arg ref="beanFactory"/>
    <property name="parameters">
        <map>
            <entry key="searchTerm" value="payload.search"/>
            <entry key="searchPattern" value="'%' + payload.search + '%'"/>
            <entry key="startDate" value="T(java.time.LocalDate).now().minusMonths(1)"/>
        </map>
    </property>
</bean>

Transaction Configuration

Basic Transaction

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="orderChannel"
    entity-class="com.example.Order"
    delete-after-poll="true">
    <int:poller fixed-delay="5000">
        <int:transactional transaction-manager="transactionManager"/>
    </int:poller>
</int-jpa:inbound-channel-adapter>

Transaction with Isolation and Propagation

<int-jpa:updating-outbound-gateway
    request-channel="updateChannel"
    reply-channel="updatedChannel"
    entity-manager-factory="entityManagerFactory"
    entity-class="com.example.Student"
    persist-mode="MERGE">
    <int-jpa:transactional
        transaction-manager="transactionManager"
        propagation="REQUIRED"
        isolation="READ_COMMITTED"
        timeout="30"
        read-only="false"/>
</int-jpa:updating-outbound-gateway>

Entity Manager Configuration

Using EntityManagerFactory (Recommended)

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="packagesToScan" value="com.example.domain"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
</bean>

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="outputChannel"
    entity-class="com.example.Student">
    <int:poller fixed-delay="10000"/>
</int-jpa:inbound-channel-adapter>

Using EntityManager

<bean id="entityManager"
      factory-bean="entityManagerFactory"
      factory-method="createEntityManager"/>

<int-jpa:inbound-channel-adapter
    entity-manager="entityManager"
    channel="outputChannel"
    entity-class="com.example.Student">
    <int:poller fixed-delay="10000"/>
</int-jpa:inbound-channel-adapter>

Using JpaOperations

<bean id="jpaOperations"
      class="org.springframework.integration.jpa.core.DefaultJpaOperations">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<int-jpa:inbound-channel-adapter
    jpa-operations="jpaOperations"
    channel="outputChannel"
    entity-class="com.example.Student">
    <int:poller fixed-delay="10000"/>
</int-jpa:inbound-channel-adapter>

Complete Application Context Example

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/integration
           https://www.springframework.org/schema/integration/spring-integration.xsd
           http://www.springframework.org/schema/integration/jpa
           https://www.springframework.org/schema/integration/jpa/spring-integration-jpa.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/tx
           https://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- Enable annotation configuration -->
    <context:component-scan base-package="com.example"/>
    <context:annotation-config/>

    <!-- Data source -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- Entity manager factory -->
    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="com.example.domain"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true"/>
                <property name="generateDdl" value="true"/>
            </bean>
        </property>
    </bean>

    <!-- Transaction manager -->
    <bean id="transactionManager"
          class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- Message channels -->
    <int:channel id="studentInputChannel"/>
    <int:channel id="studentOutputChannel"/>
    <int:channel id="findStudentChannel"/>
    <int:channel id="studentResultChannel"/>

    <!-- Inbound adapter - poll students -->
    <int-jpa:inbound-channel-adapter
        id="studentInboundAdapter"
        entity-manager-factory="entityManagerFactory"
        channel="studentOutputChannel"
        entity-class="com.example.domain.Student"
        max-results="100"
        delete-after-poll="true">
        <int:poller fixed-delay="10000">
            <int:transactional transaction-manager="transactionManager"/>
        </int:poller>
    </int-jpa:inbound-channel-adapter>

    <!-- Outbound adapter - persist students -->
    <int-jpa:outbound-channel-adapter
        id="studentOutboundAdapter"
        channel="studentInputChannel"
        entity-manager-factory="entityManagerFactory"
        entity-class="com.example.domain.Student"
        persist-mode="MERGE">
        <int-jpa:transactional transaction-manager="transactionManager"/>
    </int-jpa:outbound-channel-adapter>

    <!-- Retrieving gateway - find student by ID -->
    <int-jpa:retrieving-outbound-gateway
        id="findStudentGateway"
        request-channel="findStudentChannel"
        reply-channel="studentResultChannel"
        entity-manager-factory="entityManagerFactory"
        entity-class="com.example.domain.Student"
        id-expression="payload"
        expect-single-result="true">
        <int-jpa:transactional transaction-manager="transactionManager"/>
    </int-jpa:retrieving-outbound-gateway>

</beans>

Attribute Reference

Common Attributes (All Elements)

  • id - Component identifier
  • entity-manager-factory - Reference to EntityManagerFactory bean
  • entity-manager - Reference to EntityManager bean
  • jpa-operations - Reference to JpaOperations bean
  • auto-startup - Whether component starts automatically (default: true)

Query Type Attributes (Choose One)

  • entity-class - Fully qualified class name of entity
  • jpa-query - JPQL query string
  • native-query - Native SQL query string
  • named-query - Name of named query

Common Configuration Attributes

  • persist-mode - PERSIST, MERGE, or DELETE (outbound components)
  • flush - Whether to flush after operations (boolean)
  • flush-size - Flush every N operations (integer)
  • clear-on-flush - Clear persistence context on flush (boolean)
  • parameter-source-factory - Reference to ParameterSourceFactory bean
  • use-payload-as-parameter-source - Extract parameters from payload (boolean)

Result Configuration Attributes

  • expect-single-result - Expect single entity vs list (boolean)
  • max-results - Maximum results to retrieve (integer)
  • max-results-expression - SpEL expression for max results
  • first-result - Pagination offset (integer)
  • first-result-expression - SpEL expression for offset

Inbound Adapter Specific

  • channel - Output channel
  • delete-after-poll - Delete entities after polling (boolean)
  • delete-in-batch - Use batch delete (boolean)

Gateway Specific

  • request-channel - Input channel
  • reply-channel - Output channel
  • reply-timeout - Timeout for sending reply (milliseconds)
  • requires-reply - Whether reply is mandatory (boolean)
  • order - Component order for chaining

Retrieving Gateway Specific

  • id-expression - SpEL expression for entity ID

Migration from Java DSL

XML configuration equivalent of Java DSL:

Java DSL:

Jpa.inboundAdapter(entityManagerFactory)
    .entityClass(Student.class)
    .maxResults(100)
    .deleteAfterPoll(true)

XML:

<int-jpa:inbound-channel-adapter
    entity-manager-factory="entityManagerFactory"
    channel="outputChannel"
    entity-class="com.example.Student"
    max-results="100"
    delete-after-poll="true">
    <int:poller fixed-delay="10000"/>
</int-jpa:inbound-channel-adapter>