or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

channel-message-store.mdinbound-polling.mdindex.mdjava-dsl.mdlock-registry.mdmessage-store.mdmetadata-store.mdoutbound-gateway.mdoutbound-updates.mdparameter-factories.mdpostgres-channels.mdstored-procedures.md
tile.json

parameter-factories.mddocs/

Parameter Factories

Parameter factories provide flexible mechanisms for extracting SQL parameters from Spring Integration messages and message payloads. They enable SpEL expressions, bean property mapping, static parameters, and custom parameter extraction strategies for JDBC operations.

Key Information for Agents

Required Dependencies:

  • spring-integration-jdbc (this package)
  • spring-integration-core is required
  • BeanFactory required for ExpressionEvaluatingSqlParameterSourceFactory (for bean references in expressions)

Default Behaviors:

  • Default factory: BeanPropertySqlParameterSourceFactory (extracts bean properties or map keys)
  • usePayloadAsParameterSource=true (only payload used, not headers)
  • Parameter names are case-sensitive (must match SQL exactly)
  • Static parameters take precedence over dynamic parameters when both provided
  • Expression evaluation is cached for performance

Threading Model:

  • Parameter sources are created per message (thread-safe)
  • ParameterSourceFactory instances should be thread-safe (reusable)
  • Expression evaluation is thread-safe (uses thread-local evaluation context)
  • Bean property extraction is thread-safe

Lifecycle:

  • ParameterSourceFactory instances are typically Spring beans (singleton)
  • ParameterSource instances are created per message (short-lived)
  • No special lifecycle management required

Exceptions:

  • IllegalArgumentException - Invalid parameter name or configuration
  • EvaluationException - SpEL expression evaluation failures
  • PropertyAccessException - Bean property access failures
  • NoSuchParameterException - Parameter not found in source (when accessing)

Edge Cases:

  • Parameter names are case-sensitive (must match query exactly)
  • Missing parameters: hasValue() returns false, getValue() may return null or throw exception
  • BeanPropertySqlParameterSource uses Spring's BeanWrapper for property access
  • Nested property access supported (e.g., :customer.name)
  • Static parameters merged with dynamic parameters
  • Expression caching improves performance but may cause issues with mutable state (use createParameterSourceNoCache())
  • SpEL expressions can reference Spring beans with @beanName syntax
  • System properties accessible via @environment.getProperty()

Core Interfaces and Classes

SqlParameterSourceFactory

package org.springframework.integration.jdbc;

@FunctionalInterface
public interface SqlParameterSourceFactory {
    SqlParameterSource createParameterSource(Object input);
}

BeanPropertySqlParameterSourceFactory

package org.springframework.integration.jdbc;

public class BeanPropertySqlParameterSourceFactory implements SqlParameterSourceFactory {
    public void setStaticParameters(Map<String, Object> staticParameters);
    public SqlParameterSource createParameterSource(Object input);
}

ExpressionEvaluatingSqlParameterSourceFactory

package org.springframework.integration.jdbc;

public class ExpressionEvaluatingSqlParameterSourceFactory
    extends AbstractExpressionEvaluator implements SqlParameterSourceFactory {

    public void setStaticParameters(Map<String, Object> staticParameters);
    public void setParameterExpressions(Map<String, String> parameterExpressions);
    public void setSqlParameterTypes(Map<String, Integer> sqlParametersTypes);

    public SqlParameterSource createParameterSource(Object input);
    public SqlParameterSource createParameterSourceNoCache(Object input);
}

Usage Examples

Lambda Implementation

import org.springframework.integration.jdbc.SqlParameterSourceFactory;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;

// Lambda implementation for simple mapping
SqlParameterSourceFactory simpleFactory = input -> {
    Order order = (Order) input;
    return new MapSqlParameterSource()
        .addValue("orderId", order.getId())
        .addValue("amount", order.getAmount())
        .addValue("status", order.getStatus());
};

// Use in JDBC handler
JdbcMessageHandler handler = new JdbcMessageHandler(
    dataSource,
    "INSERT INTO orders (order_id, amount, status) VALUES (:orderId, :amount, :status)"
);
handler.setSqlParameterSourceFactory(simpleFactory);

Bean Property Mapping

import org.springframework.integration.jdbc.BeanPropertySqlParameterSourceFactory;

// Basic bean property mapping
BeanPropertySqlParameterSourceFactory beanFactory =
    new BeanPropertySqlParameterSourceFactory();

// Given Order bean with getId(), getOrderNumber(), getAmount()
// Creates parameters: :id, :orderNumber, :amount

JdbcMessageHandler handler = new JdbcMessageHandler(
    dataSource,
    "INSERT INTO orders (id, order_number, amount) VALUES (:id, :orderNumber, :amount)"
);
handler.setSqlParameterSourceFactory(beanFactory);
handler.setUsePayloadAsParameterSource(true);

