DATAREDIS-336 - Removed old docbook reference documentation.

Original pull request: #94.
This commit is contained in:
Oliver Gierke
2014-09-03 13:32:24 +02:00
parent fdfd7fe6e7
commit 81a14b6c02
15 changed files with 0 additions and 1333 deletions

View File

@@ -1,180 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<appendix xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="appendix-command-reference" xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Spring Data Redis Supported Commands</title>
<table>
<title>Redis commands supported by <classname>RedisTemplate</classname>.</title>
<tgroup cols="2">
<colspec colwidth="2*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Command</entry>
<entry>Template Support</entry>
</row>
</thead>
<tbody>
<row><entry><code>APPEND</code></entry><entry>X</entry></row>
<row><entry><code>AUTH</code></entry><entry>X</entry></row>
<row><entry><code>BGREWRITEAOF</code></entry><entry>X</entry></row>
<row><entry><code>BGSAVE</code></entry><entry>X</entry></row>
<row><entry><code>BITCOUNT</code></entry><entry>X</entry></row>
<row><entry><code>BITOP</code></entry><entry>X</entry></row>
<row><entry><code>BLPOP</code></entry><entry>X</entry></row>
<row><entry><code>BRPOP</code></entry><entry>X</entry></row>
<row><entry><code>BRPOPLPUSH</code></entry><entry>X</entry></row>
<row><entry><code>CLIENT KILL</code></entry><entry>X</entry></row>
<row><entry><code>CLIENT GETNAME</code></entry><entry>X</entry></row>
<row><entry><code>CLIENT LIST</code></entry><entry>X</entry></row>
<row><entry><code>CLIENT SETNAME</code></entry><entry>X</entry></row>
<row><entry><code>CONFIG GET</code></entry><entry>X</entry></row>
<row><entry><code>CONFIG RESETSTAT</code></entry><entry>X</entry></row>
<row><entry><code>CONFIG REWRITE</code></entry><entry>-</entry></row>
<row><entry><code>CONFIG SET</code></entry><entry>X</entry></row>
<row><entry><code>DBSIZE</code></entry><entry>X</entry></row>
<row><entry><code>DEBUG OBJECT</code></entry><entry>-</entry></row>
<row><entry><code>DEBUG SEGFAULT</code></entry><entry>-</entry></row>
<row><entry><code>DECR</code></entry><entry>X</entry></row>
<row><entry><code>DECRBY</code></entry><entry>X</entry></row>
<row><entry><code>DEL</code></entry><entry>X</entry></row>
<row><entry><code>DISCARD</code></entry><entry>X</entry></row>
<row><entry><code>DUMP</code></entry><entry>X</entry></row>
<row><entry><code>ECHO</code></entry><entry>X</entry></row>
<row><entry><code>EVAL</code></entry><entry>X</entry></row>
<row><entry><code>EVALSHA</code></entry><entry>X</entry></row>
<row><entry><code>EXEC</code></entry><entry>X</entry></row>
<row><entry><code>EXISTS</code></entry><entry>X</entry></row>
<row><entry><code>EXPIRE</code></entry><entry>X</entry></row>
<row><entry><code>EXPIREAT</code></entry><entry>X</entry></row>
<row><entry><code>FLUSHALL</code></entry><entry>X</entry></row>
<row><entry><code>FLUSHDB</code></entry><entry>X</entry></row>
<row><entry><code>GET</code></entry><entry>X</entry></row>
<row><entry><code>GETBIT</code></entry><entry>X</entry></row>
<row><entry><code>GETRANGE</code></entry><entry>X</entry></row>
<row><entry><code>GETSET</code></entry><entry>X</entry></row>
<row><entry><code>HDEL</code></entry><entry>X</entry></row>
<row><entry><code>HEXISTS</code></entry><entry>X</entry></row>
<row><entry><code>HGET</code></entry><entry>X</entry></row>
<row><entry><code>HGETALL</code></entry><entry>X</entry></row>
<row><entry><code>HINCRBY</code></entry><entry>X</entry></row>
<row><entry><code>HINCRBYFLOAT</code></entry><entry>X</entry></row>
<row><entry><code>HKEYS</code></entry><entry>X</entry></row>
<row><entry><code>HLEN</code></entry><entry>X</entry></row>
<row><entry><code>HMGET</code></entry><entry>X</entry></row>
<row><entry><code>HMSET</code></entry><entry>X</entry></row>
<row><entry><code>HSCAN</code></entry><entry>X</entry></row>
<row><entry><code>HSET</code></entry><entry>X</entry></row>
<row><entry><code>HSETNX</code></entry><entry>X</entry></row>
<row><entry><code>HVALS</code></entry><entry>X</entry></row>
<row><entry><code>INCR</code></entry><entry>X</entry></row>
<row><entry><code>INCRBY</code></entry><entry>X</entry></row>
<row><entry><code>INCRBYFLOAT</code></entry><entry>X</entry></row>
<row><entry><code>INFO</code></entry><entry>X</entry></row>
<row><entry><code>KEYS</code></entry><entry>X</entry></row>
<row><entry><code>LASTSAVE</code></entry><entry>X</entry></row>
<row><entry><code>LINDEX</code></entry><entry>X</entry></row>
<row><entry><code>LINSERT</code></entry><entry>X</entry></row>
<row><entry><code>LLEN</code></entry><entry>X</entry></row>
<row><entry><code>LPOP</code></entry><entry>X</entry></row>
<row><entry><code>LPUSH</code></entry><entry>X</entry></row>
<row><entry><code>LPUSHX</code></entry><entry>X</entry></row>
<row><entry><code>LRANGE</code></entry><entry>X</entry></row>
<row><entry><code>LREM</code></entry><entry>X</entry></row>
<row><entry><code>LSET</code></entry><entry>X</entry></row>
<row><entry><code>LTRIM</code></entry><entry>X</entry></row>
<row><entry><code>MGET</code></entry><entry>X</entry></row>
<row><entry><code>MIGRATE</code></entry><entry>-</entry></row>
<row><entry><code>MONITOR</code></entry><entry>-</entry></row>
<row><entry><code>MOVE</code></entry><entry>X</entry></row>
<row><entry><code>MSET</code></entry><entry>X</entry></row>
<row><entry><code>MSETNX</code></entry><entry>X</entry></row>
<row><entry><code>MULTI</code></entry><entry>X</entry></row>
<row><entry><code>OBJECT</code></entry><entry>-</entry></row>
<row><entry><code>PERSIST</code></entry><entry>X</entry></row>
<row><entry><code>PEXIPRE</code></entry><entry>X</entry></row>
<row><entry><code>PEXPIREAT</code></entry><entry>X</entry></row>
<row><entry><code>PING</code></entry><entry>X</entry></row>
<row><entry><code>PSETEX</code></entry><entry>X</entry></row>
<row><entry><code>PSUBSCRIBE</code></entry><entry>X</entry></row>
<row><entry><code>PTTL</code></entry><entry>X</entry></row>
<row><entry><code>PUBLISH</code></entry><entry>X</entry></row>
<row><entry><code>PUBSUB</code></entry><entry>-</entry></row>
<row><entry><code>PUBSUBSCRIBE</code></entry><entry>-</entry></row>
<row><entry><code>QUIT</code></entry><entry>X</entry></row>
<row><entry><code>RANDOMKEY</code></entry><entry>X</entry></row>
<row><entry><code>RENAME</code></entry><entry>X</entry></row>
<row><entry><code>RENAMENX</code></entry><entry>X</entry></row>
<row><entry><code>RESTORE</code></entry><entry>X</entry></row>
<row><entry><code>RPOP</code></entry><entry>X</entry></row>
<row><entry><code>RPOPLPUSH</code></entry><entry>X</entry></row>
<row><entry><code>RPUSH</code></entry><entry>X</entry></row>
<row><entry><code>RPUSHX</code></entry><entry>X</entry></row>
<row><entry><code>SADD</code></entry><entry>X</entry></row>
<row><entry><code>SAVE</code></entry><entry>X</entry></row>
<row><entry><code>SCAN</code></entry><entry>X</entry></row>
<row><entry><code>SCARD</code></entry><entry>X</entry></row>
<row><entry><code>SCRIPT EXITS</code></entry><entry>X</entry></row>
<row><entry><code>SCRIPT FLUSH</code></entry><entry>X</entry></row>
<row><entry><code>SCRIPT KILL</code></entry><entry>X</entry></row>
<row><entry><code>SCRIPT LOAD</code></entry><entry>X</entry></row>
<row><entry><code>SDIFF</code></entry><entry>X</entry></row>
<row><entry><code>SDIFFSTORE</code></entry><entry>X</entry></row>
<row><entry><code>SELECT</code></entry><entry>X</entry></row>
<row><entry><code>SENTINEL FAILOVER</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL GET-MASTER-ADD-BY-NAME</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL MASTER</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL MASTERS</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL MONITOR</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL REMOVE</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL RESET</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL SET</code></entry><entry>-</entry></row>
<row><entry><code>SENTINEL SLAVES</code></entry><entry>-</entry></row>
<row><entry><code>SET</code></entry><entry>X</entry></row>
<row><entry><code>SETBIT</code></entry><entry>X</entry></row>
<row><entry><code>SETEX</code></entry><entry>X</entry></row>
<row><entry><code>SETNX</code></entry><entry>X</entry></row>
<row><entry><code>SETRANGE</code></entry><entry>X</entry></row>
<row><entry><code>SHUTDOWN</code></entry><entry>X</entry></row>
<row><entry><code>SINTER</code></entry><entry>X</entry></row>
<row><entry><code>SINTERSTORE</code></entry><entry>X</entry></row>
<row><entry><code>SISMEMBER</code></entry><entry>X</entry></row>
<row><entry><code>SLAVEOF</code></entry><entry>X</entry></row>
<row><entry><code>SLOWLOG</code></entry><entry>-</entry></row>
<row><entry><code>SMEMBERS</code></entry><entry>X</entry></row>
<row><entry><code>SMOVE</code></entry><entry>X</entry></row>
<row><entry><code>SORT</code></entry><entry>X</entry></row>
<row><entry><code>SPOP</code></entry><entry>X</entry></row>
<row><entry><code>SRANDMEMBER</code></entry><entry>X</entry></row>
<row><entry><code>SREM</code></entry><entry>X</entry></row>
<row><entry><code>SSCAN</code></entry><entry>X</entry></row>
<row><entry><code>STRLEN</code></entry><entry>X</entry></row>
<row><entry><code>SUBSCRIBE</code></entry><entry>X</entry></row>
<row><entry><code>SUNION</code></entry><entry>X</entry></row>
<row><entry><code>SUNIONSTORE</code></entry><entry>X</entry></row>
<row><entry><code>SYNC</code></entry><entry>-</entry></row>
<row><entry><code>TIME</code></entry><entry>X</entry></row>
<row><entry><code>TTL</code></entry><entry>X</entry></row>
<row><entry><code>TYPE</code></entry><entry>X</entry></row>
<row><entry><code>UNSUBSCRIBE</code></entry><entry>X</entry></row>
<row><entry><code>UNWATCH</code></entry><entry>X</entry></row>
<row><entry><code>WATCH</code></entry><entry>X</entry></row>
<row><entry><code>ZADD</code></entry><entry>X</entry></row>
<row><entry><code>ZCARD</code></entry><entry>X</entry></row>
<row><entry><code>ZCOUNT</code></entry><entry>X</entry></row>
<row><entry><code>ZINCRBY</code></entry><entry>X</entry></row>
<row><entry><code>ZINTERSTORE</code></entry><entry>X</entry></row>
<row><entry><code>ZRANGE</code></entry><entry>X</entry></row>
<row><entry><code>ZRANGEBYSCORE</code></entry><entry>X</entry></row>
<row><entry><code>ZRANK</code></entry><entry>X</entry></row>
<row><entry><code>ZREM</code></entry><entry>X</entry></row>
<row><entry><code>ZREMRANGEBYRANK</code></entry><entry>X</entry></row>
<row><entry><code>ZREVRANGE</code></entry><entry>X</entry></row>
<row><entry><code>ZREVRANGEBYSCORE</code></entry><entry>X</entry></row>
<row><entry><code>ZREVRANK</code></entry><entry>X</entry></row>
<row><entry><code>ZSCAN</code></entry><entry>X</entry></row>
<row><entry><code>ZSCORE</code></entry><entry>X</entry></row>
<row><entry><code>ZUNINONSTORE</code></entry><entry>X</entry></row>
</tbody>
</tgroup>
</table>
</appendix>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<appendix xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="appendix-schema" xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Spring Data Redis Schema(s)</title>
<para>Core schema</para>
<programlisting language="xml"><xi:include href="../../../src/main/resources/org/springframework/data/redis/config/spring-redis-1.0.xsd" parse="text" xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:fallback href="https://raw.github.com/spring-projects/spring-data-redis/src/main/resources/org/springframework/data/redis/config/spring-redis-1.0.xsd" parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</xi:include>
</programlisting>
</appendix>

