You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dm...@apache.org on 2020/09/24 23:03:38 UTC

[ignite] branch IGNITE-7595 updated: ported the Spring-related docs

This is an automated email from the ASF dual-hosted git repository.

dmagda pushed a commit to branch IGNITE-7595
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/IGNITE-7595 by this push:
     new 7f82c5d  ported the Spring-related docs
7f82c5d is described below

commit 7f82c5dab5abd7db0323163d13d023d60305cbdc
Author: Denis Magda <dm...@gridgain.com>
AuthorDate: Thu Sep 24 16:03:19 2020 -0700

    ported the Spring-related docs
---
 docs/_data/toc.yaml                                |   8 +
 .../spring/spring-boot.adoc                        | 196 ++++++++++++++++++
 .../spring/spring-caching.adoc                     | 218 +++++++++++++++++++++
 .../spring/spring-data.adoc                        | 214 ++++++++++++++++++++
 4 files changed, 636 insertions(+)

diff --git a/docs/_data/toc.yaml b/docs/_data/toc.yaml
index 9489c96..1d32928 100644
--- a/docs/_data/toc.yaml
+++ b/docs/_data/toc.yaml
@@ -373,6 +373,14 @@
   url: sqlline
 - title: Extensions and Integrations
   items:
+    - title: Spring
+      items:
+        - title: Spring Boot
+          url: extensions-and-integrations/spring/spring-boot
+        - title: Spring Data
+          url: extensions-and-integrations/spring/spring-data
+        - title: Spring Caching
+          url: extensions-and-integrations/spring/spring-caching
     - title: Ignite for Spark
       items:
         - title: Overview
