From 7efb14cf60d77057cb06c99e82c207077558255c Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 25 Feb 2019 20:02:46 -0500 Subject: [PATCH] GH-2753: Remove Guava dependency Fixes https://github.com/spring-projects/spring-integration/issues/2753 * Remove Guava dependency and its minor functionality from the `StoredProcExecutor` * Remove `@ManagedResource` and its operations/attributes from `StoredProcExecutor` since they are not relevant any more * Remove tests related to JMX and Guava * Refactor all other tests in the affected classes * Some code polishing in the `StoredProcExecutor` --- build.gradle | 2 - .../integration/jdbc/StoredProcExecutor.java | 304 ++++-------------- .../jdbc/StoredProcExecutorTests.java | 290 ++++------------- .../StoredProcJmxManagedBeanTests-context.xml | 63 ---- .../jdbc/StoredProcJmxManagedBeanTests.java | 209 ------------ 5 files changed, 126 insertions(+), 742 deletions(-) delete mode 100644 spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests-context.xml delete mode 100644 spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests.java diff --git a/build.gradle b/build.gradle index 907facd597..e8cbc6724b 100644 --- a/build.gradle +++ b/build.gradle @@ -102,7 +102,6 @@ subprojects { subproject -> ftpServerVersion = '1.1.1' googleJsr305Version = '3.0.2' groovyVersion = '2.5.6' - guavaVersion = '26.0-jre' hamcrestVersion = '2.1' hazelcastVersion = '3.11.1' hibernateVersion = '5.4.1.Final' @@ -493,7 +492,6 @@ project('spring-integration-jdbc') { dependencies { compile project(":spring-integration-core") compile "org.springframework:spring-jdbc:$springVersion" - compile ("com.google.guava:guava:$guavaVersion", optional) testCompile "com.h2database:h2:$h2Version" testCompile "org.hsqldb:hsqldb:$hsqldbVersion" diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcExecutor.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcExecutor.java index 5fdce4bce0..fd57624712 100644 --- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcExecutor.java +++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/StoredProcExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-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. @@ -17,7 +17,6 @@ package org.springframework.integration.jdbc; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -39,18 +38,9 @@ import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcCall; import org.springframework.jdbc.core.simple.SimpleJdbcCallOperations; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedMetric; -import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.CacheStats; -import com.google.common.cache.LoadingCache; /** @@ -60,31 +50,25 @@ import com.google.common.cache.LoadingCache; * @author Gunnar Hillert * @author Artem Bilan * @author Gary Russell + * * @since 2.1 * */ -@ManagedResource public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { - private static final boolean guavaPresent = ClassUtils.isPresent("com.google.common.cache.LoadingCache", - StoredProcExecutor.class.getClassLoader()); + private final DataSource dataSource; - private volatile EvaluationContext evaluationContext; + private Map> returningResultSetRowMappers = new HashMap<>(0); - private volatile BeanFactory beanFactory = null; + private EvaluationContext evaluationContext; - private volatile int jdbcCallOperationsCacheSize = 10; + private BeanFactory beanFactory; - /** - * For {@code optional} Google Guava library in the CLASSPATH - */ - private volatile GuavaCacheWrapper guavaCacheWrapper; + private int jdbcCallOperationsCacheSize = 10; - private final Object jdbcCallOperationsMapMonitor = new Object(); + private Map jdbcCallOperationsMap; - private volatile Map jdbcCallOperationsMap; - - private volatile Expression storedProcedureNameExpression; + private Expression storedProcedureNameExpression; /** * For fully supported databases, the underlying {@link SimpleJdbcCall} can @@ -93,17 +77,15 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * not support meta data lookups or if you like to provide customized * parameter definitions, this flag can be set to 'true'. It defaults to 'false'. */ - private volatile boolean ignoreColumnMetaData = false; + private boolean ignoreColumnMetaData = false; /** * If this variable is set to true then all results from a stored procedure call * that don't have a corresponding SqlOutParameter declaration will be bypassed. - * * The value is set on the underlying {@link org.springframework.jdbc.core.JdbcTemplate}. - * * Value defaults to true. */ - private volatile boolean skipUndeclaredResults = true; + private boolean skipUndeclaredResults = true; /** * If your database system is not fully supported by Spring and thus obtaining @@ -112,51 +94,41 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * {@link org.springframework.jdbc.core.SqlOutParameter} and * {@link org.springframework.jdbc.core.SqlInOutParameter}. */ - private volatile List sqlParameters = new ArrayList(0); + private List sqlParameters = new ArrayList<>(0); /** * By default bean properties of the passed in {@link Message} will be used * as a source for the Stored Procedure's input parameters. By default a * {@link BeanPropertySqlParameterSourceFactory} will be used. - * * This may be sufficient for basic use cases. For more sophisticated options * consider passing in one or more {@link ProcedureParameter}. */ - private volatile SqlParameterSourceFactory sqlParameterSourceFactory = null; + private SqlParameterSourceFactory sqlParameterSourceFactory; /** * Indicates that whether only the payload of the passed-in {@link Message} * shall be used as a source of parameters. - * * @see #setUsePayloadAsParameterSource(boolean) */ - private volatile Boolean usePayloadAsParameterSource = null; + private Boolean usePayloadAsParameterSource; /** * Custom Stored Procedure parameters that may contain static values * or Strings representing an {@link Expression}. */ - private volatile List procedureParameters; + private List procedureParameters; - private volatile boolean isFunction = false; + private boolean isFunction = false; - private volatile boolean returnValueRequired = false; - - private volatile Map> returningResultSetRowMappers = new HashMap>(0); - - private final DataSource dataSource; - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + private boolean returnValueRequired = false; /** * Constructor taking {@link DataSource} from which the DB Connection can be * obtained. - * * @param dataSource used to create a {@link SimpleJdbcCall} instance, must not be Null */ public StoredProcExecutor(DataSource dataSource) { - Assert.notNull(dataSource, "dataSource must not be null."); this.dataSource = dataSource; } @@ -168,78 +140,66 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { */ @Override public void afterPropertiesSet() { - - if (this.storedProcedureNameExpression == null) { - throw new IllegalArgumentException("You must either provide a " - + "Stored Procedure Name or a Stored Procedure Name Expression."); - } + Assert.notNull(this.storedProcedureNameExpression, + "You must either provide a Stored Procedure Name or a Stored Procedure Name Expression."); if (this.procedureParameters != null) { - if (this.sqlParameterSourceFactory == null) { ExpressionEvaluatingSqlParameterSourceFactory expressionSourceFactory = new ExpressionEvaluatingSqlParameterSourceFactory(); expressionSourceFactory.setBeanFactory(this.beanFactory); - expressionSourceFactory.setStaticParameters(ProcedureParameter.convertStaticParameters(this.procedureParameters)); - expressionSourceFactory.setParameterExpressions(ProcedureParameter.convertExpressions(this.procedureParameters)); + expressionSourceFactory + .setStaticParameters(ProcedureParameter.convertStaticParameters(this.procedureParameters)); + expressionSourceFactory + .setParameterExpressions(ProcedureParameter.convertExpressions(this.procedureParameters)); this.sqlParameterSourceFactory = expressionSourceFactory; - } else { - - if (!(this.sqlParameterSourceFactory instanceof ExpressionEvaluatingSqlParameterSourceFactory)) { - throw new IllegalStateException("You are providing 'ProcedureParameters'. " - + "Was expecting the the provided sqlParameterSourceFactory " - + "to be an instance of 'ExpressionEvaluatingSqlParameterSourceFactory', " - + "however the provided one is of type '" + this.sqlParameterSourceFactory.getClass().getName() + "'"); - } - + Assert.isInstanceOf(ExpressionEvaluatingSqlParameterSourceFactory.class, + this.sqlParameterSourceFactory, + () -> "You are providing 'ProcedureParameters'. " + + "Was expecting the the provided 'sqlParameterSourceFactory' " + + "to be an instance of 'ExpressionEvaluatingSqlParameterSourceFactory', " + + "however the provided one is of type '" + + this.sqlParameterSourceFactory.getClass().getName() + "'"); } if (this.usePayloadAsParameterSource == null) { this.usePayloadAsParameterSource = false; } - } else { - if (this.sqlParameterSourceFactory == null) { this.sqlParameterSourceFactory = new BeanPropertySqlParameterSourceFactory(); } - if (this.usePayloadAsParameterSource == null) { this.usePayloadAsParameterSource = true; } - } - if (guavaPresent) { - this.guavaCacheWrapper = new GuavaCacheWrapper(this, this.jdbcCallOperationsCacheSize); - } - else { - this.jdbcCallOperationsMap = - new LinkedHashMap(this.jdbcCallOperationsCacheSize + 1, 0.75f, - true) { - - private static final long serialVersionUID = 3801124242820219131L; - - @Override - protected boolean removeEldestEntry(Entry eldest) { - return size() > StoredProcExecutor.this.jdbcCallOperationsCacheSize; - } - - }; - } + this.jdbcCallOperationsMap = buildJdbcCallOperationsMap(); this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.beanFactory); } + private Map buildJdbcCallOperationsMap() { + return new LinkedHashMap(this.jdbcCallOperationsCacheSize + 1, 0.75f, + true) { + + private static final long serialVersionUID = 3801124242820219131L; + + @Override + protected boolean removeEldestEntry(Entry eldest) { + return size() > StoredProcExecutor.this.jdbcCallOperationsCacheSize; + } + + }; + } + private SimpleJdbcCall createSimpleJdbcCall(String storedProcedureName) { - - final SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(this.dataSource); - + SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(this.dataSource); if (this.isFunction) { simpleJdbcCall.withFunctionName(storedProcedureName); } @@ -251,11 +211,9 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { simpleJdbcCall.withoutProcedureColumnMetaDataAccess(); } - simpleJdbcCall.declareParameters(this.sqlParameters.toArray(new SqlParameter[this.sqlParameters.size()])); - + simpleJdbcCall.declareParameters(this.sqlParameters.toArray(new SqlParameter[0])); if (!this.returningResultSetRowMappers.isEmpty()) { - for (Entry> mapEntry : this.returningResultSetRowMappers.entrySet()) { simpleJdbcCall.returningResultSet(mapEntry.getKey(), mapEntry.getValue()); } @@ -273,7 +231,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * Execute a Stored Procedure or Function - Use when no {@link Message} is * available to extract {@link ProcedureParameter} values from it. - * * @return Map containing the stored procedure results if any. */ public Map executeStoredProcedure() { @@ -283,12 +240,10 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * Execute a Stored Procedure or Function - Use with {@link Message} is * available to extract {@link ProcedureParameter} values from it. - * * @param message A message. * @return Map containing the stored procedure results if any. */ public Map executeStoredProcedure(Message message) { - Assert.notNull(message, "The message parameter must not be null."); Assert.notNull(this.usePayloadAsParameterSource, "Property usePayloadAsParameterSource " + "was Null. Did you call afterPropertiesSet()?"); @@ -311,21 +266,19 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { ? this.storedProcedureNameExpression.getValue(this.evaluationContext, String.class) : this.storedProcedureNameExpression.getValue(this.evaluationContext, message, String.class); - Assert.hasText(storedProcedureNameToUse, String.format( - "Unable to resolve Stored Procedure/Function name for the provided Expression '%s'.", - this.storedProcedureNameExpression.getExpressionString())); + Assert.hasText(storedProcedureNameToUse, + () -> "Unable to resolve Stored Procedure/Function name for the provided Expression '" + + this.storedProcedureNameExpression.getExpressionString() + "'."); return storedProcedureNameToUse; } /** * Execute the Stored Procedure using the passed in {@link Message} as a source * for parameters. - * * @param input The message is used to extract parameters for the stored procedure. * @return A map containing the return values from the Stored Procedure call if any. */ private Map executeStoredProcedureInternal(Object input, String storedProcedureName) { - Assert.notNull(this.sqlParameterSourceFactory, "Property sqlParameterSourceFactory " + "was Null. Did you call afterPropertiesSet()?"); @@ -339,22 +292,7 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { } private SimpleJdbcCallOperations obtainSimpleJdbcCall(String storedProcedureName) { - if (guavaPresent) { - return this.guavaCacheWrapper.jdbcCallOperationsCache.getUnchecked(storedProcedureName); - } - else { - SimpleJdbcCallOperations operations = this.jdbcCallOperationsMap.get(storedProcedureName); - if (operations == null) { - synchronized (this.jdbcCallOperationsMapMonitor) { - operations = this.jdbcCallOperationsMap.get(storedProcedureName); - if (operations == null) { - operations = createSimpleJdbcCall(storedProcedureName); - this.jdbcCallOperationsMap.put(storedProcedureName, operations); - } - } - } - return operations; - } + return this.jdbcCallOperationsMap.computeIfAbsent(storedProcedureName, this::createSimpleJdbcCall); } //~~~~~Setters for Properties~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -365,7 +303,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * from the JDBC Meta-data. However, if the used database does not support * meta data lookups or if you like to provide customized parameter definitions, * this flag can be set to 'true'. It defaults to 'false'. - * * @param ignoreColumnMetaData true to ignore column metadata. */ public void setIgnoreColumnMetaData(boolean ignoreColumnMetaData) { @@ -375,35 +312,23 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * Custom Stored Procedure parameters that may contain static values * or Strings representing an {@link Expression}. - * * @param procedureParameters The parameters. */ public void setProcedureParameters(List procedureParameters) { - - Assert.notEmpty(procedureParameters, "procedureParameters must not be null or empty."); - - for (ProcedureParameter procedureParameter : procedureParameters) { - Assert.notNull(procedureParameter, "The provided list (procedureParameters) cannot contain null values."); - } - + Assert.notEmpty(procedureParameters, "'procedureParameters' must not be null or empty."); + Assert.noNullElements(procedureParameters.toArray(), "'procedureParameters' cannot contain null values."); this.procedureParameters = procedureParameters; - } /** * If you database system is not fully supported by Spring and thus obtaining * parameter definitions from the JDBC Meta-data is not possible, you must define * the {@link SqlParameter} explicitly. - * * @param sqlParameters The parameters. */ public void setSqlParameters(List sqlParameters) { - Assert.notEmpty(sqlParameters, "sqlParameters must not be null or empty."); - - for (SqlParameter sqlParameter : sqlParameters) { - Assert.notNull(sqlParameter, "The provided list (sqlParameters) cannot contain null values."); - } - + Assert.notEmpty(sqlParameters, "'sqlParameters' must not be null or empty."); + Assert.noNullElements(sqlParameters.toArray(), "'sqlParameters' cannot contain null values."); this.sqlParameters = sqlParameters; } @@ -412,11 +337,9 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * Keep in mind that if {@link ProcedureParameter} are set explicitly and * you would like to provide a custom {@link SqlParameterSourceFactory}, * then you must provide an instance of {@link ExpressionEvaluatingSqlParameterSourceFactory}. - * * If not the SqlParameterSourceFactory will be replaced the default * {@link ExpressionEvaluatingSqlParameterSourceFactory}. - * - * @param sqlParameterSourceFactory The paramtere source factory. + * @param sqlParameterSourceFactory the parameter source factory. */ public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) { Assert.notNull(sqlParameterSourceFactory, "sqlParameterSourceFactory must not be null."); @@ -426,7 +349,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * @return the name of the Stored Procedure or Function if set. Null otherwise. * */ - @ManagedAttribute(defaultValue = "Null if not Set.") public String getStoredProcedureName() { return this.storedProcedureNameExpression instanceof LiteralExpression ? this.storedProcedureNameExpression.getValue(String.class) : null; @@ -435,7 +357,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * @return the Stored Procedure Name Expression as a String if set. Null otherwise. * */ - @ManagedAttribute(defaultValue = "Null if not Set.") public String getStoredProcedureNameExpressionAsString() { return this.storedProcedureNameExpression != null ? this.storedProcedureNameExpression.getExpressionString() @@ -446,15 +367,11 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * The name of the Stored Procedure or Stored Function to be executed. * If {@link StoredProcExecutor#isFunction} is set to "true", then this * property specifies the Stored Function name. - * * Alternatively you can also specify the Stored Procedure name via * {@link StoredProcExecutor#setStoredProcedureNameExpression(Expression)}. - * * E.g., that way you can specify the name of the Stored Procedure or Stored Function * through {@link org.springframework.messaging.MessageHeaders}. - * * @param storedProcedureName Must not be null and must not be empty - * * @see StoredProcExecutor#setStoredProcedureNameExpression(Expression) */ public void setStoredProcedureName(String storedProcedureName) { @@ -466,28 +383,21 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * Using the {@link StoredProcExecutor#storedProcedureNameExpression} the * {@link Message} can be used as source for the name of the * Stored Procedure or Stored Function. - * * If {@link StoredProcExecutor#isFunction} is set to "true", then this * property specifies the Stored Function name. - * * By providing a SpEL expression as value for this setter, a subset of the * original payload, a header value or any other resolvable SpEL expression * can be used as the basis for the Stored Procedure / Function. - * * For the Expression evaluation the full message is available as the root object. - * * For instance the following SpEL expressions (among others) are possible: - * *
    *
  • payload.foo
  • *
  • headers.foobar
  • *
  • new java.util.Date()
  • *
  • 'foo' + 'bar'
  • *