View File

@@ -1,9 +0,0 @@
<partintro>
<title>Document structure</title>
<para>
Various appendixes outside the reference documentation.
</para>
<para><xref linkend="appendix-schema"/> defines the schemas provided by Spring Data Redis.</para>
</partintro>

View File

@@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<book xmlns="http://docbook.org/ns/docbook" version="5.0"
xml:id="spring-data-keyvalue-reference"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink">
<bookinfo>
<title>Spring Data Redis Reference Documentation</title>
<titleabbrev>Spring Data Redis ${version}</titleabbrev>
<releaseinfo>${version}</releaseinfo>
<productname>Spring Data Redis</productname>
<authorgroup>
<author>
<firstname>Costin</firstname>
<surname>Leau</surname>
<affiliation>SpringSource</affiliation>
</author>
<author>
<firstname>Jennifer</firstname>
<surname>Hickey</surname>
<affiliation>SpringSource</affiliation>
</author>
<author>
<firstname>Christoph</firstname>
<surname>Strobl</surname>
<affiliation>Pivotal Software, Inc.</affiliation>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Darimont</surname>
<affiliation>Pivotal Software, Inc.</affiliation>
</author>
</authorgroup>
<legalnotice>
<para>
Copies of this document may be made for your own use and for distribution
to others, provided that you do not charge any fee for such copies and
further provided that each copy contains this Copyright Notice, whether
distributed in print or electronically.
</para>
</legalnotice>
<copyright xmlns:xi="http://www.w3.org/2001/XInclude">
<year>2011-2014</year>
<holder>The original authors.</holder>
</copyright>
</bookinfo>
<toc/>
<xi:include href="preface.xml"/>
<part id="introduction">
<title>Introduction</title>
<xi:include href="introduction/introduction.xml"/>
<xi:include href="introduction/why-sdr.xml"/>
<xi:include href="introduction/requirements.xml"/>
<xi:include href="introduction/getting-started.xml"/>
</part>
<part id="reference">
<title>Reference Documentation</title>
<xi:include href="reference/introduction.xml"/>
<xi:include href="reference/redis.xml"/>
</part>
<part id="appendixes">
<title>Appendixes</title>
<xi:include href="appendix/introduction.xml"/>
<xi:include href="appendix/appendix-schema.xml"/>
<xi:include href="appendix/appendix-command-reference.xml"/>
</part>
</book>

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="get-started">
<title>Getting Started</title>
<para>Learning a new framework is not always straight forward. In this section, we (the Spring Data team)
tried to provide, what we think is, an easy to follow guide for starting with the Spring Data Redis module.
Of course, feel free to create your own learning 'path' as you see fit and, if possible, please report back
any improvements to the documentation that can help others.</para>
<section id="get-started:first-steps">
<title>First Steps</title>
<para>As explained in <xref linkend="why-spring-redis"/>, Spring Data Redis (SDR) provides integration
between Spring framework and the Redis key value store. Thus, it is important to become acquainted with both of these
frameworks (storages or environments depending on how you want to name them). Throughout the SDR documentation,
each section provides links to resources relevant however, it is best to become familiar with these topics beforehand.</para>
<section id="get-started:first-steps:spring">
<title>Knowing Spring</title>
<para>Spring Data uses heavily Spring framework's <ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-core.html">core</ulink> functionality,
such as the <ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html">IoC</ulink> container,
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html">resource</ulink> abstract or
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html">AOP</ulink> infrastructure. While it is not important
to know the Spring APIs, understanding the concepts behind them is. At a minimum, the idea behind IoC should be familiar.
That being said, the more knowledge one has about the Spring, the faster she will pick up Spring Data Redis.
Besides the very comprehensive (and sometimes disarming) documentation that explains in detail the Spring Framework,
there are a lot of articles, blog entries and books on the matter - take a look at the Spring Guides
<ulink url="http://spring.io/guides">home page</ulink> for more information. In general, this should be the starting point for
developers wanting to try Spring DR.</para>
</section>
<section id="get-started:first-steps:nosql">
<title>Knowing NoSQL and Key Value stores</title>
<para>NoSQL stores have taken the storage world by storm. It is a vast domain with a plethora of solutions, terms and patterns (to make things worse even the
term itself has multiple <ulink url="http://www.google.com/search?q=nosoql+acronym">meanings</ulink>).
While some of the principles are common, it is crucial that the user is familiar to some degree with the stores supported by SDR.
The best way to get acquainted with these solutions is to read their documentation and follow their examples - it usually doesn't take more then 5-10 minutes
to go through them and if you are coming from an RDMBS-only background many times these exercises can be an eye opener.
</para>
</section>
<section id="get-started:first-steps:samples">
<title>Trying Out The Samples</title>
<para>One can find various samples for key value stores in the dedicated example repo, at
<ulink url="https://github.com/spring-projects/spring-data-keyvalue-examples">http://github.com/spring-projects/spring-data-keyvalue-examples</ulink>. For Spring Data Redis,
of interest is the <literal>retwisj</literal> sample, a Twitter-clone built on top of Redis which can be run locally or be deployed into the cloud. See its
<ulink url="http://static.springsource.org/spring-data/data-keyvalue/examples/retwisj/current/">documentation</ulink>, the following blog
<ulink url="http://blog.springsource.com/2011/04/27/getting-started-redis-spring-cloud-foundry/">entry</ulink> or the
<ulink url="http://retwisj.cloudfoundry.com/">live instance</ulink> for more information.</para>
</section>
</section>
<section id="get-started:help">
<title>Need Help?</title>
<para>If you encounter issues or you are just looking for advice, feel free to use one of the links below:</para>
<section id="get-started:help:community">
<title>Community Support</title>
<para>The Spring Data tag on <ulink url="http://stackoverflow.com/questions/tagged/spring-data">Stackoverflow</ulink> is a message board for all Spring Data (not just Redis) users to
share information and help each other. Note that registration is needed <emphasis>only</emphasis> for posting.
</para>
</section>
<section id="get-started:help:professional">
<title>Professional Support</title>
<para>Professional, from-the-source support, with guaranteed response time, is available from <ulink url="http://www.gopivotal.com/">Pivotal Software, Inc.</ulink>,
the company behind Spring Data and Spring.
</para>
</section>
</section>
<section id="get-started:up-to-date">
<title>Following Development</title>
<para>For information on the Spring Data source code repository, nightly builds and snapshot artifacts please see the Spring Data home
<ulink url="http://spring.io/spring-data">page</ulink>.
</para>
<para>You can help make Spring Data best serve the needs of the Spring community by interacting with developers on
<ulink url="http://stackoverflow.com/questions/tagged/spring-data">Stackoverflow</ulink>.</para>
<para>If you encounter a bug or want to suggest an improvement,
please create a ticket on the Spring Data issue <ulink url="https://jira.springsource.org/browse/DATAREDIS">tracker</ulink>.</para>
<para>To stay up to date with the latest news and announcements in the Spring eco system, subscribe to the
Spring Community <ulink url="http://spring.io/">Portal</ulink>.</para>
<para>Lastly, you can follow the Spring <ulink url="http://spring.io/blog/">blog</ulink> or the project team (<ulink url="http://twitter.com/thomasdarimont ">Thomas</ulink> and <ulink url="http://twitter.com/stroblchristoph">Christoph</ulink>) on Twitter.
</para>
</section>
</chapter>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<partintro xmlns="http://docbook.org/ns/docbook" version="5.0">
<para>
<para>This document is the reference guide for Spring Data Redis (SDR) Support.
It explains Key Value module concepts and semantics and the syntax for various
stores namespaces.</para>
<para>For an introduction to key value stores or Spring, or Spring Data examples, please refer to
<xref linkend="get-started"/> - this documentation refers only to Spring Data Redis Support and
assumes the user is familiar with the key value storages and Spring concepts.</para>
</para>
</partintro>