// Send Order object as payload
Order order = new Order(123L, "ORD-456", new BigDecimal("99.99"));
handler.handleMessage(MessageBuilder.withPayload(order).build());

Static Parameters

// Static parameters combined with dynamic values
BeanPropertySqlParameterSourceFactory factoryWithStatics =
    new BeanPropertySqlParameterSourceFactory();

Map<String, Object> staticParams = Map.of(
    "source", "WEB_APP",
    "version", "2.0",
    "region", "US-WEST"
);
factoryWithStatics.setStaticParameters(staticParams);

JdbcMessageHandler staticHandler = new JdbcMessageHandler(
    dataSource,
    "INSERT INTO events (event_type, data, source, version, region) " +
    "VALUES (:eventType, :data, :source, :version, :region)"
);
staticHandler.setSqlParameterSourceFactory(factoryWithStatics);

// Only need to provide eventType and data; static params added automatically
Event event = new Event("USER_LOGIN", "user data");
staticHandler.handleMessage(MessageBuilder.withPayload(event).build());

SpEL Expression Evaluation

import org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory;

// Basic expression mapping
ExpressionEvaluatingSqlParameterSourceFactory exprFactory =
    new ExpressionEvaluatingSqlParameterSourceFactory();

Map<String, String> expressions = Map.of(
    "orderId", "payload.id",
    "orderNumber", "payload.orderNumber",
    "totalAmount", "payload.amount"
);
exprFactory.setParameterExpressions(expressions);

JdbcMessageHandler handler = new JdbcMessageHandler(
    dataSource,
    "INSERT INTO orders (order_id, order_number, total_amount) " +
    "VALUES (:orderId, :orderNumber, :totalAmount)"
);
handler.setSqlParameterSourceFactory(exprFactory);
handler.setUsePayloadAsParameterSource(false); // Process entire message

Complex Expressions

// Expressions with calculations and transformations
ExpressionEvaluatingSqlParameterSourceFactory calcFactory =
    new ExpressionEvaluatingSqlParameterSourceFactory();

Map<String, String> calcExpressions = Map.of(
    "orderId", "payload.id",
    "subtotal", "payload.items.![price * quantity].sum()",
    "tax", "payload.items.![price * quantity].sum() * 0.08",
    "total", "payload.items.![price * quantity].sum() * 1.08",
    "itemCount", "payload.items.size()"
);
calcFactory.setParameterExpressions(calcExpressions);

Header Access

// Access message headers
ExpressionEvaluatingSqlParameterSourceFactory headerFactory =
    new ExpressionEvaluatingSqlParameterSourceFactory();

Map<String, String> headerExpressions = Map.of(
    "orderId", "payload.id",
    "userId", "headers['user-id']",
    "correlationId", "headers['correlation-id']",
    "timestamp", "headers.timestamp",
    "priority", "headers.priority != null ? headers.priority : 0"
);
headerFactory.setParameterExpressions(headerExpressions);

Integration with JDBC Components

Parameter factories integrate with all JDBC message handlers and gateways:

// Inbound adapter update parameters
JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter(
    dataSource,
    "SELECT * FROM orders WHERE processed = false"
);

ExpressionEvaluatingSqlParameterSourceFactory updateFactory =
    new ExpressionEvaluatingSqlParameterSourceFactory();
updateFactory.setParameterExpressions(Map.of(
    "id", "id",
    "processedAt", "T(System).currentTimeMillis()",
    "processedBy", "@environment.getProperty('instance.id')"
));

adapter.setUpdateSql("UPDATE orders SET processed = true, processed_at = :processedAt, processed_by = :processedBy WHERE id = :id");
adapter.setUpdateSqlParameterSourceFactory(updateFactory);

Key Considerations

  • Interface Simplicity: SqlParameterSourceFactory is functional interface; can use lambdas
  • Default Factory: BeanPropertySqlParameterSourceFactory used by default
  • Bean Property Mapping: Extracts parameters from bean getters (JavaBean convention)
  • Map Support: BeanPropertySqlParameterSourceFactory works with Map payloads
  • Static Parameters: Both factories support static parameters merged with dynamic values
  • SpEL Power: ExpressionEvaluatingSqlParameterSourceFactory provides full SpEL capabilities
  • Message Context: Set usePayloadAsParameterSource=false to access headers in expressions
  • Expression Caching: Expressions compiled and cached for performance
  • Type Control: Optional SQL type specification for explicit type handling
  • Null Safety: Handle nulls in expressions with conditional operators
  • Collection Processing: SpEL provides powerful collection projection and selection
  • Performance: Bean property access is faster than expression evaluation
  • Debugging: Expression evaluation errors include expression string in exception
  • Spring Beans: Expressions can reference Spring beans with @beanName syntax
  • System Properties: Access via @environment.getProperty()
  • Transformation: Expressions enable data transformation during parameter extraction