This is an automated email from the ASF dual-hosted git repository. namelchev pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new 61f3992 IGNITE-15674 Migrate CacheSpringStoreSessionListener to ignite-extensions. (#9467) 61f3992 is described below commit 61f39927fdb102db1296b2514bffb8788d95b784 Author: Mikhail Petrov <32207922+ololo3...@users.noreply.github.com> AuthorDate: Thu Oct 14 16:26:22 2021 +0300 IGNITE-15674 Migrate CacheSpringStoreSessionListener to ignite-extensions. (#9467) --- .../store/spring/CacheSpringPersonStore.java | 118 ----------- .../store/spring/CacheSpringStoreExample.java | 160 -------------- .../datagrid/store/spring/package-info.java | 22 -- modules/spring/pom.xml | 59 ++---- .../spring/CacheSpringStoreSessionListener.java | 212 ------------------- .../ignite/cache/store/spring/package-info.java | 22 -- .../CacheSpringStoreSessionListenerSelfTest.java | 230 --------------------- .../ignite/testsuites/IgniteSpringTestSuite.java | 3 - 8 files changed, 17 insertions(+), 809 deletions(-) diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/CacheSpringPersonStore.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/CacheSpringPersonStore.java deleted file mode 100644 index c4b52bb..0000000 --- a/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/CacheSpringPersonStore.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.apache.ignite.examples.datagrid.store.spring; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.concurrent.atomic.AtomicInteger; -import javax.cache.Cache; -import javax.cache.integration.CacheLoaderException; -import javax.sql.DataSource; -import org.apache.ignite.IgniteException; -import org.apache.ignite.cache.store.CacheStore; -import org.apache.ignite.cache.store.CacheStoreAdapter; -import org.apache.ignite.examples.model.Person; -import org.apache.ignite.lang.IgniteBiInClosure; -import org.h2.jdbcx.JdbcConnectionPool; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.jdbc.core.RowMapper; - -/** - * Example of {@link CacheStore} implementation that uses JDBC - * transaction with cache transactions and maps {@link Long} to {@link Person}. - */ -public class CacheSpringPersonStore extends CacheStoreAdapter<Long, Person> { - /** Data source. */ - public static final DataSource DATA_SRC = - JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", ""); - - /** Spring JDBC template. */ - private JdbcTemplate jdbcTemplate; - - /** - * Constructor. - * - * @throws IgniteException If failed. - */ - public CacheSpringPersonStore() throws IgniteException { - jdbcTemplate = new JdbcTemplate(DATA_SRC); - } - - /** {@inheritDoc} */ - @Override public Person load(Long key) { - System.out.println(">>> Store load [key=" + key + ']'); - - try { - return jdbcTemplate.queryForObject("select * from PERSON where id = ?", new RowMapper<Person>() { - @Override public Person mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Person(rs.getLong(1), rs.getString(2), rs.getString(3)); - } - }, key); - } - catch (EmptyResultDataAccessException ignored) { - return null; - } - } - - /** {@inheritDoc} */ - @Override public void write(Cache.Entry<? extends Long, ? extends Person> entry) { - Long key = entry.getKey(); - Person val = entry.getValue(); - - System.out.println(">>> Store write [key=" + key + ", val=" + val + ']'); - - int updated = jdbcTemplate.update("update PERSON set first_name = ?, last_name = ? where id = ?", - val.firstName, val.lastName, val.id); - - if (updated == 0) { - jdbcTemplate.update("insert into PERSON (id, first_name, last_name) values (?, ?, ?)", - val.id, val.firstName, val.lastName); - } - } - - /** {@inheritDoc} */ - @Override public void delete(Object key) { - System.out.println(">>> Store delete [key=" + key + ']'); - - jdbcTemplate.update("delete from PERSON where id = ?", key); - } - - /** {@inheritDoc} */ - @Override public void loadCache(final IgniteBiInClosure<Long, Person> clo, Object... args) { - if (args == null || args.length == 0 || args[0] == null) - throw new CacheLoaderException("Expected entry count parameter is not provided."); - - int entryCnt = (Integer)args[0]; - - final AtomicInteger cnt = new AtomicInteger(); - - jdbcTemplate.query("select * from PERSON limit ?", new RowCallbackHandler() { - @Override public void processRow(ResultSet rs) throws SQLException { - Person person = new Person(rs.getLong(1), rs.getString(2), rs.getString(3)); - - clo.apply(person.id, person); - - cnt.incrementAndGet(); - } - }, entryCnt); - - System.out.println(">>> Loaded " + cnt + " values into cache."); - } -} diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/CacheSpringStoreExample.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/CacheSpringStoreExample.java deleted file mode 100644 index 4bb5d1d..0000000 --- a/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/CacheSpringStoreExample.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.apache.ignite.examples.datagrid.store.spring; - -import java.util.UUID; -import javax.cache.configuration.Factory; -import javax.cache.configuration.FactoryBuilder; -import org.apache.ignite.Ignite; -import org.apache.ignite.IgniteCache; -import org.apache.ignite.IgniteException; -import org.apache.ignite.Ignition; -import org.apache.ignite.cache.store.CacheStoreSessionListener; -import org.apache.ignite.cache.store.spring.CacheSpringStoreSessionListener; -import org.apache.ignite.configuration.CacheConfiguration; -import org.apache.ignite.examples.ExampleNodeStartup; -import org.apache.ignite.examples.ExamplesUtils; -import org.apache.ignite.examples.model.Person; -import org.apache.ignite.examples.util.DbH2ServerStartup; -import org.apache.ignite.transactions.Transaction; - -import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL; - -/** - * Demonstrates usage of cache with underlying persistent store configured. - * <p> - * This example uses {@link CacheSpringPersonStore} as a persistent store. - * <p> - * To start the example, you should: - * <ul> - * <li>Start H2 database TCP server using {@link DbH2ServerStartup}.</li> - * <li>Start a few nodes using {@link ExampleNodeStartup}.</li> - * <li>Start example using {@link CacheSpringStoreExample}.</li> - * </ul> - * <p> - * Remote nodes can be started with {@link ExampleNodeStartup} in another JVM which will - * start node with {@code examples/config/example-ignite.xml} configuration. - */ -public class CacheSpringStoreExample { - /** Cache name. */ - private static final String CACHE_NAME = CacheSpringStoreExample.class.getSimpleName(); - - /** Heap size required to run this example. */ - public static final int MIN_MEMORY = 1024 * 1024 * 1024; - - /** Number of entries to load. */ - private static final int ENTRY_COUNT = 100_000; - - /** Global person ID to use across entire example. */ - private static final Long id = Math.abs(UUID.randomUUID().getLeastSignificantBits()); - - /** - * Executes example. - * - * @param args Command line arguments, none required. - * @throws IgniteException If example execution failed. - */ - public static void main(String[] args) throws IgniteException { - ExamplesUtils.checkMinMemory(MIN_MEMORY); - - // To start ignite with desired configuration uncomment the appropriate line. - try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { - System.out.println(); - System.out.println(">>> Cache store example started."); - - CacheConfiguration<Long, Person> cacheCfg = new CacheConfiguration<>(CACHE_NAME); - - // Set atomicity as transaction, since we are showing transactions in example. - cacheCfg.setAtomicityMode(TRANSACTIONAL); - - // Configure Spring store. - cacheCfg.setCacheStoreFactory(FactoryBuilder.factoryOf(CacheSpringPersonStore.class)); - - // Configure Spring session listener. - cacheCfg.setCacheStoreSessionListenerFactories(new Factory<CacheStoreSessionListener>() { - @Override public CacheStoreSessionListener create() { - CacheSpringStoreSessionListener lsnr = new CacheSpringStoreSessionListener(); - - lsnr.setDataSource(CacheSpringPersonStore.DATA_SRC); - - return lsnr; - } - }); - - cacheCfg.setReadThrough(true); - cacheCfg.setWriteThrough(true); - - // Auto-close cache at the end of the example. - try (IgniteCache<Long, Person> cache = ignite.getOrCreateCache(cacheCfg)) { - // Make initial cache loading from persistent store. This is a - // distributed operation and will call CacheStore.loadCache(...) - // method on all nodes in topology. - loadCache(cache); - - // Start transaction and execute several cache operations with - // read/write-through to persistent store. - executeTransaction(cache); - } - finally { - // Distributed cache could be removed from cluster only by #destroyCache() call. - ignite.destroyCache(CACHE_NAME); - } - } - } - - /** - * Makes initial cache loading. - * - * @param cache Cache to load. - */ - private static void loadCache(IgniteCache<Long, Person> cache) { - long start = System.currentTimeMillis(); - - // Start loading cache from persistent store on all caching nodes. - cache.loadCache(null, ENTRY_COUNT); - - long end = System.currentTimeMillis(); - - System.out.println(">>> Loaded " + cache.size() + " keys with backups in " + (end - start) + "ms."); - } - - /** - * Executes transaction with read/write-through to persistent store. - * - * @param cache Cache to execute transaction on. - */ - private static void executeTransaction(IgniteCache<Long, Person> cache) { - try (Transaction tx = Ignition.ignite().transactions().txStart()) { - Person val = cache.get(id); - - System.out.println("Read value: " + val); - - val = cache.getAndPut(id, new Person(id, "Isaac", "Newton")); - - System.out.println("Overwrote old value: " + val); - - val = cache.get(id); - - System.out.println("Read value: " + val); - - tx.commit(); - } - - System.out.println("Read value after commit: " + cache.get(id)); - } -} diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/package-info.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/package-info.java deleted file mode 100644 index 211239f..0000000 --- a/examples/src/main/java/org/apache/ignite/examples/datagrid/store/spring/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 description. --> - * Contains Spring-based cache store implementation. - */ -package org.apache.ignite.examples.datagrid.store.spring; diff --git a/modules/spring/pom.xml b/modules/spring/pom.xml index 5796cf0..675107a 100644 --- a/modules/spring/pom.xml +++ b/modules/spring/pom.xml @@ -49,47 +49,11 @@ <dependency> <groupId>org.springframework</groupId> - <artifactId>spring-core</artifactId> - <version>${spring.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-aop</artifactId> - <version>${spring.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-beans</artifactId> - <version>${spring.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-expression</artifactId> - <version>${spring.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-tx</artifactId> - <version>${spring.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-jdbc</artifactId> - <version>${spring.version}</version> - </dependency> - - <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> @@ -161,19 +125,30 @@ <instructions> <Fragment-Host>${project.groupId}.ignite-core</Fragment-Host> <Require-Bundle> - org.apache.servicemix.bundles.spring-beans, org.apache.servicemix.bundles.spring-context, - org.apache.servicemix.bundles.spring-context-support, - org.apache.servicemix.bundles.spring-core, - org.apache.servicemix.bundles.spring-expression, - org.apache.servicemix.bundles.spring-jdbc, - org.apache.servicemix.bundles.spring-tx </Require-Bundle> </instructions> </configuration> </plugin> <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-libs</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <includeGroupIds>org.springframework,commons-logging</includeGroupIds> + <excludeTransitive>false</excludeTransitive> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> diff --git a/modules/spring/src/main/java/org/apache/ignite/cache/store/spring/CacheSpringStoreSessionListener.java b/modules/spring/src/main/java/org/apache/ignite/cache/store/spring/CacheSpringStoreSessionListener.java deleted file mode 100644 index 77e0cd3..0000000 --- a/modules/spring/src/main/java/org/apache/ignite/cache/store/spring/CacheSpringStoreSessionListener.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.apache.ignite.cache.store.spring; - -import javax.cache.integration.CacheWriterException; -import javax.sql.DataSource; -import org.apache.ignite.IgniteException; -import org.apache.ignite.IgniteLogger; -import org.apache.ignite.cache.store.CacheStoreSession; -import org.apache.ignite.cache.store.CacheStoreSessionListener; -import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.lifecycle.LifecycleAware; -import org.apache.ignite.resources.LoggerResource; -import org.apache.ignite.transactions.Transaction; -import org.apache.ignite.transactions.TransactionIsolation; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.DefaultTransactionDefinition; - -/** - * Cache store session listener based on Spring transaction management. - * <p> - * This listener starts a new DB transaction for each session and commits - * or rolls it back when session ends. If there is no ongoing - * cache transaction, this listener is no-op. - * <p> - * Store implementation can use any Spring APIs like {@link JdbcTemplate} - * and others. The listener will guarantee that if there is an - * ongoing cache transaction, all store operations within this - * transaction will be automatically enlisted in the same database - * transaction. - * <p> - * {@link CacheSpringStoreSessionListener} requires that either - * {@link #setTransactionManager(PlatformTransactionManager) transaction manager} - * or {@link #setDataSource(DataSource) data source} is configured. If non of them is - * provided, exception is thrown. Is both are provided, data source will be - * ignored. - * <p> - * If there is a transaction, a {@link TransactionStatus} object will be saved - * as a store session {@link CacheStoreSession#attachment() attachment}. It - * can be used to acquire current DB transaction status. - */ -public class CacheSpringStoreSessionListener implements CacheStoreSessionListener, LifecycleAware { - /** Transaction manager. */ - private PlatformTransactionManager txMgr; - - /** Data source. */ - private DataSource dataSrc; - - /** Logger. */ - @LoggerResource - private IgniteLogger log; - - /** - * Sets transaction manager. - * <p> - * Either transaction manager or data source is required. - * If none is provided, exception will be thrown on startup. - * - * @param txMgr Transaction manager. - */ - public void setTransactionManager(PlatformTransactionManager txMgr) { - this.txMgr = txMgr; - } - - /** - * Gets transaction manager. - * - * @return Transaction manager. - */ - public PlatformTransactionManager getTransactionManager() { - return txMgr; - } - - /** - * Sets data source. - * <p> - * Either transaction manager or data source is required. - * If none is provided, exception will be thrown on startup. - * - * @param dataSrc Data source. - */ - public void setDataSource(DataSource dataSrc) { - this.dataSrc = dataSrc; - } - - /** - * Gets data source. - * - * @return Data source. - */ - public DataSource getDataSource() { - return dataSrc; - } - - /** {@inheritDoc} */ - @Override public void start() throws IgniteException { - if (txMgr == null && dataSrc == null) - throw new IgniteException("Either transaction manager or data source is required by " + - getClass().getSimpleName() + '.'); - - if (dataSrc != null) { - if (txMgr == null) - txMgr = new DataSourceTransactionManager(dataSrc); - else - U.warn(log, "Data source configured in " + getClass().getSimpleName() + - " will be ignored (transaction manager is already set)."); - } - - assert txMgr != null; - } - - /** {@inheritDoc} */ - @Override public void stop() throws IgniteException { - // No-op. - } - - /** {@inheritDoc} */ - @Override public void onSessionStart(CacheStoreSession ses) { - if (ses.isWithinTransaction() && ses.attachment() == null) { - try { - TransactionDefinition def = definition(ses.transaction(), ses.cacheName()); - - ses.attach(txMgr.getTransaction(def)); - } - catch (TransactionException e) { - throw new CacheWriterException("Failed to start store session [tx=" + ses.transaction() + ']', e); - } - } - } - - /** {@inheritDoc} */ - @Override public void onSessionEnd(CacheStoreSession ses, boolean commit) { - if (ses.isWithinTransaction()) { - TransactionStatus tx = ses.attach(null); - - if (tx != null) { - try { - if (commit) - txMgr.commit(tx); - else - txMgr.rollback(tx); - } - catch (TransactionException e) { - throw new CacheWriterException("Failed to end store session [tx=" + ses.transaction() + ']', e); - } - } - } - } - - /** - * Gets DB transaction isolation level based on ongoing cache transaction isolation. - * - * @return DB transaction isolation. - */ - private TransactionDefinition definition(Transaction tx, String cacheName) { - assert tx != null; - - DefaultTransactionDefinition def = new DefaultTransactionDefinition(); - - def.setName("Ignite Tx [cache=" + (cacheName != null ? cacheName : "<default>") + ", id=" + tx.xid() + ']'); - def.setIsolationLevel(isolationLevel(tx.isolation())); - - long timeoutSec = (tx.timeout() + 500) / 1000; - - if (timeoutSec > 0 && timeoutSec < Integer.MAX_VALUE) - def.setTimeout((int)timeoutSec); - - return def; - } - - /** - * Gets DB transaction isolation level based on ongoing cache transaction isolation. - * - * @param isolation Cache transaction isolation. - * @return DB transaction isolation. - */ - private int isolationLevel(TransactionIsolation isolation) { - switch (isolation) { - case READ_COMMITTED: - return TransactionDefinition.ISOLATION_READ_COMMITTED; - - case REPEATABLE_READ: - return TransactionDefinition.ISOLATION_REPEATABLE_READ; - - case SERIALIZABLE: - return TransactionDefinition.ISOLATION_SERIALIZABLE; - - default: - throw new IllegalStateException(); // Will never happen. - } - } -} diff --git a/modules/spring/src/main/java/org/apache/ignite/cache/store/spring/package-info.java b/modules/spring/src/main/java/org/apache/ignite/cache/store/spring/package-info.java deleted file mode 100644 index 408ba24..0000000 --- a/modules/spring/src/main/java/org/apache/ignite/cache/store/spring/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -/** - * Contains cache store session listener based on Spring transaction management. - */ - -package org.apache.ignite.cache.store.spring; diff --git a/modules/spring/src/test/java/org/apache/ignite/cache/store/spring/CacheSpringStoreSessionListenerSelfTest.java b/modules/spring/src/test/java/org/apache/ignite/cache/store/spring/CacheSpringStoreSessionListenerSelfTest.java deleted file mode 100644 index d3db02c..0000000 --- a/modules/spring/src/test/java/org/apache/ignite/cache/store/spring/CacheSpringStoreSessionListenerSelfTest.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.apache.ignite.cache.store.spring; - -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import javax.cache.Cache; -import javax.cache.configuration.Factory; -import javax.cache.integration.CacheLoaderException; -import javax.cache.integration.CacheWriterException; -import javax.sql.DataSource; -import org.apache.ignite.cache.store.CacheStore; -import org.apache.ignite.cache.store.CacheStoreAdapter; -import org.apache.ignite.cache.store.CacheStoreSession; -import org.apache.ignite.cache.store.CacheStoreSessionListener; -import org.apache.ignite.cache.store.CacheStoreSessionListenerAbstractSelfTest; -import org.apache.ignite.cache.store.jdbc.CacheJdbcStoreSessionListener; -import org.apache.ignite.internal.processors.query.h2.DistributedSqlConfiguration; -import org.apache.ignite.internal.processors.query.h2.FunctionsManager; -import org.apache.ignite.lang.IgniteBiInClosure; -import org.apache.ignite.resources.CacheStoreSessionResource; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.datasource.DataSourceUtils; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.transaction.TransactionStatus; - -/** - * Tests for {@link CacheJdbcStoreSessionListener}. - */ -public class CacheSpringStoreSessionListenerSelfTest extends CacheStoreSessionListenerAbstractSelfTest { - /** */ - private static final DataSource DATA_SRC = new DriverManagerDataSource(URL); - - /** */ - private static Method FunctionManager_removeFunctions; - - /** {@inheritDoc} */ - @Override protected void beforeTestsStarted() throws Exception { - super.beforeTestsStarted(); - - FunctionManager_removeFunctions = FunctionsManager.class.getDeclaredMethod("removeFunctions", Set.class); - - FunctionManager_removeFunctions.setAccessible(true); - - // Cleanup disabled functions because transaction manager uses LOCK_MODE() - FunctionManager_removeFunctions.invoke(FunctionsManager.class, Collections.emptySet()); - } - - /** {@inheritDoc} */ - @Override protected void afterTestsStopped() throws Exception { - FunctionManager_removeFunctions.invoke(FunctionsManager.class, DistributedSqlConfiguration.DFLT_DISABLED_FUNCS); - - super.afterTestsStopped(); - } - - /** {@inheritDoc} */ - @Override protected Factory<? extends CacheStore<Integer, Integer>> storeFactory() { - return new Factory<CacheStore<Integer, Integer>>() { - @Override public CacheStore<Integer, Integer> create() { - return new Store(new JdbcTemplate(DATA_SRC)); - } - }; - } - - /** {@inheritDoc} */ - @Override protected Factory<CacheStoreSessionListener> sessionListenerFactory() { - return new Factory<CacheStoreSessionListener>() { - @Override public CacheStoreSessionListener create() { - CacheSpringStoreSessionListener lsnr = new CacheSpringStoreSessionListener(); - - lsnr.setDataSource(DATA_SRC); - - return lsnr; - } - }; - } - - /** - */ - private static class Store extends CacheStoreAdapter<Integer, Integer> { - /** */ - private static String SES_CONN_KEY = "ses_conn"; - - /** */ - private final JdbcTemplate jdbc; - - /** */ - @CacheStoreSessionResource - private CacheStoreSession ses; - - /** - * @param jdbc JDBC template. - */ - private Store(JdbcTemplate jdbc) { - this.jdbc = jdbc; - } - - /** {@inheritDoc} */ - @Override public void loadCache(IgniteBiInClosure<Integer, Integer> clo, Object... args) { - loadCacheCnt.incrementAndGet(); - - checkTransaction(); - checkConnection(); - } - - /** {@inheritDoc} */ - @Override public Integer load(Integer key) throws CacheLoaderException { - loadCnt.incrementAndGet(); - - checkTransaction(); - checkConnection(); - - return null; - } - - /** {@inheritDoc} */ - @Override public void write(Cache.Entry<? extends Integer, ? extends Integer> entry) - throws CacheWriterException { - writeCnt.incrementAndGet(); - - checkTransaction(); - checkConnection(); - - if (write.get()) { - String table; - - switch (ses.cacheName()) { - case "cache1": - table = "Table1"; - - break; - - case "cache2": - if (fail.get()) - throw new CacheWriterException("Expected failure."); - - table = "Table2"; - - break; - - default: - throw new CacheWriterException("Wring cache: " + ses.cacheName()); - } - - jdbc.update("INSERT INTO " + table + " (key, value) VALUES (?, ?)", - entry.getKey(), entry.getValue()); - } - } - - /** {@inheritDoc} */ - @Override public void delete(Object key) throws CacheWriterException { - deleteCnt.incrementAndGet(); - - checkTransaction(); - checkConnection(); - } - - /** {@inheritDoc} */ - @Override public void sessionEnd(boolean commit) { - assertNull(ses.attachment()); - } - - /** - */ - private void checkTransaction() { - TransactionStatus tx = ses.attachment(); - - if (ses.isWithinTransaction()) { - assertNotNull(tx); - assertFalse(tx.isCompleted()); - } - else - assertNull(tx); - } - - /** - */ - private void checkConnection() { - Connection conn = DataSourceUtils.getConnection(jdbc.getDataSource()); - - assertNotNull(conn); - - try { - assertFalse(conn.isClosed()); - assertEquals(!ses.isWithinTransaction(), conn.getAutoCommit()); - } - catch (SQLException e) { - throw new RuntimeException(e); - } - - verifySameInstance(conn); - } - - /** - * @param conn Connection. - */ - private void verifySameInstance(Connection conn) { - Map<String, Connection> props = ses.properties(); - - Connection sesConn = props.get(SES_CONN_KEY); - - if (sesConn == null) - props.put(SES_CONN_KEY, conn); - else { - assertSame(conn, sesConn); - - reuseCnt.incrementAndGet(); - } - } - } -} diff --git a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java index a50d0d7..4389a5b 100644 --- a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java +++ b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java @@ -21,7 +21,6 @@ import org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactorySelfTest; import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactorySelfTest; import org.apache.ignite.cache.store.jdbc.CachePojoStoreXmlSelfTest; import org.apache.ignite.cache.store.jdbc.CachePojoStoreXmlWithSqlEscapeSelfTest; -import org.apache.ignite.cache.store.spring.CacheSpringStoreSessionListenerSelfTest; import org.apache.ignite.cdc.CdcConfigurationTest; import org.apache.ignite.cluster.ClusterStateXmlPropertiesTest; import org.apache.ignite.encryption.SpringEncryptedCacheRestartClientTest; @@ -63,8 +62,6 @@ import org.junit.runners.Suite; IgniteStartFromStreamConfigurationTest.class, - CacheSpringStoreSessionListenerSelfTest.class, - CacheJdbcBlobStoreFactorySelfTest.class, CacheJdbcPojoStoreFactorySelfTest.class, CachePojoStoreXmlSelfTest.class,