View File

@@ -1,11 +0,0 @@
<chapter xml:id="requirements" xmlns="http://docbook.org/ns/docbook" version="5.0">
<title>Requirements</title>
<para>Spring Data Redis 1.2.x binaries requires JDK level 6.0 and above,
and <ulink url="http://projects.spring.io/spring-framework/">Spring Framework</ulink>
3.2.8 and above.</para>
<para>
In terms of key value stores, <ulink url="http://redis.io">Redis</ulink> 2.6.x or higher
is required. Spring Data Redis is currently tested against the latest 2.6 and 2.8 releases.
</para>
</chapter>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="why-spring-redis" xmlns="http://docbook.org/ns/docbook" version="5.0">
<title>Why Spring Data Redis?</title>
<para>The Spring Framework is the leading full-stack Java/JEE
application framework. It provides a lightweight container and a
non-invasive programming model enabled by the use of dependency
injection, AOP, and portable service abstractions.</para>
<para><ulink url="http://en.wikipedia.org/wiki/NoSQL">NoSQL</ulink>
storages provide an alternative to classical RDBMS for horizontal scalability
and speed. In terms of implementation, Key Value stores represent one of the
largest (and oldest) members in the NoSQL space.</para>
<para>The Spring Data Redis (or SDR) framework makes it easy to
write Spring applications that use the Redis key value store by eliminating the redundant
tasks and boiler plate code required for interacting with the store through
Spring's excellent infrastructure support.</para>
</chapter>

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<preface xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="preface">
<title>Preface</title>
<para>The Spring Data Redis project applies core Spring concepts to the development of solutions using a key-value style data store.
We provide a "template" as a high-level abstraction for sending and receiving messages.
You will notice similarities to the JDBC support in the Spring Framework.
</para>
</preface>

View File

