org.springframework.integration.jdbc.store.channel.ChannelMessageStorePreparedStatementSetter Maven / Gradle / Ivy
Show all versions of spring-integration-jdbc Show documentation
/*
* Copyright 2017-2019 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
*
* https://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.channel;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Objects;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.util.UUIDConverter;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
/**
* Callback to be used with the {@link org.springframework.integration.jdbc.store.JdbcChannelMessageStore}.
*
* Behavior is same as standard {@link org.springframework.jdbc.core.PreparedStatementSetter},
* it takes in additional {@code Message requestMessage}, {@code Object groupId},
* {@code String region} and {@code boolean priorityEnabled} parameters used
* for {@code addMessageToGroup} method
* in the {@link org.springframework.integration.jdbc.store.JdbcChannelMessageStore}.
*
* This class can be extended for any custom data structure or columns types.
* For this purpose the {@code protected} constructor is provided for inheritors.
* In this case the {@link #serializer} and {@link #lobHandler} are null to avoid
* extra serialization actions if the target custom behavior doesn't imply them.
*
* @author Meherzad Lahewala
* @author Artem Bilan
*
* @since 5.0
*
* @see org.springframework.jdbc.core.PreparedStatementSetter
*/
public class ChannelMessageStorePreparedStatementSetter {
private final SerializingConverter serializer;
private final LobHandler lobHandler;
/**
* Instantiate a {@link ChannelMessageStorePreparedStatementSetter} with the provided
* serializer and lobHandler, which both must not be null.
* @param serializer the {@link SerializingConverter} to build {@code byte[]} from
* the request message
* @param lobHandler the {@link LobHandler} to store {@code byte[]} of the request
* message to prepared statement
*/
public ChannelMessageStorePreparedStatementSetter(SerializingConverter serializer, LobHandler lobHandler) {
Assert.notNull(serializer, "'serializer' must not be null");
Assert.notNull(lobHandler, "'lobHandler' must not be null");
this.serializer = serializer;
this.lobHandler = lobHandler;
}
/**
* The default constructor for inheritors who are not interested in the message
* serialization to {@code byte[]}.
* The {@link #serializer} and {@link #lobHandler} are null from this constructor,
* therefore any serialization isn't happened in the default {@link #setValues} implementation.
* A target implementor must ensure the proper custom logic for storing message.
*/
protected ChannelMessageStorePreparedStatementSetter() {
this.serializer = null;
this.lobHandler = null;
}
/**
* Perform a preparedStatement parameters population according provided arguments.
* The default functionality is (parameter - data):
*
* - 1 - messageId
*
- 2 - groupKey
*
- 3 - region
*
- 4 - createdDate
*
- 5 - priority if enabled, otherwise null
*
- 6 - serialized message if {@link #serializer} and {@link #lobHandler} are provided.
*
* An inheritor may consider to call this method for population common properties and perform
* custom message serialization logic for the parameter #6.
* Any custom data structure population can be achieved with full overriding of this method.
* @param preparedStatement the {@link PreparedStatement} to populate columns based on the provided arguments
* @param requestMessage the {@link Message} to store
* @param groupId the group id for the message to store
* @param region the region in the target table to distinguish different data base clients
* @param priorityEnabled the flag to indicate if priority has to be stored
* @throws SQLException the exception throws during data population
*/
public void setValues(PreparedStatement preparedStatement, Message requestMessage, Object groupId, String region,
boolean priorityEnabled) throws SQLException {
String groupKey = Objects.toString(UUIDConverter.getUUID(groupId), null);
long createdDate = System.currentTimeMillis();
String messageId = Objects.toString(UUIDConverter.getUUID(requestMessage.getHeaders().getId()), null);
preparedStatement.setString(1, messageId);
preparedStatement.setString(2, groupKey);
preparedStatement.setString(3, region); // NOSONAR magic number
preparedStatement.setLong(4, createdDate); // NOSONAR magic number
Integer priority = requestMessage.getHeaders().get(IntegrationMessageHeaderAccessor.PRIORITY, Integer.class);
if (priorityEnabled && priority != null) {
preparedStatement.setInt(5, priority); // NOSONAR magic number
}
else {
preparedStatement.setNull(5, Types.NUMERIC); // NOSONAR magic number
}
if (this.serializer != null) {
byte[] messageBytes = this.serializer.convert(requestMessage);
this.lobHandler.getLobCreator().setBlobAsBytes(preparedStatement, 6, messageBytes); // NOSONAR magic number
}
}
}