blob: e11c1c0dfb39defbc6ea4a9537155e2d8c5acc6e [file] [log] [blame]
/*
* 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.springdata;
import java.io.Serializable;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.client.IgniteClient;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.ClientConfiguration;
import org.apache.ignite.configuration.ClientConnectorConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.ignite.springdata22.repository.IgniteRepository;
import org.apache.ignite.springdata22.repository.config.EnableIgniteRepositories;
import org.apache.ignite.springdata22.repository.config.RepositoryConfig;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import static org.apache.ignite.testframework.GridTestUtils.assertThrowsAnyCause;
import static org.springframework.context.annotation.FilterType.ASSIGNABLE_TYPE;
/** Tests Spring Data repository cluster connection configurations. */
public class IgniteSpringDataConnectionConfigurationTest extends GridCommonAbstractTest {
/** */
private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
/** */
private static final String CACHE_NAME = "PersonCache";
/** */
private static final int CLI_CONN_PORT = 10810;
/** */
private static final String CLI_NAME = "cli-node";
/** */
private static final String SRV_NAME = "srv-node";
/** */
private static final String LOCAL_HOST = "127.0.0.1";
/** Tests repository configuration in case {@link IgniteConfiguration} is used to access the Ignite cluster. */
@Test
public void testRepositoryWithIgniteConfiguration() {
checkRepositoryConfiguration(IgniteConfigurationApplication.class, IgniteConfigRepository.class);
assertClientNodeIsStopped();
}
/** Tests repository configuration in case {@link ClientConfiguration} is used to access the Ignite cluster. */
@Test
public void testRepositoryWithClientConfiguration() {
checkRepositoryConfiguration(ClientConfigurationApplication.class, IgniteClientConfigRepository.class);
}
/** Tests repository configuration in case {@link Ignite} with non default is used to access the Ignite cluster. */
@Test
public void testRepositoryWithoutIgniteInstanceParameter() {
checkRepositoryConfiguration(DefaultIgniteBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
}
/** Tests repository configuration in case {@link IgniteClient} with non default name is used to access the Ignite cluster. */
@Test
public void testRepositoryWithoutIgniteClientInstanceParameter() {
checkRepositoryConfiguration(DefaultIgniteClientBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
}
/** Tests repository configuration in case {@link ClientConfiguration} with non default name is used to access the Ignite cluster. */
@Test
public void testRepositoryWithoutIgnitClientConfigurationParameter() {
checkRepositoryConfiguration(DefaultIgniteClientConfigurationBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
}
/** Tests repository configuration in case {@link IgniteConfiguration} with non default name is used to access the Ignite cluster. */
@Test
public void testRepositoryWithoutIgniteConfigurationParameter() {
checkRepositoryConfiguration(DefaultIgniteConfigurationBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
}
/**
* Tests repository configuration in case {@link IgniteConfiguration} that refers to existing Ignite node instance
* used to access the Ignite cluster.
*/
@Test
public void testRepositoryWithExistingIgniteInstance() throws Exception {
try (Ignite ignored = startGrid(getIgniteConfiguration(CLI_NAME, true))) {
checkRepositoryConfiguration(IgniteConfigurationApplication.class, IgniteConfigRepository.class);
assertNotNull(Ignition.ignite(CLI_NAME));
}
}
/** Tests repository configuration in case specified cache name is invalid. */
@Test
public void testRepositoryWithInvalidCacheNameConfiguration() {
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext()) {
ctx.register(InvalidCacheNameApplication.class);
assertThrowsAnyCause(log,
() -> {
ctx.refresh();
return null;
},
IllegalArgumentException.class,
"Cache 'invalidCache' not found for repository interface" +
" org.apache.ignite.springdata.IgniteSpringDataConnectionConfigurationTest$InvalidCacheNameRepository." +
" Please, add a cache configuration to ignite configuration or pass autoCreateCache=true to" +
" org.apache.ignite.springdata22.repository.config.RepositoryConfig annotation.");
}
assertClientNodeIsStopped();
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
super.afterTest();
grid(SRV_NAME).cache(CACHE_NAME).clear();
}
/** */
private void assertClientNodeIsStopped() {
assertFalse(Ignition.allGrids().stream().map(Ignite::name).anyMatch(CLI_NAME::equals));
}
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
super.beforeTestsStarted();
startGrid(getIgniteConfiguration(SRV_NAME, false));
}
/**
* Checks that repository created based on specified Spring application configuration is properly initialized and
* got access to the Ignite cluster.
*/
private void checkRepositoryConfiguration(
Class<?> cfgCls,
Class<? extends IgniteRepository<Object, Serializable>> repoCls
) {
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext()) {
ctx.register(cfgCls);
ctx.refresh();
IgniteRepository<Object, Serializable> repo = ctx.getBean(repoCls);
IgniteCache<Object, Serializable> cache = grid(SRV_NAME).cache(CACHE_NAME);
assertEquals(0, repo.count());
assertEquals(0, cache.size());
int key = 0;
repo.save(key, "1");
assertEquals(1, repo.count());
assertNotNull(cache.get(key));
}
}
/**
* Spring Application configuration for repository testing in case {@link IgniteConfiguration} is used
* for accessing the cluster.
*/
@Configuration
@EnableIgniteRepositories(
considerNestedRepositories = true,
includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = InvalidCacheNameRepository.class))
public static class InvalidCacheNameApplication {
/** Ignite configuration bean. */
@Bean
public IgniteConfiguration igniteConfiguration() {
return getIgniteConfiguration(CLI_NAME, true);
}
}
/**
* Spring Application configuration for repository testing in case {@link IgniteConfiguration} is used
* for accessing the cluster.
*/
@Configuration
@EnableIgniteRepositories(
considerNestedRepositories = true,
includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteConfigRepository.class))
public static class IgniteConfigurationApplication {
/** Ignite configuration bean. */
@Bean
public IgniteConfiguration igniteConfiguration() {
return getIgniteConfiguration(CLI_NAME, true);
}
}
/**
* Spring Application configuration for repository testing in case {@link ClientConfiguration} is used
* for accessing the cluster.
*/
@Configuration
@EnableIgniteRepositories(
considerNestedRepositories = true,
includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteClientConfigRepository.class))
public static class ClientConfigurationApplication {
/** Ignite client configuration bean. */
@Bean
public ClientConfiguration clientConfiguration() {
return new ClientConfiguration().setAddresses(LOCAL_HOST + ':' + CLI_CONN_PORT);
}
}
/**
* Spring Application configuration for repository testing in case if Ignite bean name was not provided
* through {@link RepositoryConfig#igniteInstance()} ()}.
*/
@Configuration
@EnableIgniteRepositories(
considerNestedRepositories = true,
includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
)
public static class DefaultIgniteBeanApplication {
/** Ignite bean. */
@Bean
public Ignite someIgnite() {
return Ignition.start(getIgniteConfiguration("test", false));
}
}
/**
* Spring Application configuration for repository testing in case if IgniteClient bean name was not provided
* through {@link RepositoryConfig#igniteInstance()} ()}.
*/
@Configuration
@EnableIgniteRepositories(
considerNestedRepositories = true,
includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
)
public static class DefaultIgniteClientBeanApplication {
/** Ignite client bean. */
@Bean
public IgniteClient someIgnite() {
return Ignition.startClient(new ClientConfiguration().setAddresses(LOCAL_HOST + ':' + CLI_CONN_PORT));
}
}
/**
* Spring Application configuration for repository testing in case if ClientConfiguration bean name was not provided
* through {@link RepositoryConfig#igniteCfg()}.
*/
@Configuration
@EnableIgniteRepositories(
considerNestedRepositories = true,
includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
)
public static class DefaultIgniteClientConfigurationBeanApplication {
/** Ignite client configuration bean. */
@Bean
public ClientConfiguration someCfg() {
return new ClientConfiguration().setAddresses(LOCAL_HOST + ':' + CLI_CONN_PORT);
}
}
/**
* Spring Application configuration for repository testing in case if IgniteConfiguration bean name was not provided
* through {@link RepositoryConfig#igniteCfg()}.
*/
@Configuration
@EnableIgniteRepositories(
considerNestedRepositories = true,
includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
)
public static class DefaultIgniteConfigurationBeanApplication {
/** Ignite client configuration bean. */
@Bean
public IgniteConfiguration someCfg() {
return getIgniteConfiguration("test", false);
}
}
/** Repository for testing configuration approach through default ignite beans. */
@RepositoryConfig(cacheName = "PersonCache")
public interface IgniteRepositoryWithoutExplicitIgnite extends IgniteRepository<Object, Serializable> {
// No-op.
}
/** Repository for testing configuration approach through {@link IgniteConfiguration}. */
@RepositoryConfig(cacheName = "PersonCache", igniteCfg = "igniteConfiguration")
public interface IgniteConfigRepository extends IgniteRepository<Object, Serializable> {
// No-op.
}
/** Repository for testing repository configuration approach through {@link ClientConfiguration}. */
@RepositoryConfig(cacheName = "PersonCache", igniteCfg = "clientConfiguration")
public interface IgniteClientConfigRepository extends IgniteRepository<Object, Serializable> {
// No-op.
}
/** Repository for testing application behavior in case invalid cache is specified in the repository configuration. */
@RepositoryConfig(cacheName = "invalidCache", igniteCfg = "igniteConfiguration")
public interface InvalidCacheNameRepository extends IgniteRepository<Object, Serializable> {
// No-op.
}
/** */
private static IgniteConfiguration getIgniteConfiguration(String name, boolean clientMode) {
return new IgniteConfiguration()
.setIgniteInstanceName(name)
.setClientMode(clientMode)
.setLocalHost(LOCAL_HOST)
.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(IP_FINDER))
.setClientConnectorConfiguration(new ClientConnectorConfiguration().setPort(CLI_CONN_PORT))
.setCacheConfiguration(new CacheConfiguration<>(CACHE_NAME));
}
}