@@ -1,9 +0,0 @@
<partintro>
<title>Document structure</title>
<para>This part of the reference documentation explains the core functionality
offered by Spring Data Redis.</para>
<para><xref linkend="redis"/> introduces the Redis module feature set.</para>
</partintro>

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="pipeline">
<title>Pipelining</title>
<para>Redis provides support for <ulink url="http://redis.io/topics/pipelining">pipelining</ulink>, which involves sending multiple
commands to the server without waiting for the replies and then reading the replies in a single step. Pipelining can improve performance
when you need to send several commands in a row, such as adding many elements to the same List.</para>
<para>Spring Data Redis provides several <classname>RedisTemplate</classname> methods for executing commands in a pipeline. If you don't
care about the results of the pipelined operations, you can use the standard <literal>execute</literal> method, passing <literal>true</literal>
for the <literal>pipeline</literal> argument. The <literal>executePipelined</literal> methods will execute the provided <interfacename>RedisCallback</interfacename> or
<interfacename>SessionCallback</interfacename> in a pipeline and return the results. For example:
</para>
<programlisting language="java"><![CDATA[ //pop a specified number of items from a queue
List<Object> results = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
for(int i=0; i< batchSize; i++) {
stringRedisConn.rPop("myqueue");
}
return null;
}
});]]></programlisting>
<para>The example above executes a bulk right pop of items from a queue in a pipeline. The <literal>results</literal> List contains all of the popped items.
<classname>RedisTemplate</classname> uses its value, hash key, and hash value serializers to deserialize all results before returning, so the returned items in
the above example will be Strings. There are additional <literal>executePipelined</literal> methods that allow you to pass a custom serializer for pipelined results.
</para>
<para>
Note that the value returned from the <interfacename>RedisCallback</interfacename> is required to be null, as this value is discarded in favor
of returning the results of the pipelined commands.
</para>
<note>An important change has been made to the <literal>closePipeline</literal> method of <interfacename>RedisConnection</interfacename> in version 1.1.
Previously this method returned the results of pipelined operations directly from the connectors. This means that the data types often differed from those
returned by the methods of <interfacename>RedisConnection</interfacename>. For example, <literal>zAdd</literal> returns a boolean indicating
that the element has been added to the sorted set. Most connectors return this value as a long and Spring Data Redis performs the conversion. Another common
difference is that most connectors return a status reply (usually the String "OK") for operations like <literal>set</literal>. These replies are typically discarded by Spring Data Redis.
Prior to 1.1, these conversions were not performed on the results of <literal>closePipeline</literal>. If this change breaks your application, you can
set <literal>convertPipelineAndTxResults</literal> to false on your <interfacename>RedisConnectionFactory</interfacename> to disable this behavior.
</note>
</section>

View File