- * * Alternatively you can also specify the Stored Procedure name via * {@link StoredProcExecutor#setStoredProcedureName(String)} - * * @param storedProcedureNameExpression Must not be null. * */ @@ -500,17 +410,14 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * If set to 'true', the payload of the Message will be used as a source for * providing parameters. If false the entire {@link Message} will be available * as a source for parameters. - * * If no {@link ProcedureParameter} are passed in, this property will default to * true. This means that using a default {@link BeanPropertySqlParameterSourceFactory} * the bean properties of the payload will be used as a source for parameter * values for the to-be-executed Stored Procedure or Function. - * * However, if {@link ProcedureParameter}s are passed in, then this property * will by default evaluate to false. {@link ProcedureParameter} * allow for SpEl Expressions to be provided and therefore it is highly * beneficial to have access to the entire {@link Message}. - * * @param usePayloadAsParameterSource If false the entire {@link Message} is used as parameter source. */ public void setUsePayloadAsParameterSource(boolean usePayloadAsParameterSource) { @@ -520,7 +427,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * Indicates whether a Stored Procedure or a Function is being executed. * The default value is false. - * * @param isFunction If set to true an Sql Function is executed rather than a Stored Procedure. */ public void setIsFunction(boolean isFunction) { @@ -530,7 +436,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * Indicates the procedure's return value should be included in the results * returned. - * * @param returnValueRequired true to include the return value. */ public void setReturnValueRequired(boolean returnValueRequired) { @@ -542,18 +447,13 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * procedure call that don't have a corresponding * {@link org.springframework.jdbc.core.SqlOutParameter} * declaration will be bypassed. - * * E.g. Stored Procedures may return an update count value, even though your * Stored Procedure only declared a single result parameter. The exact behavior * depends on the used database. - * * The value is set on the underlying {@link org.springframework.jdbc.core.JdbcTemplate}. - * * Only few developers will probably ever like to process update counts, thus * the value defaults to true. - * * @param skipUndeclaredResults The boolean. - * */ public void setSkipUndeclaredResults(boolean skipUndeclaredResults) { this.skipUndeclaredResults = skipUndeclaredResults; @@ -562,77 +462,40 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { /** * If the Stored Procedure returns ResultSets you may provide a map of * {@link RowMapper} to convert the {@link java.sql.ResultSet} to meaningful objects. - * * @param returningResultSetRowMappers The map may not be null and must not contain null values. */ public void setReturningResultSetRowMappers(Map> returningResultSetRowMappers) { - - Assert.notNull(returningResultSetRowMappers, "returningResultSetRowMappers must not be null."); - - for (RowMapper rowMapper : returningResultSetRowMappers.values()) { - Assert.notNull(rowMapper, "The provided map cannot contain null values."); - } - + Assert.notNull(returningResultSetRowMappers, "'returningResultSetRowMappers' must not be null."); + Assert.noNullElements(returningResultSetRowMappers.values().toArray(), + "'returningResultSetRowMappers' cannot contain null values."); this.returningResultSetRowMappers = returningResultSetRowMappers; } /** - * Allows for the retrieval of metrics ({@link CacheStats}) for the - * {@link GuavaCacheWrapper#jdbcCallOperationsCache}, which is used to store - * instances of {@link SimpleJdbcCallOperations}. - * - * @return {@link CacheStats} object for {@link GuavaCacheWrapper#jdbcCallOperationsCache}. - * Since Google Guava is an optional dependency for Spring Integration this method can't - * return Guava {@link CacheStats} type directly because of some reflection manipulation - * by the Spring bean definition phase. + * Allows for the retrieval of metrics. + * @return the metrics. + * @deprecated since 5.2 + * @throws UnsupportedOperationException since this functionality isn't supported any more. */ + @Deprecated public Object getJdbcCallOperationsCacheStatistics() { - if (!guavaPresent) { - throw new UnsupportedOperationException("The Google Guava library isn't present in the classpath."); - } - return this.guavaCacheWrapper.jdbcCallOperationsCache.stats(); + throw new UnsupportedOperationException("The Google Guava cache isn't supported any more."); } /** - * Allows for the retrieval of metrics ({@link CacheStats}) for the - * {@link GuavaCacheWrapper#jdbcCallOperationsCache}. - * - * Provides the properties of {@link CacheStats} as a {@link Map}. This allows - * for exposing the those properties easily via JMX. - * + * Allows for the retrieval of metrics. * @return Map containing metrics of the JdbcCallOperationsCache - * - * @see StoredProcExecutor#getJdbcCallOperationsCacheStatistics() + * @deprecated since 5.2 + * @throws UnsupportedOperationException since this functionality isn't supported any more. */ - @ManagedMetric + @Deprecated public Map getJdbcCallOperationsCacheStatisticsAsMap() { - if (!guavaPresent) { - throw new UnsupportedOperationException("The Google Guava library isn't present in the classpath."); - } - final CacheStats cacheStats = (CacheStats) getJdbcCallOperationsCacheStatistics(); - final Map cacheStatistics = new HashMap(11); - cacheStatistics.put("averageLoadPenalty", cacheStats.averageLoadPenalty()); - cacheStatistics.put("evictionCount", cacheStats.evictionCount()); - cacheStatistics.put("hitCount", cacheStats.hitCount()); - cacheStatistics.put("hitRate", cacheStats.hitRate()); - cacheStatistics.put("loadCount", cacheStats.loadCount()); - cacheStatistics.put("loadExceptionCount", cacheStats.loadExceptionCount()); - cacheStatistics.put("loadExceptionRate", cacheStats.loadExceptionRate()); - cacheStatistics.put("loadSuccessCount", cacheStats.loadSuccessCount()); - cacheStatistics.put("missCount", cacheStats.missCount()); - cacheStatistics.put("missRate", cacheStats.missRate()); - cacheStatistics.put("totalLoadTime", cacheStats.totalLoadTime()); - return Collections.unmodifiableMap(cacheStatistics); + throw new UnsupportedOperationException("The Google Guava cache isn't supported any more."); } /** * Defines the maximum number of {@link SimpleJdbcCallOperations} - * ({@link SimpleJdbcCall}) instances to be held by - * {@link GuavaCacheWrapper#jdbcCallOperationsCache}. - * * A value of zero will disable the cache. The default is 10. - * - * @see CacheBuilder#maximumSize(long) * @param jdbcCallOperationsCacheSize Must not be negative. */ public void setJdbcCallOperationsCacheSize(int jdbcCallOperationsCacheSize) { @@ -645,7 +508,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { * {@link org.springframework.expression.BeanResolver} to the * {@link org.springframework.expression.spel.support.StandardEvaluationContext}. * If not set this property defaults to null. - * * @param beanFactory If set must not be null. */ @Override @@ -653,32 +515,6 @@ public class StoredProcExecutor implements BeanFactoryAware, InitializingBean { this.beanFactory = beanFactory; } - /** - * The lazy-load workaround class to avoid {@link NoClassDefFoundError} - * for {@link CacheLoader} class, when Google Guava isn't present in the CLASSPATH. - * - * @since 4.2 - */ - private static final class GuavaCacheWrapper { - - private final LoadingCache jdbcCallOperationsCache; - - private GuavaCacheWrapper(final StoredProcExecutor executor, int size) { - this.jdbcCallOperationsCache = CacheBuilder.newBuilder() - .maximumSize(size) - .recordStats() - .build(new CacheLoader() { - - @Override - public SimpleJdbcCallOperations load(String key) throws Exception { - return executor.createSimpleJdbcCall(key); - } - - }); - } - - } - } diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcExecutorTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcExecutorTests.java index 714191579f..5f450bdaf5 100644 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcExecutorTests.java +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcExecutorTests.java @@ -17,6 +17,7 @@ package org.springframework.integration.jdbc; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.mock; @@ -27,8 +28,6 @@ import java.util.Map; import javax.sql.DataSource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.Test; import org.springframework.beans.DirectFieldAccessor; @@ -37,15 +36,10 @@ import org.springframework.expression.Expression; import org.springframework.integration.config.ExpressionFactoryBean; import org.springframework.integration.jdbc.storedproc.ProcedureParameter; import org.springframework.integration.support.MessageBuilder; -import org.springframework.integration.test.util.TestUtils; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.SqlParameter; -import org.springframework.jdbc.core.simple.SimpleJdbcCall; import org.springframework.jdbc.core.simple.SimpleJdbcCallOperations; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.CacheStats; - /** * @author Gunnar Hillert * @author Artem Bilan @@ -53,56 +47,33 @@ import com.google.common.cache.CacheStats; */ public class StoredProcExecutorTests { - private static final Log LOGGER = LogFactory.getLog(StoredProcExecutorTests.class); - @Test public void testStoredProcExecutorWithNullDataSource() { - - try { - new StoredProcExecutor(null); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("dataSource must not be null."); - return; - } - - fail("Exception expected."); + assertThatIllegalArgumentException() + .isThrownBy(() -> new StoredProcExecutor(null)) + .withMessage("dataSource must not be null."); } @Test public void testStoredProcExecutorWithNullProcedureName() { - DataSource datasource = mock(DataSource.class); - try { - StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - storedProcExecutor.setBeanFactory(mock(BeanFactory.class)); - storedProcExecutor.afterPropertiesSet(); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("You must either provide a " - + "Stored Procedure Name or a Stored Procedure Name Expression."); - return; - } - - fail("Exception expected."); + StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); + storedProcExecutor.setBeanFactory(mock(BeanFactory.class)); + assertThatIllegalArgumentException() + .isThrownBy(storedProcExecutor::afterPropertiesSet) + .withMessage("You must either provide a " + + "Stored Procedure Name or a Stored Procedure Name Expression."); } @Test public void testStoredProcExecutorWithEmptyProcedureName() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - try { - storedProcExecutor.setStoredProcedureName(" "); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("storedProcedureName must not be null and cannot be empty."); - return; - } - - fail("Exception expected."); + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setStoredProcedureName(" ")) + .withMessage("storedProcedureName must not be null and cannot be empty."); } @Test @@ -124,7 +95,7 @@ public class StoredProcExecutorTests { } @Test - public void testGetStoredProcedureNameExpressionAsString2() throws Exception { + public void testGetStoredProcedureNameExpressionAsString2() { DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); @@ -139,41 +110,25 @@ public class StoredProcExecutorTests { @Test public void testSetReturningResultSetRowMappersWithNullMap() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - try { - storedProcExecutor.setReturningResultSetRowMappers(null); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("returningResultSetRowMappers must not be null."); - return; - } - - fail("Exception expected."); - + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setReturningResultSetRowMappers(null)) + .withMessage("'returningResultSetRowMappers' must not be null."); } @Test public void testSetReturningResultSetRowMappersWithMapContainingNullValues() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - Map> rowmappers = new HashMap>(); - rowmappers.put("results", null); - - try { - storedProcExecutor.setReturningResultSetRowMappers(rowmappers); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("The provided map cannot contain null values."); - return; - } - - fail("Exception expected."); + Map> rowMappers = new HashMap<>(); + rowMappers.put("results", null); + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setReturningResultSetRowMappers(rowMappers)) + .withMessage("'returningResultSetRowMappers' cannot contain null values."); } @Test @@ -209,102 +164,62 @@ public class StoredProcExecutorTests { @Test public void testSetSqlParametersWithNullValueInList() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - List sqlParameters = new ArrayList(); + List sqlParameters = new ArrayList<>(); sqlParameters.add(null); - try { - storedProcExecutor.setSqlParameters(sqlParameters); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("The provided list (sqlParameters) cannot contain null values."); - return; - } - - fail("Exception expected."); - + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setSqlParameters(sqlParameters)) + .withMessage("'sqlParameters' cannot contain null values."); } @Test public void testSetSqlParametersWithEmptyList() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - List sqlParameters = new ArrayList(); - - try { - storedProcExecutor.setSqlParameters(sqlParameters); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("sqlParameters must not be null or empty."); - return; - } - - fail("Exception expected."); + List sqlParameters = new ArrayList<>(); + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setSqlParameters(sqlParameters)) + .withMessage("'sqlParameters' must not be null or empty."); } @Test public void testSetSqlParametersWithNullList() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - try { - storedProcExecutor.setSqlParameters(null); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("sqlParameters must not be null or empty."); - return; - } - - fail("Exception expected."); - + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setSqlParameters(null)) + .withMessage("'sqlParameters' must not be null or empty."); } @Test public void testSetProcedureParametersWithNullValueInList() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - List procedureParameters = new ArrayList(); + List procedureParameters = new ArrayList<>(); procedureParameters.add(null); - try { - storedProcExecutor.setProcedureParameters(procedureParameters); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("The provided list (procedureParameters) cannot contain null values."); - return; - } - - fail("Exception expected."); - + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setProcedureParameters(procedureParameters)) + .withMessage("'procedureParameters' cannot contain null values."); } @Test public void testSetProcedureParametersWithEmptyList() { - DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - List procedureParameters = new ArrayList(); - - try { - storedProcExecutor.setProcedureParameters(procedureParameters); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("procedureParameters must not be null or empty."); - return; - } - - fail("Exception expected."); + List procedureParameters = new ArrayList<>(); + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setProcedureParameters(procedureParameters)) + .withMessage("'procedureParameters' must not be null or empty."); } @Test @@ -313,21 +228,13 @@ public class StoredProcExecutorTests { DataSource datasource = mock(DataSource.class); StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - try { - storedProcExecutor.setProcedureParameters(null); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).isEqualTo("procedureParameters must not be null or empty."); - return; - } - - fail("Exception expected."); - + assertThatIllegalArgumentException() + .isThrownBy(() -> storedProcExecutor.setProcedureParameters(null)) + .withMessage("'procedureParameters' must not be null or empty."); } @Test public void testStoredProcExecutorWithNonResolvingExpression() throws Exception { - final DataSource datasource = mock(DataSource.class); final StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); @@ -341,8 +248,11 @@ public class StoredProcExecutorTests { storedProcExecutor.afterPropertiesSet(); - this.mockTheOperationsCache(storedProcExecutor); + Map jdbcCallOperationsMap = new HashMap<>(); + jdbcCallOperationsMap.put("123", mock(SimpleJdbcCallOperations.class)); + new DirectFieldAccessor(storedProcExecutor) + .setPropertyValue("jdbcCallOperationsMap", jdbcCallOperationsMap); //This should work storedProcExecutor.executeStoredProcedure( @@ -352,102 +262,14 @@ public class StoredProcExecutorTests { //This should cause an exception - try { - storedProcExecutor.executeStoredProcedure( - MessageBuilder.withPayload("test") - .setHeader("some_other_header", "123") - .build()); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()) - .isEqualTo("Unable to resolve Stored Procedure/Function name for the provided Expression " + - "'headers['stored_procedure_name']'."); - return; - } - - fail("IllegalArgumentException expected."); - - } - - @Test - public void testStoredProcExecutorJdbcCallOperationsCache() throws Exception { - - final DataSource datasource = mock(DataSource.class); - - final StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - - final ExpressionFactoryBean efb = new ExpressionFactoryBean("headers['stored_procedure_name']"); - efb.afterPropertiesSet(); - final Expression expression = efb.getObject(); - - storedProcExecutor.setStoredProcedureNameExpression(expression); - storedProcExecutor.setBeanFactory(mock(BeanFactory.class)); - - storedProcExecutor.afterPropertiesSet(); - - this.mockTheOperationsCache(storedProcExecutor); - - for (int i = 1; i <= 3; i++) { - storedProcExecutor.executeStoredProcedure( - MessageBuilder.withPayload("test") - .setHeader("stored_procedure_name", "123") - .build()); - } - - final CacheStats stats = (CacheStats) storedProcExecutor.getJdbcCallOperationsCacheStatistics(); - LOGGER.info(stats); - LOGGER.info(stats.totalLoadTime() / 1000 / 1000); - - assertThat(2).isEqualTo(stats.hitCount()); - assertThat(1).isEqualTo(stats.missCount()); - assertThat(1).isEqualTo(stats.loadCount()); - - } - - @Test - public void testSetJdbcCallOperationsCacheSize() throws Exception { - - final DataSource datasource = mock(DataSource.class); - - final StoredProcExecutor storedProcExecutor = new StoredProcExecutor(datasource); - - storedProcExecutor.setJdbcCallOperationsCacheSize(0); - - final ExpressionFactoryBean efb = new ExpressionFactoryBean("headers['stored_procedure_name']"); - efb.afterPropertiesSet(); - final Expression expression = efb.getObject(); - - storedProcExecutor.setStoredProcedureNameExpression(expression); - storedProcExecutor.setBeanFactory(mock(BeanFactory.class)); - - storedProcExecutor.afterPropertiesSet(); - - this.mockTheOperationsCache(storedProcExecutor); - - for (int i = 1; i <= 10; i++) { - storedProcExecutor.executeStoredProcedure( - MessageBuilder.withPayload("test") - .setHeader("stored_procedure_name", "123") - .build()); - } - - final CacheStats stats = (CacheStats) storedProcExecutor.getJdbcCallOperationsCacheStatistics(); - LOGGER.info(stats); - assertThat(stats.missCount()).as("Expected a cache misscount of 10").isEqualTo(10); - - } - - private void mockTheOperationsCache(final StoredProcExecutor storedProcExecutor) { - Object cache = TestUtils.getPropertyValue(storedProcExecutor, - "guavaCacheWrapper.jdbcCallOperationsCache.localCache"); - new DirectFieldAccessor(cache) - .setPropertyValue("defaultLoader", new CacheLoader() { - - @Override - public SimpleJdbcCall load(String storedProcedureName) { - return mock(SimpleJdbcCall.class); - } - }); + assertThatIllegalArgumentException() + .isThrownBy(() -> + storedProcExecutor.executeStoredProcedure( + MessageBuilder.withPayload("test") + .setHeader("some_other_header", "123") + .build())) + .withMessage("Unable to resolve Stored Procedure/Function name for the provided Expression " + + "'headers['stored_procedure_name']'."); } } diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests-context.xml deleted file mode 100644 index 82fd154bf3..0000000000 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests-context.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests.java deleted file mode 100644 index dde59d2c65..0000000000 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcJmxManagedBeanTests.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2002-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 - * - * 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; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectName; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.integration.jdbc.storedproc.CreateUser; -import org.springframework.integration.jdbc.storedproc.User; -import org.springframework.messaging.Message; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.annotation.DirtiesContext.ClassMode; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Gunnar Hillert - * @author Artem Bilan - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) -public class StoredProcJmxManagedBeanTests { - - @Autowired - private Consumer consumer; - - @Autowired - CreateUser userService; - - @Test - @SuppressWarnings("unchecked") - public void testCollectJmxAttributes() throws Exception { - - final List servers = MBeanServerFactory.findMBeanServer(null); - assertThat(servers.size()).isEqualTo(1); - - final MBeanServer server = servers.iterator().next(); - - // MessageHandler - - final Set messageHandlerObjectNames = server.queryNames( - ObjectName.getInstance( - "org.springframework.integration.jdbc.test:name=outboundChannelAdapter.adapter.storedProcExecutor,*"), - null); - assertThat(messageHandlerObjectNames.size()).isEqualTo(1); - ObjectName messageHandlerObjectName = messageHandlerObjectNames.iterator().next(); - Map messageHandlerCacheStatistics = (Map) server - .getAttribute(messageHandlerObjectName, "JdbcCallOperationsCacheStatisticsAsMap"); - - assertThat(messageHandlerCacheStatistics.size()).isEqualTo(11); - - assertThat(messageHandlerCacheStatistics.get("hitCount")).isEqualTo(0L); - assertThat(messageHandlerCacheStatistics.get("loadCount")).isEqualTo(0L); - assertThat(messageHandlerCacheStatistics.get("loadExceptionCount")).isEqualTo(0L); - assertThat(messageHandlerCacheStatistics.get("loadSuccessCount")).isEqualTo(0L); - assertThat(messageHandlerCacheStatistics.get("missCount")).isEqualTo(0L); - - // StoredProcOutboundGateway - final Set storedProcOutboundGatewayObjectNames = server.queryNames(ObjectName - .getInstance("org.springframework.integration.jdbc.test:name=my gateway.storedProcExecutor,*"), null); - assertThat(storedProcOutboundGatewayObjectNames.size()).isEqualTo(1); - ObjectName storedProcOutboundGatewayObjectName = storedProcOutboundGatewayObjectNames.iterator().next(); - Map storedProcOutboundGatewayCacheStatistics = (Map) server - .getAttribute(storedProcOutboundGatewayObjectName, "JdbcCallOperationsCacheStatisticsAsMap"); - - assertThat(messageHandlerCacheStatistics.size()).isEqualTo(11); - - assertThat(storedProcOutboundGatewayCacheStatistics.get("hitCount")).isEqualTo(0L); - assertThat(storedProcOutboundGatewayCacheStatistics.get("loadCount")).isEqualTo(0L); - assertThat(storedProcOutboundGatewayCacheStatistics.get("loadExceptionCount")).isEqualTo(0L); - assertThat(storedProcOutboundGatewayCacheStatistics.get("loadSuccessCount")).isEqualTo(0L); - assertThat(storedProcOutboundGatewayCacheStatistics.get("missCount")).isEqualTo(0L); - - // StoredProcPollingChannelAdapter - - final Set storedProcPollingChannelAdapterObjectNames = server.queryNames( - ObjectName.getInstance( - "org.springframework.integration.jdbc.test:name=inbound-channel-adapter.storedProcExecutor,*"), - null); - assertThat(storedProcPollingChannelAdapterObjectNames.size()).isEqualTo(1); - ObjectName storedProcPollingChannelAdapterObjectName = storedProcPollingChannelAdapterObjectNames.iterator() - .next(); - Map storedProcPollingChannelAdapterCacheStatistics = (Map) server - .getAttribute(storedProcPollingChannelAdapterObjectName, "JdbcCallOperationsCacheStatisticsAsMap"); - - assertThat(storedProcPollingChannelAdapterCacheStatistics.size()).isEqualTo(11); - - assertThat(storedProcPollingChannelAdapterCacheStatistics.get("hitCount")).isEqualTo(0L); - assertThat(storedProcPollingChannelAdapterCacheStatistics.get("loadCount")).isEqualTo(0L); - assertThat(storedProcPollingChannelAdapterCacheStatistics.get("loadExceptionCount")).isEqualTo(0L); - assertThat(storedProcPollingChannelAdapterCacheStatistics.get("loadSuccessCount")).isEqualTo(0L); - assertThat(storedProcPollingChannelAdapterCacheStatistics.get("missCount")).isEqualTo(0L); - - } - - @Test - @SuppressWarnings("unchecked") - public void testOutboundGateWayJmxAttributes() throws Exception { - - final List servers = MBeanServerFactory.findMBeanServer(null); - assertThat(servers.size()).isEqualTo(1); - - final MBeanServer server = servers.iterator().next(); - - final Set objectNames = server.queryNames( - ObjectName.getInstance("org.springframework.integration.jdbc.test:name=my gateway.storedProcExecutor,*"), - null); - assertThat(objectNames.size()).isEqualTo(1); - ObjectName name = objectNames.iterator().next(); - Map cacheStatistics = - (Map) server.getAttribute(name, "JdbcCallOperationsCacheStatisticsAsMap"); - - assertThat(cacheStatistics.size()).isEqualTo(11); - - assertThat(cacheStatistics.get("hitCount")).isEqualTo(0L); - assertThat(cacheStatistics.get("loadCount")).isEqualTo(0L); - assertThat(cacheStatistics.get("loadExceptionCount")).isEqualTo(0L); - assertThat(cacheStatistics.get("loadSuccessCount")).isEqualTo(0L); - assertThat(cacheStatistics.get("missCount")).isEqualTo(0L); - - userService.createUser(new User("myUsername", "myPassword", "myEmail")); - - List>> received = new ArrayList>>(); - - received.add(consumer.poll(2000)); - - Message> message = received.get(0); - - assertThat(message).isNotNull(); - assertThat(message.getPayload()).isNotNull(); - - Map cacheStatistics2 = - (Map) server.getAttribute(name, "JdbcCallOperationsCacheStatisticsAsMap"); - - assertThat(cacheStatistics2.size()).isEqualTo(11); - - assertThat(cacheStatistics2.get("hitCount")).isEqualTo(0L); - assertThat(cacheStatistics2.get("loadCount")).isEqualTo(1L); - assertThat(cacheStatistics2.get("loadExceptionCount")).isEqualTo(0L); - assertThat(cacheStatistics2.get("loadSuccessCount")).isEqualTo(1L); - assertThat(cacheStatistics2.get("missCount")).isEqualTo(1L); - - } - - static class Counter { - - private final AtomicInteger count = new AtomicInteger(); - - public Integer next() throws InterruptedException { - if (count.get() > 2) { - //prevent message overload - return null; - } - return count.incrementAndGet(); - } - - } - - - static class Consumer { - - private final BlockingQueue>> messages = - new LinkedBlockingQueue>>(); - - @ServiceActivator - public void receive(Message> message) { - messages.add(message); - } - - Message> poll(long timeoutInMillis) throws InterruptedException { - return messages.poll(timeoutInMillis, TimeUnit.MILLISECONDS); - } - - } - -}