diff --git a/docs/_docs/extensions-and-integrations/spring/spring-boot.adoc b/docs/_docs/extensions-and-integrations/spring/spring-boot.adoc
new file mode 100644
index 0000000..ee7207f
--- /dev/null
+++ b/docs/_docs/extensions-and-integrations/spring/spring-boot.adoc
@@ -0,0 +1,196 @@
+= Apache Ignite With Spring Boot
+
+== Overview
+
+https://spring.io/projects/spring-boot[Spring Boot, window="_blank"] is a widely used Java framework that makes it easy
+to create stand-alone Spring-based applications.
+
+Apache Ignite provides two extensions that automate Ignite configuration withing the Spring Boot environment:
+
+* `ignite-spring-boot-autoconfigure-ext` - autoconfigures ignite server and client nodes within Spring Boot.
+* `ignite-spring-boot-thin-client-autoconfigure-ext` - autoconfigures link:thin-clients/java-thin-client[Ignite Thin Client] with Spring Boot.
+
+== Autoconfiguration of Apache Ignite Servers and Clients
+
+You need to use `ignite-spring-boot-autoconfigure-ext` extension to autoconfigure Ignite servers or clients (aka. thick clients) with Spring Boot.
+
+The extension can be added with Maven as follows:
+
+[tabs]
+--
+tab:pom.xml[]
+[source,xml]
+----
+<dependency>
+  <groupId>org.apache.ignite</groupId>
+  <artifactId>ignite-spring-boot-autoconfigure-ext</artifactId>
+   <version>1.0.0</version>
+</dependency>
+----
+--
+
+Once added, Spring will create an Ignite instance on start-up automatically.
+
+=== Set Ignite Up Via Spring Boot Configuration
+
+You can use a regular Spring Boot configuration to set Ignite-specific settings. Use `ignite` as a prefix:
+
+[tabs]
+--
+tab:application.yml[]
+[source,yaml]
+----
+ignite:
+  igniteInstanceName: properties-instance-name
+  communicationSpi:
+    localPort: 5555
+  dataStorageConfiguration:
+    defaultDataRegionConfiguration:
+      initialSize: 10485760 #10MB
+    dataRegionConfigurations:
+      - name: my-dataregion
+        initialSize: 104857600 #100MB
+  cacheConfiguration:
+    - name: accounts
+      queryEntities:
+      - tableName: ACCOUNTS
+        keyFieldName: ID
+        keyType: java.lang.Long
+        valueType: java.lang.Object
+        fields:
+          ID: java.lang.Long
+          amount: java.lang.Double
+          updateDate: java.util.Date
+    - name: my-cache2
+----
+--
+
+=== Set Ignite Up Programmatically
+
+There are two ways to configure Ignite programmatically.
+
+**1. Create IgniteConfiguration Bean**
+
+Just create a method that returns `IgniteConfiguration` bean that will be used to initialize an Ignite node with the settings you set:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+@Bean
+  public IgniteConfiguration igniteConfiguration() {
+     // If you provide a whole ClientConfiguration bean then configuration properties will not be used.
+    IgniteConfiguration cfg = new IgniteConfiguration();
+    cfg.setIgniteInstanceName("my-ignite");
+    return cfg;
+  }
+----
+--
+
+**2. Customize IgniteConfiguration Created With Spring Boot Configuration**
+
+If you want to customize `IgniteConfiguration` that was initially created with Spring Boot configuration file, then
+provide an implementation of `IgniteConfigurer` interface for your application context.
+
+First, `IgniteConfiguration` will be loaded from the Spring Boot configuration and then that instance will be passed to the configurer for extra settings.
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+@Bean
+  public IgniteConfigurer nodeConfigurer() {
+    return cfg -> {
+      //Setting some property.
+      //Other will come from `application.yml`
+      cfg.setIgniteInstanceName("my-ignite");
+    };
+  }
+----
+--
+
+== Autoconfiguration of Apache Ignite Thin Client
+
+You need to use `ignite-spring-boot-thin-client-autoconfigure-ext` extension to autoconfigure Ignite Thin Client with Spring Boot.
+
+[tabs]
+--
+tab:pom.xml[]
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.ignite</groupId>
+  <artifactId>ignite-spring-boot-thin-client-autoconfigure-ext</artifactId>
+  <version>1.0.0</version>
+</dependency>
+----
+--
+
+Once added, Spring will create an instance of Ignite Thin client connection on start-up automatically.
+
+=== Set Thin Client Up Via Spring Boot Configuration
+
+You can use a regular Spring Boot configuration to configure `IgniteClient` object. Use `ignite-client` for Ignite-specific settings:
+
+[tabs]
+--
+tab:application.yml[]
+[source,yaml]
+----
+ignite-client:
+  addresses: 127.0.0.1:10800 # this is mandatory property!
+  timeout: 10000
+  tcpNoDelay: false
+----
+--
+
+=== Set Thin Client Up Programmatically
+
+You can use two ways to configure `IgniteClient` object programmatically.
+
+**1. Create ClientConfiguration bean**
+
+Just create a method that returns `ClientConfiguration` bean. `IgniteClient` object will use that bean upon startup:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+@Bean
+  public ClientConfiguration clientConfiguration() {
+    // If you provide a whole ClientConfiguration bean then configuration properties will not be used.
+    ClientConfiguration cfg = new ClientConfiguration();
+    cfg.setAddresses("127.0.0.1:10800");
+    return cfg;
+  }
+----
+--
+
+**2. Customize ClientConfiguration Created With Spring Boot Configuration**
+
+If you want to customize `ClientConfiguration` bean created from the Spring Boot configuration file, then provide an
+implementation of `IgniteClientConfigurer` interface in your application context.
+
+First, `ClientConfiguration` will be loaded from the Spring Boot configuration and then an instance will be passed to the configurer.
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+@Bean
+    IgniteClientConfigurer configurer() {
+        //Setting some property.
+        //Other will come from `application.yml`
+        return cfg -> cfg.setSendBufferSize(64*1024);
+    }
+----
+--
+
+== Examples
+
+Refer to several available https://github.com/apache/ignite-extensions/tree/master/modules/spring-boot-autoconfigure-ext/examples/main[examples, windows="_blank"]
+for more details.
diff --git a/docs/_docs/extensions-and-integrations/spring/spring-caching.adoc b/docs/_docs/extensions-and-integrations/spring/spring-caching.adoc
new file mode 100644
index 0000000..292aa16
--- /dev/null
+++ b/docs/_docs/extensions-and-integrations/spring/spring-caching.adoc
@@ -0,0 +1,218 @@
+= Using Spring Cache With Apache Ignite
+
+== Overview
+
+Ignite is shipped with `SpringCacheManager` - an implementation of http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html[Spring Cache Abstraction, window=_blank].
+It provides an annotation-based way to enable caching for Java methods so that the result of a method execution is stored
+in an Ignite cache. Later, if the same method is called with the same set of parameter values, the result will be retrieved
+from the cache instead of actually executing the method.
+
+== Enabling Ignite for Spring Caching
+
+Only two simple steps are required to plug in an Ignite cache into your Spring-based application:
+
+* Start an Ignite node with proper configuration in embedded mode (i.e., in the same JVM where the application is running). It can already have predefined caches, but it's not required - caches will be created automatically on first access if needed.
+* Configure `SpringCacheManager` as the cache manager in the Spring application context.
+
+The embedded node can be started by `SpringCacheManager` itself. In this case you will need to provide a path to either
+the Ignite configuration XML file or `IgniteConfiguration` bean via `configurationPath` or `configuration`
+properties respectively (see examples below). Note that setting both is illegal and results in `IllegalArgumentException`.
+
+[tabs]
+--
+tab:configuration path[]
+[source,xml]
+----
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:cache="http://www.springframework.org/schema/cache"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://www.springframework.org/schema/cache
+         http://www.springframework.org/schema/cache/spring-cache.xsd">
+    <!-- Provide configuration file path. -->
+    <bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
+        <property name="configurationPath" value="examples/config/spring-cache.xml"/>
+    </bean>
+
+    <!-- Enable annotation-driven caching. -->
+    <cache:annotation-driven/>
+</beans>
+----
+tab:configuration bean[]
+[source,xml]
+----
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:cache="http://www.springframework.org/schema/cache"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://www.springframework.org/schema/cache
+         http://www.springframework.org/schema/cache/spring-cache.xsd">
+    <-- Provide configuration bean. -->
+    <bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
+        <property name="configuration">
+            <bean class="org.apache.ignite.configuration.IgniteConfiguration">
+                 ...
+            </bean>
+        </property>
+    </bean>
+
+    <-- Enable annotation-driven caching. -->
+    <cache:annotation-driven/>
+</beans>
+----
+
+--
+
+It's possible that you already have an Ignite node running when the cache manager is initialized (e.g., it was started using
+`ServletContextListenerStartup`). In this case you should simply provide the grid name via `gridName` property.
+Note that if you don't set the grid name as well, the cache manager will try to use the default Ignite instance
+(the one with the `null` name). Here is an example:
+
+[tabs]
+--
+tab:Using an already started Ignite instance[]
+[source,xml]
+----
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:cache="http://www.springframework.org/schema/cache"
+       xsi:schemaLocation="
+         http://www.springframework.org/schema/beans
+         http://www.springframework.org/schema/beans/spring-beans.xsd
+         http://www.springframework.org/schema/cache
+         http://www.springframework.org/schema/cache/spring-cache.xsd">
+    <!-- Provide grid name. -->
+    <bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
+        <property name="gridName" value="myGrid"/>
+    </bean>
+
+    <!-- Enable annotation-driven caching. -->
+    <cache:annotation-driven/>
+</beans>
+----
+--
+
+[NOTE]
+====
+[discrete]
+Keep in mind that the node started inside your application is an entry point to the whole topology it connects to.
+You can start as many remote standalone nodes as you need and all these nodes will participate in caching the data.
+====
+
+== Dynamic Caches
+
+While you can have all required caches predefined in Ignite configuration, it's not required. If Spring wants to use a
+cache that doesn't exist, the `SpringCacheManager` will automatically create it.
+
+If otherwise not specified, a new cache will be created will all defaults. To customize it, you can provide a configuration
+template via `dynamicCacheConfiguration` property. For example, if you want to use `REPLICATED` caches instead of
+`PARTITIONED`, you should configure `SpringCacheManager` like this:
+
+[tabs]
+--
+tab:Dynamic cache configuration[]
+[source,xml]
+----
+<bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
+    ...
+
+    <property name="dynamicCacheConfiguration">
+        <bean class="org.apache.ignite.configuration.CacheConfiguration">
+            <property name="cacheMode" value="REPLICATED"/>
+        </bean>
+    </property>
+</bean>
+----
+--
+
+You can also utilize near caches on client side. To achieve this, simply provide near cache configuration via the
+`dynamicNearCacheConfiguration` property. By default, near cache is not created. Here is an example:
+
+[tabs]
+--
+tab:Dynamic near cache configuration[]
+[source,xml]
+----
+<bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
+    ...
+
+    <property name="dynamicNearCacheConfiguration">
+        <bean class="org.apache.ignite.configuration.NearCacheConfiguration">
+            <property name="nearStartSize" value="1000"/>
+        </bean>
+    </property>
+</bean>
+----
+--
+
+== Example
+
+Once you have added `SpringCacheManager` to your Spring application context, you can enable caching for any Java method by simply attaching an annotation to it.
+
+Usually, you would use caching for heavy operations, like database access. For example, let's assume you have a DAO class with
+`averageSalary(...)` method that calculates the average salary of all employees in an organization. You can use `@Cacheable`
+annotation to enable caching for this method:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+private JdbcTemplate jdbc;
+
+@Cacheable("averageSalary")
+public long averageSalary(int organizationId) {
+    String sql =
+        "SELECT AVG(e.salary) " +
+        "FROM Employee e " +
+        "WHERE e.organizationId = ?";
+
+    return jdbc.queryForObject(sql, Long.class, organizationId);
+}
+----
+--
+
+When this method is called for the first time, `SpringCacheManager` will automatically create a `averageSalary` cache.
+It will also lookup the pre-calculated average value in this cache and return it right away if it's there. If the average
+for this organization is not calculated yet, the method will be called and the result will be stored in cache. So next
+time you request the average salary for this organization, you will not need to query the database.
+
+If the salary of one of the employees is changed, you may want to remove the average value for the organization this
+employee belongs to, because otherwise the `averageSalary(...)` method will return obsolete cached result. This can be
+achieved by attaching `@CacheEvict` annotation to a method that updates employee's salary:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+private JdbcTemplate jdbc;
+
+@CacheEvict(value = "averageSalary", key = "#e.organizationId")
+public void updateSalary(Employee e) {
+    String sql =
+        "UPDATE Employee " +
+        "SET salary = ? " +
+        "WHERE id = ?";
+
+    jdbc.update(sql, e.getSalary(), e.getId());
+}
+----
+--
+
+After this method is called, average value for the provided employee's organization will be evicted from the `averageSalary` cache.
+This will force `averageSalary(...)` to recalculate the value next time it's called.
+
+[NOTE]
+====
+[discrete]
+Note that this method receives employee as a parameter, while average values are saved in cache by `organizationID`.
+To explicitly specify what is used as a cache key, we used key parameter of the annotation and Spring Expression Language.
+
+The `#e.organizationId` expression means that we need to extract the value of `organizationId` property from `e` variable.
+Essentially, `getOrganizationId()` method will be called on provided employee object and the returned value will be used as the cache key.
+====
diff --git a/docs/_docs/extensions-and-integrations/spring/spring-data.adoc b/docs/_docs/extensions-and-integrations/spring/spring-data.adoc
new file mode 100644
index 0000000..3b1a106
--- /dev/null
+++ b/docs/_docs/extensions-and-integrations/spring/spring-data.adoc
@@ -0,0 +1,214 @@
+= Apache Ignite With Spring Data
+
+== Overview
+
+Spring Data Framework provides a unified and widely used API that allows abstracting an underlying data storage from the
+application layer. Spring Data helps you avoid locking to a specific database vendor, making it easy to switch from one
+database to another with minimal efforts. Apache Ignite integrates with Spring Data by implementing Spring Data `CrudRepository` interface.
+
+== Maven Configuration
+
+The easiest way to start working with Apache Ignite's Spring Data repository is by adding the following Maven dependency
+to an application's `pom.xml` file:
+
+[tabs]
+--
+tab:pom.xml[]
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.ignite</groupId>
+    <artifactId>ignite-spring-data</artifactId>
+    <version>{ignite.version}</version>
+</dependency>
+----
+--
+
+== Apache Ignite Repository
+
+Apache Ignite introduces a special `IgniteRepository` interface that extends default `CrudRepository`. This interface
+should be extended by all custom Spring Data repositories that wish to store and query data located in an Apache Ignite cluster.
+
+For instance, let's create the first custom repository named `PersonRepository`:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+@RepositoryConfig(cacheName = "PersonCache")
+public interface PersonRepository extends IgniteRepository<Person, Long> {
+    /**
+     * Gets all the persons with the given name.
+     * @param name Person name.
+     * @return A list of Persons with the given first name.
+     */
+    public List<Person> findByFirstName(String name);
+
+    /**
+     * Returns top Person with the specified surname.
+     * @param name Person surname.
+     * @return Person that satisfy the query.
+     */
+    public Cache.Entry<Long, Person> findTopByLastNameLike(String name);
+
+    /**
+     * Getting ids of all the Person satisfying the custom query from {@link Query} annotation.
+     *
+     * @param orgId Query parameter.
+     * @param pageable Pageable interface.
+     * @return A list of Persons' ids.
+     */
+    @Query("SELECT id FROM Person WHERE orgId > ?")
+    public List<Long> selectId(long orgId, Pageable pageable);
+}
+----
+--
+
+* `@RepositoryConfig` annotation should be specified to map a repository to a distributed cache. In the above example, `PersonRepository` is mapped to `PersonCache`.
+* Signatures of custom methods like `findByFirstName(name)` and `findTopByLastNameLike(name)` will be automatically processed and turned
+into SQL queries when methods get executed. In addition, `@Query(queryString)` annotation can be used if a concrete​ SQL
+query needs to be executed as a result of a method call.
+
+
+[CAUTION]
+====
+[discrete]
+=== Unsupported CRUD Operations
+
+Some operations of CrudRepository interface are not currently supported. These are the operations that do not require providing the key as a parameter:
+
+* save(S entity)
+* save(Iterable<S> entities)
+* delete(T entity)
+* delete(Iterable<? extends T> entities)
+
+Instead of these operations you can use Ignite specific counterparts available via `IgniteRepository` interface:
+
+* save(ID key, S entity)
+* save(Map<ID, S> entities)
+* deleteAll(Iterable<ID> ids)
+
+====
+
+== Spring Data and Apache Ignite Configuration
+
+
+To enable Apache Ignite backed repositories in Spring Data, mark an application configuration with `@EnableIgniteRepositories`
+annotation, as shown below:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+@Configuration
+@EnableIgniteRepositories
+public class SpringAppCfg {
+    /**
+     * Creating Apache Ignite instance bean. A bean will be passed
+     * to IgniteRepositoryFactoryBean to initialize all Ignite based Spring Data repositories and connect to a cluster.
+     */
+    @Bean
+    public Ignite igniteInstance() {
+        IgniteConfiguration cfg = new IgniteConfiguration();
+
+        // Setting some custom name for the node.
+        cfg.setIgniteInstanceName("springDataNode");
+
+        // Enabling peer-class loading feature.
+        cfg.setPeerClassLoadingEnabled(true);
+
+        // Defining and creating a new cache to be used by Ignite Spring Data
+        // repository.
+        CacheConfiguration ccfg = new CacheConfiguration("PersonCache");
+
+        // Setting SQL schema for the cache.
+        ccfg.setIndexedTypes(Long.class, Person.class);
+
+        cfg.setCacheConfiguration(ccfg);
+
+        return Ignition.start(cfg);
+    }
+}
+----
+--
+
+The configuration has to instantiate Apache Ignite bean (node) that will be passed to `IgniteRepositoryFactoryBean`
+and will be used by all the Apache Ignite repositories in order to connect to the cluster.
+
+In the example above, the bean is initialized directly by the application and is named `igniteInstance`.
+Alternatively, the following beans can be registered in your configuration and an Apache Ignite node will be started automatically:
+
+* `IgniteConfiguration` object named as `igniteCfg` bean.
+* A path to Apache Ignite's Spring XML configuration named `igniteSpringCfgPath`.
+
+== Using Apache Ignite Repositories
+
+Once all the configurations and repositories are ready to be used, you can register the configuration in an application context and get a reference to the repository.
+The following example shows how to register `SpringAppCfg` - our sample configuration from the section above - in an application context and get a reference to `PersonRepository`:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+ctx = new AnnotationConfigApplicationContext();
+
+// Explicitly registering Spring configuration.
+ctx.register(SpringAppCfg.class);
+
+ctx.refresh();
+
+// Getting a reference to PersonRepository.
+repo = ctx.getBean(PersonRepository.class);
+----
+--
+
+Now, you can put data in Ignite using Spring Data API:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+TreeMap<Long, Person> persons = new TreeMap<>();
+
+persons.put(1L, new Person(1L, 2000L, "John", "Smith", 15000, "Worked for Apple"));
+
+persons.put(2L, new Person(2L, 2000L, "Brad", "Pitt", 16000, "Worked for Oracle"));
+
+persons.put(3L, new Person(3L, 1000L, "Mark", "Tomson", 10000, "Worked for Sun"));
+
+// Adding data into the repository.
+repo.save(persons);
+----
+--
+
+To query the data, we can use basic CRUD operations or methods that will be automatically turned into Apache Ignite SQL queries:
+
+[tabs]
+--
+tab:Java[]
+[source,java]
+----
+List<Person> persons = repo.findByFirstName("John");
+
+for (Person person: persons)
+    System.out.println("   >>>   " + person);
+
+Cache.Entry<Long, Person> topPerson = repo.findTopByLastNameLike("Smith");
+
+System.out.println("\n>>> Top Person with surname 'Smith': " +
+        topPerson.getValue());
+----
+--
+
+== Example
+
+The complete example is available on link:{githubUrl}/examples/src/main/java/org/apache/ignite/examples/springdata[GitHub, window=_blank].
+
+== Tutorial
+
+Follow the tutorial that shows how to build a https://www.gridgain.com/docs/tutorials/spring/spring-ignite-tutorial[RESTful web service with Apache Ignite and Spring Data, window=_blank].
+