@@ -1,205 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="pubsub">
<title>Redis Messaging/PubSub</title>
<para>Spring Data provides dedicated messaging integration for Redis,
very similar in functionality and naming to the JMS integration in
Spring Framework; in fact, users familiar with the JMS support in Spring should
feel right at home.</para>
<para>Redis messaging can be roughly divided into two areas of functionality, namely
the production or publication and consumption or subscription of messages, hence the shortcut
pubsub (Publish/Subscribe). The
<classname>RedisTemplate</classname> class is used for message production.
For asynchronous reception similar to
Java EE's message-driven bean style, Spring Data provides a dedicated message
listener container that is used to create Message-Driven POJOs
(MDPs) and for synchronous reception, the <interfacename>RedisConnection</interfacename> contract.</para>
<para>The package <literal>org.springframework.data.redis.connection</literal> and
<literal>org.springframework.data.redis.listener</literal> provide
the core functionality for using Redis messaging.</para>
<section id="redis:pubsub:publish">
<title>Sending/Publishing messages</title>
<para>To publish a message, one can use, as with the other operations, either the low-level
<interfacename>RedisConnection</interfacename> or the high-level <classname>RedisTemplate</classname>.
Both entities offer the <methodname>publish</methodname> method that accepts as argument the message
that needs to be sent as well as the destination channel. While <interfacename>RedisConnection</interfacename>
requires raw-data (array of bytes), the <classname>RedisTemplate</classname> allow arbitrary objects to be passed
in as messages:</para>
<programlisting language="java">// send message through connection
RedisConnection con = ...
byte[] msg = ...
byte[] channel = ...
con.publish(msg, channel);
// send message through RedisTemplate
RedisTemplate template = ...
template.convertAndSend("hello!", "world");
</programlisting>
</section>
<section id="redis:pubsub:subscribe">
<title>Receiving/Subscribing for messages</title>
<para>On the receiving side, one can subscribe to one or multiple channels either by naming them directly or by using
pattern matching. The latter approach is quite useful as it not only allows multiple subscriptions to be created with
one command but to also listen on channels not yet created at subscription time (as long as they match the pattern).
</para>
<para>At the low-level, <interfacename>RedisConnection</interfacename> offers <methodname>subscribe</methodname> and
<methodname>pSubscribe</methodname> methods that map the Redis commands for subscribing by channel respectively by pattern.
Note that multiple channels or patterns can be used as arguments. To change the subscription of a connection or simply query
whether it is listening or not, <interfacename>RedisConnection</interfacename>
provides <methodname>getSubscription</methodname> and <methodname>isSubscribed</methodname> method.</para>
<important>Subscription commands in Spring Data Redis are blocking. That is, calling subscribe on a connection will cause
the current thread to block as it will start waiting for messages - the thread will be released only if the subscription
is canceled, that is an additional thread invokes <methodname>unsubscribe</methodname> or <methodname>pUnsubscribe</methodname>
on the <emphasis>same</emphasis> connection. See <link linkend="redis:pubsub:subscribe:containers">message listener container</link> below
for a solution to this problem.</important>
<para>As mentioned above, once subscribed a connection starts waiting for messages. No other commands can be invoked on it except
for adding new subscriptions or modifying/canceling the existing ones. That is, invoking anything other then <methodname>subscribe</methodname>,
<methodname>pSubscribe</methodname>, <methodname>unsubscribe</methodname>, or <methodname>pUnsubscribe</methodname> is illegal and will
throw an exception.</para>
<para>In order to subscribe for messages, one needs to implement the <interfacename>MessageListener</interfacename> callback: each time
a new message arrives, the callback gets invoked and the user code executed through <methodname>onMessage</methodname> method.
The interface gives access not only to the actual message but to the channel it has been received through and the pattern (if any) used
by the subscription to match the channel. This information allows the callee to differentiate between various messages not just by content but
also through data.
</para>
<section id="redis:pubsub:subscribe:containers">
<title>Message Listener Containers</title>
<para>Due to its blocking nature, low-level subscription is not attractive as it requires connection and thread management for every single
listener. To alleviate this problem, Spring Data offers <classname>RedisMessageListenerContainer</classname> which does all the heavy lifting
on behalf of the user - users familiar with EJB and JMS should find the concepts familiar as it is designed as close as possible to the
support in Spring Framework and its message-driven POJOs (MDPs)</para>
<para><classname>RedisMessageListenerContainer</classname> acts as a message listener container; it is used to receive messages from a
Redis channel and drive the MessageListeners that are injected into
it. The listener container is responsible for all threading of message
reception and dispatches into the listener for processing. A message
listener container is the intermediary between an MDP and a messaging
provider, and takes care of registering to receive messages, resource acquisition and release,
exception conversion and the like. This allows you as an application
developer to write the (possibly complex) business logic associated with
receiving a message (and reacting to it), and delegates
boilerplate Redis infrastructure concerns to the framework.
</para>
<para>Furthermore, to minimize the application footprint, <classname>RedisMessageListenerContainer</classname> allows one connection and one thread
to be shared by multiple listeners even though they do not share a subscription. Thus no matter how many listeners or channels an application tracks,
the runtime cost will remain the same through out its lifetime. Moreover, the container allows runtime configuration changes so one can add or remove
listeners while an application is running without the need for restart. Additionally, the container uses a lazy subscription approach, using a
<interfacename>RedisConnection</interfacename> only when needed - if all the listeners are unsubscribed, cleanup is automatically performed and the used
thread released.</para>
<para>To help with the asynch manner of messages, the container requires a <interfacename>java.util.concurrent.Executor</interfacename> (
or Spring's <interfacename>TaskExecutor</interfacename>) for dispatching the messages. Depending on the load, the number of listeners or the runtime
environment, one should change or tweak the executor to better serve her needs - in particular in managed environments (such as app servers), it is
highly recommended to pick a a proper <interfacename>TaskExecutor</interfacename> to take advantage of its runtime.</para>
</section>
<section id="redis:pubsub:subscribe:adapter">
<title>The <classname>MessageListenerAdapter</classname></title>
<para>The <classname>MessageListenerAdapter</classname> class is the
final component in Spring's asynchronous messaging support: in a
nutshell, it allows you to expose almost <emphasis>any</emphasis> class
as a MDP (there are of course some constraints).</para>
<para>Consider the following interface definition. Notice that although
the interface extends the
<interfacename>MessageListener</interfacename> interface,
it can still be used as a MDP via the use of the
<classname>MessageListenerAdapter</classname> class. Notice also how the
various message handling methods are strongly typed according to the
<emphasis>contents</emphasis> of the various
<interfacename>Message</interfacename> types that they can receive and
handle. In addition, the channel or pattern to which a message is sent can be passed in
to the method as the second argument of type String:</para>
<programlisting language="java">public interface MessageDelegate {
void handleMessage(String message);
void handleMessage(Map message);
void handleMessage(byte[] message);
void handleMessage(Serializable message);
// pass the channel/pattern as well
void handleMessage(Serializable message, String channel);
}</programlisting>
<programlisting language="java">public class DefaultMessageDelegate implements MessageDelegate {
<lineannotation>// implementation elided for clarity...</lineannotation>
}</programlisting>
<para>In particular, note how the above implementation of the
<interfacename>MessageDelegate</interfacename> interface (the above
<classname>DefaultMessageDelegate</classname> class) has
<emphasis>no</emphasis> Redis dependencies at all. It truly is a POJO that
we will make into an MDP via the following configuration.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<lineannotation>xmlns:redis="http://www.springframework.org/schema/redis"</lineannotation>
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
<lineannotation>http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd"</lineannotation>&gt;
&lt;!-- the default ConnectionFactory --&gt;
&lt;redis:listener-container&gt;
&lt;!-- the method attribute can be skipped as the default method name is "handleMessage" --&gt;
&lt;redis:listener ref="listener" method="handleMessage" topic="chatroom" /&gt;
&lt;/redis:listener-container&gt;
&lt;bean id="listener" class="redisexample.DefaultMessageDelegate"/&gt;
...
&lt;beans&gt;
</programlisting>
<note>The listener topic can be either a channel (e.g. <literal>topic="chatroom"</literal>) or a pattern (e.g. <literal>topic="*room"</literal>)</note>
<para>The example above uses the Redis namespace to declare the message listener container and automatically register the POJOs as listeners. The full blown, <emphasis>beans</emphasis> definition
is displayed below:</para>
<programlisting language="xml"><lineannotation>&lt;!-- this is the Message Driven POJO (MDP) --&gt;</lineannotation>
<emphasis role="bold">&lt;bean id="messageListener" class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter"&gt;</emphasis>
&lt;constructor-arg&gt;
&lt;bean class="redisexample.DefaultMessageDelegate"/&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
<lineannotation>&lt;!-- and this is the message listener container... --&gt;</lineannotation>
&lt;bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer"&gt;
&lt;property name="connectionFactory" ref="connectionFactory"/&gt;
&lt;property name="messageListeners"&gt;
<lineannotation>&lt;!-- map of listeners and their associated topics (channels or/and patterns) --&gt;</lineannotation>
&lt;map&gt;
<emphasis role="bold">&lt;entry key-ref="messageListener"&gt;</emphasis>
&lt;bean class="org.springframework.data.redis.listener.ChannelTopic">
&lt;constructor-arg value="chatroom"&gt;
&lt;/bean&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
<para>Each time a message is received, the adapter automatically performs
translation (using the configured <interfacename>RedisSerializer</interfacename>)
between the low-level format and the required object type transparently. Any exception caused by the method invocation
is caught and handled by the container (by default, being logged).
</para>
</section>
</section>
</section>

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="scripting">
<title>Redis Scripting</title>
<para>Redis versions 2.6 and higher provide support for execution of Lua scripts through the <ulink url="http://redis.io/commands/eval">eval</ulink> and
<ulink url="http://redis.io/commands/evalsha">evalsha</ulink> commands. Spring Data Redis provides a high-level abstraction for script execution
that handles serialization and automatically makes use of the Redis script cache.
</para>
<para>Scripts can be run through the <literal>execute</literal> methods of <classname>RedisTemplate</classname>. RedisTemplate uses a configurable
<interfacename>ScriptExecutor</interfacename> to execute the provided script. By default, the <interfacename>ScriptExecutor</interfacename> takes care of
serializing the provided keys and arguments and deserializing the script result. This is done with the <classname>RedisTemplate</classname> key and value serializers.
There is an additional <literal>execute</literal> method that allows you to pass custom serializers for the script arguments and result.</para>
<para>The default <interfacename>ScriptExecutor</interfacename> optimizes performance by retrieving the SHA1 of the script and attempting first to
run <literal>evalsha</literal>, falling back to <literal>eval</literal> if the script is not yet present in the Redis script cache.</para>
<para>Here's an example that executes a common "check-and-set" scenario using a Lua script. This is an ideal use case for a Redis script, as
it requires that we execute a set of commands atomically and the behavior of one command is influenced by the result of another.</para>
<programlisting language="java">@Bean
public RedisScript&lt;Boolean&gt; script() {
DefaultRedisScript&lt;Boolean&gt; redisScript = new DefaultRedisScript&lt;Boolean&gt;();
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("META-INF/scripts/checkandset.lua")));
redisScript.setResultType(Boolean.class);
}
</programlisting>
<programlisting language="java"><![CDATA[
public class Example {
@Autowired
RedisScript<Boolean> script;
public boolean checkAndSet(String expectedValue, String newValue) {
return redisTemplate.execute(script, Collections.singletonList("key"),
expectedValue, newValue);
}
}]]></programlisting>
<programlisting language="lua">
-- checkandset.lua
local current = redis.call('GET', KEYS[1])
if current == ARGV[1]
then
redis.call('SET', KEYS[1], ARGV[2])
return true
end
return false
</programlisting>
<para>The XML above configures a <classname>DefaultRedisScript</classname> pointing to a file called <literal>checkandset.lua</literal>, which is
expected to return a boolean value. The script <literal>resultType</literal> should be one of Long, Boolean, List, or deserialized value type. It can also be null if the
script returns a throw-away status (i.e "OK"). It is ideal to configure a single instance of <classname>DefaultRedisScript</classname> in your application context to avoid
re-calculation of the script's SHA1 on every script execution.
</para>
<para>The checkAndSet method above then executes the configured <interfacename>RedisScript</interfacename> with the provided key and arguments and returns the result.</para>
<para>Scripts can be executed within a <interfacename>SessionCallback</interfacename> as part of a transaction or pipeline.
See <xref linkend="tx"/> and <xref linkend="pipeline"/> for more information.</para>
<para>The scripting support provided by Spring Data Redis also allows you to schedule Redis scripts for periodic execution using the Spring Task
and Scheduler abstractions. See the <literal>Spring Framework</literal> documentation for more details.</para>
</section>

View File

