Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.jdbc.store;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.serializer.Deserializer;
import org.springframework.core.serializer.Serializer;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.jdbc.JdbcMessageStore;
import org.springframework.integration.jdbc.store.channel.ChannelMessageStoreQueryProvider;
import org.springframework.integration.jdbc.store.channel.MessageRowMapper;
import org.springframework.integration.jdbc.store.channel.OracleChannelMessageStoreQueryProvider;
import org.springframework.integration.store.MessageGroup;
import org.springframework.integration.store.MessageGroupFactory;
import org.springframework.integration.store.MessageGroupStore;
import org.springframework.integration.store.MessageStore;
import org.springframework.integration.store.PriorityCapableChannelMessageStore;
import org.springframework.integration.store.SimpleMessageGroupFactory;
import org.springframework.integration.support.DefaultMessageBuilderFactory;
import org.springframework.integration.support.MessageBuilderFactory;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.integration.transaction.TransactionSynchronizationFactory;
import org.springframework.integration.util.UUIDConverter;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
*
* Channel-specific implementation of {@link MessageGroupStore} using a relational
* database via JDBC.
*
* This message store shall be used for message channels only.
*
*
* As such, the {@link JdbcChannelMessageStore} uses database specific SQL queries.
*
*
* Contrary to the {@link JdbcMessageStore}, this implementation uses a single database table,
* optimized to operate like a queue.
* The SQL scripts for creating the table are packaged
* under {@code org/springframework/integration/jdbc/messagestore/channel/schema-*.sql},
* where {@code *} denotes the target database type.
*
*
* @author Gunnar Hillert
* @author Artem Bilan
* @author Gary Russell
* @since 2.2
*/
@ManagedResource
public class JdbcChannelMessageStore implements PriorityCapableChannelMessageStore, InitializingBean, BeanFactoryAware {
private static final Log logger = LogFactory.getLog(JdbcChannelMessageStore.class);
private final Set idCache = new HashSet();
private final ReadWriteLock idCacheLock = new ReentrantReadWriteLock();
private final Lock idCacheReadLock = this.idCacheLock.readLock();
private final Lock idCacheWriteLock = this.idCacheLock.writeLock();
/**
* Default value for the table prefix property.
*/
public static final String DEFAULT_TABLE_PREFIX = "INT_";
/**
* Default region property, used to partition the message store. For example,
* a separate Spring Integration application with overlapping channel names
* may use the same message store by providing a distinct region name.
*/
public static final String DEFAULT_REGION = "DEFAULT";
private ChannelMessageStoreQueryProvider channelMessageStoreQueryProvider;
/**
* The name of the message header that stores a flag to indicate that the message has been saved. This is an
* optimization for the put method.
*/
public static final String SAVED_KEY = JdbcChannelMessageStore.class.getSimpleName() + ".SAVED";
/**
* The name of the message header that stores a timestamp for the time the message was inserted.
*/
public static final String CREATED_DATE_KEY = JdbcChannelMessageStore.class.getSimpleName() + ".CREATED_DATE";
private volatile MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
private volatile String region = DEFAULT_REGION;
private volatile String tablePrefix = DEFAULT_TABLE_PREFIX;
private volatile JdbcTemplate jdbcTemplate;
private volatile DeserializingConverter deserializer;
private volatile SerializingConverter serializer;
private volatile LobHandler lobHandler = new DefaultLobHandler();
private volatile MessageRowMapper messageRowMapper;
private volatile Map queryCache = new HashMap();
private volatile MessageGroupFactory messageGroupFactory = new SimpleMessageGroupFactory();
private boolean usingIdCache = false;
private boolean priorityEnabled;
private BeanFactory beanFactory;
/**
* Convenient constructor for configuration use.
*/
public JdbcChannelMessageStore() {
this.deserializer = new DeserializingConverter();
this.serializer = new SerializingConverter();
}
/**
* Create a {@link MessageStore} with all mandatory properties. The passed-in
* {@link DataSource} is used to instantiate a {@link JdbcTemplate}
*
* with {@link JdbcTemplate#setFetchSize(int)} set to 1
* and with {@link JdbcTemplate#setMaxRows(int)} set to 1.
*
* @param dataSource a {@link DataSource}
*/
public JdbcChannelMessageStore(DataSource dataSource) {
this();
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.jdbcTemplate.setFetchSize(1);
this.jdbcTemplate.setMaxRows(1);
}
/**
* The JDBC {@link DataSource} to use when interacting with the database.
* The passed-in {@link DataSource} is used to instantiate a {@link JdbcTemplate}
* with {@link JdbcTemplate#setFetchSize(int)} set to 1
* and with {@link JdbcTemplate#setMaxRows(int)} set to 1.
*
* @param dataSource a {@link DataSource}
*/
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.jdbcTemplate.setFetchSize(1);
this.jdbcTemplate.setMaxRows(1);
}
/**
* A converter for deserializing byte arrays to messages.
*
* @param deserializer the deserializer to set
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public void setDeserializer(Deserializer> deserializer) {
this.deserializer = new DeserializingConverter((Deserializer) deserializer);
}
/**
* The {@link JdbcOperations} to use when interacting with the database. Either
* this property can be set or the {@link #setDataSource(DataSource) dataSource}.
*
* Please consider passing in a {@link JdbcTemplate} with a fetchSize property
* of 1. This is particularly important for Oracle to ensure First In, First Out (FIFO)
* message retrieval characteristics.
*
* @param jdbcTemplate a {@link JdbcOperations}
*/
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
Assert.notNull(jdbcTemplate, "The provided jdbcTemplate must not be null.");
this.jdbcTemplate = jdbcTemplate;
}
/**
* Override the {@link LobHandler} that is used to create and unpack large objects in SQL queries. The default is
* fine for almost all platforms, but some Oracle drivers require a native implementation.
*
* @param lobHandler a {@link LobHandler}
*/
public void setLobHandler(LobHandler lobHandler) {
Assert.notNull(lobHandler, "The provided LobHandler must not be null.");
this.lobHandler = lobHandler;
}
/**
* Allows for passing in a custom {@link MessageRowMapper}. The {@link MessageRowMapper}
* is used to convert the selected database row representing the persisted
* message into the actual {@link Message} object.
*
* @param messageRowMapper Must not be null
*/
public void setMessageRowMapper(MessageRowMapper messageRowMapper) {
Assert.notNull(messageRowMapper, "The provided MessageRowMapper must not be null.");
this.messageRowMapper = messageRowMapper;
}
/**
* Sets the database specific {@link ChannelMessageStoreQueryProvider} to use.
* The {@link JdbcChannelMessageStore} provides the SQL queries to retrieve messages from
* the database. See the JavaDocs {@link ChannelMessageStoreQueryProvider} (all known
* implementing classes) to see those implementations provided by the framework.
*
You can provide your own query implementations, if you need to support additional
* databases and/or need to fine-tune the queries for your requirements.
* @param channelMessageStoreQueryProvider Must not be null.
*/
public void setChannelMessageStoreQueryProvider(ChannelMessageStoreQueryProvider channelMessageStoreQueryProvider) {
Assert.notNull(channelMessageStoreQueryProvider,
"The provided channelMessageStoreQueryProvider must not be null.");
this.channelMessageStoreQueryProvider = channelMessageStoreQueryProvider;
}
/**
* A unique grouping identifier for all messages persisted with this store.
* Using multiple regions allows the store to be partitioned (if necessary)
* for different purposes. Defaults to {@link #DEFAULT_REGION}.
*
* @param region the region name to set
*/
public void setRegion(String region) {
this.region = region;
}
/**
* A converter for serializing messages to byte arrays for storage.
*
* @param serializer The serializer to set
*/
@SuppressWarnings("unchecked")
public void setSerializer(Serializer> serializer) {
Assert.notNull(serializer, "The provided serializer must not be null.");
this.serializer = new SerializingConverter((Serializer