@@ -1,89 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="tx">
<title>Redis Transactions</title>
<para>Redis provides support for <ulink url="http://redis.io/topics/transactions">transactions</ulink> through the <literal>multi</literal>,
<literal>exec</literal>, and <literal>discard</literal> commands. These operations are available on <interfacename>RedisTemplate</interfacename>,
however <interfacename>RedisTemplate</interfacename> is not guaranteed to execute all operations in the transaction using the same connection.
</para>
<para>Spring Data Redis provides the <interfacename>SessionCallback</interfacename> interface for use when multiple operations need to be performed with the same <literal>connection</literal>,
as when using Redis transactions. For example:
</para>
<programlisting language="java"><![CDATA[ //execute a transaction
List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() {
public List<Object> execute(RedisOperations operations) throws DataAccessException {
operations.multi();
operations.opsForSet().add("key", "value1");
// This will contain the results of all ops in the transaction
return operations.exec();
}
});
System.out.println("Number of items added to set: " + txResults.get(0));
]]></programlisting>
<para><classname>RedisTemplate</classname> will use its value, hash key, and hash value serializers to deserialize all results of <literal>exec</literal>
before returning. There is an additional <literal>exec</literal> method that allows you to pass a custom serializer for transaction results.
</para>
<note>An important change has been made to the <literal>exec</literal> methods of <interfacename>RedisConnection</interfacename> and <classname>RedisTemplate</classname>
in version 1.1. Previously these methods returned the results of transactions directly from the connectors. This means that the data types often differed from those
returned from the methods of <interfacename>RedisConnection</interfacename>. For example, <literal>zAdd</literal> returns a boolean indicating
that the element has been added to the sorted set. Most connectors return this value as a long and Spring Data Redis performs the conversion. Another common
difference is that most connectors return a status reply (usually the String "OK") for operations like <literal>set</literal>. These replies are typically discarded by Spring Data Redis.
Prior to 1.1, these conversions were not performed on the results of <literal>exec</literal>. Also, results were not deserialized in <classname>RedisTemplate</classname>, so they
often included raw byte arrays. If this change breaks your application, you can
set <literal>convertPipelineAndTxResults</literal> to false on your <interfacename>RedisConnectionFactory</interfacename> to disable this behavior.
</note>
<section id="tx.spring">
<title><interfacename>@Transactional</interfacename> Support</title>
<para>Transaction Support is disabled by default and has explicitly to be enabled for each <classname>RedisTemplate</classname> in use by setting <literal>setEnableTransactionSupport(true)</literal>.
This will force binding the <interfacename>RedisConnection</interfacename> in use to the current <classname>Thread</classname> triggering <literal>MULTI</literal>. If the transaction finishes without errors, <literal>EXEC</literal> is called, otherwise <literal>DISCARD</literal>.
Once in <literal>MULTI</literal>, <classname>RedisConnection</classname> would queue write operations, all <literal>readonly</literal> operations, such as <literal>KEYS</literal> are piped to a fresh (non thread bound) <interfacename>RedisConnection</interfacename>.
</para>
<programlisting language="java"><![CDATA[ /** Sample Configuration **/
@Configuration
public class RedisTxContextConfiguration {
@Bean
public StringRedisTemplate redisTemplate() {
StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory());
// explicitly enable transaction support
template.setEnableTransactionSupport(true);
return template;
}
@Bean
public PlatformTransactionManager transactionManager() throws SQLException {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public RedisConnectionFactory redisConnectionFactory(
// jedis, lettuce, srp,...
);
@Bean
public DataSource dataSource() throws SQLException {
// ...
}
}
]]></programlisting>
<programlisting language="java"><![CDATA[ /** Usage Constrainsts **/
// executed on thread bound connection
template.opsForValue().set("foo", "bar");
// read operation executed on a free (not tx-aware) connection
template.keys("*");
// returns null as values set within transaction are not visible
template.opsForValue().get("foo");
]]></programlisting>
</section>
</section>

View File

@@ -1,503 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="redis">
<title>Redis support</title>
<para>One of the key value stores supported by Spring Data is <ulink url="http://redis.io">Redis</ulink>.
To quote the project home page:
<quote>
Redis is an advanced key-value store. It is similar to memcached but the dataset is not volatile, and values can be strings,
exactly like in memcached, but also lists, sets, and ordered sets. All this data types can be manipulated with atomic operations
to push/pop elements, add/remove elements, perform server side union, intersection, difference between sets, and so forth.
Redis supports different kind of sorting abilities.</quote>
<para>Spring Data Redis provides easy configuration and access to Redis from Spring applications. It offers both low-level and
high-level abstractions for interacting with the store, freeing the user from infrastructural concerns.</para>
</para>
<section id="redis:requirements">
<title>Redis Requirements</title>
<para>Spring Redis requires Redis 2.6 or above and Java SE 6.0 or above .
In terms of language bindings (or connectors), Spring Redis integrates with <ulink url="http://github.com/xetorthio/jedis">Jedis</ulink>,
<ulink url="http://github.com/alphazero/jredis">JRedis</ulink>,
<ulink url="http://github.com/spullara/redis-protocol">SRP</ulink> and
<ulink url="http://github.com/wg/lettuce">Lettuce</ulink>, four popular open source Java libraries for Redis.
If you are aware of any other connector that we should be integrating with please send us feedback.
</para>
</section>
<section id="redis:architecture">
<title>Redis Support High Level View</title>
<para>The Redis support provides several components (in order of dependencies):</para>
<itemizedlist>
<listitem><emphasis>Low-Level Abstractions</emphasis> - for configuring and handling communication with Redis through the various connector libraries supported as
described in <xref linkend="redis:connectors"/>. </listitem>
<listitem><emphasis>High-Level Abstractions</emphasis> - providing generified, user friendly template classes for interacting with Redis.
<xref linkend="redis:template"/> explains the abstraction built on top of the low-level <interfacename>Connection</interfacename> API to handle the
infrastructural concerns and object conversion.</listitem>
<listitem><emphasis>Support Classes</emphasis> - that offer reusable components (built on the aforementioned abstractions) such as
<interfacename>java.util.Collection</interfacename> or Spring <ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html">cache</ulink> implementation backed by
Redis as documented in <xref linkend="redis:support"/></listitem>
</itemizedlist>
<para>For most tasks, the high-level abstractions and support services are the best choice. Note that at any point, one can move between layers - for example, it's very
easy to get a hold of the low level connection (or even the native library) to communicate directly with Redis.</para>
</section>
<section id="redis:connectors">
<title>Connecting to Redis</title>
<para>One of the first tasks when using Redis and Spring is to connect to the store through the IoC container. To do that, a Java connector (or binding) is required.
No matter the library one chooses, there is only one set of Spring Data Redis API that one needs to use that behaves consistently
across all connectors, namely the <literal>org.springframework.data.redis.connection</literal> package and its
<interfacename>RedisConnection</interfacename> and <interfacename>RedisConnectionFactory</interfacename> interfaces for working with and retrieving active
<literal>connections</literal> to Redis.</para>
<section id="redis:connectors:connection">
<title><interfacename>RedisConnection</interfacename> and <interfacename>RedisConnectionFactory</interfacename></title>
<para><interfacename>RedisConnection</interfacename> provides the building block for Redis communication as it handles the communication with the Redis back-end.
It also automatically translates the underlying connecting library exceptions to Spring's consistent DAO exception
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/dao.html#dao-exceptions">hierarchy</ulink> so one can switch the connectors
without any code changes as the operation semantics remain the same.</para>
<note>For the corner cases where the native library API is required, <interfacename>RedisConnection</interfacename> provides a dedicated method
<methodname>getNativeConnection</methodname> which returns the raw, underlying object used for communication.</note>
<para>Active <interfacename>RedisConnection</interfacename>s are created through <interfacename>RedisConnectionFactory</interfacename>. In addition, the factories act as
<interfacename>PersistenceExceptionTranslator</interfacename>s, meaning once declared, they allow one to do transparent exception translation. For example, exception translation through the use of the
<literal>@Repository</literal> annotation and AOP. For more information see the dedicated
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html#orm-exception-translation">section</ulink> in Spring Framework documentation.</para>
<note>Depending on the underlying configuration, the factory can return a new connection or an existing connection (in case a pool or shared native connection is used).</note>
</section>
<para>The easiest way to work with a <interfacename>RedisConnectionFactory</interfacename> is to configure the appropriate connector through the IoC container and
inject it into the using class.</para>
<sidebar>
<title>Connector features</title>
<para>Unfortunately, currently, not all connectors support all Redis features. When invoking a method on the <interfacename>Connection</interfacename> API that is unsupported by the underlying library, a <classname>UnsupportedOperationException</classname>
is thrown.
This situation is likely to be fixed in the future, as the various connectors mature.
</para>
</sidebar>
<section id="redis:connectors:jedis">
<title>Configuring Jedis connector</title>
<para><ulink url="http://github.com/xetorthio/jedis">Jedis</ulink> is one of the connectors supported by the Spring Data Redis module through the
<literal>org.springframework.data.redis.connection.jedis</literal> package. In its simplest form, the Jedis configuration looks as follow:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Jedis ConnectionFactory -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"/>
</beans>]]></programlisting>
<para>For production use however, one might want to tweak the settings such as the host or password:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="server" p:port="6379"/>
</beans>]]></programlisting>
</section>
<section id="redis:connectors:jredis">
<title>Configuring JRedis connector</title>
<para><ulink url="http://github.com/alphazero/jredis">JRedis</ulink> is another popular, open-source connector supported by Spring Data Redis through the
<literal>org.springframework.data.redis.connection.jredis</literal> package.</para>
<para>A typical JRedis configuration can looks like this:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jredisConnectionFactory" class="org.springframework.data.redis.connection.jredis.JredisConnectionFactory"
p:host-name="server" p:port="6379"/>
</beans>]]></programlisting>
<para>The configuration is quite similar to Jedis, with one notable exception. By default, the <literal>JredisConnectionFactory</literal> pools connections.
In order to use a connection pool with JRedis, configure the <literal>JredisConnectionFactory</literal> with an instance of <literal>JredisPool</literal>. For example:
</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jredisConnectionFactory"
class="org.springframework.data.redis.connection.jredis.JredisConnectionFactory">
<constructor-arg>
<bean
class="org.springframework.data.redis.connection.jredis.DefaultJredisPool">
<constructor-arg value="localhost" />
<constructor-arg value="6379" />
</bean>
</constructor-arg>
</bean>
</beans>]]></programlisting>
</section>
<section id="redis:connectors:srp">
<title>Configuring SRP connector</title>
<para><ulink url="https://github.com/spullara/redis-protocol">SRP</ulink> (an acronym for Sam's Redis Protocol) is the third open-source connector supported by
Spring Data Redis through the <literal>org.springframework.data.redis.connection.srp</literal> package.</para>
<para>By now, its configuration is probably easy to guess:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="srpConnectionFactory" class="org.springframework.data.redis.connection.srp.SrpConnectionFactory"
p:host-name="server" p:port="6379"/>
</beans>]]></programlisting>
<para>Needless to say, the configuration is quite similar to that of the other connectors.</para>
</section>
<section id="redis:connectors:lettuce">
<title>Configuring Lettuce connector</title>
<para><ulink url="https://github.com/wg/lettuce">Lettuce</ulink> is the fourth open-source connector supported by
Spring Data Redis through the <literal>org.springframework.data.redis.connection.lettuce</literal> package.</para>
<para>Its configuration is probably easy to guess:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="lettuceConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"
p:host-name="server" p:port="6379"/>
</beans>]]></programlisting>
<para>There are also a few Lettuce-specific connection parameters that can be tweaked.
By default, all <literal>LettuceConnections</literal> created by the <literal>LettuceConnectionFactory</literal> share the same
thread-safe native connection for all non-blocking and non-transactional operations. Set <literal>shareNativeConnection</literal> to false to use a dedicated
connection each time. <literal>LettuceConnectionFactory</literal> can also be configured with a <literal>LettucePool</literal> to use for pooling
blocking and transactional connections, or all connections if <literal>shareNativeConnection</literal> is set to false.</para>
</section>
</section>
<section id="redis:sentinel">
<title>Redis Sentinel Support</title>
<para>For dealing with high available Redis there is support for <ulink url="http://redis.io/topics/sentinel">Redis Sentinel</ulink> using <classname>RedisSentinelConfiguration</classname>.</para>
<note>Please note that currently only <ulink url="http://github.com/xetorthio/jedis">Jedis</ulink> supports Redis Sentinel.</note>
<programlisting language="java"><![CDATA[@Bean
public RedisConnectionFactory jedisConnectionFactory() {
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
.master("mymaster")
.sentinel("127.0.0.1", 26379)
.sentinel("127.0.0.1", 26380);
return new JedisConnectionFactory(sentinelConfig);
}
]]></programlisting>
<para>Sometimes direct interaction with the one of the Sentinels is required. Using <classname>RedisConnectionFactory.getSentinelConnection()</classname> or
<classname>RedisConnection.getSentinelCommands()</classname> gives you access to the first active Sentinel configured.</para>
</section>
<section id="redis:template">
<title>Working with Objects through <classname>RedisTemplate</classname></title>
<para>Most users are likely to use <classname>RedisTemplate</classname> and its coresponding package <literal>org.springframework.data.redis.core</literal> - the
template is in fact the central class of the Redis module due to its rich feature set.
The template offers a high-level abstraction for Redis interactions. While <interfacename>RedisConnection</interfacename> offers low level methods that accept and return
binary values (<literal>byte</literal> arrays), the template takes care of serialization and connection management, freeing the user from dealing with such details.</para>
<para>Moreover, the template provides operations views (following the grouping from Redis command <ulink url="http://redis.io/commands">reference</ulink>)
that offer rich, generified interfaces for working against a certain type or certain key (through the <interfacename>KeyBound</interfacename> interfaces) as described below:</para>
<table id="redis-template-operations-view" pgwide="1">
<title>Operational views</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*" align="center"/>
<colspec colname="c2" colwidth="1*" align="center"/>
<spanspec spanname="both" namest="c1" nameend="c2" colsep="0" align="center" />
<thead>
<row>
<entry>Interface</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row rowsep="0">
<entry spanname="both"><emphasis><![CDATA[Key Type Operations]]></emphasis></entry>
</row>
<row>
<entry><interfacename>ValueOperations</interfacename></entry>
<entry>Redis string (or value) operations</entry>
</row>
<row>
<entry><interfacename>ListOperations</interfacename></entry>
<entry>Redis list operations</entry>
</row>
<row>
<entry><interfacename>SetOperations</interfacename></entry>
<entry>Redis set operations</entry>
</row>
<row>
<entry><interfacename>ZSetOperations</interfacename></entry>
<entry>Redis zset (or sorted set) operations</entry>
</row>
<row>
<entry><interfacename>HashOperations</interfacename></entry>
<entry>Redis hash operations</entry>
</row>
<row>
<entry spanname="both"><emphasis><![CDATA[Key Bound Operations]]></emphasis></entry>
</row>
<row>
<entry><interfacename>BoundValueOperations</interfacename></entry>
<entry>Redis string (or value) key bound operations</entry>
</row>
<row>
<entry><interfacename>BoundListOperations</interfacename></entry>
<entry>Redis list key bound operations</entry>
</row>
<row>
<entry><interfacename>BoundSetOperations</interfacename></entry>
<entry>Redis set key bound operations</entry>
</row>
<row>
<entry><interfacename>BoundZSetOperations</interfacename></entry>
<entry>Redis zset (or sorted set) key bound operations</entry>
</row>
<row>
<entry><interfacename>BoundHashOperations</interfacename></entry>
<entry>Redis hash key bound operations</entry>
</row>
</tbody>
</tgroup>
</table>
<para>Once configured, the template is thread-safe and can be reused across multiple instances.</para>
<para>Out of the box, <classname>RedisTemplate</classname> uses a Java-based serializer for most of its operations. This means that any object written or read by the template will be
serializer/deserialized through Java. The serialization mechanism can be easily changed on the template, and the Redis module offers several implementations available in the
<literal>org.springframework.data.redis.serializer</literal> package - see <xref linkend="redis:serializer"/> for more information. You can also set any of the serializers to null
and use RedisTemplate with raw <literal>byte</literal> arrays by setting the <literal>enableDefaultSerializer</literal> property to false.
Note that the template requires all keys to be non-null - values can be null as long as the underlying
serializer accepts them; read the javadoc of each serializer for more information.</para>
<para>For cases where a certain template <emphasis>view</emphasis> is needed, declare the view as a dependency and inject the template: the container will automatically perform the conversion
eliminating the <literal>opsFor[X]</literal> calls:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:use-pool="true"/>
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>
...
</beans>]]></programlisting>
<programlisting language="java"><![CDATA[public class Example {
// inject the actual template
@Autowired
private RedisTemplate<String, String> template;
// inject the template as ListOperations
@Resource(name="redisTemplate")
private ListOperations<String, String> listOps;
public void addLink(String userId, URL url) {
listOps.leftPush(userId, url.toExternalForm());
}
}]]></programlisting>
</section>
<section id="redis:string">
<title>String-focused convenience classes</title>
<para>Since it's quite common for the keys and values stored in Redis to be <classname>java.lang.String</classname>, the Redis modules provides two extensions to <interfacename>RedisConnection</interfacename>
and <classname>RedisTemplate</classname>, respectively the <interfacename>StringRedisConnection</interfacename> (and its <classname>DefaultStringRedisConnection</classname> implementation)
and <classname>StringRedisTemplate</classname> as a convenient one-stop solution
for intensive String operations. In addition to being bound to <literal>String</literal> keys, the template and the connection use the
<classname>StringRedisSerializer</classname> underneath which means the stored keys and values are human readable (assuming the same encoding is used both in Redis and your code).
For example:
</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:use-pool="true"/>
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>
...
</beans>]]></programlisting>
<programlisting language="java"><![CDATA[public class Example {
@Autowired
private StringRedisTemplate redisTemplate;
public void addLink(String userId, URL url) {
redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
}]]></programlisting>
<para>As with the other Spring templates, <classname>RedisTemplate</classname> and <classname>StringRedisTemplate</classname> allow the developer to talk directly to Redis through
the <interfacename>RedisCallback</interfacename> interface. This gives complete control to the developer as it talks directly to the <interfacename>RedisConnection</interfacename>.
Note that the callback receives an instance of <interfacename>StringRedisConnection</interfacename> when a <classname>StringRedisTemplate</classname> is used.
</para>
<programlisting language="java"><![CDATA[public void useCallback() {
redisTemplate.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
Long size = connection.dbSize();
// Can cast to StringRedisConnection if using a StringRedisTemplate
((StringRedisConnection)connection).set("key", "value");
...
}
});
}]]></programlisting>
</section>
<section id="redis:serializer">
<title>Serializers</title>
<para>From the framework perspective, the data stored in Redis is just bytes. While Redis itself supports various types, for the most part these refer to the way the data is stored
rather then what it represents. It is up to the user to decide whether the information gets translated into Strings or any other objects. The conversion between the user (custom)
types and raw data (and vice-versa) is handled in Spring Data Redis through the <interfacename>RedisSerializer</interfacename> interface
(package <literal>org.springframework.data.redis.serializer</literal>) which as the name implies, takes care of the serialization process. Multiple implementations are
available out of the box, two of which have been already mentioned before in this documentation: the <literal>StringRedisSerializer</literal> and
the <literal>JdkSerializationRedisSerializer</literal>. However one can use <classname>OxmSerializer</classname> for Object/XML mapping through Spring 3
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/oxm.html">OXM</ulink> support or either <classname>JacksonJsonRedisSerializer</classname> or
<classname>Jackson2JsonRedisSerializer</classname> for storing data in <ulink url="http://en.wikipedia.org/wiki/JSON">JSON</ulink> format. Do note that the storage format is not limited only to values - it can be used for keys, values or hashes
without any restrictions.</para>
</section>
<xi:include href="redis-messaging.xml"/>
<xi:include href="redis-transactions.xml"/>
<xi:include href="pipelining.xml"/>
<xi:include href="redis-scripting.xml"/>
<section id="redis:support">
<title>Support Classes</title>
<para>Package <literal>org.springframework.data.redis.support</literal> offers various reusable components that rely on Redis as a backing store. Curently the package contains
various JDK-based interface implementations on top of Redis such as <ulink url="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/package-summary.html">atomic</ulink>
counters and JDK <interfacename><ulink url="http://download.oracle.com/javase/6/docs/api/java/util/Collection.html">Collections</ulink></interfacename>.</para>
<para>The atomic counters make it easy to wrap Redis key incrementation while the collections allow easy management of Redis keys with minimal storage exposure or API leakage: in particular
the <interfacename>RedisSet</interfacename> and <interfacename>RedisZSet</interfacename> interfaces offer easy access to the <emphasis>set</emphasis> operations supported by Redis such as
<literal>intersection</literal> and <literal>union</literal> while <interfacename>RedisList</interfacename> implements the <interfacename>List</interfacename>,
<interfacename>Queue</interfacename> and <interfacename>Deque</interfacename> contracts (and their equivalent blocking siblings) on top of Redis, exposing the storage as a
<emphasis>FIFO (First-In-First-Out)</emphasis>, <emphasis>LIFO (Last-In-First-Out)</emphasis> or <emphasis>capped collection</emphasis> with minimal configuration:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="queue" class="org.springframework.data.redis.support.collections.DefaultRedisList">
<constructor-arg ref="redisTemplate"/>
<constructor-arg value="queue-key"/>
</bean>
</beans>]]></programlisting>
<programlisting language="java"><![CDATA[public class AnotherExample {
// injected
private Deque<String> queue;
public void addTag(String tag) {
queue.push(tag);
}
}]]></programlisting>
<para>As shown in the example above, the consuming code is decoupled from the actual storage implementation - in fact there is no indication that Redis is used underneath. This makes moving from
development to production environments transparent and highly increases testability (the Redis implementation can just as well be replaced with an in-memory one).</para>
<section id="redis:support:cache-abstraction">
<title>Support for Spring Cache Abstraction</title>
<para>Spring Redis provides an implementation for Spring <ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html">cache abstraction</ulink>
through the <literal>org.springframework.data.redis.cache</literal> package. To use Redis as a backing implementation, simply add <literal>RedisCacheManager</literal> to your configuration:</para>
<programlisting language="xml"><![CDATA[<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"
xmlns:c="http://www.springframework.org/schema/c"
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">
<!-- turn on declarative caching -->
<cache:annotation-driven />
<!-- declare Redis Cache Manager -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:template-ref="redisTemplate"/>
</beans>]]>
</programlisting>
<note>
By default <classname>RedisCacheManager</classname> will lazily initialize <classname>RedisCache</classname> whenever a <interfacename>Cache</interfacename> is requested. This can be changed by predefining a <interfacename>Set</interfacename> of cache names.
</note>
<note>
By default <classname>RedisCacheManager</classname> will not participate in any ongoing transaction. Use <methodname>setTransactionAware</methodname> to enable transaction support.
</note>
</section>
</section>
<section id="redis:future">
<title>Roadmap ahead</title>
<para>Spring Data Redis project is in its early stages. We are interested in feedback, knowing what your use cases are, what are the common patters you encounter so that the Redis module
better serves your needs. Do contact us using the channels <link linkend="get-started:help:community">mentioned</link> above, we are interested in hearing from you!</para>
</section>
</chapter>