Professional Documents
Culture Documents
Home
Page 1 of 617
Infinispan 6.0
Table of Contents
1 More Resources ___________________________________________________________________ 17
2 Getting Started Guide _______________________________________________________________ 18
2.1 Introduction ___________________________________________________________________ 19
2.2 Downloading and installing Infinispan _______________________________________________ 20
2.3 Infinispan in action - GUIDemo ____________________________________________________ 20
2.4 Using Infinispan as an embedded cache in Java SE ___________________________________ 20
2.4.1 Creating a new Infinispan project _____________________________________________ 20
2.4.2 Running Infinispan on a single node __________________________________________ 23
2.4.3 Use the default cache _____________________________________________________ 24
2.4.4 Use a custom cache _______________________________________________________ 25
2.5 Using Infinispan as an embedded data grid in Java SE _________________________________ 25
2.5.1 Running Infinispan in a cluster _______________________________________________ 26
2.5.2 Configuring the cluster _____________________________________________________ 30
2.5.3 Configuring a replicated data-grid ____________________________________________ 31
2.5.4 Configuring a distributed data-grid ____________________________________________ 32
2.6 Creating your own Infinispan project ________________________________________________ 32
2.7 Using Infinispan as a second level cache for Hibernate _________________________________ 32
2.8 Accessing an Infinispan data grid remotely ___________________________________________ 33
2.8.1 Using Hot Rod to access an Infinispan data-grid _________________________________ 33
2.8.2 Using REST to access an Infinipsan data-grid ___________________________________ 33
2.8.3 Using memcached to access an Infinispan data-grid ______________________________ 33
2.9 Using Infinispan in JBoss AS 7 ____________________________________________________ 33
2.10 Using Infinispan in servlet containers (such as Tomcat or Jetty) and other application servers (such
as GlassFish) _______________________________________________________________________ 33
2.11 Monitoring Infinispan ____________________________________________________________ 33
2.12 Getting Started Guide - Introduction ________________________________________________ 34
2.13 Getting Started Guide - Downloading, installing and running Infinispan _____________________ 35
2.14 Getting Started Guide - Embedded Cache in Java SE __________________________________ 35
2.14.1 Creating a new Infinispan project _____________________________________________ 35
2.14.2 Running Infinispan on a single node __________________________________________ 38
2.14.3 Use the default cache _____________________________________________________ 39
2.14.4 Use a custom cache _______________________________________________________ 40
2.15 Getting Started Guide - Clustered Cache in Java SE ___________________________________ 40
2.15.1 Running Infinispan in a cluster _______________________________________________ 41
2.15.2 Configuring the cluster _____________________________________________________ 45
2.15.3 Configuring a replicated data-grid ____________________________________________ 46
2.15.4 Configuring a distributed data-grid ____________________________________________ 47
2.16 Infinispan GUI demo ____________________________________________________________ 47
2.16.1 Step 1: Start the demo GUI _________________________________________________ 48
2.16.2 Step 3: Manipulate data ____________________________________________________ 48
2.16.3 Step 4: Start more cache instances ___________________________________________ 48
2.16.4 Step 5: Manipulate more data _______________________________________________ 49
Page 2 of 617
Infinispan 6.0
2.17 Getting Started Guide - JBoss AS 7 ________________________________________________ 49
2.17.1 Configuration ____________________________________________________________ 49
2.17.2 Cache container lifecycle ___________________________________________________ 52
2.18 Labs _________________________________________________________________________ 54
2.18.1 A list of the labs developed for Infinispan _______________________________________ 54
2.18.2 Lab - Getting Started with Infinispan __________________________________________ 54
3 User Guide _______________________________________________________________________ 70
3.1 New in Infinispan 4.1.0 __________________________________________________________ 71
3.2 New in Infinispan 4.2.0 __________________________________________________________ 72
3.3 New in Infinispan 5.0.0 __________________________________________________________ 72
3.4 New in Infinispan 5.2.0 __________________________________________________________ 72
3.5 Integration with other frameworks __________________________________________________ 72
3.6 Querying Infinispan _____________________________________________________________ 72
3.6.1 The infinispan-query module ________________________________________________ 73
3.6.2 Simple example __________________________________________________________ 73
3.6.3 Configuration ____________________________________________________________ 76
3.6.4 Cache modes and managing indexes _________________________________________ 78
3.6.5 Sharing the Index _________________________________________________________ 80
3.6.6 Clustering the Index in Infinispan _____________________________________________ 81
3.6.7 Rebuilding the Index ______________________________________________________ 81
3.7 Configuring cache programmatically ________________________________________________ 81
3.7.1 Programmatic Configuration ________________________________________________ 81
3.7.2 ConfigurationBuilder Programmatic Configuration API ______________________________
3.8 Grid File System _______________________________________________________________ 85
3.8.1 WebDAV demo __________________________________________________________ 86
3.9 Asynchronous API ______________________________________________________________ 86
3.9.1 Why use such an API? _____________________________________________________ 87
3.9.2 Which processes actually happen asynchronously? ______________________________ 87
3.9.3 Notifying futures __________________________________________________________ 88
3.9.4 Further reading ___________________________________________________________ 88
3.10 Tree API Module _______________________________________________________________ 88
3.10.1 Introduction _____________________________________________________________ 89
3.10.2 What is Tree API about? ___________________________________________________ 89
3.10.3 Using Tree API ___________________________________________________________ 89
3.10.4 Locking In Tree API _______________________________________________________ 93
3.10.5 Listeners for tree cache events ______________________________________________ 94
3.11 Infinispan as a storage for Lucene indexes ___________________________________________ 94
3.11.1 Additional Links __________________________________________________________ 94
3.11.2 Lucene compatibility _______________________________________________________ 94
3.11.3 How to use it ____________________________________________________________ 95
3.11.4 Limitations ______________________________________________________________ 95
3.11.5 Configuration ____________________________________________________________ 96
3.11.6 Demo __________________________________________________________________ 96
3.11.7 Maven dependencies ______________________________________________________ 96
3.11.8 Using a CacheLoader _____________________________________________________ 97
3.11.9 Architectural limitations ____________________________________________________ 98
Page 3 of 617
Infinispan 6.0
3.11.10Suggestions for optimal performance _________________________________________ 98
3.12 Infinispan Server Modules ________________________________________________________ 99
3.12.1 Introduction _____________________________________________________________ 99
3.12.2 Server Modules _________________________________________________________ 102
3.12.3 Server Comparison Summary ______________________________________________ 104
3.13 Management Tooling ___________________________________________________________ 104
3.13.1 Introduction ____________________________________________________________ 104
3.13.2 JMX __________________________________________________________________ 104
3.13.3 RHQ __________________________________________________________________ 110
3.13.4 Writing plugins for other management tools ____________________________________ 113
3.14 Asynchronous Options _________________________________________________________ 113
3.14.1 Introduction ____________________________________________________________ 114
3.14.2 Asynchronous Communications _____________________________________________ 114
3.14.3 Asynchronous Marshalling _________________________________________________ 115
3.14.4 Replication Queue _______________________________________________________ 116
3.14.5 Asynchronous API _______________________________________________________ 116
3.14.6 Return Values __________________________________________________________ 116
3.15 Infinispan as Hibernate 2nd-Level Cache in JBoss AS 5.x ______________________________ 116
3.16 Clustered Configuration QuickStart ________________________________________________ 117
3.16.1 Using an external JGroups file ______________________________________________ 118
3.16.2 Use one of the pre-configured JGroups files ___________________________________ 118
3.16.3 Further reading __________________________________________________________ 120
3.17 Locking and Concurrency _______________________________________________________ 120
3.17.1 MVCC implementation details ______________________________________________ 121
3.17.2 Isolation levels __________________________________________________________ 122
3.17.3 The LockManager _______________________________________________________ 122
3.17.4 Lock striping ____________________________________________________________ 123
3.17.5 Concurrency levels _______________________________________________________ 123
3.17.6 Explicit and implicit distributed eager locking ___________________________________ 124
3.17.7 Locking a single remote node ______________________________________________ 124
3.17.8 Non-transactional caches and concurrent updates ______________________________ 126
3.18 Configuring Cache declaratively __________________________________________________ 127
3.19 Configuration Migration Tools ____________________________________________________ 127
3.20 Consistent Concurrent Updates With Hot Rod Versioned Operations _____________________ 128
3.20.1 Introduction ____________________________________________________________ 129
3.20.2 Data Consistency Problem _________________________________________________ 129
3.21 Cache Loaders and Stores ______________________________________________________ 131
3.21.1 Introduction ____________________________________________________________ 132
3.21.2 Configuration ___________________________________________________________ 132
3.21.3 Cache Passivation _______________________________________________________ 134
3.21.4 File system based cache loaders ____________________________________________ 137
3.21.5 JDBC based cache loaders ________________________________________________ 137
3.21.6 Cloud cache loader ______________________________________________________ 142
3.21.7 Remote cache loader _____________________________________________________ 142
3.21.8 Cassandra cache loader __________________________________________________ 144
3.21.9 Cluster cache loader _____________________________________________________ 144
Page 4 of 617
Infinispan 6.0
3.21.10JPA cache store ________________________________________________________ 144
3.21.11LevelDB cache store _____________________________________________________ 147
3.21.12Cache Loaders and transactional caches _____________________________________ 150
3.21.13MongoDB cache loader ___________________________________________________ 150
3.22 Portable Serialization For Hot Rod With Apache Avro _________________________________ 151
3.22.1 Introduction ____________________________________________________________ 152
3.22.2 Languages Supported ____________________________________________________ 152
3.22.3 Object Types Supported __________________________________________________ 153
3.22.4 Java Configuration _______________________________________________________ 154
3.23 The Grouping API _____________________________________________________________ 154
3.23.1 How does it work? _______________________________________________________ 154
3.23.2 How do I use the grouping API? ____________________________________________ 154
3.24 Infinispan transactions __________________________________________________________ 156
3.24.1 JTA Support ____________________________________________________________ 158
3.24.2 Configuring transactions __________________________________________________ 159
3.24.3 Transactional modes _____________________________________________________ 159
3.24.4 Deadlock detection _______________________________________________________ 162
3.24.5 Transaction and exceptions ________________________________________________ 162
3.24.6 Transaction recovery on node failures ________________________________________ 162
3.24.7 Enlisting Synchronization __________________________________________________ 163
3.25 Load Testing Infinispan Server Modules ____________________________________________ 163
3.26 Using Infinispan as JPA-Hibernate Second Level Cache Provider ________________________ 164
3.26.1 Overview ______________________________________________________________ 165
3.26.2 Configuration ___________________________________________________________ 165
3.26.3 Default Configuration Explained _____________________________________________ 167
3.26.4 JTA Transactions Configuration _____________________________________________ 168
3.26.5 Advanced Configuration ___________________________________________________ 171
3.26.6 Integration with JBoss Application Server _____________________________________ 175
3.26.7 Using Infinispan as remote Second Level Cache? ______________________________ 176
3.26.8 Frequently Asked Questions _______________________________________________ 176
3.27 Default Values For Property Based Attributes ________________________________________ 177
3.27.1 asyncListenerExecutor ____________________________________________________ 177
3.27.2 asyncTransportExecutor __________________________________________________ 177
3.27.3 evictionScheduledExecutor ________________________________________________ 177
3.27.4 replicationQueueScheduledExecutor _________________________________________ 177
3.28 Running Infinispan on Amazon Web Services _______________________________________ 177
3.28.1 TCPPing, GossipRouter, S3_PING __________________________________________ 178
3.28.2 GossipRouter ___________________________________________________________ 179
3.28.3 S3_PING ______________________________________________________________ 180
3.28.4 JDBC_PING ____________________________________________________________ 180
3.28.5 Creating a cluster node with distributed cache _________________________________ 181
3.29 Eviction Examples _____________________________________________________________ 181
3.29.1 Introduction ____________________________________________________________ 181
3.29.2 Configuration ___________________________________________________________ 181
3.29.3 Eviction designs _________________________________________________________ 183
3.30 Clustering modes _____________________________________________________________ 183
Page 5 of 617
Infinispan 6.0
3.30.1 Introduction ____________________________________________________________ 184
3.30.2 Local Mode _____________________________________________________________ 184
3.30.3 Replicated Mode ________________________________________________________ 184
3.30.4 Invalidation Mode ________________________________________________________ 186
3.30.5 Distribution Mode ________________________________________________________ 186
3.30.6 L1 Caching _____________________________________________________________ 192
3.31 Using Infinispan as a Spring Cache provider ________________________________________ 193
3.32 Note: This page is obsolete. Please refer to Infinispan Distributed Execution Framework . ____ 195
3.33 Per-Invocation Flags ___________________________________________________________ 195
3.33.1 Examples ______________________________________________________________ 196
3.33.2 DecoratedCache ________________________________________________________ 196
3.33.3 Suppressing return values from a put() or remove() _____________________________ 197
3.34 Key affinity service ____________________________________________________________ 197
3.34.1 Introduction ____________________________________________________________ 197
3.34.2 API ___________________________________________________________________ 198
3.34.3 Lifecycle _______________________________________________________________ 198
3.34.4 Topology changes _______________________________________________________ 199
3.35 Transaction recovery ___________________________________________________________ 199
3.35.1 ______________________________________________________________________ 199
3.35.2 When to use recovery ____________________________________________________ 199
3.35.3 How does it work ________________________________________________________ 200
3.35.4 Configuring recovery
____________________________________________________ 201
Page 6 of 617
Infinispan 6.0
3.39.5 Distributed task failover ___________________________________________________ 227
3.39.6 Distributed task execution policy ____________________________________________ 229
3.39.7 Examples ______________________________________________________________ 229
3.40 Listeners and Notifications ______________________________________________________ 230
3.40.1 Cache-level notifications __________________________________________________ 231
3.40.2 Cache manager-level notifications ___________________________________________ 232
3.40.3 Synchronicity ___________________________________________________________ 232
3.40.4 Listeners on RemoteCacheManager _________________________________________ 232
3.41 Eviction _____________________________________________________________________ 232
3.41.1 Eviction in 5.2 ___________________________________________________________ 234
3.41.2 Configuration and defaults in 5.2.x ___________________________________________ 235
3.41.3 Advanced Eviction Internals ________________________________________________ 236
3.41.4 Expiration ______________________________________________________________ 236
3.41.5 Difference between Eviction and Expiration ____________________________________ 236
3.42 ServerHinting _________________________________________________________________ 236
3.42.1 What is server hinting? ____________________________________________________ 237
3.42.2 Version ________________________________________________________________ 237
3.42.3 Configuration ___________________________________________________________ 237
3.42.4 Algorithm ______________________________________________________________ 238
3.43 Java Hot Rod client ____________________________________________________________ 238
3.43.1 Introduction ____________________________________________________________ 238
3.43.2 Basic API ______________________________________________________________ 239
3.43.3 Versioned API __________________________________________________________ 240
3.43.4 Async API ______________________________________________________________ 240
3.43.5 Unsupported methods ____________________________________________________ 241
3.43.6 Return values ___________________________________________________________ 241
3.43.7 Intelligence _____________________________________________________________ 242
3.43.8 Hash-distribution-aware client ______________________________________________ 242
3.43.9 Request Balancing _______________________________________________________ 243
3.43.10Persistent connections ___________________________________________________ 243
3.43.11Marshalling data ________________________________________________________ 244
3.43.12Statistics ______________________________________________________________ 244
3.43.13Configuration ___________________________________________________________ 244
3.43.14Multi-Get Operations _____________________________________________________ 244
3.43.15More info ______________________________________________________________ 244
3.44 Configuring cache _____________________________________________________________ 244
3.44.1 Dynamically Start and Stop Clustered Cache __________________________________ 245
3.45 Write-Through And Write-Behind Caching __________________________________________ 246
3.45.1 Introduction ____________________________________________________________ 247
3.45.2 Write-Through (Synchronous) ______________________________________________ 247
3.45.3 Write-Behind (Asynchronous) ______________________________________________ 248
3.45.4 Unscheduled Write-Behind Strategy _________________________________________ 248
3.45.5 Scheduled Write-Behind Strategy ___________________________________________ 249
3.46 Cassandra CacheStore _________________________________________________________ 249
3.46.1 Version ________________________________________________________________ 249
3.46.2 ______________________________________________________________________ 249
Page 7 of 617
Infinispan 6.0
3.47 Infinispan Custom Interceptors ___________________________________________________ 251
3.47.1 Introduction ____________________________________________________________ 251
3.47.2 Adding custom interceptors declaratively ______________________________________ 252
3.47.3 Custom interceptor design _________________________________________________ 252
3.48 Talking To Infinispan Memcached Servers From Non-Java Clients _______________________ 253
3.48.1 Multi Clustered Server Tutorial ______________________________________________ 253
3.49 Plugging Infinispan With User Defined Externalizers __________________________________ 253
3.49.1 Introduction ____________________________________________________________ 254
3.49.2 Benefits of Externalizers __________________________________________________ 254
3.50 Using the Cache API ___________________________________________________________ 261
3.50.1 The Cache interface ______________________________________________________ 261
3.50.2 The AdvancedCache interface ______________________________________________ 264
3.51 Local mode cache _____________________________________________________________ 264
3.52 Infinispan Command-line Console ________________________________________________ 266
3.52.1 What is ispncon ? ________________________________________________________ 268
3.52.2 Installation _____________________________________________________________ 269
3.52.3 Basic usage ____________________________________________________________ 270
3.52.4 Configuration ___________________________________________________________ 271
3.52.5 Cache operations ________________________________________________________ 271
3.52.6 Other commands ________________________________________________________ 276
3.52.7 Interoperability with java clients _____________________________________________ 279
3.53 Server Command Line Options ___________________________________________________ 279
3.54 Interacting With Hot Rod Server From Within Same JVM _______________________________ 281
3.54.1 Introduction ____________________________________________________________ 282
3.54.2 Data Stored Directly Via A Hot Rod Client _____________________________________ 283
3.54.3 Data Stored Via Remote Cache Store ________________________________________ 283
3.55 Multiple Tiers of Caches ________________________________________________________ 285
3.55.1 Introduction ____________________________________________________________ 285
3.55.2 Building blocks __________________________________________________________ 285
3.55.3 Sample architecture/near caching ___________________________________________ 286
3.55.4 Want to know more? _____________________________________________________ 286
3.56 Infinispan REST Server _________________________________________________________ 286
3.56.1 Introduction ____________________________________________________________ 286
3.56.2 Configuration ___________________________________________________________ 287
3.56.3 Accessing Data - via URLs ________________________________________________ 288
3.56.4 Client side code _________________________________________________________ 288
3.56.5 Future: ________________________________________________________________ 291
3.57 CDI Support __________________________________________________________________ 291
3.57.1 Introduction ____________________________________________________________ 292
3.57.2 Maven Dependencies ____________________________________________________ 292
3.57.3 Embedded cache integration _______________________________________________ 292
3.57.4 Remote cache integration _________________________________________________ 296
3.57.5 Use a custom remote/embedded cache manager for one or more cache _____________ 299
3.57.6 Use a JBoss AS 7 configured cache _________________________________________ 300
3.57.7 Use JCache caching annotations ____________________________________________ 300
3.58 Marshalling __________________________________________________________________ 301
Page 8 of 617
Infinispan 6.0
3.58.1 Introduction ____________________________________________________________ 302
3.58.2 The Role Of JBoss Marshalling _____________________________________________ 302
3.58.3 Support For Non-Serializable Objects ________________________________________ 302
3.58.4 Advanced Configuration ___________________________________________________ 304
3.59 Batching ____________________________________________________________________ 307
3.59.1 Introduction ____________________________________________________________ 307
3.59.2 Configuring batching _____________________________________________________ 308
3.59.3 Batching API ___________________________________________________________ 308
3.59.4 Advanced: batching and JTA _______________________________________________ 309
3.60 Hot Rod Hash Functions ________________________________________________________ 310
3.61 Hot Rod Protocol ______________________________________________________________ 310
3.61.1 Hot Rod Protocol - Version 1.0 _____________________________________________ 310
3.61.2 Hot Rod Protocol - Version 1.1 _____________________________________________ 322
3.61.3 Hot Rod Protocol - Version 1.2 _____________________________________________ 335
3.62 Cross site replication ___________________________________________________________ 349
3.62.1 Sample deployment ______________________________________________________ 349
3.62.2 Data replication _________________________________________________________ 354
3.62.3 Taking a site offline ______________________________________________________ 356
3.62.4 Reference ______________________________________________________________ 357
3.63 Map Reduce framework ________________________________________________________ 357
3.63.1 Introduction ____________________________________________________________ 357
3.63.2 MapReduce API _________________________________________________________ 357
3.63.3 Mapper and CDI _________________________________________________________ 359
3.63.4 MapReduceTask distributed execution _______________________________________ 359
3.63.5 Examples ______________________________________________________________ 362
3.64 Rolling upgrades for remote clients using Hot Rod ____________________________________ 364
3.64.1 Steps _________________________________________________________________ 365
3.65 Command-Line Interface (CLI) ___________________________________________________ 365
3.65.1 Commands _____________________________________________________________ 367
3.65.2 Data Types _____________________________________________________________ 373
3.65.3 Time Values ____________________________________________________________ 374
3.66 Total Order based commit protocol ________________________________________________ 374
3.66.1 Introduction ____________________________________________________________ 374
3.66.2 Overview ______________________________________________________________ 374
3.66.3 Configuration ___________________________________________________________ 379
3.66.4 Total Order protocols in JGroups. ___________________________________________ 380
3.66.5 Benchmark results _______________________________________________________ 384
3.67 Using Infinispan as a JCache provider _____________________________________________ 387
3.67.1 Dependencies __________________________________________________________ 388
3.67.2 Create a local cache _____________________________________________________ 389
3.67.3 Store and retrieve data ____________________________________________________ 390
3.67.4 Comparing java.util.concurrent.ConcurrentMap and javax.cache.Cache APIs _________ 390
3.67.5 Clustering JCache instances _______________________________________________ 392
3.67.6 Expire cached data ______________________________________________________ 393
3.67.7 Annotations ____________________________________________________________ 393
3.67.8 Atomic compound operations on cache entry __________________________________ 393
Page 9 of 617
Infinispan 6.0
3.67.9 Using cache listeners _____________________________________________________ 394
3.67.10Quickstarts ____________________________________________________________ 394
3.68 Infinispan Server ______________________________________________________________ 394
3.68.1 Introduction ____________________________________________________________ 394
3.68.2 Protocols ______________________________________________________________ 394
3.68.3 Getting Started __________________________________________________________ 395
3.68.4 CLI ___________________________________________________________________ 395
3.68.5 Configuration ___________________________________________________________ 395
3.68.6 Hot Rod Server _________________________________________________________ 404
3.68.7 Memcached Server ______________________________________________________ 404
3.68.8 WebSocket Server _______________________________________________________ 406
3.69 Storing objects (e.g. arrays) with custom Equivalence functions _________________________ 410
3.69.1 The Problem of Caching Arrays _____________________________________________ 410
3.69.2 Old workaround: Wrapper Classes __________________________________________ 411
3.69.3 New solution: Plugging Equivalence functions __________________________________ 411
3.70 Interoperability between Embedded and Remote Server Endpoints _______________________ 416
3.70.1 Enable Compatibility Mode ________________________________________________ 416
3.70.2 Code examples _________________________________________________________ 417
3.71 Infinispan for HTTP session clustering and caching ___________________________________ 418
3.71.1 JBoss AS and WildFly ____________________________________________________ 418
3.71.2 Jetty __________________________________________________________________ 418
3.71.3 Other application servers and servlet containers ________________________________ 418
3.72 Design of data versioning in Infinispan _____________________________________________ 418
3.72.1 Overview ______________________________________________________________ 420
3.72.2 Configuration ___________________________________________________________ 421
3.73 Infinispan modules for JBoss AS 7.x _______________________________________________ 422
3.74 Infinispan with Groovy __________________________________________________________ 422
3.74.1 Introduction ____________________________________________________________ 423
3.74.2 Loading the configuration file _______________________________________________ 426
3.74.3 Basic cache configuration ____________________________________________________
3.74.4 Cache with transaction management _________________________________________ 428
3.74.5 Cache with a cache store __________________________________________________ 429
3.74.6 Cache with eviction ______________________________________________________ 432
3.74.7 Cache with eviction and cache store _________________________________________ 433
3.75 Using Infinispan with Scala ______________________________________________________ 433
3.75.1 Introduction ____________________________________________________________ 434
3.75.2 Environment ____________________________________________________________ 434
3.75.3 Testing Setup ___________________________________________________________ 434
3.75.4 Loading the Configuration file ______________________________________________ 435
3.75.5 Basic cache operations ___________________________________________________ 436
3.75.6 Basic cache operations with TTL ____________________________________________ 437
3.75.7 Cache restarts __________________________________________________________ 437
3.75.8 Transactional cache operations _____________________________________________ 437
3.75.9 Persistent stored backed Cache operations ___________________________________ 439
3.75.10Operating against a size bounded cache _____________________________________ 440
3.75.11Size bounded caches with persistent store ____________________________________ 441
Page 10 of 617
Infinispan 6.0
Size bounded caches with persistent store ___________________________________ 441
4 Upgrade Guide ___________________________________________________________________ 442
4.1 Upgrading from 5.0 to 5.1 _______________________________________________________ 442
4.1.1 API ___________________________________________________________________ 443
4.1.2 Eviction and Expiration ____________________________________________________ 444
4.1.3 Transactions ____________________________________________________________ 444
4.1.4 State transfer ___________________________________________________________ 444
4.1.5 Configuration ___________________________________________________________ 444
4.1.6 Flags and ClassLoaders __________________________________________________ 446
4.1.7 JGroups Bind Address ____________________________________________________ 446
4.1.8 Configuration changes from 5.0 to 5.1 ________________________________________ 446
4.2 Upgrading from 5.1 to 5.2 _______________________________________________________ 449
4.2.1 Declarative configuration __________________________________________________ 449
4.2.2 Transaction ____________________________________________________________ 449
4.2.3 Cache Loader and Store configuration _______________________________________ 449
4.2.4 Virtual Nodes > Segments _________________________________________________ 449
4.3 Upgrading from 5.2 to 5.3 _______________________________________________________ 450
5 Glossary ________________________________________________________________________ 451
5.1 Glossary ____________________________________________________________________ 451
5.2 2-phase commit _______________________________________________________________ 452
5.2.1 More resources _________________________________________________________ 452
5.3 Atomicity, Consistency, Isolation, Durability (ACID) ___________________________________ 452
5.4 Basically Available, Soft-state, Eventually-consistent (BASE) ___________________________ 452
5.4.1 More resources _________________________________________________________ 452
5.5 Cache Aside _________________________________________________________________ 452
5.6 Consistency, Availability and Partition-tolerance (CAP) Theorem ________________________ 453
5.6.1 More resources _________________________________________________________ 453
5.7 Consistent Hash ______________________________________________________________ 453
5.8 Data grid ____________________________________________________________________ 454
5.8.1 More resources _________________________________________________________ 454
5.9 Deadlock ____________________________________________________________________ 454
5.10 Distributed Hash Table (DHT) ____________________________________________________ 454
5.11 Externalizer __________________________________________________________________ 454
5.11.1 More resources _________________________________________________________ 454
5.12 Hot Rod _____________________________________________________________________ 455
5.12.1 More resources _________________________________________________________ 455
5.13 In-memory data grid ___________________________________________________________ 455
5.14 Isolation level _________________________________________________________________ 455
5.15 JTA synchronization ___________________________________________________________ 455
5.16 Livelock _____________________________________________________________________ 456
5.17 Memcached __________________________________________________________________ 456
5.17.1 More resource __________________________________________________________ 456
5.18 Multiversion Concurrency Control (MVCC) __________________________________________ 456
5.19 Near Cache __________________________________________________________________ 456
5.20 Network partition ______________________________________________________________ 456
5.21 NoSQL ______________________________________________________________________ 456
5.22 Optimistic locking _____________________________________________________________ 457
Page 11 of 617
Infinispan 6.0
5.23 Pessimistic locking ____________________________________________________________ 457
5.24 Read Ahead _________________________________________________________________ 457
5.25 READ COMMITTED ___________________________________________________________ 457
5.26 Relational Database Management System (RDBMS) __________________________________ 457
5.27 REPEATABLE READ __________________________________________________________ 458
5.28 Representational State Transfer (REST) ___________________________________________ 458
5.28.1 More resources _________________________________________________________ 458
5.29 Split brain ___________________________________________________________________ 458
5.30 Structured Query Language (SQL) ________________________________________________ 458
5.31 Write-behind _________________________________________________________________ 459
5.31.1 More resources _________________________________________________________ 459
5.32 Write skew ___________________________________________________________________ 459
5.33 Write-through _________________________________________________________________ 459
5.33.1 More resources _________________________________________________________ 459
5.34 XA resource __________________________________________________________________ 459
6 Extending Infinispan _______________________________________________________________ 460
6.1 Custom Commands ____________________________________________________________ 461
6.1.1 Preassigned Custom Command Id Ranges ____________________________________ 461
6.2 Writing custom commands in Infinispan ____________________________________________ 462
6.2.1 Preassigned Custom Command Id Ranges ____________________________________ 462
7 Contributing to Infinispan ____________________________________________________________ 463
7.1 The Basics ___________________________________________________________________ 465
7.1.1 Pre-requisites ___________________________________________________________ 466
7.1.2 Issue Management - JIRA _________________________________________________ 466
7.1.3 Source control - Git ______________________________________________________ 467
7.1.4 Build - Maven ___________________________________________________________ 474
7.1.5 Testing - TestNG ________________________________________________________ 474
7.1.6 Communicating with other Infinispan contributors _______________________________ 474
7.1.7 Style Requirements ______________________________________________________ 475
7.1.8 Configuration ___________________________________________________________ 475
7.1.9 Logging _______________________________________________________________ 475
7.2 Source Control _______________________________________________________________ 478
7.2.1 Pre-requisites ___________________________________________________________ 478
7.2.2 Repositories ____________________________________________________________ 478
7.2.3 Roles _________________________________________________________________ 478
7.2.4 Contributor License Agreement (CLA) ________________________________________ 487
7.2.5 Committing your work ____________________________________________________ 487
7.2.6 Keeping your repo in sync with upstream _____________________________________ 489
7.2.7 Tips on enhancing git _____________________________________________________ 491
7.3 Building Infinispan _____________________________________________________________ 494
7.3.1 Requirements ___________________________________________________________ 494
7.3.2 Quick command reference _________________________________________________ 496
7.3.3 Publishing releases to Maven ______________________________________________ 498
7.3.4 The Maven Archetypes ___________________________________________________ 498
7.4 API, Commons and Core _______________________________________________________ 501
7.4.1 API ___________________________________________________________________ 501
Page 12 of 617
Infinispan 6.0
7.4.2 Commons ______________________________________________________________ 501
7.4.3 Core __________________________________________________________________ 501
7.5 Running and Writing Tests ______________________________________________________ 501
7.5.1 Running the tests ________________________________________________________ 502
7.5.2 Test groups ____________________________________________________________ 505
7.5.3 Test permutations _______________________________________________________ 506
7.5.4 The Parallel Test Suite ____________________________________________________ 506
7.6 Helping Others Out ____________________________________________________________ 508
7.7 Adding Configuration ___________________________________________________________ 508
7.7.1 Adding a property ________________________________________________________ 509
7.7.2 Adding a group __________________________________________________________ 510
7.7.3 Don't forget to update the XSD and XSD test __________________________________ 510
7.7.4 Bridging to the old configuration _____________________________________________ 511
7.8 Writing Documentation and FAQs _________________________________________________ 511
7.8.1 Introduction ____________________________________________________________ 511
7.8.2 What goes where? _______________________________________________________ 512
7.8.3 Wiki markup or rich text ___________________________________________________ 512
7.8.4 Markup guide ___________________________________________________________ 512
7.8.5 Voice and grammar guide _________________________________________________ 517
7.8.6 Glossary _______________________________________________________________ 519
7.8.7 Screencasts ____________________________________________________________ 519
7.9 Managing this confluence instance. _______________________________________________ 520
7.10 Contributing - The Basics _______________________________________________________ 520
7.10.1 Pre-requisites ___________________________________________________________ 520
7.10.2 Issue Management - JIRA _________________________________________________ 520
7.10.3 Source control - Git ______________________________________________________ 521
7.10.4 Build - Maven ___________________________________________________________ 529
7.10.5 Testing - TestNG ________________________________________________________ 529
7.10.6 Communicating with other Infinispan contributors _______________________________ 529
7.10.7 Style Requirements ______________________________________________________ 530
7.10.8 Configuration ___________________________________________________________ 530
7.10.9 Logging _______________________________________________________________ 530
7.11 Contributing - Source Control ____________________________________________________ 533
7.11.1 Pre-requisites ___________________________________________________________ 533
7.11.2 Repositories ____________________________________________________________ 533
7.11.3 Roles _________________________________________________________________ 533
7.11.4 Contributor License Agreement (CLA) ________________________________________ 542
7.11.5 Committing your work ____________________________________________________ 542
7.11.6 Keeping your repo in sync with upstream _____________________________________ 544
7.11.7 Tips on enhancing git _____________________________________________________ 546
7.12 Contributing - The build _________________________________________________________ 549
7.12.1 Requirements ___________________________________________________________ 549
7.12.2 Quick command reference _________________________________________________ 551
7.12.3 Publishing releases to Maven ______________________________________________ 553
7.12.4 The Maven Archetypes ___________________________________________________ 553
7.12.5 The Maven Archetypes ___________________________________________________ 556
Page 13 of 617
Infinispan 6.0
7.13 Contributing - The test suite _____________________________________________________ 558
7.13.1 Running the tests ________________________________________________________ 559
7.13.2 Test groups ____________________________________________________________ 562
7.13.3 Test permutations _______________________________________________________ 563
7.13.4 The Parallel Test Suite ____________________________________________________ 563
7.14 Contributing - Helping Others Out _________________________________________________ 565
7.15 Contributing - Adding configuration options _________________________________________ 565
7.15.1 Adding a property ________________________________________________________ 566
7.15.2 Adding a group __________________________________________________________ 567
7.15.3 Don't forget to update the XSD and XSD test __________________________________ 567
7.15.4 Bridging to the old configuration _____________________________________________ 568
7.16 Contributing - Documentation and FAQs ___________________________________________ 568
7.16.1 Introduction ____________________________________________________________ 568
7.16.2 What goes where? _______________________________________________________ 569
7.16.3 Wiki markup or rich text ___________________________________________________ 569
7.16.4 Markup guide ___________________________________________________________ 569
7.16.5 Voice and grammar guide _________________________________________________ 574
7.16.6 Glossary _______________________________________________________________ 576
7.16.7 Screencasts ____________________________________________________________ 576
7.16.8 Managing this confluence instance. __________________________________________ 577
7.17 Contributing - API, Commons and Core ____________________________________________ 577
7.17.1 API ___________________________________________________________________ 577
7.17.2 Commons ______________________________________________________________ 577
7.17.3 Core __________________________________________________________________ 577
8 Frequently Asked Questions _________________________________________________________ 578
8.1 Project FAQs _________________________________________________________________ 578
8.2 Technical FAQs _______________________________________________________________ 578
8.3 Project Evaluation FAQs ________________________________________________________ 580
8.3.1 What is Infinispan? _______________________________________________________ 581
8.3.2 What would I use Infinispan for? ____________________________________________ 582
8.3.3 How is Infinispan related to JBoss Cache? ____________________________________ 583
8.3.4 What version of Java does Infinispan need to run? Does Infinispan need an application
server to run? __________________________________________________________________ 583
8.3.5 Will there be a POJO Cache replacement in Infinispan? __________________________ 583
8.3.6 How come Infinispan's first release is 4.0.0? This sounds weird! ___________________ 583
8.3.7 What should I use, JBoss Cache or Infinispan? _________________________________ 583
8.3.8 Where can I get more information on Infinispan? _______________________________ 584
8.3.9 How is this related to JSR 107, the JCACHE specification? _______________________ 584
8.3.10 Can I use Infinispan with Hibernate? _________________________________________ 585
8.4 Technical FAQs _______________________________________________________________ 585
8.4.1 General FAQs __________________________________________________________ 588
8.4.2 Cache Loaders and Cache Store FAQs _______________________________________ 590
8.4.3 Locking FAQs ___________________________________________________________ 592
8.4.4 Transaction FAQs _______________________________________________________ 594
8.4.5 Eviction and Expiration FAQs ______________________________________________ 594
8.4.6 Cache Manager FAQs ____________________________________________________ 596
Page 14 of 617
Infinispan 6.0
8.4.7 Cache Mode FAQs _______________________________________________________ 596
8.4.8 Listener FAQs __________________________________________________________ 601
8.4.9 Cloud FAQs ____________________________________________________________ 602
8.4.10 Demo FAQs ____________________________________________________________ 602
8.4.11 Query Module FAQs _____________________________________________________ 603
8.4.12 JBoss Application Server Integration FAQs ____________________________________ 604
8.4.13 Logging FAQs __________________________________________________________ 605
8.4.14 Third Party Container FAQs ________________________________________________ 605
8.4.15 Language FAQs _________________________________________________________ 606
8.4.16 Marshalling & Unmarshalling _______________________________________________ 606
8.4.17 Tuning FAQs ___________________________________________________________ 610
8.4.18 JNDI FAQs _____________________________________________________________ 611
8.4.19 Hibernate 2nd Level Cache FAQs ___________________________________________ 612
8.4.20 Cache Server FAQs ______________________________________________________ 613
8.4.21 Debugging FAQs ________________________________________________________ 614
8.4.22 Clustering Transport FAQs ________________________________________________ 614
8.4.23 CLI FAQs ______________________________________________________________ 615
9 Videos __________________________________________________________________________ 616
9.1 Monitoring ___________________________________________________________________ 616
9.2 Geographic failover ____________________________________________________________ 616
10 Contributor Dashboard _____________________________________________________________ 617
Page 15 of 617
Infinispan 6.0
Page 16 of 617
Infinispan 6.0
1 More Resources
DZone Refcard on Infinispan (Cheat sheet for developers)
Page 17 of 617
Infinispan 6.0
Target Audience
This guide shows you how to get started using Infinispan. It covers the common uses of Infinispan,
and shows you how to get off the ground. It also introduces to some of the essential concepts of
Infinispan.
Under development
This guide is still under development. The content you will find here is correct, but there are some
missing sections.
Introduction
Downloading and installing Infinispan
Infinispan in action - GUIDemo
Using Infinispan as an embedded cache in Java SE
Creating a new Infinispan project
Running Infinispan on a single node
Use the default cache
Use a custom cache
Using Infinispan as an embedded data grid in Java SE
Running Infinispan in a cluster
clustered-cache quickstart architecture
Configuring the cluster
Tweaking the cluster configuration for your network
Configuring a replicated data-grid
Configuring a distributed data-grid
Creating your own Infinispan project
Using Infinispan as a second level cache for Hibernate
Accessing an Infinispan data grid remotely
Using Hot Rod to access an Infinispan data-grid
Using REST to access an Infinipsan data-grid
Using memcached to access an Infinispan data-grid
Using Infinispan in JBoss AS 7
Using Infinispan in servlet containers (such as Tomcat or Jetty) and other application servers (such as
GlassFish)
Monitoring Infinispan
Page 18 of 617
Infinispan 6.0
2.1 Introduction
This guide will walk you through downloading, installing and running Infinispan for the first time. It will then
introduce to some of the key features of Infinispan.
Infinispan can be used in a variety of runtimes:
Java SE, started by your application
an application server which provides Infinispan as a service (such as JBoss AS)
bundled as a library in your application, deployed to an application server, and started on by your
application (for example, you could use Infinispan with Tomcat or GlassFish)
Infinispan offers four modes of operation, which determine how and where the data is stored:
Local, where entries are stored on the local node only, regardless of whether a cluster has formed. In
this mode Infinispan is typically operating as a local cache
Invalidation, where all entries are stored into a cache store (such as a database) only, and
invalidated from all nodes. When a node needs the entry it will load it from a cache store. In this mode
Infinispan is operating as a distributed cache, backed by a canonical data store such as a database
Replication, where all entries are replicated to all nodes. In this mode Infinispan is typically operating
as a data grid or a temporary data store, but doesn't offer an increased heap space
Distribution, where entries are distributed to a subset of the nodes only. In this mode Infinispan is
typically operating as a data grid providing an increased heap space
Invalidation, Replication and Distribution can all use synchronous or asynchronous communication.
Infinispan offers two access patterns, both of which are available in any runtime:
Embedded into your application code
As a Remote server accessed by a client (REST, memcached or Hot Rod)
This guide will introduce to each of the runtime options, access patterns and modes of operations by walking
you through simple applications for each. All these applications are available in the Infinispan Quickstart
distribution.
Page 19 of 617
Infinispan 6.0
If you already have any of these pieces of software, there is no need to install them again!
Choose your Java runtime, and follow their installation instructions. For example, you could choose one of:
OpenJDK
Oracle Java SE
Oracle JRockit
Follow the official Maven installation guide if you don't already have Maven 3 installed. You can check which
version of Maven you have installed (if any) by running mvn --version. If you see a version newer than
3.0.0, you are ready to go.
You can also deploy the examples using your favorite IDE. We provide instructions for using
Eclipse only.
Finally, download Infinispan and the Infinispan Quickstart from the download page.
embedded-cache quickstart
All the code discussed in this tutorial is available in the embedded-cache quickstart.
Page 20 of 617
Infinispan 6.0
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-embedded</artifactId>
<version>${infinispan.version}</version>
</dependency>
to your <dependencies> section of the POM. You'll need to substitute ${infinispan.version} for the
version of Infinispan you wish to use.
You'll also need to enable the JBoss Maven repository. We recommend adding a profile:
Page 21 of 617
Infinispan 6.0
pom.xml snippet
076.
077.
078.
079.
080.
081.
082.
083.
084.
085.
086.
087.
088.
089.
090.
091.
092.
093.
094.
095.
096.
097.
098.
099.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jboss-public-repository</id>
<activation>
<property>
<name>jboss-public-repository</name>
<value>!false</value>
</property>
</activation>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
Alternatively, you can use the POM from the quickstart that accompanies this tutorial.
If you are using Ant, or another build system which doesn't provide declarative dependency management,
then the Infinispan distribution zip contains a lib/ directory. Add the contents of this to the build classpath.
Page 22 of 617
Infinispan 6.0
We now need a way to run the main method! If you are using Maven, the best approach is to copy all the
project dependencies to a directory, and at the same time compile the java classes from our project:
You should see Infinispan start up, and the version in use logged to the console.
Congratulations, you now have Infinispan running as a local cache!
Page 23 of 617
Infinispan 6.0
// Add a entry
cache.put("key", "value");
// Validate the entry is now in the cache
assertEqual(1, cache.size());
assertTrue(cache.containsKey("key"));
// Remove the entry from the cache
Object v = cache.remove("key");
// Validate the entry is no longer in the cache
assertEqual("value", v);
By default entries are immortal but you can override this on a per-key basis and provide lifespans.
DefaultCacheQuickstart.java
58.
59.
//By default entries are immortal but we can override this on a per-key basis and
provide lifespans.
60.
cache.put("key", "value", 5, SECONDS);
61.
assertTrue(cache.containsKey("key"));
62.
Thread.sleep(10000);
Page 24 of 617
Infinispan 6.0
The example above uses Infinispan's fluent configuration, which offers the ability to configure your cache
programmatically. However, should you prefer to use XML, then you may. We can create an identical cache
to the one created with a programmatic configuration:
infinispan.xml
24. <infinispan
25.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
26.
xsi:schemaLocation="urn:infinispan:config:7.0
http://www.infinispan.org/schemas/infinispan-config-7.0.xsd"
27.
xmlns="urn:infinispan:config:7.0">
28.
29.
<cache-container default-cache="default">
30.
<local-cache name="xml-configured-cache">
31.
<eviction strategy="LIRS" max-entries="10" />
32.
</local-cache>
33.
</cache-container>
We then need to load the configuration file, and use the programmatically defined cache:
XmlConfiguredCacheQuickstart.java
29.
30.
public static void main(String args[]) throws Exception {
31.
Cache<Object, Object> c = new
DefaultCacheManager("infinispan.xml").getCache("xml-configured-cache");
Page 25 of 617
Infinispan 6.0
EmbeddedCacheManager cm = //
Cache<Object, Object> cache1
Cache<Object, Object> cache2
Cache<Object, Object> cache3
clustered-cache quickstart
All the code discussed in this tutorial is available in the clustered-cache quickstart.
The quickstart contains two examples of a clustered cache, one in replication mode and one distribution
mode. To run the replication mode example, we need to launch both nodes from different consoles. For the
first node:
Page 26 of 617
Infinispan 6.0
You should see JGroups and Infinispan start up on both consoles, and after about 15s the cache entry log
message appear on the console of the first node.
To run the distribution mode example, we need to launch three nodes from different consoles. For the first
node:
You should see JGroups and Infinispan start up on both consoles, and after about 15s see the 10 entries
added by third node distributed to the first and second nodes.
Page 27 of 617
Infinispan 6.0
import
import
import
import
import
import
import
org.infinispan.notifications.Listener;
org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent;
org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
org.infinispan.util.logging.Log;
org.infinispan.util.logging.LogFactory;
/**
* An Infinispan listener that simply logs cache entries being created and
* removed
*
* @author Pete Muir
*/
@Listener
public class LoggingListener {
private Log log = LogFactory.getLog(LoggingListener.class);
@CacheEntryCreated
public void observeAdd(CacheEntryCreatedEvent<?, ?> event) {
if (!event.isPre()) // So that message is only logged after operation succeeded
log.infof("Cache entry with key %s added in cache %s", event.getKey(),
event.getCache());
}
@CacheEntryRemoved
public void observeRemove(CacheEntryRemovedEvent<?, ?> event) {
log.infof("Cache entry with key %s removed in cache %s", event.getKey(),
event.getCache());
}
}
Listeners methods are declared using annotations, and receive a payload which contains metadata
about the notification. Listeners are notified of any changes. Here, the listeners simply log any
entries added or removed.
The replication mode example contains two nodes, each of which are started in a separate process. The
nodes are very simple, Node0 starts up, registers a listener that logs any changes, and waits for the cluster
to form. Node1 starts up, waits for the cluster to form, and then adds an entry. The interesting work happens
in the common super class, examined in Configuring a replicated data-grid.
Page 28 of 617
Infinispan 6.0
The distribution mode example contains three nodes, each of which are started in a separate process. The
nodes are very simple, Node0 and Node1 start up, register listeners that logs any changes, and wait for the
cluster to form. Node2 starts up, waits for the cluster to form, and then adds 20 entries. Each entry get's
distributed to it's owners, and you will see some entries add on Node0 and some on Node1. You'll notice
that Node2 gets notified of all adds - this is just because it is the node which adds the entry, it doesn't
reflect that the fact that all these entries are stored there! The interesting work happens in the common super
class, examined in Configuring a distributed data-grid.
Page 29 of 617
Infinispan 6.0
new ConfigurationBuilder()
.clustering().cacheMode(CacheMode.REPL_SYNC)
.build()
GlobalConfigurationBuilder.defaultClusteredBuilder()
.transport().addProperty("configurationFile", "jgroups.xml")
.build()
The JGroups documentation provides extensive advice on getting JGroups working on your
network. If you are new to configuring JGroups, you may get a little lost, so you might want to try
tweaking these configuration parameters:
Using the system property -Djgroups.bind_addr="127.0.0.1" causes JGroups to
bind only to your loopback interface, meaning any firewall you may have configured won't
get in the way. Very useful for testing a cluster where all nodes are on one machine.
TODO - add more tips!
You can also configure the JGroups properties to use in Infinispan's XML configuration:
<global>
<transport>
<properties>
<property name="configurationFile" value="jgroups.xml"/>
</properties>
</transport>
</global>
Page 30 of 617
Infinispan 6.0
<infinispan xsi:schemaLocation="urn:infinispan:config:5.1
http://www.infinispan.org/schemas/infinispan-config-5.1.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:infinispan:config:5.1">
<global>
<transport>
<properties>
<property name="configurationFile" value="jgroups.xml"/>
</properties>
</transport>
</global>
<default>
<!-- Configure a synchronous replication cache -->
<clustering mode="replication">
<sync/>
</clustering>
</default>
</infinispan>
Page 31 of 617
Infinispan 6.0
new ConfigurationBuilder()
.clustering()
.cacheMode(CacheMode.DIST_SYNC)
.hash().numOwners(2)
.build()
<default>
<!-- Configure a synchronous replication cache -->
<clustering mode="distribution">
<sync/>
<hash numOwners="2"/>
</clustering>
</default>
Page 32 of 617
Infinispan 6.0
Page 33 of 617
Infinispan 6.0
Page 34 of 617
Infinispan 6.0
If you already have any of these pieces of software, there is no need to install them again!
Choose your Java runtime, and follow their installation instructions. For example, you could choose one of:
OpenJDK
Oracle Java SE
Oracle JRockit
Follow the official Maven installation guide if you don't already have Maven 3 installed. You can check which
version of Maven you have installed (if any) by running mvn --version. If you see a version newer than
3.0.0, you are ready to go.
You can also deploy the examples using your favorite IDE. We provide instructions for using
Eclipse only.
Finally, download Infinispan and the Infinispan Quickstart from the download page.
embedded-cache quickstart
All the code discussed in this tutorial is available in the embedded-cache quickstart.
Page 35 of 617
Infinispan 6.0
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-embedded</artifactId>
<version>${infinispan.version}</version>
</dependency>
to your <dependencies> section of the POM. You'll need to substitute ${infinispan.version} for the
version of Infinispan you wish to use.
You'll also need to enable the JBoss Maven repository. We recommend adding a profile:
Page 36 of 617
Infinispan 6.0
pom.xml snippet
076.
077.
078.
079.
080.
081.
082.
083.
084.
085.
086.
087.
088.
089.
090.
091.
092.
093.
094.
095.
096.
097.
098.
099.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jboss-public-repository</id>
<activation>
<property>
<name>jboss-public-repository</name>
<value>!false</value>
</property>
</activation>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
Alternatively, you can use the POM from the quickstart that accompanies this tutorial.
If you are using Ant, or another build system which doesn't provide declarative dependency management,
then the Infinispan distribution zip contains a lib/ directory. Add the contents of this to the build classpath.
Page 37 of 617
Infinispan 6.0
We now need a way to run the main method! If you are using Maven, the best approach is to copy all the
project dependencies to a directory, and at the same time compile the java classes from our project:
You should see Infinispan start up, and the version in use logged to the console.
Congratulations, you now have Infinispan running as a local cache!
Page 38 of 617
Infinispan 6.0
// Add a entry
cache.put("key", "value");
// Validate the entry is now in the cache
assertEqual(1, cache.size());
assertTrue(cache.containsKey("key"));
// Remove the entry from the cache
Object v = cache.remove("key");
// Validate the entry is no longer in the cache
assertEqual("value", v);
By default entries are immortal but you can override this on a per-key basis and provide lifespans.
DefaultCacheQuickstart.java
58.
59.
//By default entries are immortal but we can override this on a per-key basis and
provide lifespans.
60.
cache.put("key", "value", 5, SECONDS);
61.
assertTrue(cache.containsKey("key"));
62.
Thread.sleep(10000);
Page 39 of 617
Infinispan 6.0
The example above uses Infinispan's fluent configuration, which offers the ability to configure your cache
programmatically. However, should you prefer to use XML, then you may. We can create an identical cache
to the one created with a programmatic configuration:
infinispan.xml
24. <infinispan
25.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
26.
xsi:schemaLocation="urn:infinispan:config:7.0
http://www.infinispan.org/schemas/infinispan-config-7.0.xsd"
27.
xmlns="urn:infinispan:config:7.0">
28.
29.
<cache-container default-cache="default">
30.
<local-cache name="xml-configured-cache">
31.
<eviction strategy="LIRS" max-entries="10" />
32.
</local-cache>
33.
</cache-container>
We then need to load the configuration file, and use the programmatically defined cache:
XmlConfiguredCacheQuickstart.java
29.
30.
public static void main(String args[]) throws Exception {
31.
Cache<Object, Object> c = new
DefaultCacheManager("infinispan.xml").getCache("xml-configured-cache");
Page 40 of 617
Infinispan 6.0
EmbeddedCacheManager cm = //
Cache<Object, Object> cache1
Cache<Object, Object> cache2
Cache<Object, Object> cache3
clustered-cache quickstart
All the code discussed in this tutorial is available in the clustered-cache quickstart.
The quickstart contains two examples of a clustered cache, one in replication mode and one distribution
mode. To run the replication mode example, we need to launch both nodes from different consoles. For the
first node:
You should see JGroups and Infinispan start up on both consoles, and after about 15s the cache entry log
message appear on the console of the first node.
Page 41 of 617
Infinispan 6.0
To run the distribution mode example, we need to launch three nodes from different consoles. For the first
node:
You should see JGroups and Infinispan start up on both consoles, and after about 15s see the 10 entries
added by third node distributed to the first and second nodes.
Page 42 of 617
Infinispan 6.0
import
import
import
import
import
import
import
org.infinispan.notifications.Listener;
org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent;
org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
org.infinispan.util.logging.Log;
org.infinispan.util.logging.LogFactory;
/**
* An Infinispan listener that simply logs cache entries being created and
* removed
*
* @author Pete Muir
*/
@Listener
public class LoggingListener {
private Log log = LogFactory.getLog(LoggingListener.class);
@CacheEntryCreated
public void observeAdd(CacheEntryCreatedEvent<?, ?> event) {
if (!event.isPre()) // So that message is only logged after operation succeeded
log.infof("Cache entry with key %s added in cache %s", event.getKey(),
event.getCache());
}
@CacheEntryRemoved
public void observeRemove(CacheEntryRemovedEvent<?, ?> event) {
log.infof("Cache entry with key %s removed in cache %s", event.getKey(),
event.getCache());
}
}
Listeners methods are declared using annotations, and receive a payload which contains metadata
about the notification. Listeners are notified of any changes. Here, the listeners simply log any
entries added or removed.
The replication mode example contains two nodes, each of which are started in a separate process. The
nodes are very simple, Node0 starts up, registers a listener that logs any changes, and waits for the cluster
to form. Node1 starts up, waits for the cluster to form, and then adds an entry. The interesting work happens
in the common super class, examined in Configuring a replicated data-grid.
Page 43 of 617
Infinispan 6.0
The distribution mode example contains three nodes, each of which are started in a separate process. The
nodes are very simple, Node0 and Node1 start up, register listeners that logs any changes, and wait for the
cluster to form. Node2 starts up, waits for the cluster to form, and then adds 20 entries. Each entry get's
distributed to it's owners, and you will see some entries add on Node0 and some on Node1. You'll notice
that Node2 gets notified of all adds - this is just because it is the node which adds the entry, it doesn't
reflect that the fact that all these entries are stored there! The interesting work happens in the common super
class, examined in Configuring a distributed data-grid.
Page 44 of 617
Infinispan 6.0
new ConfigurationBuilder()
.clustering().cacheMode(CacheMode.REPL_SYNC)
.build()
GlobalConfigurationBuilder.defaultClusteredBuilder()
.transport().addProperty("configurationFile", "jgroups.xml")
.build()
The JGroups documentation provides extensive advice on getting JGroups working on your
network. If you are new to configuring JGroups, you may get a little lost, so you might want to try
tweaking these configuration parameters:
Using the system property -Djgroups.bind_addr="127.0.0.1" causes JGroups to
bind only to your loopback interface, meaning any firewall you may have configured won't
get in the way. Very useful for testing a cluster where all nodes are on one machine.
TODO - add more tips!
You can also configure the JGroups properties to use in Infinispan's XML configuration:
<global>
<transport>
<properties>
<property name="configurationFile" value="jgroups.xml"/>
</properties>
</transport>
</global>
Page 45 of 617
Infinispan 6.0
<infinispan xsi:schemaLocation="urn:infinispan:config:5.1
http://www.infinispan.org/schemas/infinispan-config-5.1.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:infinispan:config:5.1">
<global>
<transport>
<properties>
<property name="configurationFile" value="jgroups.xml"/>
</properties>
</transport>
</global>
<default>
<!-- Configure a synchronous replication cache -->
<clustering mode="replication">
<sync/>
</clustering>
</default>
</infinispan>
Page 46 of 617
Infinispan 6.0
new ConfigurationBuilder()
.clustering()
.cacheMode(CacheMode.DIST_SYNC)
.hash().numOwners(2)
.build()
<default>
<!-- Configure a synchronous replication cache -->
<clustering mode="distribution">
<sync/>
<hash numOwners="2"/>
</clustering>
</default>
NOTE: You will need either the -bin.zip or -all.zip version for this demo.
Page 47 of 617
Infinispan 6.0
Page 48 of 617
Infinispan 6.0
2.17.1 Configuration
Unlike previous releases of JBoss AS, JBoss AS 7 centralizes all server configuration into one location. This
include Infinispan cache configurations, which are defined by the Infinispan subsystem:
$JBOSS_HOME/domain/configuration/domain.xml
The complete schema for the Infinispan subsystem is included in the AS7 binary distribution
$JBOSS_HOME/docs/schema/jboss-infinispan.xsd.
If you are familiar with Infinispan's native configuration file format or the corresponding configuration file from
JBoss AS 6, you'll notice some obvious similarities, but some noteworthy differences.
While a native Infinispan configuration file contains cache configurations for a single cache managers, like
JBoss AS 6, the Infinispan subsystem configuration defines multiple cache managers, each identified by a
name. As with AS6, cache managers can have 1 or more aliases.
Page 49 of 617
Infinispan 6.0
Being concise
The Infinispan subsystem's configuration schema attempts to be more concise than the equivalent
configuration in JBoss AS 6. This is a direct result of the following changes:
Where is <global/> ?
Much of the global configuration contains references to other JBoss AS services. In JBoss AS 7, these
services are auto-injected behind the scenes. This includes things like thread pools (described below), the
JGroups transport (also described below), and the mbean server.
https://github.com/jbossas/jboss-as/blob/master/clustering/infinispan/src/main/resources/i
.
Where is <default/> ?
The semantics of the default cache of a cache container are different in JBoss AS 7 than in native Infinispan.
In native Infinispan, the configuration within <default/> defines the cache returned by calls to
CacheContainer.getCache(), while <namedCache/> entries inherit the configuration from the default
cache.
In JBoss AS 7, all caches defined in the Infinispan subsystem are named caches. The default-cache
attribute identifies which named cache should be returned by calls to CacheContainer.getCache(). This
lets you easily modify the default cache of a cache container, without having to worry about rearranging
configuration property inheritance.
Page 50 of 617
Infinispan 6.0
Specifying a transport
The Infinispan subsystem uses with the JGroups subsystem to provide it's JGroups channel. By default,
cache containers use the default-stack as defined by the JGroups subsystem.
Changing the default stack for all clustering services is a simple as changing the default-stack attribute
defined in the JGroups subsystem. An individual cache-container can opt to use a particular stack by
specifying a stack attribute within its transport element. For example:
Page 51 of 617
Infinispan 6.0
Page 52 of 617
Infinispan 6.0
@ManagedBean
public class MyBean<K, V> {
@Resource(lookup="java:jboss/infinispan/my-container-name")
private org.infinispan.manager.CacheContainer container;
private org.infinispan.Cache<K, V> cache;
@PostConstruct
public void start() {
this.cache = this.container.getCache();
}
}
That's it! No JBoss specific classes required - only standard annotations. Pretty neat, no?
There's only one catch - due to the JBoss AS's use of modular classloading, Infinispan classes are not
available to deployments by default. You need to explicitly tell the AS to import the Infinispan API into your
application. This is most easily done by adding the following line to your application's
META-INF/MANIFEST.MF:
Page 53 of 617
Infinispan 6.0
If you're using maven you can achieve that simply by adding this configuration to you pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<!-- Java EE 6 doesn't require web.xml, Maven needs to catch up! -->
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifestEntries>
<Dependencies>org.infinispan export</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
So, how does it all work? If you recall, during server startup, JBoss AS creates and registers an on-demand
service for every Infinispan cache container defined in the Infinispan subsystem. For every cache container,
the Infinispan subsystem also creates and registers a JNDI binding service that depends on the associated
cache container service. When the JBoss AS deployer encounters the @Resource annotation, it
automatically adds a dependency to the application on the JNDI binding service associated with the
specified JNDI name. In the case of the Infinispan JNDI binding, the binding itself already depends on the
relevant Infinispan cache container service. The net effect is, your application will include a dependency on
the requested cache container. Consequently, the cache container will automatically start on deploy, and
stop (including all caches) on undeploy.
2.18 Labs
2.18.1 A list of the labs developed for Infinispan
Page 54 of 617
Infinispan 6.0
Setup
Getting setup to run the lab
presented by Pete
5 minutes
Using Infinispan 5.1.0.FINAL
Download the lab zip from
[...]
Unzip the lab to your disk to a location of your choice
If you are a git user, you can clone the repository:
each stage of this lab has a checkpoint which is a branch, you can check out the code for each
Checkpoint using. Checkpoints are mentioned in these instructions:
Introduction
Use cases, key features and benefits of Infinispan
slides, presented by Pete
20 minutes
Page 55 of 617
Infinispan 6.0
Sample project
Explanation of sample project architecture
presented by Pete
5 minutes
The lab is a simple ticket allocation and booking system
lab1 contains a project skeleton with the relevant dependencies available. It is a war, that can be
deployed on JBoss AS 7. It also use CDI to wire together the app, and JSF for the view layer. JMS is
used to provide messaging and EJB to provide a listener for messages we send via JMS.
In another console, start JBoss AS - $JBOSS_HOME/bin/standalone.sh
Deploy the project to JBoss AS 7 using mvn clean package jboss-as:deploy
visit http://localhost:8080/lab1
All cache operations hidden by service layer to allow us to swap out caching impls
Starts with a HashMap and builds on that
Import the project into your IDE, we use Eclipse with m2eclipse installed.
Show project
Checkpoint 1
Page 56 of 617
Infinispan 6.0
with
@Inject @TicketAllocationCache
private Cache<String, TicketAllocation> tickets;
Page 57 of 617
Infinispan 6.0
return tickets.get(id);
if (tickets.getConfiguration().getCacheMode() != CacheMode.LOCAL)
return tickets.getAdvancedCache().getCacheManager().getAddress().toString();
else
return "local cache";
if (tickets.getConfiguration().getCacheMode() != CacheMode.LOCAL) {
return asCommaSeparatedList(tickets.getAdvancedCache().getDistributionManager().locate(key));
} else {
return "local";
}
Page 58 of 617
Infinispan 6.0
Demo
Use Case: Have ticket allocations freed up after a period of time*
Add expiration to allocateTicket(), so you end up with
Run the demo, and you can see that entries disappear after 10s
Checkpoint 3
Page 59 of 617
Infinispan 6.0
6. Listeners
presented by Mircea
10 minutes
Use case: Prevent known ticket touts from using the system
First, copy in the AbuseListener in
Now, we need to register it
Add
@Inject
public void registerAbuseListener(@New AbuseListener abuseListener) {
tickets.addListener(abuseListener);
}
to the InfinispanTicketService.
this code simply creates a new abuse listener (injected by CDI with a logger!) and registers it with
Infinispan. It will do it automatically when the InfinispanTicketService is created
Increase expiration to 3 minutes, otherwise the demo will get tiresome!
Checkpoint 4
Transactions in action
Use Case: When ticket is booked, need to atomically take payment and book ticket, and rollback if
any errors
The webapp collects all the data from the user to process the booking, and then sends the booking to
the backend using JMS.
JBoss comes with a "test" queue, we'll abuse that so we don't have to configure messaging (not what
we are here to talk about).
Go to the pom.xml and uncomment JMS dependency
Copy the PaymentProcessor into .services
Inject JMS into InfinispanTicketService
Page 60 of 617
Infinispan 6.0
@Resource(mappedName="/ConnectionFactory")
private ConnectionFactory cf;
@Resource(mappedName = "queue/test")
private Queue queue;
try {
Connection connection = cf.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer publisher = session.createProducer(queue);
connection.start();
TextMessage message = session.createTextMessage("Book ticket for " + id);
publisher.send(message);
connection.close();
session.close();
} catch (JMSException e) {
throw new RuntimeException(e);
}
.transaction().transactionMode(TransactionMode.TRANSACTIONAL)
.transaction().transactionManagerLookup(new GenericTransactionManagerLookup())
@Resource(mappedName="/JmsXA")
private XAConnectionFactory cf;
@Resource(mappedName = "java:jboss/TransactionManager")
private TransactionManager tm;
Page 61 of 617
Infinispan 6.0
try {
XAConnection connection = null;
try {
connection = cf.createXAConnection();
connection.start();
XASession xaSession = connection.createXASession();
Session session = xaSession.getSession();
MessageProducer publisher = session.createProducer(queue);
TextMessage message = session.createTextMessage("Book ticket for " + id);
tm.begin();
tm.getTransaction().enlistResource(xaSession.getXAResource());
//following two ops need to be atomic (XA)
tickets.remove(id);
publisher.send(message);
tm.commit();
} finally {
if (connection != null) connection.close();
}
} catch (Throwable e) {
// ignore - don't do this at home :)
e.printStackTrace();
}
Break
15 minutes
Page 62 of 617
Infinispan 6.0
Distribution
presented by Sanne
15 minutes
Use case: we have so many tickets being allocated we've run out of heap on one machine, so add
some more!
During the break we added support for distribution. Take you through the changes now
Enable distribution mode in Resources
.clustering()
.mode(CacheMode.DIST_SYNC)
.l1().disable()
Make JGroups use the loopback interface to avoid network problems! Add
@Produces @ApplicationScoped
public EmbeddedCacheManager configureCacheManager() {
return new DefaultCacheManager(
GlobalConfigurationBuilder.defaultClusteredBuilder()
.transport()
.addProperty("configurationFile", "jgroups.xml")
.build());
}
Interlude - JBoss AS 7
Topics discussed include:
Introduce AS7
Cover domain mode vs standalone
Domain mode a great way to stand up a cluster of nodes!
Explain management options (CLI, web, maven plugin, XML, filesystem)
Talk about Infinispan as managed service in AS7 vs embedded - we could have used either, but to
get started quickly it's easy to embed!
Show 5 servers configured in $JBOSS_HOME/domain/configuration/host.xml - explain about
port bindings. If you are following along, add only these servers
Page 63 of 617
Infinispan 6.0
$JBOSS_HOME/domain/configuration/host.xml
<servers>
<server name="server-one" group="main-server-group">
<!-- server-one inherits the default socket-group declared in the server-group -->
</server>
<server name="server-two" group="main-server-group" auto-start="true">
<!-- server-two avoids port conflicts by incrementing the ports in
the default socket-group declared in the server-group -->
<socket-binding-group ref="standard-sockets" port-offset="100"/>
</server>
<server name="server-three" group="main-server-group" auto-start="true">
<!-- server-two avoids port conflicts by incrementing the ports in
the default socket-group declared in the server-group -->
<socket-binding-group ref="standard-sockets" port-offset="200"/>
</server>
<server name="server-four" group="main-server-group" auto-start="true">
<!-- server-two avoids port conflicts by incrementing the ports in
the default socket-group declared in the server-group -->
<socket-binding-group ref="standard-sockets" port-offset="300"/>
</server>
<server name="server-five" group="rest-server-group" auto-start="true">
<!-- server-two avoids port conflicts by incrementing the ports in
the default socket-group declared in the server-group -->
<socket-binding-group ref="standard-sockets" port-offset="1000"/>
</server>
</servers>
Now, define the server groups. We'll also add server group for the REST interface which we'll see in a
minute:
$JBOSS_HOME/domain/configuration/domain.xml
<server-groups>
<server-group name="main-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
<permgen size="128m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
<server-group name="rest-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
<permgen size="128m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
</server-groups>
Page 64 of 617
Infinispan 6.0
Note that nodes don't get much memory by default, we need to increase it
Interlude - What modes can Infinispan run in? When would you want to use them?
Topics discussed include:
What are the different modes?
When would you use the modes?
How does distribution work?
Explain CH, benefits and problems
Talk about vnodes to even distribution
Page 65 of 617
Infinispan 6.0
L1 cache
presented by Sanne
5 minutes
Explain benefits (TODO)
Start up 4 JBoss AS 7 nodes with $JBOSS_HOME/bin/domain.sh
Build latest using mvn package and in another terminal change into the project and bring up JBoss
AS CLI jboss-admin.sh --connect
Deploy app from console using deploy target/lab1.war
--server-groups=main-server-group
App now deployed to each node
bring up all 4 nodes in a web browser (port offset 100)
Just like before, except that nodes 1 & 2 are still showing all entries locally (they kept them in their
cache)
Find a node that doesn't have all entries, and query for an entry that isn't on that node. Then hit
refresh. Show that this time it's now local (L1 cache)
Show the same for putting a new entry - keep adding until you get one that isn't owned by the current
node - show that it is in the local node still.
Checkpoint 6
Page 66 of 617
Infinispan 6.0
CacheStores
presented by Mircea
10 minutes
Use case: Persist your data to disk in case of node restart
paste the JDBC cache config method from src/sample/java/jdbc.txt
Walk through the JDBC cache store set up code
Add this to the configuration:
Page 67 of 617
Infinispan 6.0
.loaders()
.shared(true)
.addCacheLoader()
.cacheLoader(new JdbcStringBasedCacheStore())
.addProperty("connectionFactoryClass",
"org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory")
.addProperty("datasourceJndiLocation", "java:jboss/datasources/ExampleDS")
.addProperty("idColumnType", "VARCHAR(255)")
.addProperty("idColumnName", "ID_COLUMN")
.addProperty("dataColumnType", "BINARY")
.addProperty("dataColumnName", "DATA_COLUMN")
.addProperty("timestampColumnName", "TIMESTAMP_COLUMN")
.addProperty("timestampColumnType", "BIGINT")
.addProperty("stringsTableNamePrefix", "persistentStore")
.addProperty("userName", "sa")
.addProperty("password", "sa")
.async().threadPoolSize(10)
Interlude - What Cache Stores are available? In what scenarios can they be used?
Topics discussed include:
Modes of cache store usage
CacheStores available as built in
Page 68 of 617
Infinispan 6.0
Bonus topics
Querying Infinispan
presented by Sanne
8 minutes
Topics discussed include:
TODO
Hibernate OGM
presented by Sanne
2 minutes
Topics discussed include:
TODO
Reduce
presented by Pete
5 minutes
Topics discussed include:
TODO
Conclusion
presented by Pete
10 minutes
Page 69 of 617
Infinispan 6.0
3 User Guide
1. What is Infinispan, and why would you use it?
1. [Project Roadmap]
2. [Public Articles on Infinispan]
3. Cheat Sheet on using Infinispan, for Developers
2. Configuring and creating a cache
1. Programmatically
2. Declaratively
3. Configuration migration tools
4. Clustered Configuration QuickStart
3. Using the Cache API
1. Storing and retrieving data
2. Listeners and Notifications
3. The Asynchronous API
4. Using per-invocation flags
5. The Grouping API
4. Eviction
1. Configuring eviction and the eviction thread
2. Expiration
3. Examples
5. Cache Loaders
1. Configuring cache loaders
2. Passivation
3. Cache loaders shipped with Infinispan
4. Write-Through And Write-Behind Caching
5. Cache loaders and transactional caches
6. JTA transactions
1. Configuring your cache to work with JTA
2. Deadlock detection
3. Batching API
4. Recovery
7. Locking and concurrency
1. Data Versioning
2. MVCC: Infinispan's concurrency model
3. Tuning concurrency level and lock striping
4. Explicit locking and the lock() methods
8. Clustering modes
1. Replication and invalidation
2. Distribution
1. L1 caching
2. Generating keys mapped to specific cluster nodes
3. Asynchronous options
9. Non-clustered, LOCAL mode
Page 70 of 617
Infinispan 6.0
10. Marshalling
1. Lazy deserialization (storeAsBinary)
11. CDI Support
12. Management tooling
1. JMX
2. RHQ
3. Writing plugins for other management tools
13. The REST server
1. Accessing data in Infinispan via RESTful interface
14. Infinispan as a Directory for Lucene
15. Running Infinispan on Amazon Web Services
16. Querying Infinispan
1. [SQL-like querying of Infinispan]
17. Writing custom interceptors
18. Using Tree API module
19. Infinispan and Grails
20. Configuration reference
1. Default values for property based configuration attributes
21. JMX attributes and operations
22. API docs (Javadocs)
23. Infinispan command-line console
24. Infinispan for HTTP session clustering and caching
Page 71 of 617
Infinispan 6.0
Page 72 of 617
Infinispan 6.0
Configuration
Indexing must be enabled in the configuration (as explained in XML Configuration or Programmatic
configuration).
This will trigger automatic indexing of objects stored in the cache; there are several different ways to specify
how these objects need to be indexed explained in the following paragraphs.
To run queries you use the SearchManager which exposes all necessary methods to get started.
Page 73 of 617
Infinispan 6.0
Now assuming we stored several Book instances in our Infinispan Cache, we can search them for any
matching field as in the following example.
A Lucene Query is often created by parsing a query in text format such as "title:infinispan AND
authors.name:sanne", or by using the query builder provided by Hibernate Search.
Page 74 of 617
Infinispan 6.0
A part from list() you have the option for streaming results, or use pagination.
This barely scratches the surface of all what is possible to do: see the Hibernate Search reference
documentation to learn about sorting, numeric fields, declarative filters, caching filters, complex object graph
indexing, custom types and the powerful faceting search API.
Page 75 of 617
Infinispan 6.0
@Transformable(transformer = CustomTransformer.class)
public class CustomKey {
...
}
public class CustomTransformer implements Transformer {
@Override
public Object fromString(String s) {
...
return new CustomKey(...);
}
@Override
public String toString(Object customType) {
CustomKey ck = (CustomKey) customType;
return ...
}
}
@ProvidedId
The org.hibernate.search.annotations.ProvidedId annotation lets you apply advanced indexing options to the
key field: the field name to be used, and/or specify a custom FieldBridge.
Page 76 of 617
Infinispan 6.0
3.6.3 Configuration
Configuration via XML
To enable indexing via XML, you need to add the <indexing ... /> element to your cache configuration, and
optionally pass additional properties to the embedded Hibernate Search engine:
In this example the index is stored in memory, so when this nodes is shutdown the index is lost: good for a
quick demo, but in real world cases you'll want to use the default (store on filesystem) or store the index in
Infinispan as well. For the complete reference of properties to define, refer to the Hibernate Search
documentation.
Lucene Directory
Infinispan Query isn't aware of where you store the indexes, it just passes the configuration of which Lucene
Directory implementation you want to use to the Hibernate Search engine. There are several Lucene
Directory implementations bundled, and you can plug your own or add third party implementations: the
Directory is the IO API for Lucene to store the indexes.
The most common Lucene Directory implementations used with Infinispan Query are:
Ram - stores the index in a local map to the node. This index can't be shared.
Filesystem - stores the index in a locally mounted filesystem. This could be a network shared FS, but
sharing this way is generally not recommended.
Infinispan - stores the index in a different dedicated Infinispan cache. This cache can be configured as
replicated or distributed, to share the index among nodes. See also Infinispan as a storage for Lucene
indexes.
Of course having a shared index vs. an independent index on each node directly affects behaviour of the
Query module; some combinations might not make much sense.
Page 77 of 617
Infinispan 6.0
LOCAL
In local mode, you may use any Lucene Directory implementation. Also the option indexLocalOnly isn't
meaningful.
Page 78 of 617
Infinispan 6.0
REPLICATION
In replication mode, each node can have it's own local copy of the index. So indexes can either be stored
locally on each node (RAMDirectory, FSDirectory, etc) but you need to set indexLocalOnly to false , so that
each node will apply needed updates it receives from other nodes in addition to the updates started locally.
Any Directory implementation can be used, but you have to make sure that when a new node is started it
receives an up to date copy of the index; typically rsync is well suited for this task, but being an external
operation you might end up with a slightly out-of-sync index, especially if updates are very frequent.
Alternately, if you use some form of shared storage for indexes (see Sharing the Index ), you then have to
set indexLocalOnly to true so that each node will apply only the changes originated locally; in this case
there's no risk in having an out-of-sync index, but to avoid write contention on the index you should make
sure that a single node is "in charge" of updating the index. Again, the Hibernate Search reference
documentation describes means to use a JMS queue or JGroups to send indexing tasks to a master node.
The diagram below shows a replicated deployment, in which each node has a local index.
Page 79 of 617
Infinispan 6.0
DISTRIBUTION
For these 2 cache modes, you need to use a shared index and set indexLocalOnly to true.
The diagram below shows a deployment with a shared index. Note that while not mandatory, a shared index
can be used for replicated (vs. distributed) caches as well.
INVALIDATION
Indexing or searching of elements under INVALIDATION mode is not supported.
Page 80 of 617
Infinispan 6.0
There is currently one limitation: the MassIndexer is implemented using Map/Reduce, which in
Infinispan 5.2 requires the underlying caches to use distribution. In other words, the MassIndexer
isn't currently functional in LOCAL and REPL cache modes.
Page 81 of 617
Infinispan 6.0
Let assume that a new synchronously replicated cache is to be configured programmatically. First, a fresh
instance of Configuration object is created using ConfigurationBuilder helper object, and the cache mode is
set to synchronous replication. Finally, the configuration is defined/registered with a manager.
Configuration c = new
ConfigurationBuilder().clustering().cacheMode(CacheMode.REPL_SYNC).build();
String newCacheName = "repl";
manager.defineConfiguration(newCacheName, c);
Cache<String, String> cache = manager.getCache(newCacheName);
The default cache configuration (or any other cache configuration) can be used as a starting point for
creation of a new cache. For example, lets say that infinispan-config-file.xml specifies a replicated
cache as a default and that a distributed cache is desired with a specific L1 lifespan while at the same time
retaining all other aspects of a default cache. Therefore, the starting point would be to read an instance of a
default Configuration object and use ConfigurationBuilder to construct and modify cache mode and L1
lifespan on a new Configuration object. As a final step the configuration is defined/registered with a
manager.
As long as the based configuration is the default named cache, the previous code works perfectly fine.
However, other times the base configuration might be another named cache. So, how can new
configurations be defined based on other defined caches? Take the previous example and imagine that
instead of taking the default cache as base, a named cache called "replicatedCache" is used as base. The
code would look something like this:
Page 82 of 617
Infinispan 6.0
Sometimes you might also want to get global JMX statistics and information about the transport, or the
cache manager in general. To enable global JMX statistics simply do:
Further options at the global JMX statistics level allows you for example to configure the cache manager
name which comes handy when you have multiple cache managers running on the same system, or how to
locate the JMX MBean Server:
Some of the Infinispan features are powered by a group of the thread pool executors which can also be
tweaked at this global level. For example:
Page 83 of 617
Infinispan 6.0
You can not only configure global, cache manager level, options, but you can also configure cache level
options such as the cluster mode:
An application might also want to interact with an Infinispan cache within the boundaries of JTA and to do
that you need to configure the transaction layer and optionally tweak the locking settings. When interacting
with transactional caches, you might want to enable recovery to deal with transactions that finished with an
heuristic outcome and if you do that, you will often want to enable JMX management and statistics gathering
too:
Configuring Infinispan with one or several chained persistent stores is simple too:
Page 84 of 617
Infinispan 6.0
For information on the individual configuration options, please check the configuration guide.
Page 85 of 617
Infinispan 6.0
InputStream in=in.getInput("/grid-movies/dvd-image.iso");
OutputStream out=new FileOutputStream("/tmp/my-movies/dvd-image.iso");
byte[] buffer=new byte[200000];
int len;
while((len=in.read(buffer, 0, buffer.length)) != -1) out.write(buffer, 0, len);
in.close();
out.close();
Page 86 of 617
Infinispan 6.0
Page 87 of 617
Infinispan 6.0
Page 88 of 617
Infinispan 6.0
3.10.1 Introduction
Infinispan's tree API module offers clients the possibility of storing data using a tree-structure like API. This
API is similar to the one provided by JBoss Cache, hence the tree module is perfect for those users wanting
to migrate their applications from JBoss Cache to Infinispan, who want to limit changes their codebase as
part of the migration. Besides, it's important to understand that Infinispan provides this tree API much more
efficiently than JBoss Cache did, so if you're a user of the tree API in JBoss Cache, you should consider
migrating to Infinispan.
<dependencies>
...
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-tree</artifactId>
<version>$put-infinispan-version-here</version>
</dependency>
...
</dependencies>
Page 89 of 617
Infinispan 6.0
import org.infinispan.config.Configuration;
import org.infinispan.tree.TreeCacheFactory;
import org.infinispan.tree.TreeCache;
...
Configuration config = new Configuration();
config.setInvocationBatchingEnabled(true);
Cache cache = new DefaultCacheManager(config).getCache();
TreeCache treeCache = TreeCacheFactory.createTreeCache(cache);
Or:
import org.infinispan.tree.Fqn;
...
Fqn johnFqn = Fqn.fromString("persons/john");
Calendar calendar = Calendar.getInstance();
calendar.set(1980, 5, 2);
treeCache.put(johnFqn, "birthdate", calendar.getTime()));
Page 90 of 617
Infinispan 6.0
2. Via Node API: It allows finer control over the individual nodes that form the FQN, allowing
manipulation of nodes relative to a particular node. For example:
import org.infinispan.tree.Node;
...
TreeCache treeCache = ...
Fqn johnFqn = Fqn.fromElements("persons", "john");
Node<String, Object> john = treeCache.getRoot().addChild(johnFqn);
john.put("surname", "Smith");
Or:
Or even:
A node also provides the ability to access its parent or children. For example:
Or:
Page 91 of 617
Infinispan 6.0
Common Operations
In the previous section, some of the most used operations, such as addition and retrieval, have been shown.
However, there are other important operations that are worth mentioning, such as remove:
You can for example remove an entire node, i.e. /persons/john , using:
treeCache.removeNode("/persons/john");
treeCache.getRoot().removeChild(Fqn.fromString("persons"));
Another important operation supported by Tree API is the ability to move nodes around in the tree. Imagine
we have a node called "john" which is located under root node. The following example is going to show how
to we can move "john" node to be under "persons" node:
Current tree structure:
/persons
/john
/persons/john
Page 92 of 617
Infinispan 6.0
/
--|-/
a
|
b
|
d
\
c
|
e
/
|
a
|
b
--|-/
d
\
c
|
e
Page 93 of 617
Infinispan 6.0
Page 94 of 617
Infinispan 6.0
import org.apache.lucene.store.Directory;
import org.infinispan.lucene.directory.DirectoryBuilder;
import org.infinispan.Cache;
Cache cache = // create an Infinispan cache, configured as you like
Directory indexDir = DirectoryBuilder.newDirectoryInstance(cache, cache, cache, indexName)
.create();
The indexName is a unique key to identify your index. It takes the same role as the path did on filesystem
based indexes: you can create several different indexes giving them different names. When you use the
same indexName in another instance connected to the same network (or instantiated on the same machine,
useful for testing) they will join, form a cluster and share all content. Using a different indexName allows you
to store different indexes in the same set of Caches.
The cache is passed three times in this example, as that is ok for a quick demo, but as the API suggests it's
a good idea to tune each cache separately as they will be used in different ways. More details provided
below.
New nodes can be added or removed dynamically, making the service administration very easy and also
suited for cloud environments: it's simple to react to load spikes, as adding more memory and CPU power to
the search system is done by just starting more nodes.
3.11.4 Limitations
As when using an IndexWriter on a filesystem based Directory, even on the clustered edition only one
IndexWriter can be opened across the whole cluster.
As an example, Hibernate Search, which includes integration with this Lucene Directory since version 3.3,
sends index change requests across a JMS queue, or a JGroups channel. Other valid approaches are to
proxy the remote IndexWriter or just design your application in such a way that only one node attempts to
write it.
Reading (searching) is of course possible in parallel, from any number of threads on each node; changes
applied to the single IndexWriter are affecting results of all threads on all nodes in a very short time, or
guaranteed to be visible after a commit when using transactions.
Page 95 of 617
Infinispan 6.0
3.11.5 Configuration
Infinispan can be configured as LOCAL clustering mode, in which case it will disable clustering features and
serve as a cache for the index, or any clustering mode.
A transaction manager is not mandatory, but when enabled the changes to the index can participate in
transactions.
Batching was required in previous versions, it's not strictly needed anymore.
As better explained in the javadocs of org.infinispan.lucene.InfinispanDirectory, it's possible for it to use more
than a single cache, using specific configurations for different purposes. When using readlocks, make sure
to not enable transactions on this cache.
Any Infinispan configuration should work fine as long as caches are not configured to remove entries after
thresholds.
3.11.6 Demo
There is a simple command-line demo of it's capabilities distributed with Infinispan under
demos/lucene-directory; make sure you grab the "Binaries, server and demos" package from download page
, which contains all demos.
Start several instances, then try adding text in one instance and searching for it on the other. The
configuration is not tuned at all, but should work out-of-the box without any changes. If your network
interface has multicast enabled, it will cluster across the local network with other instances of the demo.
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-lucene-directory</artifactId>
<version>5.3.0.Beta1</version>
</dependency>
Page 96 of 617
Infinispan 6.0
Description
Default
location
The path where the indexes are stored. Subdirectories (of first level only)
none
should contain the indexes to be loaded, each directory matching the index
(mandatory)
32MB
Page 97 of 617
Infinispan 6.0
Using a CacheStore
Currently all CacheStore implementations provided by Infinispan have a significant slowdown; we hope to
resolve that soon but for the time being if you need high performance on writes with the Lucene Directory the
best option is to disable any CacheStore; the second best option is to configure the CacheStore as async.
If you only need to load a Lucene index from read-only storage, see the above description for
org.infinispan.lucene.cachestore.LuceneCacheLoader.
Page 98 of 617
Infinispan 6.0
Page 99 of 617
Infinispan 6.0
3.12.1 Introduction
Traditionally, clients have interacted with Infinispan in a peer-to-peer (p2p) fashion where Infinispan and the
client code that accessed it lived within the same VM. When Infinispan is queried in this way, it is considered
to be accessed in an embedded fashion, as shown in the screenshot below
In other situations, Infinispan users want to have an elastic application tier where you start/stop business
processing servers very regularly. Now, if users deployed Infinispan configured with distribution or state
transfer, startup time could be greatly influenced by the shuffling around of data that happens in these
situations. So in the following diagram, assuming Infinispan was deployed in p2p mode, the app in the
second server could not access Infinispan until state transfer had completed.
Infinispan 6.0
This effectively means that bringing up new application-tier servers is impacted by things like state transfer
because applications cannot access Infinispan until these processes have finished and if the state being
shifted around is large, this could take some time. This is undesirable in an elastic environment where you
want quick application-tier server turnaround and predictable startup times. Problems like this can be solved
by accessing Infinispan in a client-server mode because starting a new application-tier server is just a matter
of starting a lightweight client that can connect to the backing data grid server. No need for rehashing or
state transfer to occur and as a result server startup times can be more predictable which is very important
for modern cloud-based deployments where elasticity in your application tier is important.
Other times, it's common to find multiple applications needing access to data storage. In this cases, you
could in theory deploy an Infinispan instance per each of those applications but this could be wasteful and
difficult to maintain. Thing about databases here, you don't deploy a database alongside each of your
applications, do you? So, alternatively you could deploy Infinispan in client-server mode keeping a pool of
Infinispan data grid nodes acting as a shared storage tier for your applications .
Deploying Infinispan in this way also allows you to manage each tier independently, for example, you can
upgrade you application or app server without bringing down your Infinispan data grid nodes.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
3.13.1 Introduction
Management of Infinispan instances is all about exposing as much relevant statistical information that allows
administrators to get view of the state of each Infinispan instance. Taking in account that a single installation
could be made up of several tens or hundreds Infinispan instances, providing clear and concise information
in an efficient manner is imperative. The following sections dive into the range of management tooling that
Infinispan provides.
3.13.2 JMX
Over the years, JMX has become the de facto standard for management and administration of middleware
and as a result, the Infinispan team has decided to standarize on this technology for the exposure of
management or statistical information.
Infinispan 6.0
<globalJmxStatistics enabled="true"/>
2. Cache level: At this level, you will receive management information generated by individual cache
instances. Details on the information exposed at the Cache level are explained below. For the
moment, let's just focus on how to enable the Cache to report management data via JMX:
If configuring the Cache via XML, make sure you add the following XML under the either <default>, if
you're configuring the default Cache instance, or under the corresponding <namedCache>:
<jmxStatistics enabled="true"/>
Infinispan 6.0
Infinispan 6.0
org.infinispan:type=Cache,name="<name-of-cache>(<cache-mode>)",manager="<name-of-cache-manager>",comp
where:
<name-of-cache> has been substituted by the actual cache name. If this cache represents the
default cache, it's name will be "_defaultCache" .
<cache-mode> has been substituted by the cache mode of the cache. The cache mode is
represented by the lower case version of the possible enumeration values shown here.
<name-of-cache-manager> has been substituted by the name of the cache manager to which
this cache belongs. The name is derived from the cacheManagerName attribute value in
globalJmxStatistics element.
<component-name> has been substituted by one of the JMX component names in the JMX
reference documentation.
For example, the cache store JMX component MBean for a default cache configured with synchronous
distribution would have the following name: org.infinispan:type=Cache,name="_defaultcache(dist_sync)",
manager="DefaultCacheManager",component=CacheStore
Please note that cache and cache manager names are quoted to protect against illegal characters being
used in these user-defined names.
Infinispan 6.0
Programmatically:
Using either of these options should result on the CacheManager MBean name being:
myInfinispan:cache-name=[global],jmx-resource=CacheManager
As you probably have guessed by now, the default JMX domain prefix is called " infinispan ".
Another related configuration option for both CacheManager and Cache JMX statistics allows for duplicate
JMX domains to be discovered. Internally, when duplicates are allowed, Infinispan takes the duplicating JMX
domain prefix, adds an index that starts at number 2 to the existing prefix and uses that JMX prefix from then
onwards. So, for example, if two CacheManagers were started with global JMX statistics enabled, no
particular JMX domain was configured, and JMX domain duplicates were allowed, the first CacheManager
would be registered under "infinispan... ", whereas the second one would be registered under: " infinispan2...
". To allow JMX duplicate domains, do the following:
Via XML:
Programmatically:
Infinispan 6.0
Programmatically:
Using either of these options should result on the CacheManager MBean name being:
org.infinispan:type=CacheManager,name="Hibernate2LC"
Please note as well that since 4.2, the default domain names has changed from "infinispan" to
"org.infinispan", as per JMX best practices.
For the time being, you can still set your own jmxDomain if you need to and we also allow duplicate
domains, or rather duplicate JMX names, but these should be limited to very special cases where different
cache managers within the same JVM are named equally.
Infinispan 6.0
Programmatically:
3.13.3 RHQ
The preferred way to manage multiple Infinispan instances spread accross different servers is to use RHQ,
which is JBoss' enterprise management solution. Thanks to RHQ's agent and auto discovery capabilities,
monitoring both Cache Manager and Cache instances is a very simple task. With RHQ, administrators have
access to graphical views of key runtime parameters or statistics and can also be notified be these exceed
or go below certain limits. The Infinispan specific statistics shown by RHQ are a reflection of the JMX
information exposed by Infinispan which has been formatted for consumption by RHQ. Please follow these
steps to get started with RHQ and have Infinispan instances monitored with it:
Infinispan 6.0
1. Firstly, download and install an RHQ server and install and start at least one RHQ agent. The job of
the RHQ agent is to send information about the Infinispan instance back to the server which is the
one that shows the information via a nice GUI. You can find detailed information on the installation
process in RHQ's installation guide and you can find information on how to run an agent in the RHQ
agent guide.
2. By now, you should have an RHQ server and agent running. It's time now to download the latest
Infinispan binary distribution (*-bin.zip or *-all.zip should do) from the downloads section and locate
the RHQ plugin jar file which should be named something like infinispan-rhq-plugin.jar. This
is located under the modules/rhq-plugin directory.
3. The adding and updating plugins section on the RHQ guide contains some more detailed information
on how to update both RHQ servers and agents with new plugins, but essentially, this process
involves uploading a new plugin to the RHQ server and then pushing the plugin to one, or several,
RHQ agents.
Infinispan 6.0
4. At this point, RHQ is ready to start monitoring Infinispan instances, but before firing them up, make
sure you start them with the following system properties so that RHQ agents can discover them:
-Dcom.sun.management.jmxremote.port=6996 -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
5. Once Infinispan instances have been discovered, you should see a new resource for each of the
cache manager running appearing in the Inventory/Discovery Queue of the RHQ server. Simply
import it now and you should see each cache manager appearing with as many child cache resources
as caches are running in each cache manager. You're now ready to monitor Infinispan!
Infinispan 6.0
Infinispan 6.0
3.14.1 Introduction
When Infinispan instances are clustered, regardless of the clustering mode, data can be propagated to other
nodes in a synchronous or asynchronous way. When synchronous, the sender waits for replies from the
receivers and when asynchronous, the sender sends the data and does not wait for replies from other nodes
in the cluster.
With asynchronous modes, speed is more important than consistency and this is particularly advantageous
in use cases such as HTTP session replication with sticky sessions enabled. In these scenarios, data, or in
this case a particular session, is always accessed on the same cluster node and only in case of failure is
data accessed in a different node. This type of architectures allow consistency to be relaxed in favour of
increased performance.
In order to choose the asynchronous configuration that best suits your application, it's important to
understand the following configuration settings:
Infinispan 6.0
cache.put("car", "bmw");
cache.remove("car");
cache.remove("car");
cache.put("car", "bmw");
The end result is clearly different which is often not desirable. So, if your application makes multiple
modifications on the same key, you should either: turned off asynchronous marshalling, or set
<asyncTransportExecutor> element's maxThreads to 1. The first modification only applies to a particular
named cache, whereas the second option affects all named caches in configuration file that are configured
with async marshalling. It's worth noting though that having this type of executor configured with a single
thread would defeat its purpose adding unnecessary contention point. It'd be better to simply switch off
async marshalling.
On the contrary, if your application only ever makes one modification per key/value pair and there's no
happens-before relationship between them, then async marshalling is a very valid optimization that can
increase performance of your application without data consistency risks.
If you have async marshalling turned on and see exceptions related to
java.util.concurrent.RejectedExecutionException, as explained in the technical faq page, you
should also consider switching off async marshalling.
Back in Infinispan 4.0, when <async> element was used, this property was set to true by default. However
due to reordering risks mentioned earlier, the default has changed to false from Infinispan 4.1 onwards.
Infinispan 6.0
Infinispan 6.0
1. Add the attached jar files to the ear lib directory. These include the core 4.1.0.GA Infinispan jar
(infinispan-core.jar), the Hibernate/Infinispan integration jar back-ported from Hibernate 3.5
(hibernate-infinispan-3.3.2.GA_CP03.jar), the JGroups jar required by Infinispan 4.1.0
(jgroups-2.10.0.GA.jar), and other required 3rd party jars (river-1.2.3.GA.jar,
marshalling-api-1.2.3.GA.jar)
2. Isolate the classloading to be ear-scoped by adding META-INF/jboss-classloading.xml
3. <classloading xmlns="urn:jboss:classloading:1.0" domain="simple-scoped"
parent-first="false" />
Infinispan 6.0
// ...
GlobalConfiguration gc = new
GlobalConfigurationBuilder().transport().addProperty("configurationFile",
"jgroups.xml").build();
// ...
and if you happen to use an XML file to configure Infinispan, just use:
<infinispan>
<global>
<transport>
<properties>
<property name="configurationFile" value="jgroups.xml" />
</properties>
</transport>
</global>
...
</infinispan>
In both cases above, Infinispan looks for jgroups.xml first in your classpath, and then for an absolute path
name if not found in the classpath.
Infinispan 6.0
jgroups-udp.xml
System Property
Description
Default
Required?
46655
No
jgroups.udp.ip_ttl
No
Infinispan 6.0
jgroups-tcp.xml
System Property
Description
Default
jgroups.tcp.address
127.0.0.1 No
jgroups.tcp.port
7800
Required?
No
228.6.7.8 No
46655
No
jgroups.udp.ip_ttl
No
Required?
jgroups-ec2.xml
System Property
Description
Default
jgroups.tcp.address
127.0.0.1 No
jgroups.tcp.port
7800
jgroups.s3.access_key
No
No
bucket
jgroups.s3.secret_access_key The Amazon S3 secret key used to access an S3
No
bucket
jgroups.s3.bucket
No
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
The size of the shared lock collection used by lock striping can be tuned using the concurrencyLevel
attribute of the <locking /> configuration element.
Infinispan 6.0
tx.begin()
cache.lock(K)
cache.put(K,V5)
tx.commit()
Implicit locking goes one step ahead and locks cache keys behind the scene as keys are accessed for
modification operations.
Consider a transaction running on one of the cache nodes:
tx.begin()
cache.put(K,V)
cache.put(K2,V2)
cache.put(K,V5)
tx.commit()
//
//
//
//
Implicit eager locking locks cache keys across cluster nodes only if it is necessary to do so. In a nutshell, if
implicit eager locking is turned on then for each modification Infinispan checks if cache key is locked locally.
If it is then a global cluster wide lock has already been obtained, otherwise a cluster wide lock request is sent
and lock is acquired.
Implicit eager locking is enabled as follows:
Infinispan 6.0
Above diagram shows the situation where eagerLockSingleNode=false (default configuration). On each lock
request, numOwners remote calls are performed (in our example 2).
Above diagram shows how lock on the same key are acquired when eagerLockSingleNode=true. The
number of remote calls being performed is always 1, disregarding numOwners values (it can actually be 0,
as we'll see later on).
In this scenario, if the lock owner fails (Node_C) then the transaction that holds the lock, which originated on
Node_A is marked for rollback.
Combining eagerLockSingleNode with the KeyAffinityService can bring some interesting advantages. The
next diagram shows this:
By using KeyAffinityService one can generate keys that would always map to the local node. If
eagerLockSingleNode=true, then the remote lock acquisition happens locally: this way one can benefit from
eager locking semantics and having the same performance as non eager locking. The optimisation is
affected by cluster topology changes, so keys might get relocated. But for clusters where topology changes
are rather rare this can bring a lot of value.
The following xml snippet shows how can be configured:
<transaction
transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"
syncRollbackPhase="false"
syncCommitPhase="false"
useEagerLocking="true" eagerLockSingleNode="true"/>
<transaction
transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"
syncRollbackPhase="false"
syncCommitPhase="false"
useEagerLocking="true" eagerLockSingleNode="true"/>
Note that the configuration is ignored if eager locking is disabled or cache mode is not DIST.
Infinispan 6.0
Consistency
The fact that a single owner is locked (as opposed to all owners being locked) does not break the following
consistency guarantee: if key K is hashed to nodes {A, B} and transaction TX1 acquires a lock for K, let's say
on A. If another transaction, TX2, is started on B (or any other node) and TX2 tries to lock K then it will fail
with a timeout as the lock is already held by TX1. The reason for this is the that the lock for a key K is
always, deterministically, acquired on the same node of the cluster, regardless of where the transaction
originates.
<locking supportsConcurrentUpdates="true"/>
When enabled (default == true), the supportConcurrentUpdates adds internal support for concurrent writes:
a locking interceptor that would serialize writes to the same key and a delegation layer, that designates a
lock owner and uses it in order to coordinate the writes to a key.
More specific, when a thread running on node A writes on key k that mapps according to the consistent hash
to nodes {B, C}
(given numOwners==2):
A forwards (RPC) the write to the primary owner. The primary owner is the first node in the list of
owners, in our example B
B acquires a lock on k. Once the lock successfully acquired,_ _it forwards (RPC) the request to the
rest of owners (in this example C) that apply it locally
B applies the result locally, releases the lock and then it returns to A
Reasoning about the performance: in order to assure consistency under concurrent update, we do 2 RPCs:
from operation originator to main owner and from main owner to the rest of the owners. That's one more
than when supportConcurrentUpdates == false: in this case the operation originator does a single (multicast)
RPC to all the owners. This induces a performance cost and whenever one uses the cache in
non-concurrent manner, it is recommended that this configuration to be set to false in order to increase the
performance. When using Infinispan in client/server mode with a Hot Rod client, this would use the main
data owner in order to write data, so in this scenario there should not be any performance cost when
supporting concurrent updates.
Infinispan 6.0
<infinispan />
However, that would only give you the most basic, local mode, non-clustered cache. Non basic
configurations are very likely to use customized global and default cache elements.
Declarative configuration is the most common approach to configuring Infinispan cache instances. In order to
read XML configuration files one would typically construct an instance of CacheManager by pointing to an
XML file containing Infinispan configuration. Once configuration file is read you can obtain reference to the
default cache instance.
Every time you define <namedCache> element in XML configuration file, in addition to <default> cache
element, you are effectively configuring additional caches whose settings are inheriting and/or overriding the
default cache.
Refer to Infinispan configuration reference for more details. If you are using XML editing tools for
configuration writing you can use provided Infinispan schema to assist you.
If you wish to help write conversion tools for other caching systems, please contact <a
href="https://lists.jboss.org/mailman/listinfo/infinispan-dev">infinispan-dev</a>.
Infinispan 6.0
There is a single scripts for importing configurations: ${INFINISPAN_HOME}/bin/importConfig.sh and an
equivalent .BAT script for Windows. Just run it and you should get a help message to assist you with the
import:
C:\infinispan\bin> importConfig.bat
Missing 'source', cannot proceed
Usage:
importConfig [-source <the file to be transformed>]
[-destination <where to store resulting XML>]
[-type <the type of the source, possible values being: [JBossCache3x, Ehcache1x, Coherence35x]
>]
C:\infinispan\bin>
Please read all warning messages carefully and inspect the generated XML for potential TODO statements
that indicate the need for manual intervention. In the case of JBoss Cache 3.x this would usually have to do
with custom extensions, such as custom CacheLoaders that cannot be automatically migrated.
For EHCache and Coherence these may also contain suggestions and warnings for configuration options
that may not have direct equivalents in Infinispan.
Infinispan 6.0
3.20.1 Introduction
Data structures, such as Infinispan Cache, that are accessed and modified concurrently can suffer from data
consistency issues unless there're mechanisms to guarantee data correctness. Infinispan Cache, since it
implements ConcurrentMap, provides operations such as conditional replace, putIfAbsent, and conditional
remove to its clients in order to guarantee data correctness. It even allows clients to operate against cache
instances within JTA transactions, hence providing the necessary data consistency guarantees.
However, when it comes to Hot Rod protocol backed servers, clients do not yet have the ability to start
remote transactions but they can call instead versioned operations to mimic the conditional methods
provided by the embedded Infinispan cache instance API. Let's look at a real example to understand how it
works.
Next a customer connects to the first ATM and requests 400 CHF to be retrieved. Based on the last value
read, the ATM could calculate what the new balance is, which is 100 CHF, and request a put with this new
value. Let's imagine now that around the same time another customer connects to the ATM and requests
200 CHF to be retrieved. Let's assume that the ATM thinks it has the latest balance and based on its
calculations it sets the new balance to 300 CHF:
Infinispan 6.0
Obviously, this would be wrong. Two concurrent updates have resulted in an incorrect account balance. The
second update should not have been allowed since the balance the second ATM had was incorrect. Even if
the ATM would have retrieved the balance before calculating the new balance, someone could have updated
between the new balance being retrieved and the update. Before finding out how to solve this issue in a
client-server scenario with Hot Rod, let's look at how this is solved when Infinispan clients run in peer-to-peer
mode where clients and Infinispan live within the same JVM.
Peer-to-Peer Solution
If the ATM and the Infinispan instance storing the bank account lived in the same JVM, the ATM could use
the conditional replace API referred at the beginning of this article. So, it could send the previous known
value to verify whether it has changed since it was last read. By doing so, the first operation could double
check that the balance is still 500 CHF when it was to update to 100 CHF. Now, when the second operation
comes, the current balance would not be 500 CHF any more and hence the conditional replace call would
fail, hence avoiding data consistency issues:
Infinispan 6.0
Client-Server Solution
In theory, Hot Rod could use the same p2p solution but sending the previous value would be not practical. In
this example, the previous value is just an integer but the value could be a lot bigger and hence forcing
clients to send it to the server would be rather wasteful. Instead, Hot Rod offers versioned operations to deal
with this situation.
Basically, together with each key/value pair, Hot Rod stores a version number which uniquely identifies each
modification. So, using an operation called getVersioned or getWithVersion, clients can retrieve not only the
value associated with a key, but also the current version. So, if we look at the previous example once again,
the ATMs could call getVersioned and get the balance's version:
When the ATMs wanted to modify the balance, instead of just calling put, they could call replaceIfUnmodified
operation passing the latest version number of which the clients are aware of. The operation will only
succeed if the version passed matches the version in the server. So, the first modification by the ATM would
be allowed since the client passes 1 as version and the server side version for the balance is also 1. On the
other hand, the second ATM would not be able to make the modification because after the first ATMs
modification the version would have been incremented to 2, and now the passed version (1) and the server
side version (2) would not match:
Finally, to find out how to call these operations from a Java environment, checkout the Java Hot Rod Client
article.
Infinispan 6.0
3.21.1 Introduction
Cache loader is Infinispan's connection to a (persistent) data store. Cache loader fetches data from a store
when that data is not in the cache, and when modifications are made to data in the cache the CacheLoader
is called to store those modifications back to the store. Cache loaders are associated with individual caches,
i.e. different caches from the same cache manager might have different cache store configurations.
3.21.2 Configuration
Cache loaders can be configured in a chain. Cache read operations will look at all of the cache loaders in the
order they've been configured until it finds a valid, non-null element of data. When performing writes all
cache loaders are written to except if the ignoreModifications element has been set to true for a specific
cache loader. See the configuration section below for details.
Infinispan 6.0
passivation (false by default) has a significant impact on how Infinispan interacts with the loaders, and
is discussed in the next paragraph.
shared (false by default) indicates that the cache loader is shared among different cache instances,
for example where all instances in a cluster use the same JDBC settings to talk to the same remote,
shared database. Setting this to true prevents repeated and unnecessary writes of the same data to
the cache loader by different cache instances.
Infinispan 6.0
preload (false by default) if true, when the cache starts, data stored in the cache loader will be
pre-loaded into memory. This is particularly useful when data in the cache loader is needed
immediately after startup and you want to avoid cache operations being delayed as a result of loading
this data lazily. Can be used to provide a 'warm-cache' on startup, however there is a performance
penalty as startup time is affected by this process. Note that preloading is done in a local fashion, so
any data loaded is only stored locally in the node. No replication or distribution of the preloaded data
happens. Also, Infinispan only preloads up to the maximum configured number of entries in eviction.
class attribute (mandatory) defines the class of the cache loader implementation.
fetchPersistentState (false by default) determines whether or not to fetch the persistent state of a
cache when joining a cluster. The aim here is to take the persistent state of a cache and apply it to the
local cache store of the joining node. Hence, if cache store is configured to be shared, since caches
access the same cache store, fetch persistent state is ignored. Only one configured cache loader may
set this property to true; if more than one cache loader does so, a configuration exception will be
thrown when starting your cache service.
purgeSynchronously will control whether the expiration takes place in the eviction thread, i.e. if
purgeSynchronously (false by default) is set to true, the eviction thread will block until the purging is
finished, otherwise would return immediately. If the cache loader supports multi-threaded purge then
purgeThreads (1 by default) are used for purging expired entries. There are cache loaders that
support multi-threaded purge (e.g. FileCacheStore) and caches that don't (e.g. JDBCCacheStore);
check the actual cache loader configuration in order to see that.
ignoreModifications(false by default) determines whether write methods are pushed down to the
specific cache loader. Situations may arise where transient application data should only reside in a file
based cache loader on the same server as the in-memory cache, for example, with a further JDBC
based cache loader used by all servers in the network. This feature allows you to write to the 'local'
file cache loader but not the shared JDBCCacheLoader.
purgeOnStatup empties the specified cache loader (if ignoreModifications is false) when the cache
loader starts up.
additional attributes configure aspects specific to each cache loader, e.g. the location attribute in the
previous example refers to where the FileCacheStore will keep the files that contain data. Other
loaders, with more complex configuration, also introduce additional sub-elements to the basic
configuration. See for example the JDBC cache store configuration examples below
singletonStore (default for enabled is false) element enables modifications to be stored by only one
node in the cluster, the coordinator. Essentially, whenever any data comes in to some node it is
always replicated(or distributed) so as to keep the caches in-memory states in sync; the coordinator,
though, has the sole responsibility of pushing that state to disk. This functionality can be activated
setting the enabled attribute to true in all nodes, but again only the coordinator of the cluster will the
modifications in the underlying cache loader as defined in loader element. You cannot define a shared
and with singletonStore enabled at the same time.
pushStateWhenCoordinator (true by default) If true, when a node becomes the coordinator, it will
transfer in-memory state to the underlying cache loader. This can be very useful in situations where
the coordinator crashes and the new coordinator is elected.
async element has to do with cache store persisting data (a)synchronously to the actual store. It is
discussed in detail here.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
JdbcBinaryCacheStore - can store any type of keys. It stores all the keys that have the same hash
value (hashCode method on key) in the same table row/blob, having as primary key the hash value.
While this offers great flexibility (can store any key type), it impacts concurrency/throughput. E.g. If
storing k1,k2 and k3 keys, and keys had same hash code, then they'd persisted in the same table
row. Now, if 3 threads try to concurrently update k1, k2 and k3 respectively, they would need to do it
sequentially since these threads would be updating the same row.
JdbcStringBasedCacheStore - stores each key in its own row, increasing throughput under concurrent
load. In order to store each key in its own column, it relies on a (pluggable) bijection that maps the
each key to a String object. The bijection is defined by the Key2StringMapper interface. Infinispans
ships a default implementation (smartly named DefaultKey2StringMapper) that knows how to handle
primitive types.
JdbcMixedCacheStore - it is a hybrid implementation that, based on the key type, delegates to either
JdbcBinaryCacheStore or JdbcStringBasedCacheStore.
Infinispan 6.0
Sample configurations
Bellow is an sample configuration for the JdbcBinaryCacheStore. For detailed description of all the
parameters used refer to the javadoc. Please note the use of multiple XML schemas, since each cachestore
has its own schema.
Infinispan 6.0
Bellow is an sample configuration for the JdbcStringBasedCacheStore. For detailed description of all the
parameters used refer to the javadoc.
<loaders>
<stringKeyedJdbcStore xmlns="urn:infinispan:config:jdbc:5.2" fetchPersistentState="false"
ignoreModifications="false" purgeOnStartup="false">
<connectionPool connectionUrl="jdbc:h2:mem:infinispan_binary_based;DB_CLOSE_DELAY=-1"
username="sa" driverClass="org.h2.Driver"/>
<stringKeyedTable dropOnExit="true" createOnStart="true" prefix="ISPN_STRING_TABLE">
<idColumn name="ID_COLUMN" type="VARCHAR(255)" />
<dataColumn name="DATA_COLUMN" type="BINARY" />
<timestampColumn name="TIMESTAMP_COLUMN" type="BIGINT" />
</stringKeyedTable>
</stringKeyedJdbcStore>
</loaders>
Bellow is an sample configuration for the JdbcMixedCacheStore. For detailed description of all the
parameters used refer to the javadoc.
Infinispan 6.0
<loaders>
<mixedKeyedJdbcStore xmlns="urn:infinispan:config:jdbc:5.2" fetchPersistentState="false"
ignoreModifications="false" purgeOnStartup="false">
<connectionPool connectionUrl="jdbc:h2:mem:infinispan_binary_based;DB_CLOSE_DELAY=-1"
username="sa" driverClass="org.h2.Driver" />
<stringKeyedTable dropOnExit="true" createOnStart="true" prefix="ISPN_MIXED_STR_TABLE">
<idColumn name="ID_COLUMN" type="VARCHAR(255)" />
<dataColumn name="DATA_COLUMN" type="BINARY" />
<timestampColumn name="TIMESTAMP_COLUMN" type="BIGINT" />
</stringKeyedTable>
<binaryKeyedTable dropOnExit="true" createOnStart="true" prefix="ISPN_MIXED_BINARY_TABLE">
<idColumn name="ID_COLUMN" type="VARCHAR(255)" />
<dataColumn name="DATA_COLUMN" type="BINARY" />
<timestampColumn name="TIMESTAMP_COLUMN" type="BIGINT" />
</binaryKeyedTable>
</loader>
</loaders>
Finally, below is an example of a JDBC cache store with a managed connection factory, which is chosen
implicitly by specifying a datasource JNDI location:
Infinispan 6.0
Infinispan 6.0
In this sample configuration, the remote cache store is configured to use the remote cache named
"mycache" on servers "one" and "two". It also configures connection pooling and provides a custom transport
executor. Additionally the cache store is asynchronous.
Infinispan 6.0
<loaders>
<clusterLoader remoteCallTimeout="500" />
</loaders>
Infinispan 6.0
Sample Usage
For example, given a persistence unit "myPersistenceUnit", and a JPA entity User:
persistence.xml
<persistence-unit name="myPersistenceUnit">
...
</persistence-unit>
@Entity
public class User implements Serializable {
@Id
private String username;
private String firstName;
private String lastName;
...
}
Then you can configure a cache "usersCache" to use JPA Cache Store, so that when you put data into the
cache, the data would be persisted into the database based on JPA configuration.
Normally a single Infinispan cache can store multiple types of key/value pairs, for example:
It's important to note that, when a cache is configured to use a JPA Cache Store, that cache would only be
able to store ONE type of data.
Infinispan 6.0
Use of @EmbeddedId is supported so that you can also use composite keys (see the test code for full
example).
@Entity
public class Vehicle implements Serializable {
@EmbeddedId
private VehicleId id;
private String color; ...
}
@Embeddable
public class VehicleId implements Serializable
{
private String state;
private String licensePlate;
...
}
Lastly, auto-generated IDs (e.g., @GeneratedValue) is not supported. When putting things into the cache
with a JPA cache store, the key should be the ID value!
Infinispan 6.0
Configuration
Sample Programatic Configuration
Configuration cacheConfig = new ConfigurationBuilder().loaders()
.addLoader(JpaCacheStoreConfigurationBuilder.class)
.persistenceUnitName("org.infinispan.loaders.jpa.configurationTest")
.entityClass(User.class)
.build();
Parameter
Description
persistenceUnitName JPA persistence unit name in JPA configuration (persistence.xml) that contains the
JPA entity class
entityClass
JPA entity class that is expected to be stored in this cache. Only one class is
allowed.
Parameter
Description
persistenceUnitName JPA persistence unit name in JPA configuration (persistence.xml) that contains the
JPA entity class
entityClassName
Fully qualified JPA entity class name that is expected to be stored in this cache.
Only one class is allowed.
Additional References
Refer to the test case for code samples in action.
Refer to test configurations for configuration samples.
Infinispan 6.0
Sample Usage
LevelDB cache store requires 2 filesystem directories to be configured - each directory for a LevelDB
database. One location is used to store non-expired data, while the second location is used to store expired
keys pending purge.
EmbeddedCacheManager cacheManager = ...;
Infinispan 6.0
Configuration
Sample Programatic Configuration
Configuration cacheConfig = new ConfigurationBuilder().loaders()
.addLoader(LevelDBCacheStoreConfigurationBuilder.class)
.location("/tmp/leveldb/data")
.expiredLocation("/tmp/leveldb/expired")
.entityClass(User.class)
.build();
Parameter
Description
location
Directory to use for LevelDB to store primary cache store data. Directory will be
auto-created if it does not exit.
expiredLocation
Directory to use for LevelDB to store expiring data pending to be purged permanently.
Directory will be auto-created if it does not exit.
expiryQueueSize
Size of the in-memory queue to hold expiring entries before it gets flushed into expired
LevelDB store
clearThreshold
There are two methods to clear all entries in LevelDB. One method is to iterate through
all entries and remove each entry individually. The other method is to delete the
database and re-init. For smaller databases, deleting individual entries is faster than
the latter method. This configuration sets the max number of entries allowed before
using the latter method
compressionType Configuration for LevelDB for data compression, see CompressionType enum for
options
blockSize
cacheSize
Infinispan 6.0
Additional References
Refer to the test case for code samples in action.
Refer to test configurations for configuration samples.
<loaders>
<mongodbStore xmlns="urn:infinispan:config:mongodb:5.3" >
<connection host="localhost" port="27017" timeout="2000" acknowledgment="0"/>
<authentication username="mongoUser" password="mongoPass" />
<storage database="infinispan_test_database" collection="infispan_cachestore" />
</mongodbStore>
</loaders>
Infinispan 6.0
The connection section contains the connection information to connect to the MongoDB server instance.
The authentication section is optional, it allows you to specificy username and password if you are using
some.
The storage section explicits where you will store the data.
Section
property
usage
default
value
connection
host
localhost
running
port
27017
timeout
password
storage
database
collection
For more information about the configuration property usage, you can refer to the official MongoDB java
driver documentation
Infinispan 6.0
3.22.1 Introduction
Starting with Infinispan 5.0, Hot Rod clients can be configured with a marshaller that produces plattform
independent payloads using Apache Avro. This means that payloads generated by a Java, Avro-based,
marshaller could be read by a Python, Avro-based, marshaller. When Hot Rod clients in other languages
such as Python or Ruby become available, this will mean that for example, data stored via Java Hot Rod
client will be readable by a Python Hot Rod client.
Infinispan 6.0
Infinispan 6.0
Note however that if all you're gonna be using are Java Hot Rod clients, there's no need to configure Avro
based marshaller. The default marshaller is capable of transforming any Serializable or Externalizable java
object into a byte array in a quick and efficient manner.
Please remember as well that when remote java clients are configured with the apache avro marshaller, the
server's marshaller does not need changing. This is because the server does not make any attempt at
unmarshalling the data that's been passed to it. Internally, it keeps the data as byte arrays.
Infinispan 6.0
<clustering>
<hash>
<groups enabled="true" />
</hash>
</clustering>
If you have control of the key class (you can alter the class definition, it's not part of an unmodifiable library),
and the determination of the group is not an orthogonal concern to the key class, then we recommend you
use an intrinsic group. The intrinsic group can be specified using the @Group annotation placed on the
method. Let's take a look at an example:
class User {
...
String office;
...
int hashCode() {
// Defines the hash for the key, normally used to determine location
...
}
// Override the location by specifying a group, all keys in the same
// group end up with the same owner
@Group
String getOffice() {
return office;
}
}
Infinispan 6.0
If you don't have control over the key class, or the determination of the group is an orthogonal concern to the
key class, we recommend you use an extrinsic group. In extrinsic group is specified by implementing the
Grouper interface, which has a single method computeGroup, which should return the group. Grouper acts
as an interceptor, passing the previously computed value in. The group passed to the first Grouper will be
that determined by @Group (if @Groupis defined). This allows you even greater control over the group
when using an intrinsic group. For a grouper to be used when determining the group for a key, it's keyType
must be assignable from the key being grouped.
Let's take a look at an example of a Grouper:
Here we determine a simple grouper that can take the key class and extract from the group from the key
using a pattern. We ignore any group information specified on the key class.
You must register every grouper you wish to have used. If you are configuring Infinispan programmatically:
<clustering>
<hash>
<groups enabled="true">
<grouper class="com.acme.KXGrouper" />
</groups>
</hash>
</clustering>
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
<transaction
transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"
transactionMode="TRANSACTIONAL"
lockingMode="OPTIMISTIC"/>
<namedCache name="transactional">
<transaction transactionMode="TRANSACTIONAL"/>
</namedCache>
transactionMode can only take two values: TRANSACTIONAL and NON_TRANSACTIONAL; one can
configure a transactional cache programatically as well:
Configuration c = new
ConfigurationBuilder().transaction().transactionMode(TransactionMode.TRANSACTIONAL).build();
assert c.transaction().transactionalCache();
Infinispan 6.0
Supported transaction models are optimistic and pessimistic. Optimistic model is an improvement over the
old transaction model as it completely defers lock acquisition to transaction prepare time. New approach
reduces lock acquisition duration and increases throughput which in turn avoids deadlocks significantly. In
pessimistic model, cluster wide-locks are acquired on each write operation only being released after the
transaction completed.
Optimistic Transactions
With optimistic transactions locks are being acquired at transaction prepare time and are only being held up
to the point the transaction commits (or rollbacks). This is different from the 5.0 default locking model where
local locks are being acquire on writes and cluster locks are being acquired during prepare time.
Optimistic transactions can be enabled in the configuration file:
<namedCache name="transactional">
<transaction transactionMode="TRANSACTIONAL" lockingMode="OPTIMISTIC"/>
</namedCache>
or programatically:
Configuration c = new
ConfigurationBuilder().transaction().lockingMode(LockingMode.OPTIMISTIC).build();
assert c.transaction().lockingMode() == LockingMode.OPTIMISTIC;
Infinispan 6.0
Pessimistic Transactions
From a lock acquisition perspective, pessimistic transactions obtain locks on keys at the time the key is
written. E.g.
transactionManager.begin();
cache.put(k1,v1); //k1 is locked
cache.remove(k2); //k2 is locked when this returns
transactionManager.commit();
When cache.put(k1,v1) returns k1 is locked and no other transaction running anywhere in the cluster can
write to it. Reading k1 is still possible. The lock on k1 is released when the transaction completes (commits
or rollbacks).
Pessimistic transactions can be enabled in the configuration file:
<namedCache name="transactional"/>
<transaction transactionMode="TRANSACTIONAL" lockingMode="PESSIMISTIC"/>
</namedCache>
or programatically:
Configuration c = new
ConfigurationBuilder().transaction().lockingMode(LockingMode.PESSIMISTIC).build();
assert c.transaction().lockingMode() == LockingMode.PESSIMISTIC;
Backward compatibility
The autoCommit attribute was added in order to assure backward compatibility. If a cache is transactional
and autoCommit is enabled (defaults to true) then any call that is performed outside of a transaction's scope
is transparently wrapped within a transaction. In other words Infinispan adds the logic for starting a
transaction before the call and committing it after the call.
Therefore if your code accesses a cache both transactionally and non-transactionally all you have to do
when migrating to Infinispan 5.1 is mark the cache as transactional and enable autoCommit (that's actually
enabled by default)
The autoCommit feature can be managed through configuration:
<namedCache name="transactional">;
<transaction transactionMode="TRANSACTIONAL" autoCommit="true"/>
</namedCache>
Infinispan 6.0
Some clues on when to enable deadlock detection. A high number of transaction rolling back due to
TimeoutException is an indicator that this functionality might help. TimeoutException might be caused by
other causes as well, but deadlocks will always result in this exception being thrown. Generally, when you
have a high contention on a set of keys, deadlock detection may help. But the best way is not to guess the
performance improvement but to benchmark and monitor it: you can have access to statistics (e.g. number
of deadlocks detected) through JMX, as it is exposed via the DeadlockDetectingLockManager MBean. For
more details on how deadlock detection works, benchmarks and design details refer to this article.
Note: deadlock detection only runs on an a per cache basis: deadlocks that spread over two or more caches
won't be detected.
Infinispan 6.0
<transaction useSynchronization="true"/>
Synchronisations have the advantage that they allow TransactionManager to optimize 2PC with a 1PC
where only one other resource is enlisted with that transaction (last resource commit optimization). E.g.
Hibernate second level cache: if Infinispan registers itself with the TransactionManager as a XAResource
than at commit time, the TransactionManager sees two XAResource (cache and database) and does not
make this optimization. Having to coordinate between two resources it needs to write the tx log to disk. On
the other hand, registering Infinispan as a Synchronisation makes the TransactionManager skip wrtting the
log to the disk (performance improvement).
Infinispan 6.0
5. It is time now to start the Infinispan server that you want to be testing. For detailed information on
starting up a Hot Rod server, check this wiki. If you want to start the Hot Rod server quickly, the
following command should do the job:
1. $INFINISPAN_HOME/bin/startServer.sh -r hotrod -l 0.0.0.0
6. Finally, let's start the load test. Currently, a single load test exists which after a warmup phase, it does
a certain amount of put/get calls on a pool of keys with a configurable distribution. By default, it
executes 20% put operations and 80% get operations. So, if you're going to start the Hot Rod test,
you'd simply do:
1. cd infinispan-server-grinder/
2. ./bin/startHotRodAgent.sh
7. Once the test has finished, the output can be located in
infinispan-server-grinder/log/out-<host>-0.log and will show something like this at the
bottom:
Tests
Errors
Mean Test
Time (ms)
Test Time
Standard
Deviation
(ms)
TPS
Test 1
Test 2
Test 3
25
400136
99864
0
0
0
13742.56
1.92
2.41
457.22
2.55
4.97
0.29
4687.08
1169.78
Totals
500025
2.70
97.26
1952.38
The output is saying that it first run 25 threads, each sending 1000 operations in order to warm up the
cache. Afterwards, each of these 25 threads send 20.000 operations making a total of 500.000
operations, out of which 400136 were get calls and 99864 were put calls, and the test here indicates
what was the mean test time for each of these operations, including standard deviation and how many
operations per second (TPS) were executed. In this case, 4686 get operations per second and 1169
put operations per second.
Infinispan 6.0
3.26.1 Overview
Following some of the principles set out by Brian Stansberry in Using JBoss Cache 3 as a Hibernate 3.5
Second Level Cache and taking in account improvements introduced by Infinispan, an Infinispan
JPA/Hibernate second level cache provider has been developed. This wiki explains how to configure
JPA/Hibernate to use the Infinispan and for those keen on lower level details, the key design decisions made
and differences with previous JBoss Cache based cache providers.
If you're unfamiliar with JPA/Hibernate Second Level Caching, I'd suggest you to read Chapter 2.1 in this
guide which explains the different types of data that can be cached.
On Caching
Query result caching, or entity caching, may or may not improve application performance. Be
sure to benchmark your application with and without caching.
3.26.2 Configuration
1. First of all, to enable JPA/Hibernate second level cache with query result caching enabled, add either of
the following:
Infinispan 6.0
2. Now, configure the Infinispan cache region factory using one of the two options below:
If the Infinispan CacheManager instance happens to be bound to JNDI select JndiInfinispanRegionFactory
as the cacheregion factory and add the cache manager's JNDI name:
If running JPA/Hibernate and Infinispan standalone or within third party Application Server, select the
InfinispanRegionFactory as the cache region factory:
Infinispan 6.0
This is all the configuration you need to have JPA/Hibernate use Infinispan as cache provider with the
default settings. You will still need to define which entities and queries need to be cached as defined in the
Hibernate reference documentation, but that configuration aspect is not peculiar to Infinispan.
This default configuration should suit the majority of use cases but sometimes, further configuration is
required and to help with such situations, please check the following section where more advanced settings
are discussed.
Infinispan 6.0
Infinispan 6.0
If you're running within an application server, it's recommended that you use:
If you're running in a standalone environment and you wanna enable JTA transaction factory, use:
The reason why JPA does not require a transaction factory class to be set up is because the entity
manager already sets it to a variant of CMTTransactionFactory.
2. Select the correct Hibernate transaction manager lookup:
If you're running within an application server, select the appropriate lookup class according to "JTA
Transaction Managers" table.
For Example if you were running with the JBoss Application Server you would set:
Infinispan 6.0
If you are running standalone and you want to add a JTA transaction manager lookup, things get a bit
more complicated. Due to a current limitation, Hibernate does not support injecting a JTA
TransactionManager or JTA UserTransaction that are not bound to JNDI. In other words, if you want
to use JTA, Hibernate expects your TransactionManager to be bound to JNDI and it also expects that
UserTransaction instances are retrieved from JNDI. This means that in an standalone environment,
you need to add some code that binds your TransactionManager and UserTransaction to JNDI. With
this in mind and with the help of one of our community contributors, we've created an example that
does just that: JBoss Standalone JTA Example. Once you have the code in place, it's just a matter of
selecting the correct Hibernate transaction manager lookup class, based on the JNDI names given. If
you take JBossStandaloneJtaExample as an example, you simply have to add:
As you probably have noted through this section, there wasn't a single mention of the need to
configure Infinispan's transaction manager lookup and there's a good reason for that. Basically, the
code within Infinispan cache provider takes the transaction manager that has been configured at the
Hibernate level and uses that. Otherwise, if no Hibernate transaction manager lookup class has been
defined, Infinispan uses a default dummy transaction manager.
Since Hibernate 4.0, the way Infinispan hooks into the transaction manager can be configured. By default,
since 4.0, Infinispan interacts with the transaction manager as an JTA synchronization, resulting in a faster
interaction with the 2LC thanks to some key optimisations that the transaction manager can apply . However
if desired, users can configure Infinispan to act as an XA resource (just like it did in 3.6 and earlier) by
disabling the use of the synchronization. For example:
value="false"/>
Infinispan 6.0
The Infinispan cache provider jar file contains an Infinispan configuration file, which is the one used by
default when configuring the Infinispan standalone cache region factory. This file contains default cache
configurations for all Hibernate data types that should suit the majority of use cases. However, if you want to
use a different configuration file, you can configure it via the following property:
For each Hibernate cache data types, Infinispan cache region factory has defined a default cache name to
look up in either the default, or the user defined, Infinispan cache configuration file. These default values can
be found in the Infinispan cache provider javadoc. You can change these cache names using the following
properties:
Infinispan 6.0
One of the key improvements brought in by Infinispan is the fact that cache instances are more lightweight
than they used to be in JBoss Cache. This has enabled a radical change in the way entity/collection type
cache management works. With the Infinispan cache provider, each entity/collection type gets each own
cache instance, whereas in old JBoss Cache based cache providers, all entity/collection types would be
sharing the same cache instance. As a result of this, locking issues related to updating different
entity/collection types concurrently are avoided completely.
This also has an important bearing on the meaning of hibernate.cache.infinispan.entity.cfg and
hibernate.cache.infinispan.collection.cfg properties. These properties define the template cache name that
should be used for all entity/collection data types. So, with the above hibernate.cache.infinispan.entity.cfg
configuration, when a region needs to be created for entity com.acme.Person, the cache instance to be
assigned to this entity will be based on a "custom-entity" named cache.
On top of that, this finer grained cache definition enables users to define cache settings on a per
entity/collection basis. For example:
Infinispan 6.0
Here, we're configuring the Infinispan cache provider so that for com.acme.Person entity type, the cache
instance assigned will be based on a "person-entity" named cache, and for com.acme.Person.addresses
collection type, the cache instance assigned will be based on a "addresses-collection" named cache. If either
of these two named caches did not exist in the Infinispan cache configuration file, the cache provider would
create a cache instance for com.acme.Person entity and com.acme.Person.addresses collection based on
the default cache in the configuration file.
Furthermore, thanks to the excellent feedback from the Infinispan community and in particular, Brian
Stansberry, we've decided to allow users to define the most commonly tweaked Infinispan cache parameters
via hibernate.cfg.xml or persistence.xml, for example eviction/expiration settings. So, with the Infinispan
cache provider, you can configure eviction/expiration this way:
Infinispan 6.0
With the above configuration, you're overriding whatever eviction/expiration settings were defined for the
default entity cache name in the Infinispan cache configuration used, regardless of whether it's the default
one or user defined. More specifically, we're defining the following:
All entities to use LRU eviction strategy
The eviction thread to wake up every 2000 milliseconds
The maximum number of entities for each entity type to be 5000 entries
The lifespan of each entity instance to be 600000 milliseconds
The maximum idle time for each entity instance to be 30000
You can also override eviction/expiration settings on a per entity/collection type basis in such way that the
overriden settings only afftect that particular entity (i.e. com.acme.Person) or collection type (i.e.
com.acme.Person.addresses). For example:
The aim of these configuration capabilities is to reduce the number of files needed to modify in order to
define the most commonly tweaked parameters. So, by enabling eviction/expiration configuration on a per
generic Hibernate data type or particular entity/collection type via hibernate.cfg.xml or persistence.xml, users
don't have to touch to Infinispan's cache configuration file any more. We believe users will like this approach
and so, if you there are any other Infinispan parameters that you often tweak and these cannot be configured
via hibernate.cfg.xml or persistence.xml, please let the Infinispan team know by sending an email to
infinispan-dev@lists.jboss.org.
Infinispan 6.0
Please note that query/timestamp caches work the same way they did with JBoss Cache based cache
providers. In other words, there's a query cache instance and timestamp cache instance shared by all. It's
worth noting that eviction/expiration settings are allowed for query cache but not for timestamp cache. So
configuring an eviction strategy other than NONE for timestamp cache would result in a failure to start up.
Finally, from Hibernate 3.5.4 and 3.6 onwards, queries with specific cache region names are stored under
matching cache instances. This means that you can now set query cache region specific settings. For
example, assuming you had a query like this:
The query would be stored under "AccountRegion" cache instance and users could control settings in similar
fashion to what was done with entities and collections. So, for example, you could define specific eviction
settings for this particular query region doing something like this:
Infinispan 6.0
Infinispan 6.0
3.27.1 asyncListenerExecutor
maxThreads = 1
threadNamePrefix = "notification-thread"
3.27.2 asyncTransportExecutor
maxThreads = 25
threadNamePrefix = "transport-thread"
3.27.3 evictionScheduledExecutor
maxThreads = 1 (cannot be changed)
threadNamePrefix = "eviction-thread"
3.27.4 replicationQueueScheduledExecutor
maxThreads = 1 (cannot be changed)
threadNamePrefix = "replicationQueue-thread"
Infinispan 6.0
Infinispan 6.0
3.28.2 GossipRouter
Another approach is to have a central server (Gossip, which each node will be configured to contact. This
central server will tell each node in the cluster about each other node. More on Gossip Router @
http://www.jboss.org/community/wiki/JGroupsGossipRouter
The address (ip:port) that the Gossip router is listening on can be injected into the JGroups configuration
used by Infinispan. To do this pass the gossip routers address as a system property to the JVM e.g.
-DGossipRouterAddress="10.10.2.4[12001]" and reference this property in the JGroups configuration that
Infinispan is using e.g.
<config>
<TCP bind_port="7800" />
<TCPGOSSIP timeout="3000" initial_hosts="$\{GossipRouterAddress\}" num_initial_members="3"
/>
.
.
</config>
Infinispan 6.0
3.28.3 S3_PING
Finally you can configure your JGroups instances to use a shared storage to exchange the details of the
cluster nodes. S3_PING was added to JGroups in 2.6.12 and 2.8, and allows the Amazon S3 to be used as
the shared storage. It is experimental at the moment but offers another method of clustering without a central
server. Be sure that you have signed up for Amazon S3 as well as EC2 to use this method.
3.28.4 JDBC_PING
A similar approach to S3_PING, but using a JDBC connection to a shared database. On EC2 that is quite
easy using Amazon RDS. See the JDBC_PING Wiki page for details.
Infinispan 6.0
3.29.2 Configuration
Eviction may be configured using the Configuration bean or the XML file. Eviction configuration is on a
per-cache basis. Valid eviction-related configuration elements are:
Infinispan 6.0
Default values
Eviction is disabled by default. If enabled (using an empty <eviction /> element), certain default values are
used:
strategy: EvictionStrategy.NONE is assumed, if a strategy is not specified..
wakeupInterval: 5000 is used if not specified.
If you wish to disable the eviction thread, set wakeupInterval to -1.
maxEntries: -1 is used if not specified, which means unlimited entries.
0 means no entries, and the eviction thread will strive to keep the cache empty.
Expiration lifespan and maxIdle both default to -1.
Infinispan 6.0
Using expiration
Expiration allows you to set either a lifespan or a maximum idle time on each key/value pair stored in the
cache. This can either be set cache-wide using the configuration, as described above, or it can be defined
per-key/value pair using the Cache interface. Any values defined per key/value pair overrides the
cache-wide default for the specific entry in question.
For example, assume the following configuration:
Infinispan 6.0
3.30.1 Introduction
Infinispan can be configured to be either local (standalone) or clustered. If in a cluster, the cache can be
configured to replicate changes to all nodes, to invalidate changes across nodes and finally to be used in
distributed mode - state changes are replicated to a small subset of nodes enough to be fault tolerant but not
to many nodes to prevent scalability.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Read consistency
Since GETs are sent to all data owners in parallel and the first returning result is used, this can lead to data
inconsistency when using an asynchronous transport. If an updating thread modifies the primary data owner,
but updates are only sent to backup nodes asynchronously, a concurrent read may read a stale value for a
short period of time until the asynchronous replication completes.
Note that this is only if the transport is asynchronous. If using a synchronous transport this behavior is not
exhibited.
Infinispan 6.0
First, let's consider how virtual nodes help conceptually by taking a couple of distribution examples, and
armed with that knowledge, look at how Infinispan uses them.
Consider a hash space of 1000 (there are 1000 buckets into which data can be placed). If there were two
nodes, it is possible you can have 1 node being used for 1 bucket, and 1 node for 999 buckets (this is the
most pessimistic distribution!). If there were 200 nodes, the worst distribution of node would end up being
199 nodes responsible for one bucket each (199 buckets in total), and 1 node being responsible for 801
buckets. If there were 1000 nodes, then each node must be responsible for 1 bucket each. From this we can
deduce that as the number of nodes tends to the size of the hash space, that the distribution of buckets to
nodes improves.
A guiding principle of Infinispan is that it always uses an algorithm to locate a key in the hash space, never
allowing the node on which the entry is stored to be specified manually. This scheme allows any node to
know which nodes owns a key, without having to distribute such ownership information. This reduces the
overhead of Infinispan, but more importantly improves redundancy as there is no need to replicate the
ownership information in case of node failure.
With this in mind, we can see that virtual nodes are an ideal solution to the distribution of nodes problem, as
it allows the location of an entry to be determined algorithmically.
Infinispan implements virtual nodes by altering the algorithm for splitting the hash space whenever a node
joins or leaves the grid. Rather than allocating a block of the hashspace to the node, it allocates a number of
blocks from throughout the hash space.
Often it's easier to understand the topology changes that virtual nodes introduce through diagrams.
Infinispan 6.0
Infinispan 6.0
<namedCache name="cacheWithVirtualNodes">
<clustering>
<hash numVirtualNodes="10" />
</clustering>
</namedCache>
new ConfigurationBuilder()
.clustering()
.hash()
.numVirtualNodes(10)
.build();
Infinispan 6.0
TODO Add notes on how to select number of virtual nodes.
3.30.6 L1 Caching
To prevent repeated remote calls when doing multiple GETs, L1 caching can be enabled. L1 caching places
remotely received values in a near cache for a short period of time (configurable) so repeated lookups would
not result in remote calls. In the above diagram, if L1 was enabled, a subsequent GET for the same key on
Server3 would not result in any remote calls.
Figure 4. L1 caching
L1 caching is not free though. Enabling it comes at a cost, and this cost is that every time a key is updated,
an invalidation message needs to be multicast to ensure nodes with the entry in L1 invalidates the entry. L1
caching causes the requesting node to cache the retrieved entry locally and listen for changes to the key on
the wire. L1-cached entries are given an internal expiry to control memory usage. Enabling L1 will improve
performance for repeated reads of non-local keys, but will increase memory consumption to some degree. It
offers a nice tradeoff between the "read-mostly" performance of an invalidated data grid with the scalability
of a distributed one. Is L1 caching right for you? The correct approach is to benchmark your application with
and without L1 enabled and see what works best for your access pattern.
Infinispan 6.0
Looking for Buddy Replication? Buddy Replication - from JBoss Cache - does not exist in
Infinispan. See this blog article which discusses the reasons why Buddy Replication was not
implemented in Infinispan, and how the same effects can be achieved using Infinispan <a
href="http://infinispan.blogspot.com/2009/08/distribution-instead-of-buddy.html">http://infinispan.blogspot.co
<a
href="http://www.springframework.org/schema/beans/spring-beans.xsd">http://www.springframework.org/schema/bean
<a
href="http://www.springframework.org/schema/cache">http://www.springframework.org/schema/cache</a>
<a
href="http://www.springframework.org/schema/cache/spring-cache.xsd">http://www.springframework.org/schema/cach
<cache:annotation-driven />
</beans>
Infinispan 6.0
somewhere in your application context. This will tell Spring to be on the lookout for
{font:monospace}@Cacheable{font} and {font:monospace}@CacheEvict{font} within your application
code.Now, assuming you've already {font:monospace}infinispan.jar{font} and its dependencies on your
classpath, all that's left to do is installing {font:monospace}infinispan-spring{font} and
{font:monospace}spring{font}. For maven users this translates into
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.1.0.M1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-spring</artifactId>
<version>5.0.0</version>
<scope>compile</scope>
</dependency>
{font:monospace}Gradle{font} users will most likely know how to adapt this to their needs. Those leaning
towards a more ... pedestrian way of managing their dependencies will need to download
{font:monospace}Spring 3.1.0 M1{font} and install it manually alongside
{font:monospace}infinispan-spring.jar{font} from the Infinispan distribution.h1. Telling Spring to use Infinispan
as its caching providerSpring 3.1's cache provider SPI comprises two interfaces,
{font:monospace}org.springframework.cache.CacheManager{font} and
{font:monospace}org.springframework.cache.Cache{font} where a {font:monospace}CacheManager{font}
serves as a factory for named {font:monospace}Cache{font} instances. By default Spring will look at runtime
for a {font:monospace}CacheManager{font} implementation having the bean name "cacheManager" in an
application's application context. So by putting
somewhere in your application context you tell Spring to henceforth use Infinispan as its caching provider.h1.
Adding caching to your application codeAs outlined above enabling caching in your application code is as
simple as adding {font:monospace}@Cacheable{font} and {font:monospace}@CacheEvict{font} to select
methods. Suppose you've got a DAO for, say, books and you want book instances to be cached once
they've been loaded from the underlying database using {font:monospace}BookDao#findBook(Integer
bookId){font}. To that end you annotate {font:monospace}findBook(Integer bookId){font} with
{font:monospace}@Cacheable{font}, as in
@Transactional
@Cacheable(value = "books", key = "#bookId")
Book findBook(Integer bookId) {...}
Infinispan 6.0
This will tell Spring to cache Book instances returned from calls to {font:monospace}findBook(Integer
bookId){font} in a named cache "books", using the parameter's "bookId" value as a cache key. Here,
"#bookId" is an expression in the [Spring Expression Language|
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/expressions.html] that
evaluates to the {font:monospace}bookId{font} argument. If you don't specify the {font:monospace}key{font}
attribute Spring will generate a hash from the supplied method arguments - in this case only
{font:monospace}bookId{font} - and use that as a cache key. Essentially, you relinquish control over what
cache key to use to Spring. Which may or may not be fine depending on your application's needs.Though
the notion of actually deleting a book will undoubtedly seem alien and outright abhorrent to any sane reader
there might come the time when your application needs to do just that. For whatever reason. In this case you
will want for such a book to be removed not only from the underlying database but from the cache, too. So
you annotate {font:monospace}deleteBook(Integer bookId){font} with {font:monospace}@CacheEvict{font} as
in
@Transactional
@CacheEvict(value = "books", key = "#bookId")
void deleteBook(Integer bookId) {...}
and you may rest assured that no stray books be left in your application once you decide to remove them.h1.
OutroHopefully you enjoyed our quick tour of Infinispan's support for Spring's cache abstraction and saw
how easy it is for all your caching woes to be taken care of by Infinispan. More information may be found in
Spring's as usual rather excellent [reference documentation|
http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/cache.html] and
[javadocs|
http://static.springsource.org/spring/docs/3.1.0.M1/javadoc-api/index.html?org/springframework/cache/package-summary.h
]. Also see [this|http://blog.springsource.com/2011/02/23/spring-3-1-m1-caching/] very nice posting on the
official Spring blog for a somewhat more comprehensive introduction to Spring's cache abstraction.{code}
Infinispan 6.0
What Infinispan is doing here is effectively saying that when putting data read from external read, it will use
an almost-zero lock acquisition time and that if the locks cannot be acquired, it will fail silently without
throwing any exception related to lock acquisition. It also specifies that regardless of the cache mode, if the
cache is clustered, it will replicate asynchronously and so won't wait for responses from other nodes. The
combination of all these flags make this kind of operation very efficient, and the efficiency comes from the
fact this type of putForExternalRead calls are used with the knowledge that client can always head back to a
persistent store of some sorts to retrieve the data that should be stored in memory. So, any attempt to store
the data is just a best effort and if not possible, the client should try again if there's a cache miss.
3.33.1 Examples
If you want to use these or any other flags available, which by the way are described in detail the Flag
enumeration, you simply need to get hold of the advanced cache and add the flags you need via the
withFlags() method call. For example:
It's worth noting that these flags are only active for the duration of the cache operation. If the same flags
need to be used in several invocations, even if they're in the same transaction, withFlags() needs to be
called repeatedly. Clearly, if the cache operation is to be replicated in another node, the flags are carried
over to the remote nodes as well.
3.33.2 DecoratedCache
Another approach would be to use the DecoratedCache wrapper. This allows you to reuse flags. For
example:
Infinispan 6.0
Infinispan 6.0
3.34.2 API
Following code snippet depicts how a reference to this service can be obtained and used.
The service is started at step 2: after this point it uses the supplied Excutor to generate and queue keys. At
step 3, we obtain a key for this service, and use it at step 4, with that guarantee that it is distributed in node
identified by cacheManager.getAddress().
3.34.3 Lifecycle
KeyAffinityService extends Lifecycle, which allows stopping and (re)starting it:
The service is instantiated through KeyAffinityServiceFactory. All the factory method have an Executors
parameter, that is used for asynchronous key generation (so that it won't happen in the caller's thread). It is
user's responsibility to handle the shutdown of this Executor.
The KeyAffinityService, once started, needs to be explicitly stopped. This stops the async key generation
and releases other held resources.
The only situation in which KeyAffinityService stops by itself is when the cache manager with wich it was
registered is shutdown.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Note: the recoveryInfoCacheName attribute is not mandatory. More information about it can be found in the
Recovery Cache section below.
Alternatively you can enable it through the fluent configuration API as follows:
Recovery can be enabled/disabled o a per cache level: e..g it is possible to have a transaction spanning a
cache that is has it enabled and another one that doesn't.
Recovery cache
In order to track in-doubt transactions and be able to reply them Infinispan caches all transaction state for
future use. This state is held only for in-doubt transaction, being removed for successfully completed
transactions after the commit/rollback phase completed.
This in-doubt transaction data is held within a local cache: this allows one to configure swapping this info to
disk through cache loader in the case it gets too big. This cache can be specified through the
"recoveryInfoCacheName" configuration attribute. If not specified infinispan will configure a local cache for
you.
It is possible (though not mandated) to share same recovery cache between all the Infinispan caches that
have recovery enabled. If default recovery cache is overridden then the specified recovery cache must use
a TransactionManagerLookup that returns a different TM than the one used by the cache itself.
Infinispan 6.0
Note: It is a common practice to run the recovery in a different process than the one running the transaction.
At the moment it is not possible to do this with infinispan: the recovery must be run from the same process
where the infinispan instance exists. This limitation will be dropped once ransactions over HotRod are
available.
The status of each in-doubt transaction is displayed(in this example "PREPARED"). There might be multiple
elements in the status field, e.g. "PREPARED" and "COMMITTED" in the case the transaction committed on
certain nodes but not on all of them.
2. SA visually maps the XID received from the TM to an Infinispna internal id, represented as a number. This
step is needed because the XID, a byte array, cannot conveniently be passed to the JMX tool (e.g.
JConsole) and then re-assembled on infinispan's side.
3. SA forces the transaction's commit/rollback through the corresponding jmx operation, based on the
internal id.
The image below is obtained by forcing the commit of the transaction based on its internal id.
Infinispan 6.0
Note: All JMX operations described above can be executed on any node, disregarding where the transaction
originated.
Infinispan 6.0
3.36.1 Introduction
IMPORTANT NOTE: From Hibernate 4.0.1 onwards, Infinispan now interacts as a synchronization
rather than as an XA resource with the transaction manager when used as second-level cache, so
there's no longer need to apply any of the changes suggested below!
Infinispans predecessor JBossCache requires integration with JTA when used as 2L-cache for a Hibernate
application. At the moment of writing this article (Hibernate 3.5.0.Beta3) also Infinspan requires integration
with JTA. Hibernate integrated with JTA is already largely used in EJB applications servers, but most users
using Hibernate with Java SE outside any EJB container, still use the plain JDBC approach instead to use
JTA.
According Hiberante documentation it should also possible to integrate JTA in a standalone application
outside any EJB container, but I did hardly find any documentation how to do that in detail. (probably the
reason is, that probably 95% of people is using hibernate within a EJB app. server or using SPRING). This
article should give you some example how to realize a standalone Hibernate app. outside of a EJB container
with JTA integration (and using Infinispan 2nd level cache).
As first thing you have to choose which implementation of TransactionManager to take. This article comes
with examples for following OpenSource TransactionManagers:
1. JBoss
2. JOTM
3. Bitronix
4. Atomikos
Datasource/Transaction interaction
A very important aspect is not forgetting to couple the datasource with your transaction manager. In
other words, the corresponding XAResource must be onto the transaction manager, otherwise only
DML-statements but no commits/rollbacks are propagated to your database.
import
import
import
import
import
Infinispan 6.0
import
import
import
import
import
import
import
import
import
import
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.Name;
javax.naming.NameNotFoundException;
javax.naming.Reference;
javax.naming.StringRefAddr;
javax.persistence.EntityManager;
javax.persistence.Persistence;
javax.transaction.TransactionManager;
javax.transaction.UserTransaction;
import
import
import
import
import
import
import
import
import
import
org.enhydra.jdbc.standard.StandardXADataSource;
org.hibernate.Session;
org.hibernate.SessionFactory;
org.hibernate.ejb.HibernateEntityManagerFactory;
org.hibernate.transaction.JBossTransactionManagerLookup;
org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup;
org.jboss.util.naming.NonSerializableFactory;
org.jnp.interfaces.NamingContext;
org.jnp.server.Main;
org.jnp.server.NamingServer;
new JBossStandaloneJTAManagerLookup();
Infinispan 6.0
xads.setDriverName("org.hsqldb.jdbcDriver");
xads.setDriverName("com.p6spy.engine.spy.P6SpyDriver"); // comment this line if you
don't want p6spy-logging
xads.setUrl("jdbc:hsqldb:hsql://localhost");
//xads.setTransactionManager(_ml.getTransactionManager()); useless here as this
information is not serialized
ictx.bind("java:/MyDatasource", xads);
final HibernateEntityManagerFactory emf =
Persistence.createEntityManagerFactory("helloworld");
(HibernateEntityManagerFactory)
a.name
ictx.close();
namingMain.stop();
emf.close();
} catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
}
public static class ExtendedXADataSource extends StandardXADataSource { // XAPOOL
@Override
public Connection getConnection() throws SQLException {
if (getTransactionManager() == null) { // although already set before, it results
null again after retrieving the datasource by jndi
TransactionManager tm; // this is because the TransactionManager information is
not serialized.
try {
tm = _ml.getTransactionManager();
} catch (Exception e) {
Infinispan 6.0
throw new SQLException(e);
}
setTransactionManager(tm); //
retrieved by jndi,
//
}
// see
http://cvs.forge.objectweb.org/cgi-bin/viewcvs.cgi/xapool/xapool/examples/xapooldatasource/DatabaseHelper.java
return super.getXAConnection().getConnection();
}
}
/**
* Helper method that binds the a non serializable object to the JNDI tree.
*
* @param jndiName Name under which the object must be bound
* @param who Object to bind in JNDI
* @param classType Class type under which should appear the bound object
* @param ctx Naming context under which we bind the object
* @throws Exception Thrown if a naming exception occurs during binding
*/
private static void bind(String jndiName, Object who, Class classType, Context ctx) throws
Exception {
// Ah ! This service isn't serializable, so we use a helper class
NonSerializableFactory.bind(jndiName, who);
Name n = ctx.getNameParser("").parse(jndiName);
while (n.size() > 1) {
String ctxName = n.get(0);
try {
ctx = (Context) ctx.lookup(ctxName);
} catch (NameNotFoundException e) {
System.out.println("Creating subcontext:" + ctxName);
ctx = ctx.createSubcontext(ctxName);
}
n = n.getSuffix(1);
}
// The helper class NonSerializableFactory uses address type nns, we go on to
// use the helper class to bind the service object in JNDI
StringRefAddr addr = new StringRefAddr("nns", jndiName);
Reference ref = new Reference(classType.getName(), addr,
NonSerializableFactory.class.getName(), null);
ctx.rebind(n.get(0), ref);
}
private static void unbind(String jndiName, Context ctx) throws Exception {
NonSerializableFactory.unbind(jndiName);
ctx.unbind(jndiName);
}
}
Infinispan 6.0
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="helloworld" transaction-type="JTA">
<jta-data-source>java:/MyDatasource</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value = "create"/>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.jndi.class"
value="org.jnp.interfaces.NamingContextFactory"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="current_session_context_class" value="jta"/>
<!-- <property name="hibernate.session_factory_name"
value="java:/hibernate/MySessionFactory"/> optional -->
<property name="hibernate.transaction.factory_class"
value="org.hibernate.transaction.JTATransactionFactory"/>
<property name="hibernate.connection.release_mode" value="auto"/>
<!-- setting above is important using XA-DataSource on SQLServer,
otherwise SQLServerException: The function START: has failed. No transaction
cookie was returned.-->
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.region.factory_class"
value="org.hibernate.cache.infinispan.InfinispanRegionFactory"/>
</properties>
</persistence-unit>
</persistence>
3.36.3 JOTM
The example with JOTM is more simple, but apparently it's JNDI implementation is not useable without
wasting any rmi port. So it is not completely 'standalone' as the JNDI service is exposed outside your virtual
machine.
Infinispan 6.0
import
import
import
import
import
javax.persistence.EntityManager;
javax.persistence.EntityManagerFactory;
javax.persistence.Persistence;
javax.transaction.TransactionManager;
javax.transaction.UserTransaction;
import
import
import
import
org.enhydra.jdbc.standard.StandardXADataSource;
org.hibernate.transaction.JOTMTransactionManagerLookup;
org.objectweb.jotm.Jotm;
org.objectweb.transaction.jta.TMService;
new JOTMTransactionManagerLookup();
// see
http://cvs.forge.objectweb.org/cgi-bin/viewcvs.cgi/xapool/xapool/examples/xapooldatasource/DatabaseHelper.java
return super.getXAConnection().getConnection();
}
}
Infinispan 6.0
// XAPOOL
ExtendedXADataSource xads = new ExtendedXADataSource();
xads.setDriverName("org.hsqldb.jdbcDriver");
xads.setDriverName("com.p6spy.engine.spy.P6SpyDriver");
xads.setUrl("jdbc:hsqldb:hsql://localhost");
jndiCtx.bind("java:/MyDatasource", xads);
/* startup JOTM */
TMService jotm = new Jotm(true, false);
jotm.getUserTransaction().setTransactionTimeout(36000); // secs, important JOTM
default is only 60 secs !
}
catch( Exception e )
{
e.printStackTrace();
}
System.exit(0);
}
Infinispan 6.0
}
<property name="hibernate.jndi.class"
value="org.ow2.carol.jndi.spi.MultiOrbInitialContextFactory"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JOTMTransactionManagerLookup"/>
For using the JTA Hibernate application as servlet in tomcat please read
http://jotm.objectweb.org/current/jotm/doc/howto-tomcat-jotm.html and also
https://forum.hibernate.org/viewtopic.php?f=1&t=1003866
3.36.4 Bitronix
The Transaction Manager comes bundled with a fake in memory jndi-implementation which is ideal for
standalone purpose. To integrate with Infinispan I did need a ad-hoc pre-alpha improvement (see attached
btm-ispn.jar by courtesy of Mr. Ludivic Orban). BitronixTM offers the so-called Last Resource Commit
optimization (aka Last Resource Gambit or Last Agent optimization) and it allows a single non-XA database
to participate in a XA transaction by cleverly ordering the resources. "Last Resource Commit" is not part of
the XA spec as it doesn't cover the transaction-recovery aspect, so if your database does not support XA (or
if you don't wish to have the Xa-driver performance overhead against the plain jdbc) then the "Last Resource
Commit" feature should be ideal for the combination 1 single database plus infinispan.
javax.naming.Context;
javax.naming.InitialContext;
javax.persistence.EntityManager;
javax.persistence.Persistence;
javax.transaction.UserTransaction;
import
import
import
import
org.hibernate.cache.infinispan.InfinispanRegionFactory;
org.hibernate.ejb.HibernateEntityManagerFactory;
org.hibernate.impl.SessionFactoryImpl;
org.infinispan.manager.CacheManager;
import bitronix.tm.resource.ResourceRegistrar;
import bitronix.tm.resource.infinispan.InfinispanCacheManager;
import bitronix.tm.resource.jdbc.PoolingDataSource;
Infinispan 6.0
"bitronix.tm.jndi.BitronixInitialContextFactory");
// Attention: BitronixInitialContextFactory is'nt a real jndi implementation: you
can't do explicit bindings
// It is ideal for hiberante standalone usage, as it automatically 'binds' the
needed things: datasource + usertransaction
System.out.println("create initial context");
InitialContext ictx = new InitialContext(props);
PoolingDataSource myDataSource = new PoolingDataSource();
myDataSource.setClassName("bitronix.tm.resource.jdbc.lrc.LrcXADataSource");
myDataSource.setMaxPoolSize(5);
myDataSource.setAllowLocalTransactions(true);
myDataSource.getDriverProperties().setProperty("driverClassName",
"com.p6spy.engine.spy.P6SpyDriver");
myDataSource.getDriverProperties().setProperty("url",
"jdbc:hsqldb:hsql://localhost");
myDataSource.getDriverProperties().setProperty("user", "sa");
myDataSource.getDriverProperties().setProperty("password", "");
myDataSource.setUniqueName("java:/MyDatasource");
myDataSource.setAutomaticEnlistingEnabled(true); // important to keep it to true
(default), otherwise commits/rollbacks are not propagated
myDataSource.init(); // does also register the datasource on the Fake-JNDI with
Unique Name
org.hibernate.transaction.BTMTransactionManagerLookup lokhiberante = new
org.hibernate.transaction.BTMTransactionManagerLookup();
HibernateEntityManagerFactory emf = (HibernateEntityManagerFactory)
Persistence.createEntityManagerFactory("helloworld");
SessionFactoryImpl sfi = (SessionFactoryImpl) emf.getSessionFactory();
InfinispanRegionFactory infinispanregionfactory = (InfinispanRegionFactory)
sfi.getSettings().getRegionFactory();
CacheManager manager = infinispanregionfactory.getCacheManager();
// register Inifinispan as a BTM resource
InfinispanCacheManager icm = new InfinispanCacheManager();
icm.setUniqueName("infinispan");
ResourceRegistrar.register(icm);
icm.setManager(manager);
final UserTransaction userTransaction = (UserTransaction)
ictx.lookup(lokhiberante.getUserTransactionName());
// begin a new Transaction
userTransaction.begin();
EntityManager em = emf.createEntityManager();
A a = new A();
a.name= "firstvalue";
em.persist(a);
em.flush();
// do manually flush here as apparently FLUSH_BEFORE_COMPLETION
seems not work, bug ?
System.out.println("Calling userTransaction.commit() (Please check if the commit is
effectively executed!)");
Infinispan 6.0
userTransaction.commit();
emf.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
}
3.36.5 Atominkos
Last but not least, the Atomikos Transaction manager. It is currently the unique Transaction manager I've
found with a online-documentation on how to integrate with Hiberantewithout Spring, outside any J2EE
container.. It seems to be the unique supporting XaDataSource together with Pooling, so it doesn't matter
that It does not come with it's own JNDI implementation (we will use the one of JBoss in following example).
java.io.Serializable;
java.sql.Connection;
java.sql.SQLException;
java.util.Properties;
import
import
import
import
import
import
import
import
import
import
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.Name;
javax.naming.NameNotFoundException;
javax.naming.Reference;
javax.naming.StringRefAddr;
javax.persistence.EntityManager;
javax.persistence.Persistence;
javax.transaction.TransactionManager;
javax.transaction.UserTransaction;
import
import
import
import
org.hibernate.Session;
org.hibernate.SessionFactory;
org.hibernate.ejb.HibernateEntityManagerFactory;
org.hibernate.impl.SessionFactoryImpl;
import org.jboss.util.naming.NonSerializableFactory;
Infinispan 6.0
import org.jnp.interfaces.NamingContext;
import org.jnp.server.Main;
import org.jnp.server.NamingServer;
import com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.atomikos.jdbc.SimpleDataSourceBean;
public class JTAStandaloneExampleAtomikos
Infinispan 6.0
Infinispan 6.0
And create a file named jta.properties in your classpath with following content:
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.automatic_resource_registration=false
com.atomikos.icatch.console_log_level=WARN
com.atomikos.icatch.force_shutdown_on_vm_exit=true
com.atomikos.icatch.enable_logging=false
NOTE: You don't need to have any experience with or knowledge of Maven's Archetypes to use this!
Just follow the simple steps below.
WARNING: These archetypes have only been tested with Maven 3. Please report back if you have any
success with using Maven 2.
Infinispan 6.0
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=newproject-archetype \
-DarchetypeVersion=1.0.13 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
You will be prompted for a few things, including the artifactId , groupId and version of your new project. And
that's it - you're ready to go!
in your newly generated project! This runs the main() method in the generated application class.
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=testcase-archetype \
-DarchetypeVersion=1.0.13 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
As above, this will prompt you for project details and again as above, you should open this project in your
IDE. Once you have done so, you will see some sample tests written for Infinispan making use of
Infinispan's test harness and testing tools along with extensive comments and links for further reading.
Infinispan 6.0
$ mvn test
Available profiles
The profiles available in the generated sample project are:
udp: use UDP for network communications rather than TCP
tcp: use TCP for network communications rather than UDP
jbosstm: Use the embedded JBoss Transaction Manager rather than Infinispan's dummy test
transaction manager
TIP: New to working with Infinispan and GitHub? Want to know how best to work with the repositories
and contribute code? Read Infinispan and GitHub
3.37.3 Versions
The archetypes generate poms with dependencies to specific versions of Infinispan. You should edit these
generated poms by hand to point to other versions of Infinispan that you are interested in.
Infinispan 6.0
Standards Red Hat is working towards standardization of the REST API as a part of the REST-*
effort. To participate in this standard, please visit this Google Group
PUT /{cacheName}/{cacheKey}
A PUT request of the above URL form will place the payload (body) in the given cache, with the given key
(the named cache must exist on the server). For example http://someserver/hr/payRoll/3 (in which case "hr"
is the cache name, and "payRoll/3" is the key). Any existing data will be replaced, and Time-To-Live and
Last-Modified values etc will updated (if applicable).
POST /{cacheName}/{cacheKey}
Exactly the same as PUT, only if a value in a cache/key already exists, it will return a Http CONFLICT status
(and the content will not be updated).
Infinispan 6.0
Headers:
Content-Type: MANDATORY (use media/mime-types for example: "application/json").
Special case
If you set the Content-Type to application/x-java-serialized-object, then it
will be stored as a Java object
performAsync: OPTIONAL true/false (if true, this will return immediately, and then replicate data to
the cluster on its own. Can help with bulk data inserts/large clusters.)
timeToLiveSeconds: OPTIONAL number (the number of seconds before this entry will
automatically be deleted)
If no parameter is sent, Infinispan assumes -1 as default value, which means that the entry will
not expire as a result of ttl. Passing any negative value will have the same effect.
maxIdleTimeSeconds: OPTIONAL number (the number of seconds after last usage of this entry
when it will automatically be deleted)
If no parameter is sent, Infinispan assumes -1 as default value, which means that the entry will
not expire as a result of idle time. Passing any negative value will have the same effect.
If both timeToLiveSeconds and maxIdleTimeSeconds are 0, the cache will use the
default lifespan and maxIdle values configured in XML/programmatically
If only maxIdleTimeSeconds is 0, it uses the timeToLiveSeconds value passed as
parameter (or -1 if not present), and default maxIdle configured in XML/programmatically
If only timeToLiveSeconds is 0, it uses 0 as timeToLiveSeconds meaning that it will
expire immediately, and maxIdle is set whatever came as parameter (or -1 if not present)
Infinispan 6.0
GET /{cacheName}/{cacheKey}
This will return the data found in the given cacheName, under the given key - as the body of the response. A
Content-Type header will be supplied which matches what the data was inserted as (other then if it is a Java
object, see below). Browsers can use the cache directly of course (eg as a CDN).
An ETag will be returned unique for each entry, as will the Last-Modified and Expires headers field indicating
the state of the data at the given URL. ETags allow browsers (and other clients) to ask for data only in the
case where it has changed (to save on bandwidth) - this is standard HTTP and is honoured by Infinispan.
Since Infinispan 5.3 it is possible to obtain additional information by appending the "extended" parameter on
the query string, as follows:
GET /cacheName/cacheKey?extended
Infinispan 6.0
HEAD /{cacheName}/{cacheKey}
The same as GET, only no content is returned (only the header fields). You will receive the same content
that you stored. E.g., if you stored a String, this is what you get back. If you stored some XML or JSON, this
is what you will receive. If you stored a binary (base 64 encoded) blob, perhaps a serialized; Java; object you will need to; deserialize this yourself.
Similarly to the GET method, the HEAD method also supports returning extended information via headers.
See above.
GET /{cacheName}
This will return a list of keys present in the given cacheName as the body of the response. The format of the
response can be controlled via the Accept header as follows:
application/xml - the list of keys will be returned in XML format.
application/json - the list of keys will be return in JSON format.
text/html - the list of keys will be returned in HTML format.
text/plain - the list of keys will be returned in plain text format, one key per line
If the cache identified by cacheName is distributed, only the keys owned by the node handling the request
will be returned. To return all keys, append the "global" parameter to the query, as follows:
GET /cacheName?global
Infinispan 6.0
DELETE /{cacheName}/{cacheKey}
Removes the given key name from the cache.
DELETE /{cacheName}
Removes ALL the entries in the given cache name (ie everything from that path down). If the operation is
successful, it returns 200 code.
Make it quicker!
Set the header performAsync to true to return immediately and let the removal happen in the
background.
Infinispan 6.0
3.39.1 Introduction
Infinispan provides distributed execution through a standard JDK ExecutorService interface. Tasks
submitted for execution, instead of being executed in a local JVM, are executed on an entire cluster of
Infinispan nodes. Every DistributedExecutorService is bound to one particular cache. Tasks submitted will
have access to key/value pairs from that particular cache if and only if the task submitted is an instance of
DistributedCallable. Also note that there is nothing preventing users from submitting a familiar Runnable
or Callable just like to any other ExecutorService. However, DistributedExecutorService, as it name implies,
will likely migrate submitted Callable or Runnable to another JVM in Infinispan cluster, execute it and return
a result to task invoker. Due to a potential task migration to other nodes every
Callable, Runnable and/or DistributedCallable submitted must be either Serializable or Externalizable. Also
the value returned from a callable must be Serializable or Externalizable as well. If the value returned is not
serializable a NotSerializableException will be thrown.
Infinispan's distributed task executors use data from Infinispan cache nodes as input for execution tasks.
Most other distributed frameworks do not have that leverage and users have to specify input for distributed
tasks from some well known location. Furthermore, users of Infinispan distributed execution framework do
not have to configure store for intermediate and final results thus removing another layer of complexity and
maintenance.
Our distributed execution framework capitalizes on the fact input data in Infinispan data grid is already load
balanced (in case of DIST mode). Since input data is already balanced execution tasks will be automatically
balanced as well; users do not have to explicitly assign work tasks to specific Infinispan nodes. However, our
framework accommodates users to specify arbitrary subset of cache keys as input for distributed execution
tasks.
Infinispan 6.0
Infinispan 6.0
@Override
public Integer call() throws Exception {
//use injected cache reference
return 1;
}
}
Infinispan 6.0
In case you need to specify more task parameters like task timeout, custom failover policy or execution
policy use DistributedTaskBuilder and DistributedTask API.
Infinispan 6.0
/**
* DistributedTaskFailoverPolicy allows pluggable fail over target selection for a failed
remotely
* executed distributed task.
*
*/
public interface DistributedTaskFailoverPolicy {
/**
* As parts of distributively executed task can fail due to the task itself throwing an
exception
* or it can be an Infinispan system caused failure (e.g node failed or left cluster during
task
* execution etc).
*
* @param failoverContext
*
the FailoverContext of the failed execution
* @return result the Address of the Infinispan node selected for fail over execution
*/
Address failover(FailoverContext context);
/**
* Maximum number of fail over attempts permitted by this DistributedTaskFailoverPolicy
*
* @return max number of fail over attempts
*/
int maxFailoverAttempts();
}
Therefore one could for example specify random failover execution policy simply by:
Infinispan 6.0
3.39.7 Examples
Pi approximation can greatly benefit from parallel distributed execution in DistributedExecutorService. Recall
that area of the square is Sa = 4r2 and area of the circle is Ca=pi*r2. Substituting r2 from the second
equation into the first one it turns out that pi = 4 * Ca/Sa. Now, image that we can shoot very large number of
darts into a square; if we take ratio of darts that land inside a circle over a total number of darts shot we will
approximate Ca/Sa value. Since we know that pi = 4 * Ca/Sa we can easily derive approximate value of pi.
The more darts we shoot the better approximation we get. In the example below we shoot 10 million darts
but instead of "shooting" them serially we parallelize work of dart shooting across entire Infinispan cluster.
Infinispan 6.0
Infinispan 6.0
Both Cache and CacheManager implement Listenable, which means you can attach listeners to either
a cache or a cache manager, to receive either cache-level or cache manager-level notifications.
For example, the following class defines a listener to print out some information every time a new entry is
added to the cache:
@Listener
public class PrintWhenAdded {
@CacheEntryCreated
public void print(CacheEntryCreatedEvent event) {
System.out.println("New entry " + event.getKey() + " created in the cache");
}
}
For more comprehensive examples, please see the Javadocs for @Listener.
NOTE: In Infinispan 5.0, additional events were added. Please refer to the <a
href="http://docs.jboss.org/infinispan/5.0/apidocs/org/infinispan/notifications/cachelistener/annotation/packa
on the org.infinispan.notifications.cachelistener.annotation package</a> for Infinispan 5.0 for
the list of cache-level notifications available in Infinispan 5.0.
Infinispan 6.0
3.40.3 Synchronicity
By default, all notifications are dispatched in the same thread that generates the event. This means that you
must write your listener such that it does not block or do anything that takes too long, as it would prevent the
thread from progressing. Alternatively, you could annotate your listener as asynchronous , in which case a
separate thread pool will be used to dispatch the notification and prevent blocking the event originating
thread. To do this, simply annotate your listener such:
Infinispan 6.0
3.41 Eviction
Eviction in 5.2
NONE
UNORDERED
LRU
LIRS
Configuration and defaults in 5.2.x
Advanced Eviction Internals
Expiration
Difference between Eviction and Expiration
Infinispan supports eviction of entries, such that you do not run out of memory. Eviction is typically used in
conjunction with a cache store, so that entries are not permanently lost when evicted, since eviction only
removes entries from memory and not from cache stores or the rest of the cluster.
Passivation is also a popular option when using eviction, so that only a single copy of an entry is
maintained - either in memory or in a cache store, but not both. The main benefit of using
passivation over a regular cache store is that updates to entries which exist in memory are cheaper
since the update doesn't need to be made to the cache store as well.
Note that eviction occurs on a local basis, and is not cluster-wide. Each node runs an eviction thread to
analyse the contents of its in-memory container and decide what to evict. Eviction does not take into account
the amount of free memory in the JVM as threshold to starts evicting entries. You have to set maxEntries
attribute of the eviction element to be greater than zero in order for eviction to be turned on. If maxEntries is
too large you can run out of memory. maxEntries attribute will probably take some tuning in each use case.
Infinispan 6.0
NONE
This eviction strategy effectively disables the eviction thread.
UNORDERED
UNORDERED eviction strategy is a legacy eviction strategy that has been deprecated. If UNORDERED
strategy is specified LRU eviction algorithm will be used.
LRU
If LRU eviction is used cache entries are selected for eviction using a well known least-recently-used pattern.
LIRS
LRU eviction algorithm, although simple and easy to understand, under performs in cases of weak access
locality (one time access entries are not timely replaced, entries to be accessed soonest are unfortunately
replaced, and so on). Recently, a new eviction algorithm - LIRS has gathered a lot of attention because it
addresses weak access locality shortcomings of LRU yet it retains LRU's simplicity. Eviction in LIRS
algorithm relies on history information of cache entries accesses using so called Inter-Reference Recency
(a.k.a IRR) and the Recency. The IRR of a cache entry A refers to number of other distinct entries accessed
between the last two consecutive accesses to cache entry A, while recency refers to the number of other
entries accessed from last reference to A up to current time point. If we relied only on cache recency we
would essentially have LRU functionality. However, in addition to recency LIRS tracks elements that are in
low IRR and high IRR, aptly named LIR and HIR cache entry blocks respectively. LIRS eviction algorithm
essentially keeps entries with a low IRR in the cache as much as possible while evicting high IRR entries if
eviction is required. If recency of a LIR cache entry increases to a certain point and entry in HIR gets
accessed at a smaller recency than that of the LIR entry, the LIR/HIR statuses of the two blocks are
switched. Entries in HIR may be evicted regardless of its recency, even if element was recently accessed.
Infinispan 6.0
Supplied
Example
Eviction behaviour
maxEntries
strategy
<eviction />
no eviction
>0
>0
>0
NONE
!= NONE
<eviction maxEntries="100"
strategy="NONE" />
<eviction maxEntries="100"
strategy="LRU" />
strategy
no eviction
NONE
<eviction maxEntries="0"
no eviction
strategy="NONE" />
0
!= NONE
<eviction maxEntries="0"
ConfigurationException
strategy="LRU" />
<0
no eviction
<0
NONE
<eviction maxEntries="-1"
no eviction
strategy="NONE" />
<0
!= NONE
<eviction maxEntries="-1"
ConfigurationException
strategy="LRU" />
Infinispan 6.0
3.41.4 Expiration
Similar to, but unlike eviction, is expiration. Expiration allows you to attach lifespan and/or maximum idle
times to entries. Entries that exceed these times are treated as invalid and are removed. When removed
expired entries are not passivated like evicted entries (if passivation is turned on).
Unlike eviction, expired entries are removed globally - from memory, cache stores, and
cluster-wide.
By default entries created are immortal and do not have a lifespan or maximum idle time. Using the cache
API, mortal entries can be created with lfiespans and/or maximum idle times. Further, default lifespans
and/or maximum idle times can be configured by adding the <expiration /> element to your <default /> or
<namedCache /> configuration sections.
Infinispan 6.0
3.42 ServerHinting
3.42.1 What is server hinting?
The motivations behind this feature is to ensure when using distribution, backups are not picked to reside on
the same physical server, rack or data centre. For obvious reasons it doesn't work with total replication.
3.42.2 Version
Server hinting was added in Infinspan 4.2.0 "Ursus". You'll need this release or later in order to use it.
3.42.3 Configuration
The hints are configured at transport level:
<transport
clusterName = "MyCluster"
machineId = "LinuxServer01"
rackId = "Rack01"
siteId = "US-WestCoast" />
All of the
above are optional, and if not provided, the distribution algorithms provide no guarantees that
backups will not be stored in instances on the same host/rack/site.
Infinispan 6.0
3.42.4 Algorithm
This is an advanced topic, useful e.g. if you need to change distribution behaviour.
The consistent hash beyond this implementation is wheel based. Conceptually this works as follows: each
node is placed on a wheel ordered by the hash code of its address. When an entry is added its owners are
chosen using this algorithm:
key's hash code is calculated
the first node on the wheel with a value grater than key's hash code is the first owner
for subsequent nodes, walk clockwise and pick nodes that have a different site id
if not enough nodes found repeat walk again and pick nodes that have different site id and rack id
if not enough nodes found repeat walk again and pick nodes that have different site id, rack id and
machine id
Ultimately cycle back to the first node selected, don't discard any nodes, regardless of machine
id/rack
3.43.1 Introduction
Hot Rod is a binary, language neutral protocol. This article explains how a Java client can interact with a
server via the Hot Rod protocol. A reference implementation of the protocol written in Java can be found in
all Infinispan distributions since 4.1, and this article focuses on the capabilities of this java client.
Infinispan 6.0
The client API maps the local API: RemoteCacheManager corresponds to DefaultCacheManager (both
implement CacheContainer). This common API facilitates an easy migration from local calls to remote calls
through Hot Rod: all one needs to do is switch between DefaultCacheManager and RemoteCacheManagerwhich is further simplified by the common CacheContainer interface that both inherit.
Starting from Infinispan 5.2, all keys can be retrieved from the remote cache (whether it's local, replicated, or
distributed) by using keySet() method. If the remote cache is a distributed cache, the server will start a
map/reduce job to retrieve all keys from clustered nodes, and return all keys to the client. Please use this
method with care if there are large number of keys.
Infinispan 6.0
remoteCache.put("car", "ferrari");
RemoteCache.VersionedValue valueBinary = remoteCache.getVersioned("car");
assert remoteCache.replace("car", "lamborghini", valueBinary.getVersion());
Infinispan 6.0
RemoteCache offers alternative versioned methods for these atomic operations, that are also network
friendly, by not sending the whole value object over the network, but a version identifier. See the section on
versioned API.
Each one of these unsupported operation is documented in the RemoteCache javadoc.
V remove(Object key);
V put(K key, V value);
By default on RemoteCache, these operations return null even if such a previous value exists. This approach
reduces the amount of data sent over the network. However, if these return values are needed they can be
enforced on an per invocation basis using flags:
cache.put("aKey", "initialValue");
assert null == cache.put("aKey", "aValue");
assert "aValue".equals(cache.withFlags(Flag.FORCE_RETURN_VALUE).put("aKey",
"newValue"));
This default behaviour can can be changed through force-return-value=true configuration parameter (see
configuration section bellow).
Infinispan 6.0
3.43.7 Intelligence
HotRod defines three level of intelligence for the clients:
basic client, interested in neither cluster nor hash information
topology-aware client, interested in cluster information
hash-distribution-aware client, that is interested in both cluster and hash information
The java client supports all 3 levels of intelligence. It is transparently notified whenever a new server is
added/removed from the HotRod cluster. At startup it only needs to know the address of one HotRod server
(ip:host). On connection to the server the cluster topology is piggybacked to the client, and all further
requests are being dispatched to all available servers. Any further topology change is also piggybacked.
Hash-distribution-aware client is discussed in the next section.
Infinispan 6.0
Custom types of balancing policies can defined by implementing the RequestBalancingStrategy and by
specifying it through the infinispan.client.hotrod.request-balancing-strategy configuration property. Please
refer to configuration section for more details on this.
Infinispan 6.0
3.43.12 Statistics
Various server usage statistics can be obtained through the RemoteCache.stats() method. This returns an
ServerStatistics object - please refer to javadoc for details on the available statistics.
3.43.13 Configuration
All the configurations are passed to the RemoteCacheManager's constructor as key-value pairs, through an
instance of java.util.Properties or reference to a .properties file. Please refer to the javadoc of
RemoteCacheManager for a exhaustive list of the possible configuration elements.
Infinispan 6.0
Declarative configuration comes in a form of XML document that adheres to a provided Infinispan
configuration XML schema. Every aspect of Infinispan that can be configured declaratively can also be
configured programmatically. In fact, declarative configuration, behind the scenes, invokes programmatic
configuration API as the XML configuration file is being processed. One can even use combination of these
approaches. For example, you can read static XML configuration files and at runtime programmatically tune
that same configuration. Or you can use a certain static configuration defined in XML as a starting point or
template for defining additional configurations in runtime.
There are two main configuration abstractions in Infinispan: global and default configuration.
Global cache configuration defines global settings shared among all cache instances created by a single
CacheManager. Shared resources like thread pools, serialization/marshalling settings, transport and network
settings, JMX domains are all part of global configuration.
Default cache configuration is more specific to actual caching domain itself. It specifies eviction, locking,
transaction, clustering, cache store settings etc. The default cache can be retrieved via the
CacheManager.getCache() API. However, the real power of default cache mechanism comes to light when
used in conjuction with named caches . Named caches have the same XML schema as the default cache.
Whenever they are specified, named caches inherit settings from the default cache while additional behavior
can be specified or overridden. Named caches are retrieved via CacheManager.getCache(String name) API.
Therefore, note that the name attribute of named cache is both mandatory and unique for every named
cache specified.
Do not forget to refer to Infinispan configuration reference for more details.
For more details, refer to the following documents:
Configuring Cache declaratively
Configuring cache programmatically
Dynamically Start and Stop Clustered Cache
Configuration Migration Tools
Infinispan 6.0
Clustered
To start a clustered cache, you'll need to do the above on every clustered node, while making sure the
cache mode is clustered, of course.
You can start the cache by calling _EmbeddedCacheManager.getCache(...). _To do this on every single
node though, you could write your own service to do that, or with JMX, or use DistributedExecutorService.
For example, write a StartCacheCallable class:
Server Mode
Hot Rod client does not support dynamically start/stop of cache.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
3.46.1 Version
The Cassandra CacheStore was added in Infinspan 4.2.0 "Ursus". You'll need this release or later in order to
use it.
3.46.2
Configuration
In order to use this CacheStore you need to create an appropriate keyspace on your Cassandra database.
The following storage-conf.xml excerpt shows the declaration of the keyspace:
<Keyspace Name="Infinispan">
<ColumnFamily CompareWith="BytesType" Name="InfinispanEntries" KeysCached="10%" />
<ColumnFamily CompareWith="LongType" Name="InfinispanExpiration" KeysCached="10%"
ColumnType="Super" CompareSubcolumnsWith="BytesType"/>
<ColumnFamily CompareWith="BytesType" Name="InfinispanEntries" KeysCached="0" />
<ColumnFamily CompareWith="LongType" Name="InfinispanExpiration" KeysCached="0"
ColumnType="Super" CompareSubcolumnsWith="BytesType"/>
<ReplicaPlacementStrategy>org.apache.cassandra.locator.RackUnawareStrategy</ReplicaPlacementStrategy>
<ReplicationFactor>2</ReplicationFactor>
<EndPointSnitch>org.apache.cassandra.locator.EndPointSnitch</EndPointSnitch>
</Keyspace>
Infinispan 6.0
The important bits are the CompareWith, ColumnType and CompareSubColumnsWith declarations.
Everything else can be changed at will. You can also have more than one Keyspace to accomodate for
multiple caches. Also bear in mind that the current version of the CassandraCacheStore only supports the
OrderPreservingPartitioner.
You then need to add an appropriate cache declaration to your infinispan.xml (or whichever file you use to
configure Infinispan):
<namedCache name="cassandraCache">
<loaders passivation="false" shared="true" preload="false">
<loader
class="org.infinispan.loaders.cassandra.CassandraCacheStore"
fetchPersistentState="true" ignoreModifications="false"
purgeOnStartup="false">
<properties>
<property name="host" value="localhost" />
<property name="keySpace" value="Infinispan" />
<property name="entryColumnFamily" value="InfinispanEntries" />
<property name="expirationColumnFamily"
value="InfinispanExpiration" />
<property name="sharedKeyspace" value="false" />
<property name="readConsistencyLevel" value="ONE" />
<property name="writeConsistencyLevel" value="ONE" />
<property name="configurationPropertiesFile"
value="cassandrapool.properties" />
<property name="keyMapper"
value="org.infinispan.loaders.keymappers.DefaultTwoWayKey2StringMapper" />
</properties>
</loader>
</loaders>
</namedCache>
It is important the the shared property on the loader element is set to true because all the Infinispan nodes
will share the same Cassandra cluster.
Since the Cassandra client library doesn't provide connection pooling, a separate project has been created
at http://github.com/tristantarrant/cassandra-connection-pool.
Configuration of the connection pool can be done by creating an appropriate properties file and specifying its
name in the configuration (configurationPropertiesFile).
The following is an example file:
socketTimeout = 5000
initialSize = 10
maxActive = 100
maxIdle = 20
minIdle = 10
maxWait = 30000testOnBorrow = false
testOnReturn = false
testWhileIdle = false
timeBetweenEvictionRunsMillis = 5000removeAbandoned = false
removeAbandonedTimeout = 60
logAbandoned = false
Infinispan 6.0
Here is a description of the various properties which can be configured:
host
port
keySpace
entryColumnFamily
the column family where entry values will be stored. Make sure you configure
your keyspace accordingly (defaults to InfinispanEntries)
expirationColumnFamily the column family where element expiration information is stored. Make sure
your (defaults to InfinispanExpiration)
sharedKeyspace
whether multiple caches are to be stored in a single keyspace. In this case the
cache name is prefixed to the key entries (defaults to false).
readConsistencyLevel
The consistency level to use when reading from Cassandra. Possible values are
ONE, QUORUM, DCQUORUM, ALL. For an explanation of these refer to the
Cassandra API documentation. (defaults to ONE)
writeConsistencyLevel
The consistency level to use when writing to Cassandra. Possible values are
ZERO, ANY, ONE, QUORUM, DCQUORUM, ALL. For an explanation of these
refer to the Cassandra API documentation. (defaults to ONE)
keyMapper
Infinispan 6.0
<namedCache name="cacheWithCustomInterceptors">
<!-Define custom interceptors. All custom interceptors need to extend
org.jboss.cache.interceptors.base.CommandInterceptor
-->
<customInterceptors>
<interceptor position="FIRST" class="com.mycompany.CustomInterceptor1">
<properties>
<property name="attributeOne" value="value1" />
<property name="attributeTwo" value="value2" />
</properties>
</interceptor>
<interceptor position="LAST" class="com.mycompany.CustomInterceptor2"/>
<interceptor index="3" class="com.mycompany.CustomInterceptor1"/>
<interceptor before="org.infinispanpan.interceptors.CallInterceptor"
class="com.mycompany.CustomInterceptor2"/>
<interceptor after="org.infinispanpan.interceptors.CallInterceptor"
class="com.mycompany.CustomInterceptor1"/>
</customInterceptors>
</namedCache>
CacheManager cm = getCacheManager();//magic
Cache aCache = cm.getCache("aName");
AdvancedCache advCache = aCache.getAdvancedCache();
Then one of the addInterceptor() methods should be used to add the actual interceptor. For further
documentation refer to AdvancedCache javadoc.
Infinispan 6.0
Execute test_memcached_write.py script which basically executes several write operations againts
the Infinispan memcached server bound to port 12211. If the script is executed successfully, you
should see an output similar to this:
Infinispan 6.0
3.49.1 Introduction
One of the key aspects of Infinispan is that it often needs to marshall/unmarshall objects in order to provide
some of its functionality. For example, if it needs to store objects in a write-through or write-behind cache
store, the stored objects need marshalling. If a cluster of Infinispan nodes is formed, objects shipped around
need marshalling. Even if you enable lazy deserialization, objects need to be marshalled so that they can be
lazily unmarshalled with the correct classloader.
Using standard JDK serialization is slow and produces payloads that are too big and can affect bandwidth
usage. On top of that, JDK serialization does not work well with objects that are supposed to be immutable.
In order to avoid these issues, Infinispan uses JBoss Marshalling for marshalling/unmarshalling objects.
JBoss Marshalling is fast, produces very space efficient payloads, and on top of that during unmarshalling, it
enables users to have full control over how to construct objects, hence allowing objects to carry on being
immutable.
Starting with 5.0, users of Infinispan can now benefit from this marshalling framework as well, and they can
provide their own externalizer implementations, but before finding out how to provide externalizers, let's look
at the benefits they bring.
Infinispan 6.0
Instead of relying on JDK serialization, Infinispan uses JBoss Marshalling to serialize objects and requires
any classes to be serialized to be associated with an Externalizer interface implementation that knows how
to transform an object of a particular class into a serialized form and how to read an object of that class from
a given input. Infinispan does not force the objects to be serialized to implement Externalizer. In fact, it is
recommended that a separate class is used to implement the Externalizer interface because, contrary to
JDK serialization, Externalizer implementations control how objects of a particular class are created when
trying to read an object from a stream. This means that readObject() implementations are responsible of
creating object instances of the target class, hence giving users a lot of flexibility on how to create these
instances (whether direct instantiation, via factory or reflection), and more importantly, allows target classes
to carry on being immutable. This type of externalizer architecture promotes good OOP designs principles,
such as the principle of single responsibility.
It's quite common, and in general recommended, that Externalizer implementations are stored as inner static
public classes within classes that they externalize. The advantages of doing this is that related code stays
together, making it easier to maintain. In Infinispan, there are two ways in which Infinispan can be plugged
with user defined externalizers:
Infinispan 6.0
import org.infinispan.marshall.Externalizer;
import org.infinispan.marshall.SerializeWith;
@SerializeWith(Person.PersonExternalizer.class)
public class Person {
final String name;
final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static class PersonExternalizer implements Externalizer<Person> {
@Override
public void writeObject(ObjectOutput output, Person person)
throws IOException {
output.writeObject(person.name);
output.writeInt(person.age);
}
@Override
public Person readObject(ObjectInput input)
throws IOException, ClassNotFoundException {
return new Person((String) input.readObject(), input.readInt());
}
}
}
At runtime JBoss Marshalling will inspect the object and discover that's marshallable thanks to the
annotation and so marshall it using the externalizer class passed. To make externalizer implementations
easier to code and more typesafe, make sure you define type <T> as the type of object that's being
marshalled/unmarshalled.
Even though this way of defining externalizers is very user friendly, it has some disadvantages:
Due to several constraints of the model, such as support different versions of the same class or the
need to marshall the Externalizer class, the payload sizes generated via this method are not the most
efficient.
This model requires for the marshalled class to be annotated with {@link SerializeWith} but a user
might need to provide an Externalizer for a class for which source code is not available, or for any
other constraints, it cannot be modified.
The use of annotations by this model might be limiting for framework developers or service providers
that try to abstract lower level details, such as the marshalling layer, away from the user.
If you're affected by any of these disadvantages, an alternative method to provide externalizers is available
via more advanced externalizers:
Infinispan 6.0
Advanced Externalizers
AdvancedExternalizer provides an alternative way to provide externalizers for marshalling/unmarshalling
user defined classes that overcome the deficiencies of the more user-friendly externalizer definition model
explained in Externalizer. For example:
import org.infinispan.marshall.AdvancedExternalizer;
public class Person {
final String name;
final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static class PersonExternalizer implements AdvancedExternalizer<Person> {
@Override
public void writeObject(ObjectOutput output, Person person)
throws IOException {
output.writeObject(person.name);
output.writeInt(person.age);
}
@Override
public Person readObject(ObjectInput input)
throws IOException, ClassNotFoundException {
return new Person((String) input.readObject(), input.readInt());
}
@Override
public Set<Class<? extends Person>> getTypeClasses() {
return Util.<Class<? extends Person>>asSet(Person.class);
}
@Override
public Integer getId() {
return 2345;
}
}
}
The first noticeable difference is that this method does not require user classes to be annotated in anyway,
so it can be used with classes for which source code is not available or that cannot be modified. The bound
between the externalizer and the classes that are marshalled/unmarshalled is set by providing an
implementation for getTypeClasses() which should return the list of classes that this externalizer can
marshall:
Infinispan 6.0
import org.infinispan.util.Util;
...
@Override
public Set<Class<? extends ReplicableCommand>> getTypeClasses() {
return Util.asSet(LockControlCommand.class, RehashControlCommand.class,
StateTransferControlCommand.class, GetKeyValueCommand.class,
ClusteredGetCommand.class, MultipleRpcCommand.class,
SingleRpcCommand.class, CommitCommand.class,
PrepareCommand.class, RollbackCommand.class,
ClearCommand.class, EvictCommand.class,
InvalidateCommand.class, InvalidateL1Command.class,
PutKeyValueCommand.class, PutMapCommand.class,
RemoveCommand.class, ReplaceCommand.class);
}
In the code above, ReplicableCommandExternalizer indicates that it can externalize several type of
commands. In fact, it marshalls all commands that extend ReplicableCommand interface, but currently the
framework only supports class equality comparison and so, it's not possible to indicate that the classes to
marshalled are all children of a particular class/interface.
However there might sometimes when the classes to be externalized are private and hence it's not possible
to reference the actual class instance. In this situations, users can attempt to look up the class with the given
fully qualified class name and pass that back. For example:
@Override
public Set<Class<? extends List>> getTypeClasses() {
return Util.<Class<? extends List>>asSet(
Util.loadClass("java.util.Collections$SingletonList"));
}
Infinispan 6.0
Externalizer Identifier
Secondly, in order to save the maximum amount of space possible in the payloads generated, advanced
externalizers require externalizer implementations to provide a positive identified via getId() implementations
or via XML/programmatic configuration that identifies the externalizer when unmarshalling a payload. In
order for this to work however, advanced externalizers require externalizers to be registered on cache
manager creation time via XML or programmatic configuration which will be explained in next section. On the
contrary, externalizers based on Externalizer and SerializeWith require no pre-registration whatsoever.
Internally, Infinispan uses this advanced externalizer mechanism in order to marshall/unmarshall internal
classes.
So, getId() should return a positive integer that allows the externalizer to be identified at read time to figure
out which Externalizer should read the contents of the incoming buffer, or it can return null. If getId() returns
null, it is indicating that the id of this advanced externalizer will be defined via XML/programmatic
configuration, which will be explained in next section.
Regardless of the source of the the id, using a positive integer allows for very efficient variable length
encoding of numbers, and it's much more efficient than shipping externalizer implementation class
information or class name around. Infinispan users can use any positive integer as long as it does not clash
with any other identifier in the system. It's important to understand that a user defined externalizer can even
use the same numbers as the externalizers in the Infinispan Core project because the internal Infinispan
Core externalizers are special and they use a different number space to the user defined externalizers. On
the contrary, users should avoid using numbers that are within the pre-assigned identifier ranges which can
be found at the end of this article. Infinispan checks for id duplicates on startup, and if any are found, startup
is halted with an error.
When it comes to maintaining which ids are in use, it's highly recommended that this is done in a centralized
way. For example, getId() implementations could reference a set of statically defined identifiers in a separate
class or interface. Such class/interface would give a global view of the identifiers in use and so can make it
easier to assign new ids.
<infinispan>
<global>
<serialization>
<advancedExternalizers>
<advancedExternalizer externalizerClass="Person$PersonExternalizer"/>
</advancedExternalizers>
</serialization>
</global>
...
</infinispan>
Infinispan 6.0
Programmatically:
As mentioned earlier, when listing these externalizer implementations, users can optionally provide the
identifier of the externalizer via XML or programmatically instead of via getId() implementation. Again, this
offers a centralized way to maintain the identifiers but it's important that the rules are clear: An
AdvancedExternalizer implementation, either via XML/programmatic configuration or via annotation, needs
to be associated with an identifier. If it isn't, Infinispan will throw an error and abort startup. If a particular
AdvancedExternalizer implementation defines an id both via XML/programmatic configuration and
annotation, the value defined via XML/programmatically is the one that will be used. Here's an example of an
externalizer whose id is defined at registration time:
<infinispan>
<global>
<serialization>
<advancedExternalizers>
<advancedExternalizer id="123"
externalizerClass="Person$PersonExternalizer"/>
</advancedExternalizers>
</serialization>
</global>
...
</infinispan>
Programmatically:
builder.serialization()
.addAdvancedExternalizer(new Person.PersonExternalizer(),
new Address.AddressExternalizer());
Infinispan 6.0
1000 - 1099
1100 - 1199
1300 - 1399
Hibernate OGM:
1400 - 1499
Hibernate Search:
1500 - 1599
Infinispan 6.0
The Cache interface exposes simple methods for adding, retrieving and removing entries, including atomic
mechanisms exposed by the JDK's ConcurrentMap interface. Based on the cache mode used, invoking
these methods will trigger a number of things to happen, potentially even including replicating an entry to a
remote node or looking up an entry from a remote node, or potentially a cache store.
Note: For simple usage, using the Cache API should be no different from using the JDK Map API,
and hence migrating from simple in-memory caches based on a Map to Infinispan's Cache should be
trivial.
Infinispan 6.0
putForExternalRead operation
Infinispan's Cache class contains a different 'put' operation called putForExternalRead. This operation is
particularly useful when Infinispan is used as a temporary cache for data that is persisted elsewhere. Under
heavy read scenarios, contention in the cache should not delay the real transactions at hand, since caching
should just be an optimization and not something that gets in the way.
To achieve this, putForExternalRead acts as a put call that only operates if the key is not present in the
cache, and fails fast and silently if another thread is trying to store the same key at the same time. In this
particular scenarion, caching data is a way to optimise the system and it's not desirable that a failure in
caching affects the on-going transaction, hence why failure is handled differently. putForExternalRead is
consider to be a fast operation because regardless of whether it's successful or not, it doesn't wait for any
locks, and so returns to the caller promptly.
To understand how to use this operation, let's look at basic example. Imagine a cache of Person instances,
each keyed by a PersonId, whose data originates in a separate data store. The following code shows the
most common pattern of using putForExternalRead within the context of this example:
Please note that putForExternalRead should never be used as a mechanism to update the cache with a new
Person instance originating from application execution (i.e. from a transaction that modifies a Person's
address). When updating cached values, please use the standard put operation, otherwise the possibility of
caching corrupt data is likely.
Infinispan 6.0
Flags
Flags are applied to regular cache methods to alter the behavior of certain methods. For a list of all
available flags, and their effects, see the Flag enumeration. Flags are applied using
AdvancedCache.withFlags(). This builder method can be used to apply any number of flags to a cache
invocation, for example:
advancedCache.withFlags(Flag.CACHE_MODE_LOCAL, Flag.SKIP_LOCKING)
.withFlags(Flag.FORCE_SYNCHRONOUS)
.put("hello", "world");
Custom Interceptors
The AdvancedCache interface also offers advanced developers a mechanism with which to attach custom
interceptors. Custom interceptors allow developers to alter the behavior of the cache API methods, and the
AdvancedCache interface allows developers to attach these interceptors programmatically, at run-time. See
the AdvancedCache Javadocs for more details.
For more information on writing custom interceptors, see /javascript:;
Infinispan 6.0
<infinispan/>
is enough to get you started, or you can create DefaultCacheManager with no -argument constructor. Either
approach creates local default cache.
All the features above are exposed via an easy-to-use Cache interface, which extends ConcurrentMap and
is compatible with many other cache systems. Infinispan even ships with migration tools to help you move off
other cache solutions onto Infinispan, whether you need a cache to store data retrieved remotely or simply
as a 2nd level cache for Hibernate.
Performance
In the process of testing and tuning Infinispan on very large clusters, we have started to put together a
benchmarking framework. As a part of this framework, we have the ability to measure cache performance in
standalone, local mode. We compared Infinispan 4.0 in local mode against the latest JBoss Cache release
(3.2.2.GA) and EHCache (1.7.2). Some background on the tests:
Used a latest snapshot of the CacheBenchFwk
Run on a RHEL 5 server with 4 Intel Xeon cores, 4GB of RAM
Sun JDK 1.6.0_18, with -Xms1g -Xmx1g
Test run on a single node, with 25 concurrent threads, using randomly generated Strings as keys and
values and a 1kb payload for each entry, with a 80/20 read/write ratio.
Performance measured in transactions per second (higher = better).
Infinispan 6.0
In summary, what we have here is that when run in local mode, Infinispan is a high-performance standalone
caching engine which offers a rich set of features while still being trivially simple to configure and use.
Infinispan 6.0
Infinispan 6.0
Furthermore it creates an abstraction above the specifics of the client/server protocol you use to access the
cache. The basic commands look the same whether you use Hot Rod, memcached or REST. The
client/protocol specifics are handled via protocol-specific configuration options or command arguments.
Your shell scripts should look basically the same for all the client modes, if you don't use any protocol
specific features.
Behind the scenes the console tool uses existing python clients to handle the communication with particular
server modules. The implementations are listed in the following table:
Client
Client implementation
Web
Hot Rod
https://github.com/infinispan/python-client
Memcached python-memcached
REST
https://launchpad.net/python-memcached
The source code and issue reporting for ispncon can be found here: https://github.com/infinispan/ispncon
Infinispan 6.0
3.52.2 Installation
Ispncon requires
python 2.6
python modules: python-devel, setuptools, infinispan, python-memcached
Installation steps:
Make this part of your .bashrc or whatever so you have ispncon command on path
export ISPNCON_HOME=/path/to/ispncon
export PATH=$ISPNCON_HOME/bin:$PATH
Infinispan 6.0
Options
Option
Meaning
-c --client
-C
--cache-name
<name>
-v --version
-e
If true and operation fails, then fail with an exit code. If false just print ERROR message
--exit-on-error
-P --config
override configuration option <key> with value <value>. NOTE: the quotes are
"<key>
<value>"
The possible Operations are put, get, delete, clear, exists, help, config, include and each one is described in
the sections Cache operations and Other commands .
Infinispan 6.0
3.52.4 Configuration
On start-up ispncon reads the file ~/.ispncon to configure some of the default values to use, so that the user
doesn't have to enter the options like host, port, client type and cache name everytime he types a cache
command.
The format of the config file is like this:
[ispncon]
host = localhost
port = 8080
client_type = rest
cache =
exit_on_error = False
default_codec = None
[rest]
server_url = /infinispan-server-rest/rest
content_type = text/plain
[hotrod]
use_river_string_keys = True
The config parameters in the section ispncon are described in the_Basic usage_ section. The rest is
described here:
Config key
Meaning
rest.server_url
location of the REST server service, in the above example the HTTP
requests would be sent tohttp://localhost:8080/infinispan-server-rest/rest
rest.content_type
default MIME content type for entries stored via REST interface
default_codec
hotrod.use_river_string_keys If set to True, hotrod client will encode keys with RiverString codec - this is
necessary to be able to access the same data as via Java HotRod Client
using the same string keys.
see section Interoperability with java clients for further info
Infinispan 6.0
Options
Option
Meaning
-i --input-filename
Don't specify the value, instead put the contents of the specified file.
<filename>
-v --version <version>
Put only if version equals version given. Version format differs between
protocols:
HotRod: 64-bit integer version number
Memcached: 64-bit integer unique version id
REST: ETag string
Not yet implemented for REST client in infinispan, watch ISPN-1084 for more
info.
-l --lifespan <seconds>
-I --max-idle <seconds>
Specifies max idle time for the entry. Integer, number of seconds.
-a --put-if-absent
Return CONFLICT if value already exists and don't put anything in that case
-e --encode <codec>
Return values
Exit
Output
Result description
STORED
ERROR
code
<msg>
2
CONFLICT
-a option was used and the entry already exists, or -v was used and versions
don't match
NOTE: memcached client won't distinguish between states NOT_FOUND, CONFLICT and ERROR and
always will return ERROR if operation wasn't successfull. this is a limitation of python-memcached client.
see issues:
https://bugs.launchpad.net/python-memcached/+bug/684689
https://bugs.launchpad.net/python-memcached/+bug/684690
for discussion.
Infinispan 6.0
In later ispncon versions python-memcached client might get replaced by a customized version.
get
Get the data stored under the specified key.
Format
Options
Option
Meaning
-o --output-filename
Stores the output of the get operation into the file specified.
<filename>
-v --version
Get version along with the data. Version format differs between protocols:
HotRod: 64-bit integer version number
Memcached: 64-bit integer unique version id
REST: ETag string
-d --decode <codec>
Return values
Exit
Output
Result description
returned.
code
0
(NOTE: the data might contain binary content, that is not suitable
for reading in terminal)
In case a filename was specified, nothing is printed on standard
output.
In case -v was specified, the output is prepended with one line:
VERSION <version>
1
ERROR <msg>
NOT_FOUND
Infinispan 6.0
delete
Delete the entry with the specified key.
Format
Options
Option
Meaning
-v --version
Deletes only if the specified version matches the version in the cache
<version>
NOTE: versioned delete is not supported with memcached client. attempt to delete with -v
flag will end in ERROR message.
with REST client the situation is different, the protocol allows this, but it's not yet
implemented in infinispan, watch ISPN-1084 for more info
Return values
Exit code Output
Result description
DELETED
NOT_FOUND
CONFLICT
clear
Clear the cache
Format
clear
Return values
Exit code Output
Result description
DELETED
Infinispan 6.0
exists
Verify if the entry exists in the cache
Format
exists <key>
Return values
Exit code Output
Result description
EXISTS
NOT_FOUND
NOTE: memcached protocol doesn't support querying for existence of an entry in the cache so exists
operation is implemented (inefficiently) by get opeartion, that gets the whole entry with all the data from the
server.
Infinispan 6.0
version
Get version of the entry. Version format differs between protocols:
HotRod: 64-bit integer version number
Memcached: 64-bit integer unique version id
REST: ETag string
NOTE: The purpose of this command is to facilitate the parsing of the version string. HotRod and
Memcached client don't support efficient implementation of this operation. They transfer the whole entry from
the server to determine the version, so if applicable you are encouraged to use "get -v" command to obtain
version together with the data.
REST client implements this operation efficiently by executing HEAD method.
Format
version <key>
Return values
Exit code Output
Result description
<version>
NOT_FOUND
help <operation>
Infinispan 6.0
config
Change internal state/config of the client. This opeartion has only client-side effect.
Format
config
config save
config <key> <value>
Configuration values
see section Configuration for the meaning of different configuration options. Currently supported keys are:
cache
host
port
client_type
exit_on_error
rest.server_url
rest.content_type
These values directly correspond to the keys in the ~/.ispncon config file. The format of the key is
<section>.<config_key>
Result description
STORED
multi-line output with config values If config command with no parameters was entered.
ERROR <msg>
Infinispan 6.0
include
Process cache commands from the specified batch file. The commands will be processed line by line.
Format
include <filename>
Return values
Exit code
Output
Result description
NOTE: The name of this command and it's behaviour is going to change in the next version.
Infinispan 6.0
Infinispan 6.0
[g@eq]~/infinispan-4.1.0-SNAPSHOT% ./bin/startServer.sh -h
usage: startServer [options]
options:
-h, --help
Show this help message
-V, --version
Show version information
-Stop processing options
-p, --port=<num>
TCP port number to listen on
(default: 11211 for Memcached, 11222 for Hot Rod
and 8181 for WebSocket server)
-l, --host=<host or ip>
Interface to listen on
(default: 127.0.0.1, localhost)
-m, --master_threads=<num>
Number of threads accepting incoming connections
(default: unlimited while resources are available)
-t, --work_threads=<num>
Number of threads processing incoming requests and sending responses
(default: unlimited while resources are available)
-c, --cache_config=<filename>
Cache configuration file
(default: creates cache with default values)
-r, --protocol=[memcached|hotrod|websocket]
Protocol to understand by the server.
This is a mandatory option and you should choose one of these options
-i, --idle_timeout=<num>
Idle read timeout, in seconds, used to detect stale connections
(default: -1)
If no new messages have been read within this time,
the server disconnects the channel.
Passing -1 disables idle timeout.
-n, --tcp_no_delay=[true|false]
TCP no delay flag switch (default: true)
-s, --send_buf_size=<num>
Send buffer size (default: as defined by the OS).
-e, --recv_buf_size=<num>
Receive buffer size (default: as defined by the OS).
-o, --proxy_host=<host or ip>
Host address to expose in topology information sent to clients.
If not present, it defaults to configured host.
Servers that do not transmit topology information ignore this setting.
Infinispan 6.0
-x, --proxy_port=<num>
Port to expose in topology information sent to clients.
If not present, it defaults to configured port.
Servers that do not transmit topology information ignore this setting.
-k, --topo_lock_timeout=<num>
Controls lock timeout (in milliseconds) for those servers that maintain
the topology information in an internal cache.
-u, --topo_repl_timeout=<num>
Sets the maximum replication time (in milliseconds) for transfer of
topology information between servers.
If state transfer is enabled, this setting also controls the topology
cache state transfer timeout.
If state transfer is disabled, it controls the amount of time to wait
for this topology data to be lazily loaded from a different node when
not present locally.
-a, --topo_state_trasfer=[true|false]
Enabling topology information state transfer means that when a server
starts it retrieves this information from a different node.
Otherwise, if set to false, the topology information is lazily loaded
if not available locally.
-D<name>[=<value>]
Set a system property
Infinispan 6.0
3.54.1 Introduction
Normally, a Hot Rod server is accessed via a Hot Rod protocol client such as the Java Hot Rod client.
However, there might be situations where not only do you want to access the Hot Rod server remotely, you
might also want to access it locally from within the same JVM that the Hot Rod server is running. For
example, you might have an Infinispan cache pushing changes via the RemoteCacheStore to a Hot Rod
server, and if the cache goes down, you might want to access the data directly from the Hot Rod server
itself.
In this situations, we have to remember that the Hot Rod protocol specifies that keys and values are stored
as byte arrays. This means that if the client code, using an existing Hot Rod client, stored Strings or Integers,
or any other complex serializable or externalizable object, you won't be able to retrieve these objects straight
from the cache that the Hot Rod server uses.
To actually get the fully constructed objects that you're after, you're gonna need to take the byte arrays
stored within the Hot Rod server and unmarshall them into something that you can use. In the future, this is
something that might be done for you, as suggested in ISPN-706 (superseded by ISPN-2281), but for the
time being, clients wanting to access Hot Rod server data will have to do it themselves.
Two different use cases need to be differentiated at this stage and to explain how to transform the Hot Rod
server data into something usable, we'll assume that the clients are java clients:
Infinispan 6.0
import org.infinispan.marshall.jboss.GenericJBossMarshaller;
import org.infinispan.util.ByteArrayKey;
import org.infinispan.server.core.CacheValue;
...
// Create a new instance of the marshaller:
GenericJBossMarshaller marshaller = new GenericJBossMarshaller();
Object key = ...
// Take the cache key and convert into a byte array,
// and wrap it with an instance of ByteArrayKey
ByteArrayKey bytesKey = new ByteArrayKey(marshaller.objectToByteBuffer(key));
// Internally, Hot Rod stores values wrapped in a CacheValue, so retrieve it
CacheValue cacheValue = (CacheValue) cache.get(bytesKey);
// Take the data part which is byte array and unmarshall it to retrieve the value
Object value = marshaller.objectFromByteBuffer(cacheValue.data());
If you want to store data directly in the HotRod server, you'd have to execute something like this:
import org.infinispan.marshall.jboss.GenericJBossMarshaller;
import org.infinispan.util.ByteArrayKey;
import org.infinispan.server.core.CacheValue;
...
// Create a new instance of the marshaller:
GenericJBossMarshaller marshaller = new GenericJBossMarshaller();
Object key = ...
Object value = ...
// Take the cache key and convert into a byte array,
// and wrap it with an instance of ByteArrayKey
ByteArrayKey bytesKey = new ByteArrayKey(marshaller.objectToByteBuffer(key));
// Internally, Hot Rod stores values wrapped in a CacheValue, so create instance
// Remember that you need to give it a version number, so either:
// 1. Increment previous value's version
// 2. Or generate a new version number that minimises potential clash
//
with a concurrent update to the same key in the cluster
CacheValue cacheValue = new CacheValue(marshaller.objectToByteBuffer(value), 1)
// Finally, store it in the cache
cache.put(bytesKey, cacheValue);
Infinispan 6.0
import
import
import
import
...
org.infinispan.marshall.VersionAwareMarshaller;
org.infinispan.util.ByteArrayKey;
org.infinispan.server.core.CacheValue;
org.infinispan.container.entries.CacheEntry;
And to actually write data back into the Hot Rod server directly:
Infinispan 6.0
import
import
import
import
import
...
org.infinispan.marshall.VersionAwareMarshaller;
org.infinispan.util.ByteArrayKey;
org.infinispan.server.core.CacheValue;
org.infinispan.container.entries.CacheEntry;
org.infinispan.container.entries.InternalEntryFactory;
Infinispan 6.0
The diagram above shows an Infinispan server cluster running 3 hotrod servers. This cluster is accessed
remotely, through HotRod, by another infinispan cluster: client cluster (upper part of the image). All the
nodes in the server cluster are configured to run HotRod servers, so requests from remote loader are being
balanced between them. The client cluster is configured with invalidation as cluster mode and a
RemoteCacheLoader to acess data stored in the server cluster. Application data is held on the server cluster
which runs in DIST mode for scalability.
In this deployment the client code, running in same address space with the client cluster, holds all its data in
the server cluster. Client cluster acts as an near-cache for frequently accessed entries.
Infinispan 6.0
3.56.2 Configuration
Out of the box, Infinispan will create and use a new LOCAL mode cache. To set a custom configuration:
1. Unzip the REST WAR file (or use an exploded deployment)
2. Create an Infinispan configuration XML file and name this infinispan.xml
3. Place this file in infinispan-server-rest.war/WEB-INF/classes
Alternatively, you could:
1. Unzip the REST WAR file (or use an exploded deployment)
2. Create an Infinispan configuration XML file, call it whatever you want and place it wherever you want
3. Edit infinispan-server-rest.war/WEB-INF/web.xml and look for the infinispan.config
init-param. Change the value of this init-param to the full path to your Infinispan configuration.
Please note that the REST server only allows interaction with either the default cache (named
___defaultcache) or one of the named caches in the configuration file. This is because the REST server
starts the default and pre-defined caches on startup in order to provide consistent behaivor.
Warning
Creation of new named caches on the fly is not supported.
As a result, if you don't use a custom configuration file, you'll only be able to interact with the default cache.
To interact with more caches, use a configuration file with the desired named caches.
Infinispan 6.0
Infinispan 6.0
#putting data in
conn = httplib.HTTPConnection("localhost:8080")
data = "SOME DATA HERE \!" #could be string, or a file...
conn.request("POST", "/infinispan/rest/Bucket/0", data, {"Content-Type": "text/plain"})
response = conn.getresponse()
print response.status
#getting data out
import httplib
conn = httplib.HTTPConnection("localhost:8080")
conn.request("GET", "/infinispan/rest/Bucket/0")
response = conn.getresponse()
print response.status
print response.read()
java.io.BufferedReader;
java.io.IOException;
java.io.InputStreamReader;
java.io.OutputStreamWriter;
java.net.HttpURLConnection;
java.net.URL;
/**
* Rest example accessing Infinispan Cache.
* @author Samuel Tauil (samuel@redhat.com)
*
*/
public class RestExample {
/**
* Method that puts a String value in cache.
* @param urlServerAddress
* @param value
* @throws IOException
*/
public void putMethod(String urlServerAddress, String value) throws IOException {
System.out.println("----------------------------------------");
System.out.println("Executing PUT");
System.out.println("----------------------------------------");
URL address = new URL(urlServerAddress);
System.out.println("executing request " + urlServerAddress);
HttpURLConnection connection = (HttpURLConnection) address.openConnection();
Infinispan 6.0
System.out.println("Executing put method of value: " + value);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Type", "text/plain");
connection.setDoOutput(true);
OutputStreamWriter outputStreamWriter = new
OutputStreamWriter(connection.getOutputStream());
outputStreamWriter.write(value);
connection.connect();
outputStreamWriter.flush();
System.out.println("----------------------------------------");
System.out.println(connection.getResponseCode() + " " + connection.getResponseMessage());
System.out.println("----------------------------------------");
connection.disconnect();
}
/**
* Method that gets an value by a key in url as param value.
* @param urlServerAddress
* @return String value
* @throws IOException
*/
public String getMethod(String urlServerAddress) throws IOException {
String line = new String();
StringBuilder stringBuilder = new StringBuilder();
System.out.println("----------------------------------------");
System.out.println("Executing GET");
System.out.println("----------------------------------------");
URL address = new URL(urlServerAddress);
System.out.println("executing request " + urlServerAddress);
HttpURLConnection connection = (HttpURLConnection) address.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "text/plain");
connection.setDoOutput(true);
BufferedReader bufferedReader = new BufferedReader(new
InputStreamReader(connection.getInputStream()));
connection.connect();
while ((line = bufferedReader.readLine()) \!= null) {
stringBuilder.append(line + '\n');
}
System.out.println("Executing get method of value: " + stringBuilder.toString());
System.out.println("----------------------------------------");
System.out.println(connection.getResponseCode() + " " + connection.getResponseMessage());
System.out.println("----------------------------------------");
connection.disconnect();
Infinispan 6.0
return stringBuilder.toString();
}
/**
* Main method example.
* @param args
* @throws IOException
*/
public static void main(String\[\] args) throws IOException {
//Attention to the cache name "cacheX" it was configured in xml file with tag <namedCache
name="cacheX">
RestExample restExample = new RestExample();
restExample.putMethod("http://localhost:8080/infinispan/rest/cacheX/1", "Infinispan REST
Test");
restExample.getMethod("http://localhost:8080/infinispan/rest/cacheX/1");
}
}
3.56.5 Future:
Sample persistence options to make this a long term data grid
Query and indexing (of known MIME types, and JSON, XML etc)
Returning both lists of buckets + entries as <link> relations (where it makes sense)
Monitoring of stats via Web interface
(optional: WADL?)
Infinispan 6.0
3.57.1 Introduction
Infinispan includes integration with CDI in the infinispan-cdi module. Configuration and injection of the
Inifispan's Cache API is provided, and it is planned to bridge Cache listeners to the CDI event system. The
module also provide partial support of the JCache (JSR-107) caching annotations - for further details see
Chapter 8 of the JCACHE specification.
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-cdi</artifactId>
<version>${infinispan.version}</version>
</dependency>
Infinispan 6.0
...
import javax.inject.Inject;
public class GreetingService {
@Inject
private Cache<String, String> cache;
public String greet(String user) {
String cachedValue = cache.get(user);
if (cachedValue == null) {
cachedValue = "Hello " + user;
cache.put(user, cachedValue);
}
return cachedValue;
}
}
If you want to use a specific cache you just have to provide your own cache configuration and cache
qualifier. For example, if you want to use a custom cache for the GreetingService you should write your
own qualifier (here GreetingCache) and define its configuration:
...
import javax.inject.Qualifier;
@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GreetingCache {
}
Infinispan 6.0
...
import
import
import
import
org.infinispan.configuration.cache.Configuration;
org.infinispan.configuration.cache.ConfigurationBuilder;
org.infinispan.cdi.ConfigureCache;
javax.enterprise.inject.Produces;
To use this cache in the GreetingService add the @GeetingCache qualifier on your cache injection
point. Simple!
Infinispan 6.0
You can override the default cache configuration used by the default embedded cache manager. For that,
you just have to create one Configuration producer with the @Default qualifier as illustrated in the
following snippet:
It's also possible to override the default embedded cache manager used. The new default cache manager
produced must have the @Default qualifier and the scope @ApplicationScoped.
...
import javax.enterprise.context.ApplicationScoped;
public class Config {
@Produces
@ApplicationScoped
public EmbeddedCacheManager defaultEmbeddedCacheManager() {
return new DefaultCacheManager(new ConfigurationBuilder()
.eviction()
.strategy(EvictionStrategy.LRU)
.maxEntries(100)
.build());
}
}
Infinispan 6.0
...
package org.infinispan.configuration.global.GlobalConfigurationBuilder;
@Produces
@ApplicationScoped
public EmbeddedCacheManager defaultClusteredCacheManager() {
return new DefaultCacheManager(
new GlobalConfigurationBuilder().transport().defaultTransport().build(),
new ConfigurationBuilder().eviction().maxEntries(7).build()
);
}
Infinispan 6.0
If you want to use another cache, for example the greeting-cache, add the @Remote qualifier on the cache
injection point which contains the cache name.
Adding the @Remote cache qualifier on each injection point might be error prone. That's why the remote
cache integration provides another way to achieve the same goal. For that you have to create your own
qualifier annotated with @Remote:
@Remote("greeting-cache")
@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RemoteGreetingCache {
}
To use this cache in the GreetingService add the qualifier @RemoteGreetingCache qualifier on your
cache injection.
Infinispan 6.0
Infinispan 6.0
With the above code the GreetingCache or the RemoteGreetingCache will be associated with the
produced cache manager.
Infinispan 6.0
...
import javax.annotation.Resource;
public class Config {
@Produces
@ApplicationScoped
@Resource(lookup="java:jboss/infinispan/my-container-name")
private EmbeddedCacheManager defaultCacheManager;
}
To use these annotations the following interceptors must be declared in your application beans.xml.
Infinispan 6.0
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>org.infinispan.cdi.interceptor.CacheResultInterceptor</class>
<class>org.infinispan.cdi.interceptor.CachePutInterceptor</class>
<class>org.infinispan.cdi.interceptor.CacheRemoveEntryInterceptor</class>
<class>org.infinispan.cdi.interceptor.CacheRemoveAllInterceptor</class>
</interceptors>
</beans>
The following snippet of code illustrates the use of @CacheResult annotation. As you can see it simplifies
the caching of the Greetingservice#greet method results.
import javax.cache.interceptor.CacheResult;
public class GreetingService {
@CacheResult
public String greet(String user) {
return "Hello" + user;
}
}
The first version of the GreetingService and the above version have exactly the same behavior. The only
difference is the cache used. By default it's the fully qualified name of the annotated method with its
parameter types (e.g. org.infinispan.example.GreetingService.greet(java.lang.String)).
@CacheResult(cacheName = "greeting-cache")
Infinispan 6.0
3.58 Marshalling
Introduction
The Role Of JBoss Marshalling
Support For Non-Serializable Objects
Store As Binary
Equality Considerations
Store-by-value via defensive copying
Advanced Configuration
Troubleshooting
3.58.1 Introduction
Marshalling is the process of converting Java POJOs into something that can be written in a format that can
be transfered over the wire. Unmarshalling is the reverse process whereby data read from a wire format is
transformed back into Java POJOs. Infinispan uses marshalling/unmarshalling in order to:
Transform data so that it can be send over to other Infinispan nodes in a cluster.
Transform data so that it can be stored in underlying cache stores.
Store data in Infinispan in a wire format to provide lazy deserialization capabilities.
Infinispan 6.0
If either of these options is true, key/value pairs in the cache will need to be marshalled and currently they
require to either to extend java.io.Serializable or java.io.Externalizable. However, since Infinispan 5.0,
marshalling non-Serializable key/value objects is supported as long as users can to provide meaningful
Externalizer implementations for these non-Seralizable objects, see this article to find out more.
If you're unable to retrofit Serializable or Externalizable into the classes whose instances are stored in
Infinispan, you could alternatively use something like XStream to convert your Non-Serializable objects into
an String that can be stored into Infinispan. You can find an example on how to use XStream here. The one
caveat about using XStream is that it slows down the process of storing key/value objects due to the XML
transformation that it needs to do.
Store As Binary
Store as binary enables data to be stored in its serialized form. This can be useful to achieve lazy
deserialization, which is the mechanism by which Infinispan by which serialization and deserialization of
objects is deferred till the point in time in which they are used and needed. This typically means that any
deserialization happens using the thread context class loader of the invocation that requires deserialization,
and is an effective mechanism to provide classloader isolation. By default lazy deserialization is disabled but
if you want to enable it, you can do it like this:
Via XML at the Cache level, either under <namedCache> or <default> elements:
<storeAsBinary enabled="true"/>
Programmatically:
Infinispan 6.0
Equality Considerations
When using lazy deserialization/storing as binary, keys and values are wrapped as MarshalledValues. It is
this wrapper class that transparently takes care of serialization and deserialization on demand, and internally
may have a reference to the object itself being wrapped, or the serialized, byte array representation of this
object.
This has a particular effect on the behavior of equality. The equals() method of this class will either compare
binary representations (byte arrays) or delegate to the wrapped object instance's equals() method,
depending on whether both instances being compared are in serialized or deserialized form at the time of
comparison. If one of the instances being compared is in one form and the other in another form, then one
instance is either serialized or deserialized. The preference will be to compare object representations,
unless the cache is compacted, in which case byte array comparison is favored.
This will affect the way keys stored in the cache will work, when {{storeAsBinary]} is used, since
comparisons happen on the key which will be wrapped by a MarshalledValue. Implementers of equals()
methods on their keys need to be aware of the behavior of equality comparison, when a key is wrapped as a
MarshalledValue, as detailed above.
Programmatically:
Infinispan 6.0
<serialization marshallerClass="com.acme.MyMarshaller"/>
Programatically:
Troubleshooting
Sometimes it might happen that the Infinispan marshalling layer, and in particular JBoss Marshalling, might
have issues marshalling/unmarshalling some user object. In Infinispan 4.0, marshalling exceptions will
contain further information on the objects that were being marshalled. Example:
Infinispan 6.0
The way the "in object" messages are read is the same in which stacktraces are read. The highest "in
object" being the most inner one and the lowest "in object" message being the most outer one. So, the
above example indicates that a java.lang.Object instance contained in an instance of
org.infinispan.commands.write.PutKeyValueCommand could not be serialized because
java.lang.Object@b40ec4 is not serializable.
This is not all though! If you enable DEBUG or TRACE logging levels, marshalling exceptions will contain
show the toString() representations of objects in the stacktrace. For example:
With regards to unmarshalling exceptions, showing such level of information it's a lot more complicated but
where possible. Infinispan will provide class type information. For example:
In this example, an IOException was thrown when trying to unmarshall a instance of the inner class
org.infinispan.marshall.VersionAwareMarshallerTest$1. In similar fashion to marshalling exceptions, when
DEBUG or TRACE logging levels are enabled, classloader information of the class type is provided. For
example:
Infinispan 6.0
Finding the root cause of marshalling/unmarshalling exceptions can sometimes be really daunting but we
hope that the above improvements would help get to the bottom of those in a more quicker and efficient
manner.
3.59 Batching
3.59.1 Introduction
Generally speaking, one should use batching API whenever the only participant in the transaction is an
Infinispan cluster. On the other hand, JTA transactions (involving TransactionManager) should be used
whenever the transactions involves multiple systems. E.g. considering the "Hello world!" of transactions:
transferring money from one bank account to the other. If both accounts are stored within Infinispan, then
batching can be used. If one account is in a database and the other is Infinispan, then distributed
transactions are required.
Infinispan 6.0
Configuration.setInvocationBatchingEnabled(true);
Infinispan 6.0
<transaction
syncRollbackPhase="false" syncCommitPhase="false"
useEagerLocking="true" eagerLockSingleNode="true" />
Infinispan 6.0
Infinispan 6.0
Introduction
This article provides detailed information about the first version of the custom TCP client/server Hot Rod
protocol.
Infinispan versions
This version of the protocol is implemented since Infinispan 4.1.0.Final
All key and values are sent and stored as byte arrays. Hot Rod makes no assumptions about their
types. Some clarifications about the other types:
vInt: Refers to unsigned variable length integer values as specified in here. They're
between 1 and 5 bytes long.
vLong: Refers to unsigned variable length long values similar to vInt but applied to longer
values. They're between 1 and 9 bytes long.
String: Strings are always represented using UTF-8 encoding.
Infinispan 6.0
Request Header
The header for a request is composed of:
Magic Message Version Opcode Cache
Cache
Flags Client
[1b]
Name [
Id [
[1b]
[1b]
vLong]
Name
Topology Transaction
Intelligence Id [vInt]
Type [1b]
[1b]
Cache Name Length : Length of cache name. If the passed length is 0 (followed by no cache name),
the operation will interact with the default cache.
Cache Name : Name of cache on which to operate. This name must match the name of predefined
cache in the Infinispan configuration file.
Infinispan 6.0
Flags : A variable length number representing flags passed to the system. Each flags is represented
by a bit. Note that since this field is sent as variable length, the most significant bit in a byte is used to
determine whether more bytes need to be read, hence this bit does not represent any flag. Using this
model allows for flags to be combined in a short space. Here are the current values for each flag:
0x0001 ForceReturnPreviousValue
Client Intelligence : This byte hints the server on the client capabilities:
0x01 - basic client, interested in neither cluster nor hash information
0x02 - topology-aware client, interested in cluster information
0x03 - hash-distribution-aware client, that is interested in both cluster and hash information
Topology Id : This field represents the last known view in the client. Basic clients will only send 0 in
this field. When topology-aware or hash-distribution-aware clients will send 0 until they have received
a reply from the server with the current view id. Afterwards, they should send that view id until they
receive a new view id in a response
Transaction Type : This is a 1 byte field, containing one of the following well-known supported
transaction types (For this version of the protocol, the only supported transaction type is 0):
0 - Non-transactional call, or client does not support transactions. The subsequent TX_ID field
will be omitted.
1 - X/Open XA transaction ID (XID). This is a well-known, fixed-size format.
Transaction Id : The byte array uniquely identifying the transaction associated to this call. It's length
is determined by the transaction type. If transaction type is 0, no transaction id will be present.
Response Header
Magic [1b] Message Id [vLong] Op code [1b] Status [1b] Topology Change Marker [1b]
Opcode : Op code representing a response to a particular operation, or error condition.
Status : Status of the response, possible values:
0x00 - No error
0x01 - Not
put/removed/replaced
0x81 - Invalid magic or message
id
0x84 - Request parsing error
out
Exceptional error status responses, those that start with 0x8..., are followed by the length of the error
message (as a vInt) and error message itself as String.
Topology Change Marker : This is a marker byte that indicates whether the response is prepended
with topology change information. When no topology change follows, the content of this byte is 0. If a
topology change follows, its contents are 1.
Infinispan 6.0
Topology Id [vInt]
marker
m1: Host/IP length [vInt]
string]
Short]
string]
Short]
...etc
Num servers in topology : Number of Infinispan Hot Rod servers running within the cluster. This
could be a subset of the entire cluster if only a fraction of those nodes are running Hot Rod servers.
Host/IP address length : Length of hostname or IP address of individual cluster member that Hot
Rod client can use to access it. Using variable length here allows for covering for hostnames, IPv4
and IPv6 addresses.
Host/IP address : String containing hostname or IP address of individual cluster member that Hot
Rod client can use to access it.
Port : Port that Hot Rod clients can use to communicat with this cluster member.
Infinispan 6.0
Topology Id
Hash
Hash
Num servers
2b - Unsigned
Function
space
in topology
marker
Short]
[vInt]
vInt]
m1: Host/IP length [
m1: Host/IP
m1:
vInt]
address [
unsigned short]
Hashcode [
string]
4b]
m2: Host/IP
m2:
vInt]
address [
unsigned short]
Hashcode [
string]
4b]
...etc
It's important to note that since hash headers rely on the consistent hash algorithm used by the server and
this is a factor of the cache interacted with, hash-distribution-aware headers can only be returned to
operations that target a particular cache. Currently ping command does not target any cache (this is to
change as per ISPN-424, hence calls to ping command with hash-topology-aware client settings will return a
hash-distribution-aware header with "Num Key Owners", "Hash Function Version", "Hash space size" and
each individual host's hash code all set to 0. This type of header will also be returned as response to
operations with hash-topology-aware client settings that are targeting caches that are not configured with
distribution.
Number key owners : Globally configured number of copies for each Infinispan distributed key
Hash function version : Hash function version, pointing to a specific hash function in use. See Hot
Rod hash functions for details.
Hash space size : Modulus used by Infinispan for for all module arithmetic related to hash code
generation. Clients will likely require this information in order to apply the correct hash calculation to
the keys.
Num servers in topology : If virtual nodes are disabled, this number represents the number of Hot
Rod servers in the cluster. If virtual nodes are enabled, this number represents all the virtual nodes in
the cluster which are calculated as (num configured virtual nodes) * (num cluster members).
Regardless of whether virtual nodes are configured or not, the number represented by this field
indicates the number of 'host:port:hashId' tuples to be read in the response.
Hashcode : 32 bit integer representing the hashcode of a cluster member that a Hot Rod client can
use indentify in which cluster member a key is located having applied the CSA to it.
Infinispan 6.0
Operations
Get/Remove/ContainsKey/GetWithVersion
Common request format:
Header Key Length [vInt] Key [byte-array]
Key Length : Length of key. Note that the size of a vint can be up to 5 bytes which in theory
can produce bigger numbers than Integer.MAX_VALUE. However, Java cannot create a
single array that's bigger than Integer.MAX_VALUE, hence the protocol is limiting vint array
lengths to Integer.MAX_VALUE.
Key : Byte array containing the key whose value is being requested.
Response status:
0x00 - success, if key present/retrieved/removed
0x02 - if key does not exist
Get response:
Header Value Length [vInt] Value [byte-array]
Value Length : Length of value
Value : The requested value. If key does not exist, status returned in 0x02. See encoding
section for more info.
Remove response:
If ForceReturnPreviousValue has been passed, remove response will contain previous value
(including value length) for that key. If the key does not exist or previous was null, value length would
be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be empty.
ContainsKey response:
Empty
GetWithVersion response:
Header Entry Version [8b] Value Length [vInt] Value [byte-array]
Entry Version : Unique value of an existing entry's modification. The protocol does not
mandate that entry_version values are sequential. They just need to be unique per update at
the key level.
Infinispan 6.0
BulkGet
Request format:
Header Entry Count [vInt]
Entry Count : Maximum number of Infinispan entries to be returned by the server (entry ==
key + associated value). Needed to support CacheLoader.load(int). If 0 then all entries are
returned (needed for CacheLoader.loadAll()).
Response:
Header More
[1b]
Key
Key Value
Value More
Key
Key Value
Value More [
Size 1
Size 2
Size 1
[1b]
Size 2
1b] ...
More : One byte representing whether more entries need to be read from the stream. So, when
it's set to 1, it means that an entry followes, whereas when it's set to 0, it's the end of stream
and no more entries are left to read.
For more information on BulkGet look here
Put/PutIfAbsent/Replace
Common request format:
Header Key Length [ Key [
vInt]
Lifespan [
byte-array vInt]
Max Idle [
Value Length
Value [
vInt]
[vInt]
byte-array]
]
Lifespan : Number of seconds that a entry during which the entry is allowed to life. If number
of seconds is bigger than 30 days, this number of seconds is treated as UNIX time and so,
represents the number of seconds since 1/1/1970. If set to 0, lifespan is unlimited.
Max Idle : Number of seconds that a entry can be idle before it's evicted from the cache. If 0,
no max idle time.
Put response status:
0x00 if stored
Replace response status:
0x00 if stored
0x01 if store did not happen because key does not exist
PutIfAbsent response status:
0x00 if stored
0x01 if store did not happen because key was present
Put/PutIfAbsent/Replace response:
If ForceReturnPreviousValue has been passed, these responses will contain previous value
(and corresponding value length) for that key. If the key does not exist or previous was null, value
length would be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be
empty.
Infinispan 6.0
ReplaceIfUnmodified
Request format:
Header Key
Key [
Lifespan Max
Entry
Value
Value [
Length [
byte-array [vInt]
Idle [
Version [
Length [
byte-array
vInt]
vInt]
8b]
vInt]
RemoveIfUnmodified
Request format:
Header Key Length [vInt] Key [byte-array] Entry Version [8b]
Response status
0x00 status if replaced/removed
0x01 status if replace/remove did not happen because key had been modified
0x02 status if key does not exist
Response:
If ForceReturnPreviousValue has been passed, this responses will contain previous value (and
corresponding value length) for that key. If the key does not exist or previous was null, value length
would be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be empty.
Clear
Request format:
Header
Response status:
0x00 status if infinispan was cleared
Infinispan 6.0
Stats
Returns a summary of all available statistics. For each statistic returned, a name and a value is returned
both in String UTF-8 format. The supported stats are the following:
Name
Explanation
timeSinceStart
stores
retrievals
hits
misses
removeHits
removeMisses
Response
Header Number
Name1
Name1
of stats [ length [ [
vInt]
vInt]
Value1
Value1
length [ [
string vInt]
String
length
Ping
Application level request to see if the server is available.
Response status:
0x00 - if no errors
Infinispan 6.0
Error Handling
Response header Error Message Length vInt Error Message string
Response header contains error op code response and corresponding error status number as well as the
following two:
Error Message Length : Length of error message
Error message : Error message. In the case of 0x84, this error field contains the latest version
supported by the hot rod server. Length is defined by total body length.
Multi-Get Operations
A multi-get operation is a form of get operation that instead of requesting a single key, requests a set of
keys. The Hot Rod protocol does not include such operation but remote Hot Rod clients could easily
implement this type of operations by either parallelizing/pipelining individual get requests. Another possibility
would be for remote clients to use async or non-blocking get requests. For example, if a client wants N keys,
it could send send N async get requests and then wait for all the replies. Finally, multi-get is not to be
confused with bulk-get operations. In bulk-gets, either all or a number of keys are retrieved, but the client
does not know which keys to retrieve, whereas in multi-get, the client defines which keys to retrieve.
Infinispan 6.0
0x09
0x41
0x01
0x07
0x4D
0x79
0x43
('M')
('y')
('C')
0x00
0x03
0x00
0x00
0x00
16
24
32
0xA0
0x61
0x63
0x68
0x65
('a')
('c')
('h')
('e')
0x00
0x05
0x48
0x65
0x6C
0x6C
0x6F
('H')
('e')
('l')
('l')
('o')
0x57
0x6F
0x72
0x6C
0x64
('W')
('o')
('r')
('l')
('d')
0x00
0x05
Field explanation
Field Name
Value
Field Name
Value
Magic (0)
0xA0
Message Id (1)
0x09
Version (2)
0x41
Opcode (3)
0x01
Cache name(5-11)
'MyCache'
Flag (12)
0x00
Topology Id (14)
0x00
0x00
Transaction Id (16)
0x00
0x05
0x00
Value (26-30)
'World'
0x00
0x05
Infinispan 6.0
Coded response
Byte 0
8
5 6 7
Field Explanation
Field Name
Value
Magic (0)
0xA1
Opcode (2)
0x01
Status (3)
0x00
Infinispan 6.0
Introduction
This article provides detailed information about the first version of the custom TCP client/server Hot Rod
protocol.
Infinispan versions
This version of the protocol is implemented since Infinispan 5.1.0.FINAL
All key and values are sent and stored as byte arrays. Hot Rod makes no assumptions about their
types. Some clarifications about the other types:
vInt: Refers to unsigned variable length integer values as specified in here. They're
between 1 and 5 bytes long.
vLong: Refers to unsigned variable length long values similar to vInt but applied to longer
values. They're between 1 and 9 bytes long.
String: Strings are always represented using UTF-8 encoding.
Request Header
The header for a request is composed of:
Magic Message Version Opcode Cache
Cache
Flags Client
[1b]
Name [
Id [
[1b]
[1b]
vLong]
Name
Topology Transaction
Intelligence Id [vInt]
Type [1b]
[1b]
Infinispan 6.0
Opcode : Possible values are only the ones on the request column:
Request operation codes
Cache Name Length : Length of cache name. If the passed length is 0 (followed by no cache name),
the operation will interact with the default cache.
Cache Name : Name of cache on which to operate. This name must match the name of predefined
cache in the Infinispan configuration file.
Flags : A variable length number representing flags passed to the system. Each flags is represented
by a bit. Note that since this field is sent as variable length, the most significant bit in a byte is used to
determine whether more bytes need to be read, hence this bit does not represent any flag. Using this
model allows for flags to be combined in a short space. Here are the current values for each flag:
0x0001 ForceReturnPreviousValue
Client Intelligence : This byte hints the server on the client capabilities:
0x01 - basic client, interested in neither cluster nor hash information
0x02 - topology-aware client, interested in cluster information
0x03 - hash-distribution-aware client, that is interested in both cluster and hash information
Topology Id : This field represents the last known view in the client. Basic clients will only send 0 in
this field. When topology-aware or hash-distribution-aware clients will send 0 until they have received
a reply from the server with the current view id. Afterwards, they should send that view id until they
receive a new view id in a response
Infinispan 6.0
Transaction Type : This is a 1 byte field, containing one of the following well-known supported
transaction types (For this version of the protocol, the only supported transaction type is 0):
0 - Non-transactional call, or client does not support transactions. The subsequent TX_ID field
will be omitted.
1 - X/Open XA transaction ID (XID). This is a well-known, fixed-size format.
Transaction Id : The byte array uniquely identifying the transaction associated to this call. It's length
is determined by the transaction type. If transaction type is 0, no transaction id will be present.
Response Header
Magic [1b] Message Id [vLong] Op code [1b] Status [1b] Topology Change Marker [1b]
Opcode : Op code representing a response to a particular operation, or error condition.
Status : Status of the response, possible values:
0x00 - No error
0x01 - Not
put/removed/replaced
0x81 - Invalid magic or message
id
0x84 - Request parsing error
out
Exceptional error status responses, those that start with 0x8..., are followed by the length of the error
message (as a vInt) and error message itself as String.
Topology Change Marker : This is a marker byte that indicates whether the response is prepended
with topology change information. When no topology change follows, the content of this byte is 0. If a
topology change follows, its contents are 1.
Infinispan 6.0
Topology Id [vInt]
marker
m1: Host/IP length [vInt]
string]
Short]
string]
Short]
...etc
Num servers in topology : Number of Infinispan Hot Rod servers running within the cluster. This
could be a subset of the entire cluster if only a fraction of those nodes are running Hot Rod servers.
Host/IP address length : Length of hostname or IP address of individual cluster member that Hot
Rod client can use to access it. Using variable length here allows for covering for hostnames, IPv4
and IPv6 addresses.
Host/IP address : String containing hostname or IP address of individual cluster member that Hot
Rod client can use to access it.
Port : Port that Hot Rod clients can use to communicat with this cluster member.
This is what hash-distribution-aware clients receive as response header when a topology change is sent
back:
Infinispan 6.0
Response header
Topology
Num Key
Hash
Hash
Num
Num Virtual
with topology
Id [vInt]
Owners [2b -
Function
space
servers in
Nodes
Unsigned
Version [
size [
topology
Owners [
Short]
1b]
vInt]
[vInt]
vInt]
change marker
m1:
m1:
[vInt]
Host/IP
unsigned
Hashcode
address [
short]
[4b]
string]
m2: Host/IP length
m2:
m1:
[vInt]
Host/IP
unsigned
Hashcode
address [
short]
[4b]
string]
...etc
Number key owners : Globally configured number of copies for each Infinispan distributed key. If the
cache is not configured with distribution, this field will return 0.
Hash function version : Hash function version, pointing to a specific hash function in use. See Hot
Rod hash functions for details. If cache is not configured with distribution, this field will contain 0.
Hash space size : Modulus used by Infinispan for for all module arithmetic related to hash code
generation. Clients will likely require this information in order to apply the correct hash calculation to
the keys. If cache is not configured with distribution, this field will contain 0.
Num servers in topology : Represents the number of servers in the Hot Rod cluster which
represents the number of host:port pairings to be read in the header.
Number virtual nodes : Field added in version 1.1 of the protocol that represents the number of
configured virtual nodes. If no virtual nodes are configured or the cache is not configured with
distribution, this field will contain 0.
Infinispan 6.0
Server node hash code calculation
Adding support for virtual nodes has made version 1.0 of the Hot Rod protocol impractical due to bandwidth
it would have taken to return hash codes for all virtual nodes in the clusters (this number could easily be in
the millions). So, as of version 1.1 of the Hot Rod protocol, clients are given the base hash id or hash code
of each server, and then they have to calculate the real hash position of each server both with and without
virtual nodes configured. Here are the rules clients should follow when trying to calculate a node's hash
code:
1. With virtual nodes disabled:
Once clients have received the base hash code of the server, they need to normalize it in order to find
the exact position of the hash wheel. The process of normalization involves passing the base hash
code to the hash function, and then do a small calculation to avoid negative values. The resulting
number is the node's position in the hash wheel:
Infinispan 6.0
Operations
Get/Remove/ContainsKey/GetWithVersion
Common request format:
Header Key Length [vInt] Key [byte-array]
Key Length : Length of key. Note that the size of a vint can be up to 5 bytes which in theory
can produce bigger numbers than Integer.MAX_VALUE. However, Java cannot create a
single array that's bigger than Integer.MAX_VALUE, hence the protocol is limiting vint array
lengths to Integer.MAX_VALUE.
Key : Byte array containing the key whose value is being requested.
Response status:
0x00 - success, if key present/retrieved/removed
0x02 - if key does not exist
Get response:
Header Value Length [vInt] Value [byte-array]
Value Length : Length of value
Value : The requested value. If key does not exist, status returned in 0x02. See encoding
section for more info.
Remove response:
If ForceReturnPreviousValue has been passed, remove response will contain previous value
(including value length) for that key. If the key does not exist or previous was null, value length would
be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be empty.
ContainsKey response:
Empty
GetWithVersion response:
Header Entry Version [8b] Value Length [vInt] Value [byte-array]
Entry Version : Unique value of an existing entry's modification. The protocol does not
mandate that entry_version values are sequential. They just need to be unique per update at
the key level.
Infinispan 6.0
BulkGet
Request format:
Header Entry Count [vInt]
Entry Count : Maximum number of Infinispan entries to be returned by the server (entry ==
key + associated value). Needed to support CacheLoader.load(int). If 0 then all entries are
returned (needed for CacheLoader.loadAll()).
Response:
Header More
[1b]
Key
Key Value
Value More
Key
Key Value
Value More [
Size 1
Size 2
Size 1
[1b]
Size 2
1b] ...
More : One byte representing whether more entries need to be read from the stream. So, when
it's set to 1, it means that an entry followes, whereas when it's set to 0, it's the end of stream
and no more entries are left to read.
For more information on BulkGet look here
Put/PutIfAbsent/Replace
Common request format:
Header Key Length [ Key [
vInt]
Lifespan [
byte-array vInt]
Max Idle [
Value Length
Value [
vInt]
[vInt]
byte-array]
]
Lifespan : Number of seconds that a entry during which the entry is allowed to life. If number
of seconds is bigger than 30 days, this number of seconds is treated as UNIX time and so,
represents the number of seconds since 1/1/1970. If set to 0, lifespan is unlimited.
Max Idle : Number of seconds that a entry can be idle before it's evicted from the cache. If 0,
no max idle time.
Put response status:
0x00 if stored
Replace response status:
0x00 if stored
0x01 if store did not happen because key does not exist
PutIfAbsent response status:
0x00 if stored
0x01 if store did not happen because key was present
Put/PutIfAbsent/Replace response:
If ForceReturnPreviousValue has been passed, these responses will contain previous value
(and corresponding value length) for that key. If the key does not exist or previous was null, value
length would be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be
empty.
Infinispan 6.0
ReplaceIfUnmodified
Request format:
Header Key
Key [
Lifespan Max
Entry
Value
Value [
Length [
byte-array [vInt]
Idle [
Version [
Length [
byte-array
vInt]
vInt]
8b]
vInt]
RemoveIfUnmodified
Request format:
Header Key Length [vInt] Key [byte-array] Entry Version [8b]
Response status
0x00 status if replaced/removed
0x01 status if replace/remove did not happen because key had been modified
0x02 status if key does not exist
Response:
If ForceReturnPreviousValue has been passed, this responses will contain previous value (and
corresponding value length) for that key. If the key does not exist or previous was null, value length
would be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be empty.
Clear
Request format:
Header
Response status:
0x00 status if infinispan was cleared
Infinispan 6.0
Stats
Returns a summary of all available statistics. For each statistic returned, a name and a value is returned
both in String UTF-8 format. The supported stats are the following:
Name
Explanation
timeSinceStart
stores
retrievals
hits
misses
removeHits
removeMisses
Response
Header Number
Name1
Name1
of stats [ length [ [
vInt]
vInt]
Value1
Value1
length [ [
string vInt]
String
length
Ping
Application level request to see if the server is available.
Response status:
0x00 - if no errors
Infinispan 6.0
Error Handling
Response header Error Message Length vInt Error Message string
Response header contains error op code response and corresponding error status number as well as the
following two:
Error Message Length : Length of error message
Error message : Error message. In the case of 0x84, this error field contains the latest version
supported by the hot rod server. Length is defined by total body length.
Multi-Get Operations
A multi-get operation is a form of get operation that instead of requesting a single key, requests a set of
keys. The Hot Rod protocol does not include such operation but remote Hot Rod clients could easily
implement this type of operations by either parallelizing/pipelining individual get requests. Another possibility
would be for remote clients to use async or non-blocking get requests. For example, if a client wants N keys,
it could send send N async get requests and then wait for all the replies. Finally, multi-get is not to be
confused with bulk-get operations. In bulk-gets, either all or a number of keys are retrieved, but the client
does not know which keys to retrieve, whereas in multi-get, the client defines which keys to retrieve.
Infinispan 6.0
0x09
0x41
0x01
0x07
0x4D
0x79
0x43
('M')
('y')
('C')
0x00
0x03
0x00
0x00
0x00
16
24
32
0xA0
0x61
0x63
0x68
0x65
('a')
('c')
('h')
('e')
0x00
0x05
0x48
0x65
0x6C
0x6C
0x6F
('H')
('e')
('l')
('l')
('o')
0x57
0x6F
0x72
0x6C
0x64
('W')
('o')
('r')
('l')
('d')
0x00
0x05
Field explanation
Field Name
Value
Field Name
Value
Magic (0)
0xA0
Message Id (1)
0x09
Version (2)
0x41
Opcode (3)
0x01
Cache name(5-11)
'MyCache'
Flag (12)
0x00
Topology Id (14)
0x00
0x00
Transaction Id (16)
0x00
0x05
0x00
Value (26-30)
'World'
0x00
0x05
Infinispan 6.0
Coded response
Byte 0
8
5 6 7
Field Explanation
Field Name
Value
Magic (0)
0xA1
Opcode (2)
0x01
Status (3)
0x00
Infinispan 6.0
Introduction
This article provides detailed information about the first version of the custom TCP client/server Hot Rod
protocol.
Infinispan versions
This version of the protocol is implemented since Infinispan 5.2.0.Final. Since Infinispan 5.3.0,
HotRod supports encryption via SSL. However, since this only affects the transport, the version
number of the protocol has not been incremented.
All key and values are sent and stored as byte arrays. Hot Rod makes no assumptions about their
types. Some clarifications about the other types:
vInt: Refers to unsigned variable length integer values as specified in here. They're
between 1 and 5 bytes long.
vLong: Refers to unsigned variable length long values similar to vInt but applied to longer
values. They're between 1 and 9 bytes long.
String: Strings are always represented using UTF-8 encoding.
Request Header
The header for a request is composed of:
Magic Message Version Opcode Cache
Cache
Flags Client
[1b]
Name [
Id [
[1b]
[1b]
vLong]
Name
Topology Transaction
Intelligence Id [vInt]
Type [1b]
[1b]
Infinispan 6.0
Opcode : Possible values are only the ones on the request column:
Request operation codes
Cache Name Length : Length of cache name. If the passed length is 0 (followed by no cache name),
the operation will interact with the default cache.
Cache Name : Name of cache on which to operate. This name must match the name of predefined
cache in the Infinispan configuration file.
Flags : A variable length number representing flags passed to the system. Each flags is represented
by a bit. Note that since this field is sent as variable length, the most significant bit in a byte is used to
determine whether more bytes need to be read, hence this bit does not represent any flag. Using this
model allows for flags to be combined in a short space. Here are the current values for each flag:
0x0001 ForceReturnPreviousValue
0x0002 DefaultLifespan
0x0004 DefaultMaxIdle
Infinispan 6.0
Client Intelligence : This byte hints the server on the client capabilities:
0x01 - basic client, interested in neither cluster nor hash information
0x02 - topology-aware client, interested in cluster information
0x03 - hash-distribution-aware client, that is interested in both cluster and hash information
Topology Id : This field represents the last known view in the client. Basic clients will only send 0 in
this field. When topology-aware or hash-distribution-aware clients will send 0 until they have received
a reply from the server with the current view id. Afterwards, they should send that view id until they
receive a new view id in a response
Transaction Type : This is a 1 byte field, containing one of the following well-known supported
transaction types (For this version of the protocol, the only supported transaction type is 0):
0 - Non-transactional call, or client does not support transactions. The subsequent TX_ID field
will be omitted.
1 - X/Open XA transaction ID (XID). This is a well-known, fixed-size format.
Transaction Id : The byte array uniquely identifying the transaction associated to this call. It's length
is determined by the transaction type. If transaction type is 0, no transaction id will be present.
Response Header
Magic [1b] Message Id [vLong] Op code [1b] Status [1b] Topology Change Marker [1b]
Opcode : Op code representing a response to a particular operation, or error condition.
Status : Status of the response, possible values:
0x00 - No error
0x01 - Not
put/removed/replaced
0x81 - Invalid magic or message
id
0x84 - Request parsing error
out
Exceptional error status responses, those that start with 0x8..., are followed by the length of the error
message (as a vInt) and error message itself as String.
Topology Change Marker : This is a marker byte that indicates whether the response is prepended
with topology change information. When no topology change follows, the content of this byte is 0. If a
topology change follows, its contents are 1.
Infinispan 6.0
Topology Id [vInt]
marker
vInt]
string]
Short]
string]
Short]
...etc
Num servers in topology : Number of Infinispan Hot Rod servers running within the cluster. This
could be a subset of the entire cluster if only a fraction of those nodes are running Hot Rod servers.
Host/IP address length : Length of hostname or IP address of individual cluster member that Hot
Rod client can use to access it. Using variable length here allows for covering for hostnames, IPv4
and IPv6 addresses.
Host/IP address : String containing hostname or IP address of individual cluster member that Hot
Rod client can use to access it.
Port : Port that Hot Rod clients can use to communicat with this cluster member.
Topology
Num Key
Hash
Hash
Num
Num Virtual
with topology
Id [vInt]
Owners [2b -
Function
space
servers in
Nodes
Unsigned
Version [
size [
topology
Owners [
Short]
1b]
vInt]
[vInt]
vInt]
change marker
m1:
m1:
[vInt]
Host/IP
unsigned
Hashcode
address [
short]
[4b]
string]
m2: Host/IP length
m2:
m1:
[vInt]
Host/IP
unsigned
Hashcode
address [
short]
[4b]
string]
...etc
Infinispan 6.0
Number key owners : Globally configured number of copies for each Infinispan distributed key. If the
cache is not configured with distribution, this field will return 0.
Hash function version : Hash function version, pointing to a specific hash function in use. See Hot
Rod hash functions for details. If cache is not configured with distribution, this field will contain 0.
Hash space size : Modulus used by Infinispan for for all module arithmetic related to hash code
generation. Clients will likely require this information in order to apply the correct hash calculation to
the keys. If cache is not configured with distribution, this field will contain 0.
Num servers in topology : Represents the number of servers in the Hot Rod cluster which
represents the number of host:port pairings to be read in the header.
Number virtual nodes : Field added in version 1.1 of the protocol that represents the number of
configured virtual nodes. If no virtual nodes are configured or the cache is not configured with
distribution, this field will contain 0.
Server node hash code calculation
Adding support for virtual nodes has made version 1.0 of the Hot Rod protocol impractical due to bandwidth
it would have taken to return hash codes for all virtual nodes in the clusters (this number could easily be in
the millions). So, as of version 1.1 of the Hot Rod protocol, clients are given the base hash id or hash code
of each server, and then they have to calculate the real hash position of each server both with and without
virtual nodes configured. Here are the rules clients should follow when trying to calculate a node's hash
code:
1. With virtual nodes disabled:
Once clients have received the base hash code of the server, they need to normalize it in order to find
the exact position of the hash wheel. The process of normalization involves passing the base hash
code to the hash function, and then do a small calculation to avoid negative values. The resulting
number is the node's position in the hash wheel:
Infinispan 6.0
Operations
Get/Remove/ContainsKey/GetWithVersion/GetWithMetadata
Common request format:
Header Key Length [vInt] Key [byte-array]
Key Length : Length of key. Note that the size of a vint can be up to 5 bytes which in theory
can produce bigger numbers than Integer.MAX_VALUE. However, Java cannot create a
single array that's bigger than Integer.MAX_VALUE, hence the protocol is limiting vint array
lengths to Integer.MAX_VALUE.
Key : Byte array containing the key whose value is being requested.
Response status:
0x00 - success, if key present/retrieved/removed
0x02 - if key does not exist
Get response:
Header Value Length [vInt] Value [byte-array]
Value Length : Length of value
Value : The requested value. If key does not exist, status returned in 0x02. See encoding
section for more info.
Remove response:
If ForceReturnPreviousValue has been passed, remove response will contain previous value
(including value length) for that key. If the key does not exist or previous was null, value length would
be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be empty.
ContainsKey response:
Empty
GetWithVersion response:
Header Entry Version [8b] Value Length [vInt] Value [byte-array]
Entry Version : Unique value of an existing entry's modification. The protocol does not
mandate that entry_version values are sequential. They just need to be unique per update at
the key level.
Infinispan 6.0
GetWithMetadata response:
Header Flag
Created
(byte) [Long]
Lifespan
LastUsed
MaxIdle
Entry
[vInt]
[Long]
[vInt]
Value
Value [
[vInt]
Flag : a flag indicating whether the response contains expiration information. The value of the
flag is obtained as a bitwise OR operation between INFINITE_LIFESPAN (0x01) and
INFINITE_MAXIDLE (0x02)
Created : a Long representing the timestamp when the entry was created on the server. This
value is returned only if the flag's INFINITE_LIFESPAN bit is not set
Lifespan : a vInt representing the lifespan of the entry in seconds. This value is returned only if
the flag's INFINITE_LIFESPAN bit is not set
LastUsed : a Long representing the timestamp when the entry was last accessed on the
server. This value is returned only if the flag's INFINITE_MAXIDLE bit is not set
MaxIdle : a vInt representing the maxIdle of the entry in seconds. This value is returned only if
the flag's INFINITE_MAXIDLE bit is not set
Entry Version : Unique value of an existing entry's modification. The protocol does not
mandate that entry_version values are sequential. They just need to be unique per update at
the key level.
BulkGet
Request format:
Header Entry Count [vInt]
Entry Count : Maximum number of Infinispan entries to be returned by the server (entry ==
key + associated value). Needed to support CacheLoader.load(int). If 0 then all entries are
returned (needed for CacheLoader.loadAll()).
Response:
Header More
[1b]
Key
Key Value
Value More
Key
Key Value
Value More [
Size 1
Size 2
Size 1
[1b]
Size 2
1b] ...
More : One byte representing whether more entries need to be read from the stream. So, when
it's set to 1, it means that an entry followes, whereas when it's set to 0, it's the end of stream
and no more entries are left to read.
For more information on BulkGet look here
Infinispan 6.0
BulkKeysGet
Request format:
Header Scope [vInt]
Scope :
0 - Default Scope - This scope is used by RemoteCache.keySet() method. If the remote cache
is a distributed cache, the server launch a map/reduce operation to retrieve all keys from all of
the nodes. (Remember, a topology-aware Hot Rod Client could be load balancing the request
to any one node in the cluster). Otherwise, it'll get keys from the cache instance local to the
server receiving the request (that is because the keys should be the same across all nodes in a
replicated cache).
1 - Global Scope - This scope behaves the same to Default Scope.
2 - Local Scope - In case when remote cache is a distributed cache, the server will not launch
a map/reduce operation to retrieve keys from all nodes. Instead, it'll only get keys local from
the cache instance local to the server receiving the request.
Response:
Header More [1b] Key Size 1 Key 1 More [1b] Key Size 2 Key 2 More [1b] ...
More : One byte representing whether more keys need to be read from the stream. So, when
it's set to 1, it means that a key followes, whereas when it's set to 0, it's the end of stream and
no more entries are left to read.
Infinispan 6.0
Put/PutIfAbsent/Replace
Common request format:
Header Key Length [ Key [
vInt]
Lifespan [
byte-array vInt]
Max Idle [
Value Length
Value [
vInt]
[vInt]
byte-array]
]
Lifespan : Number of seconds that a entry during which the entry is allowed to life. If number
of seconds is bigger than 30 days, this number of seconds is treated as UNIX time and so,
represents the number of seconds since 1/1/1970. If set to 0, lifespan is unlimited.
Max Idle : Number of seconds that a entry can be idle before it's evicted from the cache. If 0,
no max idle time.
Put response status:
0x00 if stored
Replace response status:
0x00 if stored
0x01 if store did not happen because key does not exist
PutIfAbsent response status:
0x00 if stored
0x01 if store did not happen because key was present
Put/PutIfAbsent/Replace response:
If ForceReturnPreviousValue has been passed, these responses will contain previous value
(and corresponding value length) for that key. If the key does not exist or previous was null, value
length would be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be
empty.
ReplaceIfUnmodified
Request format:
Header Key
Entry
Value
Value [
Length [
Key [
byte-array [vInt]
Lifespan Max
Idle [
Version [
Length [
byte-array
vInt]
vInt]
8b]
vInt]
Infinispan 6.0
RemoveIfUnmodified
Request format:
Header Key Length [vInt] Key [byte-array] Entry Version [8b]
Response status
0x00 status if replaced/removed
0x01 status if replace/remove did not happen because key had been modified
0x02 status if key does not exist
Response:
If ForceReturnPreviousValue has been passed, this responses will contain previous value (and
corresponding value length) for that key. If the key does not exist or previous was null, value length
would be 0. Otherwise, if no ForceReturnPreviousValue was sent, the response would be empty.
Clear
Request format:
Header
Response status:
0x00 status if infinispan was cleared
Infinispan 6.0
Stats
Returns a summary of all available statistics. For each statistic returned, a name and a value is returned
both in String UTF-8 format. The supported stats are the following:
Name
Explanation
timeSinceStart
stores
retrievals
hits
misses
removeHits
removeMisses
Response
Header Number
Name1
Name1
of stats [ length [ [
vInt]
vInt]
Value1
Value1
length [ [
string vInt]
String
length
Ping
Application level request to see if the server is available.
Response status:
0x00 - if no errors
Infinispan 6.0
Error Handling
Response header Error Message Length vInt Error Message string
Response header contains error op code response and corresponding error status number as well as the
following two:
Error Message Length : Length of error message
Error message : Error message. In the case of 0x84, this error field contains the latest version
supported by the hot rod server. Length is defined by total body length.
Multi-Get Operations
A multi-get operation is a form of get operation that instead of requesting a single key, requests a set of
keys. The Hot Rod protocol does not include such operation but remote Hot Rod clients could easily
implement this type of operations by either parallelizing/pipelining individual get requests. Another possibility
would be for remote clients to use async or non-blocking get requests. For example, if a client wants N keys,
it could send send N async get requests and then wait for all the replies. Finally, multi-get is not to be
confused with bulk-get operations. In bulk-gets, either all or a number of keys are retrieved, but the client
does not know which keys to retrieve, whereas in multi-get, the client defines which keys to retrieve.
Infinispan 6.0
0x09
0x41
0x01
0x07
0x4D
0x79
0x43
('M')
('y')
('C')
0x00
0x03
0x00
0x00
0x00
16
24
32
0xA0
0x61
0x63
0x68
0x65
('a')
('c')
('h')
('e')
0x00
0x05
0x48
0x65
0x6C
0x6C
0x6F
('H')
('e')
('l')
('l')
('o')
0x57
0x6F
0x72
0x6C
0x64
('W')
('o')
('r')
('l')
('d')
0x00
0x05
Field explanation
Field Name
Value
Field Name
Value
Magic (0)
0xA0
Message Id (1)
0x09
Version (2)
0x41
Opcode (3)
0x01
Cache name(5-11)
'MyCache'
Flag (12)
0x00
Topology Id (14)
0x00
0x00
Transaction Id (16)
0x00
0x05
0x00
Value (26-30)
'World'
0x00
0x05
Infinispan 6.0
Coded response
Byte 0
8
5 6 7
Field Explanation
Field Name
Value
Magic (0)
0xA1
Opcode (2)
0x01
Status (3)
0x00
Infinispan 6.0
Infinispan 6.0
3.63 Configuration
The cross-site replication configuration spreads over the following files:
Infinispan 6.0
1. the backup policy for each individual cache is defined in infinispan's .xml configuration file (
infinispan.xml in attachment)
2. cluster's jgroups xml configuration file: RELAY2 protocol needs to be added to the JGroups protocol
stack (jgroups.xml)
3. RELAY2 configuration file: RELAY2 has an own configuration file (relay2.xml)
4. the jgroups channel that is used by RELAY2 has its own configuration file ( jgroups-relay2.xml)
<global>
...
<site local="LON"/>
...
</global>
The names of the site (case sensitive) should match the name of a site as defined within JGroups'
RELAY2 protocol configuration file.
Besides the global configuration, each cache specifies its backup policy in the "site" element:
<namedCache name="users">
<sites>
<backups>
<backup site="NYC" backupFailurePolicy="WARN" strategy="SYNC" timeout="12000"/>
<backup site="SFO" backupFailurePolicy="IGNORE" strategy="ASYNC"/>
<backup site="LON" strategy="SYNC" enabled="false"/>
</backups>
</sites>
</namedCache>
The "users" cache backups its data to the "NYC" and "SFO" sites. Even though the "LON" appears as
a backup site, it has the "enabled" attribute set to false so it will be ignored .
For each site backup, the following configuration attributes can be specified:
Infinispan 6.0
strategy - the strategy used for backing up data, either "SYNC" or "ASYNC". Defaults to "ASYNC"
backupFailurePolicy - Decides what the system would do in case of failure during backup. Possible
values are:
IGNORE - allow the local operation/transaction to succeed
WARN - same as IGNORE but also logs an warning message. Default.
FAIL - only in effect if "strategy" is "SYNC" - fails local cluster operation/transaction by throwing
an exception to the user
CUSTOM - user provided, see "failurePolicyClass" below
failurePolicyClass - If the 'backupFailurePolicy' is set to 'CUSTOM' then this attribute is required and
should contain the fully qualified name of a class implementing
org.infinispan.xsite.CustomFailurePolicy
timeout - The timeout(milliseconds) to be used when backing up data remotely. Defaults to 10000 (10
seconds)
The same setup can be achieved programatically:
The "users" cache above doesn't know on which cache on the remote sites its data is being replicated. By
default the remote site writes the backup data to a cache having the same name as the originator, i.e.
"users". This behaviour can be overridden with an "backupFor" element. For example the following
configuration in SFO makes the "usersLONBackup" cache act as the backup cache for the "users" cache
defined above in the LON site:
<infinispan>
<namedCache name="usersLONBackup">
<sites>
<backupFor remoteCache="users" remoteSite="LON"/>
</sites>
</namedCache>
</infinispan>
Infinispan 6.0
<infinispan>
..
<global>
<transport clusterName="infinispan-cluster">
<properties>
<property name="configurationFile" value="jgroups.xml"/>
</properties>
</transport>
</global>
..
</infinispan>
In order to allow inter-site calls, the RELAY2 protocol needs to be added to the protocol stack defined in the
jgroups configuration (see attached jgroups.xml for an example).
Infinispan 6.0
Transactional caches
For synchronous transactional caches, Infinispan internally uses a two phase commit protocol: lock
acquisition during the 1st phase (prepare) and apply changes during the 2nd phase (commit). For
asynchronous caches the two phases are merged, the "apply changes" message being sent asynchronously
to the owners of data. This 2PC protocol maps to 2PC received from the JTA transaction manager.
For transactional caches, both optimistic and pessimistic, the backup to remote sites happens during the
prepare and commit phase only.
Infinispan 6.0
Configuration
The taking offline of a site can be configured as follows:
<namedCache name="bestEffortBackup">
...
<sites>
<backups>
<backup site="NYC" strategy="SYNC" backupFailurePolicy="FAIL">
<takeOffline afterFailures="500" minTimeToWait="10000"/>
</backup>
</backups>
</sites>
...
</namedCache>
The takeOfline element under the backup configures the taking offline of a site:
*afterFailure - the number of failed backup operations after which this site should be taken offline. Defaults to
0 (never). A negative value would mean that the site will be taken offline after minTimeToWait
*minTimeToWait - the number of milliseconds in which a site is not marked offline even if it is unreachable
for 'afterFailures' number of times. If smaller or equal to 0, then only afterFailures is considered.
The equivalent programmatic configuration is:
lon.sites().addBackup()
.site("NYC")
.backupFailurePolicy(BackupFailurePolicy.FAIL)
.strategy(BackupConfiguration.BackupStrategy.SYNC)
.takeOffline()
.afterFailures(500)
.minTimeToWait(10000);
Infinispan 6.0
3.63.5 Reference
This document (Sept 2012) describes the technical design of cross site replication in more detail.
3.64.1 Introduction
MapReduce is a programming model allowing transparent distributed processing of very large data sets over
data grids. The name MapReduce comes from an idea of using two distinct computational phases of map
and reduce. In the map phase, master node that initiates a task takes the task input, divides it and sends
tasks for map phase execution on the grid. Each node in turns executes a map function on its input returning
intermediate results back to master node. Master node task collects all intermediate results from map
phase combines them by intermediate result keys and sends intermediate keys/values for reduction on the
grid. Finally master tasks node receives all results from reduction phases and returns the final result to
invoker of the MapReduce task.
Infinispan 6.0
The Reducer, as its name implies, reduces a list of intermediate results from map phase of
MapReduceTask. Infinispan distributed execution environment creates one instance of Reducer per
execution node.
Collator coordinates results from Reducers executed on Infinispan cluster and assembles a final result
returned to an invoker of MapReduceTask. Collator is applied to final Map<KOut,VOut> result of
MapReduceTask.
Finally, MapReduceTask is a distributed task unifying Mapper, Reducer and Collator into a cohesive large
scale computation to be transparently parallelized across Infinispan cluster nodes. Users of MapReduceTask
need to provide a cache whose data is used as input for this task. Infinispan execution environment will
instantiate and migrate instances of provided mappers and reducers seamlessly across Infinispan nodes.
Unless otherwise specified using onKeys method input keys filter all available key value pairs of a specified
cache will be used as input data for this task.
Infinispan 6.0
It is possible to set a timeout value for each Map/Reduce tasks. However, if no timeout is specified, it uses
the replication timeout as a default timeout (the same behavior as the previous Infinispan versions).
You can set the timeout in your task by doing the following:
Also, it is possible to know which is the current timeout value for the task:
For more information about this, please check the java doc in Map Reduce Task API Documentation
Infinispan 6.0
Results are collected with an Infinispan supplied Collector, and combine phase is initiated. A Combiner, if
specified, takes KOut keys and immediately invokes reduce phase on keys. The result of mapping phase
executed on each node is KOut/VOut map. There will be one resulting map per execution node N per
launched MapReduceTask.
Intermediate KOut/VOut migration phase
Infinispan 6.0
In order to proceed with reduce phase, all intermediate keys and values need to be grouped by intermediate
KOut keys. More specifically, as map phases around the cluster can produce identical intermediate keys, all
those identical intermediate keys and their values need to be grouped before reduce is executed on any
particular intermediate key.
Therefore at the end of combine phase, instead of returning map with intermediate keys and values to the
master task node, we instead hash each intermediate key KOut and migrate it with its VOut values to
Infinispan node where keys KOut are hashed to. We achieve this using a temporary DIST cache and
underlying consistent hashing mechanism. Using DeltaAware cache insertion we effectively collect all VOut
values under each KOut for all executed map functions across the cluster
At this point, map and combine phase have finished its execution; list of KOut keys is returned to a master
node and its initiating MapReduceTask. We do not return VOut values as we do not need them at master
task node. MapReduceTask is ready to start with reduce phase.
Reduce phase
Reduce phase is easy to accomplish now as Infinispan's consistent hashing already finished all the hard
lifting for us. To complete reduce phase, MapReduceTask groups KOut keys by execution node N they are
hashed to. For each node N and its grouped input KOut keys, MapReduceTask sends a reduce command to
a node N where KOut keys are hashed. Once reduce command arrives on target execution node, it looks up
temporary cache belonging to MapReduce task - and for each KOut key, grabs a list of VOut values, wraps it
with an Iterator and invokes reduce on it.
Infinispan 6.0
A result of each reduce is a map where each key is KOut and value is VOut. Each Infinispan execution node
N returns one map with KOut/VOut result values. As all initiated reduce commands return to a calling node,
MapReduceTask simply combines all resulting maps into map M and returns M as a result of
MapReduceTask.
Distributed reduce phase is turned on by using a MapReduceTask constructor specifying cache to use as
input data for the task and boolean parameter distributeReducePhase set to true. Map/Reduce API javadoc
and demos are included in distribution.
3.64.5 Examples
Word count is a classic, if not overused, example of map/reduce paradigm. Assume we have a mapping of
key-->sentence stored on Infinispan nodes. Key is a String, each sentence is also a String, and we have to
count occurrence of all words in all sentences available. The implementation of such a distributed task could
be defined as follows:
Infinispan 6.0
c1.put("12","JBoss Application Server");
c2.put("15", "Hello world");
c1.put("14", "Infinispan community");
c2.put("15", "Hello world");
c1.put("111",
c2.put("112",
c1.put("113",
c2.put("114",
c1.put("211",
c2.put("212",
c1.put("213",
c2.put("214",
As we have seen it is relatively easy to specify map reduce task counting number of occurrences for each
word in all sentences. Best of all result is returned to task invoker in the form of Map<KOut,VOut> rather
than being written to a stream.
Infinispan 6.0
What if we need to find the most frequent word in our word count example? All we have to do is to define a
Collator that will transform the result of MapReduceTask Map<KOut,VOut> into a String which in turn is
returned to a task invoker. We can think of Collator as transformation function applied to a final result of
MapReduceTask.
Infinispan 6.0
3.65.1 Steps
1. Start a new cluster (Target Cluster) with the new version of Infinispan, using either different network
settings or JGroups cluster name so that the old cluster (Source Cluster) and the new one don't
overlap.
2. For each cache to be migrated, the Target Cluster is configured with a RemoteCacheStore with the
following settings:
1. servers should point to the Source Cluster
2. remoteCacheName must coincide with the name of the cache on the Source Cluster
3. hotRodWrapping must be enabled (true)
3. Configure clients to point to the Target Cluster instead of the Source Cluster, and one by one,
restart each client node. Gradually, all requests will be handled by the Target Cluster rather than the
Source Cluster. The Target Cluster will lazily load data from the Source Cluster on demand via the
RemoteCacheStore.
4. Once all connections have switched to using the Target Cluster the keyset on the Source Cluster
must be dumped. This can be achieved either via a JMX operation or via the CLI:
1. JMX: invoke the recordKnownGlobalKeyset operation on the RollingUpgradeManager MBean
on the Source Cluster for all of the caches that need to be migrated
2. CLI: invoke the upgrade --dumpkeys command on the Source Cluster for all of the caches
that need to be migrated (additionally the --all switch can be used to dump all caches in the
cluster)
5. At this point the Target Cluster needs to fetch all remaining data from the Source Cluster:
1. JMX: invoke the synchronizeData operation specifying the "hotrod" parameter on the
RollingUpgradeManager MBean on the Target Cluster for all of the caches that need to be
migrated
2. CLI: invoke the upgrade --synchronize=hotrod command on the Target Cluster for all of the
caches that need to be migrated (additionally the --all switch can be used to synchronize all
caches in the cluster)
6. Once the above operation is complete, the RemoteCacheStore on the Target Cluster must be
disabled as follows:
1. JMX: invoke the disconnectSource operation specifying the "hotrod" parameter on the
RollingUpgradeManager MBean on the Target Cluster for all of the caches that have been
migrated
2. CLI: invoke the upgrade --disconnectsource=hotrod command on the Target Cluster for all of
the caches that have been migrated (additionally the --all switch can be used to disconnect all
caches in the cluster)
7. The Source Cluster can be decomissioned now.
Infinispan 6.0
-c, --connect=URL
-h, --help
-v, --version
* JMX over RMI is the traditional way in which JMX clients connect to MBeanServers. Please refer to the
JDK Monitoring and Management documentation for details on how to configure the process to be monitored
JMX over JBoss Remoting is the protocol of choice when your Infinispan application is running within
JBoss AS7 or EAP6.
The connection to the application can also be initiated from within the CLI using the connect command.
The CLI prompt will show the active connection information, including the currently selected CacheManager.
Initially no cache is selected so, before performing any cache operations, one must be selected. For this the
cache command is used. The CLI supports tab-completion for all commands and options and for most
parameters where it makes sense to do so. Therefore typing cache and pressing TAB will show a list of
active caches:
Infinispan 6.0
[jmx://localhost:12000/MyCacheManager/> cache
___defaultcache namedCache
[jmx://localhost:12000/MyCacheManager/]> cache ___defaultcache
[jmx://localhost:12000/MyCacheManager/___defaultcache]>
Pressing TAB at an empty prompt will show the list of all available commands:
alias
upgrade
abort
version
begin
cache
container
encoding
get
locate
remove
site
clear
create
end
help
put
replace
start
commit
disconnect
evict
info
quit
rollback
stats
The CLI is based on sh and therefore offers many keyboard shortcuts to navigate and search the history
of commands, to manipulate the cursor at the prompt, including both Emacs and VI modes of operation.
3.66.1 Commands
abort
The abort command is used to abort a running batch initiated by the start command
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
null
start
put a a
abort
get a
begin
The begin command starts a transaction. In order for this command to work, the cache(s) on which the
subsequent operations are invoked must have transactions enabled.
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
begin
put a a
put b b
commit
Infinispan 6.0
cache
The cache command selects the cache to use as default for all subsequent operations. If it is invoked
without parameters it shows the currently selected cache.
clear
The clear command clears a cache from all content.
[jmx://localhost:12000/MyCacheManager/namedCache]> put a a
[jmx://localhost:12000/MyCacheManager/namedCache]> clear
[jmx://localhost:12000/MyCacheManager/namedCache]> get a
null
commit
The commit command commits an ongoing transaction
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
begin
put a a
put b b
commit
container
The container command selects the default container (cache manager). Invoked without parameters it lists
all available containers
[jmx://localhost:12000/MyCacheManager/namedCache]> container
MyCacheManager OtherCacheManager
[jmx://localhost:12000/MyCacheManager/namedCache]> container OtherCacheManager
[jmx://localhost:12000/OtherCacheManager/]>
create
The create command creates a new cache based on the configuration of an existing cache definition
Infinispan 6.0
disconnect
The disconnect command disconnects the currently active connection allowing the CLI to connect to another
instance.
[jmx://localhost:12000/MyCacheManager/namedCache]> disconnect
[disconnected//]
encoding
The encoding command is used to set a default codec to use when reading/writing entries from/to a cache.
When invoked without arguments it shows the currently selected codec.
This command is useful since currently remote protocols such as HotRod and Memcached wrap keys and
values in specialized structures.
[jmx://localhost:12000/MyCacheManager/namedCache]> encoding
none
[jmx://localhost:12000/MyCacheManager/namedCache]> encoding --list
memcached
hotrod
none
rest
[jmx://localhost:12000/MyCacheManager/namedCache]> encoding hotrod
end
The end command is used to successfully end a running batch initiated by the start command
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
a
start
put a a
end
get a
evict
The evict command is used to evict from the cache the entry associated with a specific key.
[jmx://localhost:12000/MyCacheManager/namedCache]> put a a
[jmx://localhost:12000/MyCacheManager/namedCache]> evict a
Infinispan 6.0
get
The get command is used to show the value associated to a specified key. For primitive types and Strings,
the get command will simply print the default representation. For other objects, a JSON representation of the
object will be printed.
[jmx://localhost:12000/MyCacheManager/namedCache]> put a a
[jmx://localhost:12000/MyCacheManager/namedCache]> get a
a
info
The info command is used to show the configuration of the currently selected cache or container.
[jmx://localhost:12000/MyCacheManager/namedCache]> info
GlobalConfiguration{asyncListenerExecutor=ExecutorFactoryConfiguration{factory=org.infinispan.executors.Defaul
asyncTransportExecutor=ExecutorFactoryConfiguration{factory=org.infinispan.executors.DefaultExecutorFactory@7b
evictionScheduledExecutor=ScheduledExecutorFactoryConfiguration{factory=org.infinispan.executors.DefaultSchedu
replicationQueueScheduledExecutor=ScheduledExecutorFactoryConfiguration{factory=org.infinispan.executors.Defau
globalJmxStatistics=GlobalJmxStatisticsConfiguration{allowDuplicateDomains=true, enabled=true,
jmxDomain='jboss.infinispan',
mBeanServerLookup=org.jboss.as.clustering.infinispan.MBeanServerProvider@6c0dc01,
cacheManagerName='local', properties={}}, transport=TransportConfiguration{clusterName='ISPN',
machineId='null', rackId='null', siteId='null', strictPeerToPeer=false,
distributedSyncTimeout=240000, transport=null, nodeName='null', properties={}},
serialization=SerializationConfiguration{advancedExternalizers={1100=org.infinispan.server.core.CacheValue$Ext
1101=org.infinispan.server.memcached.MemcachedValue$Externalizer@720bffd,
1104=org.infinispan.server.hotrod.ServerAddress$Externalizer@771c7eb2},
marshaller=org.infinispan.marshall.VersionAwareMarshaller@6fc21535, version=52,
classResolver=org.jboss.marshalling.ModularClassResolver@2efe83e5},
shutdown=ShutdownConfiguration{hookBehavior=DONT_REGISTER}, modules={},
site=SiteConfiguration{localSite='null'}}
locate
The locate command shows the physical location of a specified entry in a distributed cluster.
[jmx://localhost:12000/MyCacheManager/namedCache]> locate a
[host/node1,host/node2]
Infinispan 6.0
put
The put command inserts an entry in the cache. If the cache previously contained a mapping for the key, the
old value is replaced by the specified value. The user can control the type of data that the CLI will use to
store the key and value. See the Data Types paragraph.
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
null, "b": true } }
put
put
put
put
put
a
b
c
d
e
a
100
4139l
true
{ "package.MyClass": {"i": 5, "x":
The put command can optionally specify a lifespan and a maximum idle time.
replace
The replace command replaces an existing entry in the cache. If an old value is specified, then the
replacement happens only if the value in the cache coincides.
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
b
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
c
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
c
put a a
replace a b
get a
replace a b c
get a
replace a b d
get a
rollback
The rollback command rolls back an ongoing transaction
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
begin
put a a
put b b
rollback
Infinispan 6.0
site
The site command performs operations related to the administration of cross-site replication. It can be used
to obtain information related to the status of a site and to change the status (online/offline)
[jmx://localhost:12000/MyCacheManager/namedCache]>
online
[jmx://localhost:12000/MyCacheManager/namedCache]>
ok
[jmx://localhost:12000/MyCacheManager/namedCache]>
offline
[jmx://localhost:12000/MyCacheManager/namedCache]>
start
The start command initiates a batch of operations.
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
[jmx://localhost:12000/MyCacheManager/namedCache]>
start
put a a
put b b
end
stats
The stats command displays statistics about a cache
[jmx://localhost:12000/MyCacheManager/namedCache]> stats
Statistics: {
averageWriteTime: 143
evictions: 10
misses: 5
hitRatio: 1.0
readWriteRatio: 10.0
removeMisses: 0
timeSinceReset: 2123
statisticsEnabled: true
stores: 100
elapsedTime: 93
averageReadTime: 14
removeHits: 0
numberOfEntries: 100
hits: 1000
}
LockManager: {
concurrencyLevel: 1000
numberOfLocksAvailable: 0
numberOfLocksHeld: 0
}
Infinispan 6.0
upgrade
The ugrade command performs operations used during the rolling upgrade procedure. For a detailed
description of this procedure please see Rolling upgrades
version
The version command displays version information about both the CLI client and the server
[jmx://localhost:12000/MyCacheManager/namedCache]> version
Client Version 5.2.1.Final
Server Version 5.2.1.Final
Infinispan 6.0
3.67.1 Introduction
The Total Order based protocol is a multi-master scheme (in this context, multi-master scheme means that
all nodes can update all the data) as the (optimistic/pessimist) locking model implemented in Infinispan. This
commit protocol relies on the concept of totally ordered delivery of messages which, informally, implies that
each node which delivers a set of messages, delivers them in the same order.
This protocol comes with this advantages.
1. transactions can be committed in one phase, as they are delivered in the same order by the nodes
that receive them.
2. it mitigates distributed deadlocks.
The weaknesses of this approach are the fact that its implementation relies on a single thread per node
which delivers the transaction and its modification, and the slightly higher number of messages exchanged
by JGroups.
Thus, this protocol delivers best performance in scenarios of high contention, in which it can benefit from
the single-phase commit and the deliver thread is not the bottleneck.
Currently, the Total Order based protocol is available only in transactional caches for replicated and
distributed modes.
Infinispan 6.0
3.67.2 Overview
The Total Order based commit protocol only affects how transactions are committed and it depends of the
isolation level configured, more precisely the write skew check. Note that it only provides the same
isolation levels as the locking model, i.e. read-committed and repeatable-read. If the write skew check is
not enabled, then all the transaction are committed in one phase (independently if Infinispan is enlisted as
Synchronization or XaResource). In this case, the isolation level is not violated because it is ensured during
the transaction execution. Also the transactions always commit successfully because they do not need to
perform any validation in prepare phase.
On other hand, when write skew check is enabled, the protocol adapts using one phase commit when it is
safe. However, if Infinispan is enlisted as Synchronization, it always commit in two phases, because the
Transaction Manager does not provide any information if Infinispan is the only resource enlisted or not. In
XaResource enlistment, we can use one phase if the Transaction Manager request a commit in one phase
(i.e. one-phase optimization, usually used when the transaction has a single XaResource registered, see
XaResource.commit()) and the Infinispan cache is configured in replicated mode or in distributed mode (the
last one, when the writeSkew==false). This optimization is not safe in distributed mode when
writeSkew==true because each node performs the validation in different keys subset.
Infinispan 6.0
The figure above demonstrates a high level example with 3 nodes. Node1 and Node3 are running one
transaction each and lets assume that both transaction writes on the same key. To make it more interesting,
lets assume that both nodes tries to commit at the same time, represented by the first colored circle in the
figure. The blue circle represents the transaction tx1 and the green the transaction tx2. Both nodes do a
remote invocation in total order (to-send) with the transaction's modifications. At this moment, all the nodes
will agree in the same deliver order, for example, tx1 followed by tx2. Then, each node delivers tx1, perform
the validation and commits the modifications. The same steps are performed for tx2 but, in this case, the
validation will fail and the transaction is rollback in all the involved nodes.
Infinispan 6.0
The figure above shows the scenario described in the first figure but now committing the transactions using
two phases. When tx1 is deliver, it performs the validation and it replies to the Transaction Manager. Next,
lets assume that tx2 is deliver before the Transaction Manager request the second phase for tx1. In this
case, tx2 will be enqueued and it will be validated only when tx1 is completed. Eventually, the Transaction
Manager for tx1 will request the second phase (the commit) and all the nodes are free to perform the
validation of tx2.
Transaction Recovery
Transaction Recovery is currently not available for Total Order based commit protocol
Infinispan 6.0
Warning
The total order executor service needs an ExecutorService (see the Configuration section). Please
make sure that the ExecutorService does not reject tasks otherwise your data becomes
inconsistent.
Infinispan 6.0
State Transfer
For simplicity reasons, the total order based commit protocol uses a blocking version of the current state
transfer. The main differences are:
1. enqueue the transaction deliver while the state transfer is in progress;
2. the state transfer control messages (CacheTopologyControlCommand) are sent in total order.
This way, it provides a synchronization between the state transfer and the transactions deliver that is the
same all the nodes. Although, the transactions caught in the middle of state transfer (i.e. sent before the
state transfer start and deliver after it) needs to be re-sent to find a new total order involving the new joiners.
The figure above describes a node joining. In the scenario, the tx2 is sent in topologyId=1 but when it is
received, it is in topologyId=2. So, the transaction is re-sent involving the new nodes.
3.67.3 Configuration
To use Total Order based commit protocol in your Infinispan cache, you need to configure a couple of thing:
add the total order protocols in JGroups configuration file:
Infinispan 6.0
<SEQUENCER />
<tom.TOA />
Check the JGroups manual for more detail in here: JGroups Manual
configure the Infinispan cache as a transactional cache and set the transaction protocol to total order:
<namedCache >
<transaction
transactionMode="TRANSACTIONAL"
transactionProtocol="TOTAL_ORDER" />
</namedCache>
You can build the same configuration programmatically in the following way:
Optionally, you can configure the total order executor to use your own executor services. By default, it
creates an executor service with coreThreads=1 and maxThreads=32. It can be configured in the following
way:
<global>
<totalOrderExecutor factory="org.infinispan.executor.DefaultExecutorFactory>
<property name="coreThreads" value="1" />
<property name="maxThreads" value="32" />
</totalOrderExecutor>
</global>
or programmaticaly:
Beside the coreThreads and the maxThreads, the DefaultExecutorFactory also accepts as properties as the
queueSize, keepAliveTime (in milliseconds), threadPriority, threadNamePrefix and threadNameSuffix. Note
that, this parameters are used by the ExecutorService. The total order executor uses an unbouded queue.
Also, when you provide an ExecutorService, make sure that it will no reject tasks, otherwise your data can
became inconsistent.
Infinispan 6.0
The figure above shows the the communication steps to total order broadcast two messages M1 and M2
from different senders. Below, the figure shows the communication steps needed to commit a single
transaction, when two phase are used. The dotted line represents the communications steps performed by
the SEQUENCER. As it is possible to see, ensure total order is not a cheap operation and it has a cost of an
extra communication step comparing with the lock based implementation.
Infinispan 6.0
More information about the SEQUENCER in JGroups manual: SEQUENCER - JGroups Manual page
Infinispan 6.0
The next figure show one transaction to be committed in detail, including all the communication steps. The
dotted line represents the messages exchanged by TOA and the solid lines a single unicast message. This
figure shows that the total order protocol has 2 more communications steps than the lock based
implementation.
Infinispan 6.0
More information about the Total Order Anycast in JGroups manual: TOA - JGroups Manual page
Infinispan 6.0
Infinispan 6.0
...
<benchmark initSize="2" maxSize="${10:slaves}" increment="2">
<DestroyWrapper runOnAllSlaves="true"/>
<StartCluster staggerSlaveStartup="true" delayAfterFirstSlaveStarts="5000"
delayBetweenStartingSlaves="500"/>
<ClusterValidation partialReplication="false"/>
<StressTestWarmup duration="1m" opsCountStatusLog="5000" numThreads="8"
transactionSize="10"
useTransactions="true" writePercentage="50" numEntries="1000"
sharedKeys="false"/>
<StressTest duration="5m" opsCountStatusLog="5000" numThreads="8" transactionSize="10"
useTransactions="true" writePercentage="50" numEntries="1000"
sharedKeys="false"/>
<CsvReportGeneration targetDir="no_contention"/>
<ClearCluster/>
<StressTestWarmup duration="1m" opsCountStatusLog="5000" numThreads="8"
transactionSize="10"
useTransactions="true" writePercentage="50" numEntries="1000"
sharedKeys="true"/>
<StressTest duration="5m" opsCountStatusLog="5000" numThreads="8" transactionSize="10"
useTransactions="true" writePercentage="50" numEntries="1000"
sharedKeys="true"/>
<CsvReportGeneration targetDir="contention"/>
</benchmark>
...
The difference between the contention and no contention is the pool of key. In the first case the pool of keys
are shared among all the threads (and nodes) and in the last case each threads has it own private pool of
keys.
The first group of plots shows the performance in the contented scenario:
Infinispan 6.0
Infinispan 6.0
At the time of writing, Infinispan 6.0.0.Alpha4 implements version 0.8 of the JCache specification.
3.68.1 Dependencies
In order to start using Infinispan JCache implementation, a single dependency needs to be added to the
Maven pom.xml file:
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-jcache</artifactId>
<version>...</version> <!-- i.e. 6.0.0.Alpha4 -->
<scope>test</scope>
</dependency>
Infinispan 6.0
import
import
import
import
javax.cache.Cache;
javax.cache.CacheManager;
javax.cache.Caching;
javax.cache.configuration.MutableConfiguration;
By default, the JCache API specifies that data should be stored as storeByValue, so that object
state mutations outside of operations to the cache, won't have an impact in the objects stored in the
cache. Infinispan has so far implemented this using serialization/marshalling to make copies to
store in the cache, and that way adhere to the spec. Hence, if using default JCache configuration
with Infinispan, data stored must be marshallable. Instructions on how to make data stored in
Infinispan marshallable can be found here.
Alternatively, JCache can be configured to store data by reference (just like Infinispan or JDK Collections
work). To do that, simply call:
Infinispan 6.0
import
import
import
import
javax.cache.Cache;
javax.cache.CacheManager;
javax.cache.Caching;
javax.cache.configuration.MutableConfiguration;
Contrary to standard java.util.Map, javax.cache.Cache comes with two basic put methods called
put and getAndPut. The former returns void whereas the latter returns the previous value associated with
the key. So, the equivalent of java.util.Map.put(K) in JCache is
javax.cache.Cache.getAndPut(K).
Even though JCache API only convers standalone caching, it can be plugged with a persistence
store, and has been designed with clustering or distribution in mind. The reason why
javax.cache.Cache offers two put methods is because standard java.util.Map put call
forces implementors to calculate the previous value. When a persistent store is in use, or the cache
is distributed, returning the previous value could be an expensive operation, and often users call
standard java.util.Map.put(K) without using the return value. Hence, JCache users need to
think about whether the return value is relevant to them, in which case they need to call
javax.cache.Cache.getAndPut(K), otherwise they can call javax.cache.Cache.put(K)
which avoids returning the potentially expensive operation of returning the previous value.
Infinispan 6.0
Operation
V getAndPut(K key)
boolean putIfAbsent(K
previous value
store if not present
key, V value)
retrieve
V get(Object key)
V get(K key)
delete if present
V remove(Object key)
V remove(Object key)
V getAndRemove(K key)
value)
oldValue)
previous value
delete conditional
replace if present
V value)
replace and return
previous value
replace conditional
V getAndReplace(K key,
V value)
newValue)
V oldValue, V newValue)
Comparing the two APIs, it's obvious to see that where possible JCache avoids returning the previous value
to avoid operations doing expensive network or IO operations. This is an overriding principle in the design of
JCache API. In fact, there's a set of operations that are present in
java.util.concurrent.ConcurrentMap, but are not present in the javax.cache.Cache because
they could be expensive to compute in a distributed cache. The only exception is iterating over the contents
of the cache:
Infinispan 6.0
Operation
calculate size of
int size()
cache
return all keys in the
Set<K> keySet()
cache
return all values in
Collection<V> values()
the cache
return all entries in
the cache
iterate over the cache use iterator() method on keySet, values or
entrySet
Iterator<Cache.Entry<K,
V>> iterator()
Infinispan 6.0
import
import
import
import
javax.cache.Cache;
javax.cache.CacheManager;
javax.cache.Caching;
java.net.URI;
// For multiple cache managers to be constructed with the standard JCache API and live in the
same JVM, either their names, or their classloaders, must be different.
// This example shows how to force their classloaders to be different. An alternative method
would have been to duplicate the XML file and give it a different name,
// but this results in unnecessary file duplication.
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
CacheManager cacheManager1 =
Caching.getCachingProvider().getCacheManager(URI.create("infinispan-jcache-cluster.xml"), new
TestClassLoader(tccl));
CacheManager cacheManager2 =
Caching.getCachingProvider().getCacheManager(URI.create("infinispan-jcache-cluster.xml"), new
TestClassLoader(tccl));
Cache<String, String> cache1 = cacheManager1.getCache("namedCache");
Cache<String, String> cache2 = cacheManager2.getCache("namedCache");
cache1.put("hello", "world");
String value = cache2.get("hello"); // Returns "world" if clustering is working
// -public static class TestClassLoader extends ClassLoader {
public TestClassLoader(ClassLoader parent) {
super(parent);
}
}
If using custom objects, make sure they are serializable/marshallable as per the instructions here.
3.68.7 Annotations
TODO
Infinispan 6.0
3.68.10 Quickstarts
TODO
3.69.2 Protocols
Hot Rod
Hot Rod is Infinispan's own topology-aware high-performance remote protocol. See Hot Rod
Memcached
Memcached is a very popular caching server with its own protocol. See Memcached
Rest
Rest uses HTTP methods to perform operations on a cache. See Accessing data in Infinispan via RESTful
interface
WebSocket
The WebSocket protocol is a technology used to provide persistent bidirectional communication between
(but not limited to) a web browser and a server. See WebSocket Server
Infinispan 6.0
3.69.4 CLI
The Infinispan CLI can be used to connect to the server. You need to use the remoting protocol and connect
to port 9999. By default the CLI will use the special silent SASL authenticator, which won't require a
username/password:
bin/ispn-cli.sh
[disconnected//]> connect localhost
[remoting://localhost:9999/local/]> cache default
[remoting://localhost:9999/local/default]> encoding hotrod
[remoting://localhost:9999/local/default]> put a a
[remoting://localhost:9999/local/default]> get a
a
Infinispan 6.0
3.69.5 Configuration
Since the server is based on the JBoss AS 7.2 codebase, it must configured be using the AS configuration
schema, apart from the JGroups, Infinispan and Endpoint subsytems.
<subsystem xmlns="urn:jboss:domain:jgroups:1.2"
default-stack="${jboss.default.jgroups.stack:udp}">
...
</subsystem>
Within the subsystem, you need to declare the stacks that you wish to use and name them. The
default-stack attribute in the subsystem declaration must point to one of the declared stacks. You can switch
stacks from the command-line using the jboss.default.jgroups.stack property:
bin/clustered.sh -Djboss.default.jgroups.stack=tcp
A stack declaration is composed of a transport (UDP or TCP) followed by a list of protocols. For each of
these elements you can tune specific properties adding child <property
name="prop_name">prop_value</property> elements. Since the amount of protocols and their
configuration options in JGroups is huge, please refer to the appropriate JGroups Protocol documentation.
The following are the default stacks:
Infinispan 6.0
<stack name="udp">
<transport type="UDP" socket-binding="jgroups-udp"/>
<protocol type="PING"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
<protocol type="FD_ALL"/>
<protocol type="pbcast.NAKACK"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<protocol type="MPING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK">
<property name="use_mcast_xmit">false</property>
</protocol>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
The default TCP stack uses the MPING protocol for discovery, which uses UDP multicast. If you need to use
a different protocol, look at the JGroups Discovery Protocols. The following example stack configures the
TCPPING discovery protocol with two initial hosts:
Infinispan 6.0
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<protocol type="TCPPING">
<property name="initial_hosts">HostA[7800],HostB[7800]</property>
</protocol>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK">
<property name="use_mcast_xmit">false</property>
</protocol>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
Infinispan 6.0
Containers
One major difference between the Infinispan library schema and the server schema is that in the latter
multiple containers can be declared. A container is declared as follows:
Another difference is the lack of an implicit default cache, but the ability to specify a named cache as the
default.
If you need to declare clustered caches (distributed, replicated, invalidation), you also need to specify the
<transport/> element which references an existing JGroups transport. This is not needed if you only
intend to have local caches only.
Caches
Now you can declare your caches. Please be aware that only the caches declared in the configuration will be
available to the endpoints and that attempting to access an undefined cache is an illegal operation. Contrast
this with the default Infinispan library behaviour where obtaining an undefined cache will implicitly create one
using the default settings. The following are example declarations for all four available types of caches:
Infinispan 6.0
Expiration
To define a default expiration for entries in a cache, add the <expiration/> element as follows:
Eviction
To define an eviction strategy for a cache, add the <eviction/> element as follows:
Infinispan 6.0
Locking
To define the locking configuration for a cache, add the <locking/> element as follows:
Transactions
While it is possible to configure server caches to be transactional, none of the available protocols offer
transaction capabilities.
<subsystem xmlns="urn:infinispan:server:endpoint:5.3">
...
</subsystem>
Infinispan 6.0
HotRod
The following connector declaration enables a HotRod server using the hotrod socket binding (declared
within a <socket-binding-group /> element) and exposing the caches declared in the local container, using
defaults for all other settings.
The connector will create a supporting topology cache with default settings. If you wish to tune these settings
add the <topology-state-transfer /> child element to the connector as follows:
The HotRod connector can be further tuned with additional settings such as concurrency and buffering. See
the protocol connector settings paragraph for additional details
Furthermore the HotRod connector can be secured using SSL. First you need to declare an SSL server
identity within a security realm in the management section of the configuration file. The SSL server identity
should specify the path to a keystore and its secret. Refer to the AS7.2 documentation on this. Next add the
<security /> element to the HotRod connector as follows:
Memcached
The following connector declaration enables a Memcached server using the memcached socket binding
(declared within a <socket-binding-group /> element) and exposing the memcachedCache cache declared
in the local container, using defaults for all other settings. Because of limitations in the Memcached protocol,
only one cache can be exposed by a connector. If you wish to expose more than one cache, declare
additional memcached-connectors on different socket-bindings.
WebSocket
<websocket-connector socket-binding="websocket" cache-container="local"/>
Infinispan 6.0
REST
The REST connector differs from the above connectors because it piggybacks on the web subsystem.
Therefore configurations such as socket binding, worker threads, timeouts, etc must be performed on the
web subsystem.
Protocol Interoperability
By default each protocol stores data in the cache in the most efficient format for that protocol, so that no
transformations are required when retrieving entries. If instead you need to access the same data from
multiple protocols, you should enable compatibility mode on the caches that you want to share. This is done
by adding the <compatibility /> element to a cache definition, as follows:
Infinispan 6.0
Introduction
Starting with version 4.1, Infinispan distribution contains a server module that implements Infinispan's
custom binary protocol called Hot Rod. The protocol was designed to enable faster client/server interactions
compared to other existing text based protocols and to allow clients to make more intelligent decisions with
regards to load balancing, failover and even data location operations.
Introduction
As of Infinispan 5.3, the supported way to start an Infinispan Memcached server is via the Infinispan Server.
This page details differences between the original Memcached server functionality and the Infinispan
implementation
Infinispan 6.0
Command Clarifications
Flush All
Even in a clustered environment, flush_all command leads to the clearing of the Infinispan Memcached
server where the call lands. There's no attempt to propagate this flush to other nodes in the cluster. This is
done so that flush_all with delay use case can be reproduced with the Infinispan Memcached server.
The aim of passing a delay to flush_all is so that different Memcached servers in a full can be flushed at
different times, and hence avoid overloading the database with requests as a result of all Memcached
servers being empty. For more info, check the Memcached text protocol section on flush_all.
Infinispan 6.0
Unsupported Features
This section explains those parts of the memcached text protocol that for one reason or the other, are not
currently supported by the Infinispan based memcached implementation.
Individual Stats
Due to difference in nature between the original memcached implementation which is C/C++ based and the
Infinispan implementation which is Java based, there're some general purpose stats that are not supported.
For these unsupported stats, Infinispan memcached server always returns 0.
Here's the list of currently unsupported stats:
pid
pointer_size
rusage_user
rusage_system
bytes
curr_connections
total_connections
connection_structures
auth_cmds
auth_errors
limit_maxbytes
threads
conn_yields
reclaimed
Statistic Settings
The settings statistics section of the text protocol has not been implemented due to its volatility.
Verbosity Command
Verbosity command is not supported since Infinispan logging cannot be simplified to defining the logging
level alone.
Infinispan 6.0
Javascript API
Writing a web page that uses the Infinispan Cache API is trivial. The page simply needs to include a
<script> declaration for the infinispan-ws.js Javascript source file. This script is served up by
WebSocket Server.
So, for loading infinispan-ws.js from a WebSocket Server instance running on www.acme.com:8181
(default port):
Infinispan 6.0
<script type="text/javascript">
var cache = new Cache();
// etc...
</script>
By default, the Cache instance will interface to the default Infinispan Cache associated with the WebSocket
Server from which the infinispan-ws.js Javascript source file was loaded. So, in the above case, the
Cache object instance will connect to the WebSocket Server running on www.acme.com:8181 (i.e.
ws://www.acme.com:8181).
The Infinispan Cache name and WebSocket Server address can be specified in the {{Cache} object
constructor as follows:
Infinispan 6.0
Cache Operations
A number of cache operations can be performed via the Cache object instance such as get, put, remove,
notify and unnotify.
The get and notify operations require a callback function to be registered with the Cache object
instance. This callback function receives all add/update/remove notifications on any cache entries for which
the notify function was invoked. It also asynchronously receives the result of a single invocation of the
get function i.e. get can be thought of as "notify once, immediately".
The callback function is registered with the Cache object instance via the registerCallback function.
The function should have 2 parameters - key and value, relating to the cache key and value.
Getting and updating data in the cache is done by simply calling the get, put and remove functions on the
Cache object instance. These operations could be triggered by user interaction with a web form e.g.
Sample code
Infinispan's source tree contains a sample HTML document that makes use of the WebSocket server.
Browse through the source of this HTML document here.
Infinispan 6.0
Browser Support
At the time of writing, Google Chrome was the only browser with native WebSocket support. However, the
jWebSocket project provides a client side Javascript library that adds WebSocket support to any Flash
enabled browser.
Screencast
See the following demo of the Infinispan WebSocket Server in action.
Status
Prototype/Alpha.
Source
Browse Infinispan's Git repository.
Infinispan 6.0
The problem with these classes is that they result in extra memory consumption due to the extra objects
required to support data types such as arrays and really, these classes just a workaround for the lack of
ability to provide a way to pass in a function that specifies how two byte arrays are are compared, or how to
calculate the hash code of a given array.
Infinispan 6.0
Infinispan 6.0
* Compares the two given objects for order. Returns a negative integer,
* zero, or a positive integer as the first object is less than, equal to,
* or greater than the second object.
*
* @param obj first object to be compared
* @param otherObj second object to be compared
* @return a negative integer, zero, or a positive integer as the
*
first object is less than, equal to, or greater than the
*
second object
*/
int compare(Object obj, Object otherObj); // For future support for objects that are not
comparable, i.e. arrays
}
Implementations of these function can be pretty flexible. On one side, they could focus on a single, particular
type, such as ByteArrayEquivalence below which expects nothing else other than byte arrays, such as
in the case of Hot Rod based Infinispan remote caches:
package com.acme;
public class ByteArrayEquivalence implements Equivalence<byte[]> {
public static final Equivalence<byte[]> INSTANCE = new ByteArrayEquivalence();
@Override
public int hashCode(Object obj) {
return 41 + Arrays.hashCode((byte[]) obj);
}
@Override
public boolean equals(byte[] obj, Object otherObj) {
if (obj == otherObj) return true;
if (obj == null) return false;
if (otherObj == null || byte[].class != otherObj.getClass()) return false;
byte[] otherByteArray = (byte[]) otherObj;
return Arrays.equals(obj, otherByteArray);
}
@Override
public String toString(Object obj) {
return Arrays.toString((byte[]) obj);
}
@Override
public boolean isComparable(Object obj) {
return false;
}
@Override
public int compare(Object obj, Object otherObj) {
return 0; // irrelevant
}
}
Infinispan 6.0
Or you could have implementations that support multiple different types, in case you store varied
information, for example AnyServerEquivalence which supports both arrays and normal objects:
Infinispan 6.0
If you were trying to store both byte arrays as keys and values, you'd configure valueEquivalence
attribute in <dataContainer> XML element:
<dataContainer keyEquivalence="com.acme.ByteArrayEquivalence"
valueEquivalence="com.acme.ByteArrayEquivalence" />
Infinispan 6.0
<namedCache...>
<compatibility enabled="true"/>
</namedCache>
Or programmatically:
Infinispan 6.0
The key thing to remember about Infinispan's compatibility mode is that where possible, it tries to store data
unmarshalling or deserializing it. It does so because the most common use case is for it to store Java
objects and having Java objects stored in deserialized form means that they're very easy to use from an
embedded cache. With this in mind, it makes some assumptions. For example, if something it's stored via
Hot Rod, it's most likely coming from the reference Hot Rod client, which is written in Java, and which uses a
marshaller that keeps binary payloads very compact. So, when the Hot Rod operation reaches the
compatibility layer, it will try to unmarshall it, by default using the same default marshaller used by the Java
Hot Rod client, hence providing good out-of-the-box support for the majority of cases.
<namedCache...>
<compatibility enabled="true" marshallerClass="com.acme.CustomMarshaller"/>
</namedCache>
Or programmatically:
One concrete example of this marshaller logic can be found in the SpyMemcachedCompatibleMarshaller.
Spy Memcached uses their own transcoders in order to marshall objects, so the compatibility marshaller
created is in charge of marshalling/unmarshalling data stored via Spy Memcached client. If you want to
retrieve data stored via Spy Memcached via say Hot Rod, you can configure the Java Hot Rod client to use
this same marshaller, and this is precisely what the test where the Spy Memcached marshaller is located is
demonstrating.
Infinispan 6.0
3.72.2 Jetty
Jetty can be set up to use Infinispan for HTTP session management, using this adapter.
Infinispan 6.0
Infinispan 6.0
3.73.1 Overview
Infinispan will offer three forms of data versioning, including simple, partition aware and external. Each case
is described in detail below.
Simple versioning
The purpose of simple versioning is to provide a reliable mechanism of write skew checks when using
optimistic transactions, REPEATABLE_READ and a clustered cache. Write skew checks are performed at
prepare-time to ensure a concurrent transaction hasn't modified an entry while it was read and potentially
updated based on the value read.
When operating in LOCAL mode, write skew checks rely on Java object references to compare differences
and this is adequate to provide a reliable write-skew check, however this technique is useless in a cluster
and a more reliable form of versioning is necessary to provide reliable write skew checks.
Simple versioning is an implementation of the proposed EntryVersion interface, backed by a long that is
incremented each time the entry is updated.
Partition-aware versioning
This versioning scheme makes use of vector clocks to provide a network partition resilient form of
versioning.
Unlike simple versioning, which is maintained per entry, a vector clock's node counter is maintained
per-node.
External versioning
This scheme is used to encapsulate an external source of data versioning within Infinispan, such as when
using Infinispan with Hibernate which in turn gets it's data version information directly from a database.
In this scheme, a mechanism to pass in the version becomes necessary, and overloaded versions of put()
and putForExternalRead() will be provided in AdvancedCache to take in an external data version. This
is then stored on the InvocationContext and applied to the entry at commit time.
Write skew checks cannot and will not be performed in the case of external data versioning.
Tombstones
To deal with deletions of entries, tombstones will be maintained as null entries that have been deleted, so
that version information of the deleted entry can be maintained and write skews can still be detected.
However this is an expensive thing to do, and as such, is a configuration option, disabled by default. Further,
tombstones will follow a strict lifespan and will be cleared from the system after a specific amount of time.
Infinispan 6.0
3.73.2 Configuration
By default versioning will be disabled. This will mean write skew checks when using transactions and
REPEATABLE_READ as an isolation level will be unreliable when used in a cluster. Note that this doesn't
affect single-node, LOCAL mode usage.
Via XML
<versioning enabled="false" type="SIMPLE|PARTITION_AWARE|EXTERNAL" useTombstones="false"
tombstoneLifespan="60000"/>
Infinispan 6.0
If you are using Maven to generate your artifacts, mark the Infinispan dependencies as provided and
configure your artifact archiver to generate the appropriate MANIFEST.MF file:
pom.xml
<dependencies>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<version>5.2.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-cachestore-jdbc</artifactId>
<version>5.2.0.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>org.infinispan:5.2 services, org.infinispan.cachestore.jdbc:5.2
services</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Infinispan 6.0
Introduction
The Infinispan tutorial makes use of Groovy to get a more interactive experience when starting to learn about
how to use the Infinispan API. So you will need to install a few prerequisites before getting started:
The Groovy Platform, I used Groovy 1.6.3
Java and Infinispan
Download those and extract/install where you feel appropriate, depending on your operating system and
personal preferences you will either have installers or compressed distributions. You can read more about
read installing Java and Infinispan in Installing Infinispan for the tutorials.
Infinispan 6.0
Installing Groovy
You can use the installer or compressed file to install the Groovy Platform, I used the compressed file and
decompressed at C:\Program Files\groovy\groovy-1.6.3. Once you have installed the Groovy Platform you
should set some environment variables:
GROOVY_HOME=C:\Program Files\groovy\groovy-1.6.3
PATH=%PATH%;%GROOVY_HOME%\bin
test that everything is correct by executing in a Command Shell/Terminal the commands shown:
$> groovy -v
Groovy Version: 1.6.3 JVM: 1.6.0_14
Installing Infinispan
Now you should add the Infinispan libraries to the Groovy Platform so you will able to access the API from
the Groovy console. Add the infinispan-core.jar and its dependencies to the $USER_HOME/.groovy/lib
directory, the jar is located in $INFINISPAN_HOME/modules/core and the dependencies at
$INIFINISPAN_HOME/modules/core/lib.
For example, on Windows, you need to copy it to:
or on Linux:
/home/amontenegro/.groovy/lib
Infinispan 6.0
or, on Linux:
CLASSPATH=$CLASSPATH:/home/amontenegro/.groovy/cp
Infinispan 6.0
It's time to start typing some commands, first start by importing the necessary libraries
And now, create a cache manager indicating the file with the cache definitions.
the cache manager has now the knowledge of all the named caches defined in the configuration file and also
has a no named cache that's used by default. You can now access any of the cache's by interacting with the
cache manager as shown.
<namedCache name="Local"/>
Infinispan 6.0
That's all you have to add to the configuration file to have a simple named cache, now its time to interact
with the cache by using the Infinispan API. Lets start by getting the named cache and put some objects
inside it.
So you have seen the basic of the Infinispan API, adding, getting and removing from the cache, there is
more, but don't forget that you are working with a cache that are an extension of java.util.ConcurrentHasMap
and the rest of the API is as simple as the one shown above, many of the cool things in Infinispan are totally
transparent (that's actually the coolest thing about Infinispan) and depends only on the configuration of your
cache.
If you check the Infinispan JavaDoc you will see that the Cache#put() method has been overridden several
times.
Infinispan 6.0
The Infinispan API also allows you to manage the life cycle of the cache, you can stop and start a cache but
by default you will loose the content of the cache except if you configure a cache store, more about that later
in the tutorial. lets check what happens when you restart the cache
groovy:000> localCache.size()
===> 1
//RESTARTING CACHE
groovy:000> localCache.stop()
===> null
groovy:000> localCache.start()
===> null
//DAMN! LOST THE CONTENT OF THE CACHE
groovy:000> localCache.size()
===> 0
Thats all related to the use of the Infinispan API, now lets check some different behaviors depending on the
configuration of the cache.
Infinispan 6.0
Each use different methods to lookup the transaction manager, depending on the environment you are
running Infinispan you should figure out which one to use. Check the JavaDoc for more details.
For the tutorial its enough to use:
<namedCache name="LocalTX">
<transaction
transactionManagerLookupClass="org.infinispan.transaction.lookup.DummyTransactionManagerLookup"/></namedCache>
Lets check how to interact with the Transaction Manager and to have the control over a transaction
As shown in the example, the transaction is controlled explicitly and the changes in the cache wont be
reflected until you make the commit.
Infinispan 6.0
<namedCache name="CacheStore">
<loaders passivation="false" shared="false" preload="true">
<loader class="org.infinispan.loaders.file.FileCacheStore" fetchPersistentState="true"
ignoreModifications="false" purgeOnStartup="false">
<properties>
<property name="location" value="/tmp"/>
</properties>
</loader>
</loaders>
</namedCache>
Now you have a cache with persistent store, lets try it to see how it works
Infinispan 6.0
Infinispan 6.0
<namedCache name="Eviction">
<eviction wakeUpInterval="500" maxEntries="2" strategy="FIFO"/>
</namedCache>
The strategy has been set to FIFO, so the oldest objects will be removed first and the maximum number of
objects are only 2, so it will be easy to show how it works
Now you are sure that your cache wont consume all your memory and hang your system, but its an
expensive price you have to pay for it, you are loosing objects in your cache. The good news is that you can
mix cache store with the eviction policy and avoid loosing objects.
Infinispan 6.0
<namedCache name="CacheStoreEviction">
<loaders passivation="false" shared="false" preload="true">
<loader class="org.infinispan.loaders.file.FileCacheStore" fetchPersistentState="true"
ignoreModifications="false" purgeOnStartup="false">
<properties>
<property name="location" value="/tmp"/>
</properties>
</loader>
</loaders>
<eviction wakeUpInterval="500" maxEntries="2" strategy="FIFO"/>
</namedCache>
Infinispan 6.0
3.76.2 Environment
Preparing the environment is almost similar to one described here, but with a minor difference that unlike
Groovy which uses ~/.groovy/lib folder to extend initial classpath, we will use classic CLASSPATH
environment variable with Scala. Another issue is that with the recent edition of Infinispan core jar file is in
the root folder of $INIFINISPAN_HOME, hence here a sample bash script to prepare CLASSPATH for our
demo:
export INFINISPAN_HOME=~/build/infinispan/infinispan-4.2.1.CR1
for j in $INFINISPAN_HOME/lib/*.jar; do CLASSPATH=$CLASSPATH:$j; done
export CLASSPATH=$CLASSPATH:$INFINISPAN_HOME/infinispan-core.jar
export CLASSPATH=$CLASSPATH:[Path to folder containing sample-configurations.xml file]
[z@dnb:~/Go/demos/interactive-infinispan-scala]% ./scala
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import org.infinispan._
import org.infinispan._
scala> println(Version.version)
4.2.1.CR1
Infinispan 6.0
In this next example, a named cache is retrieved, again with keys and values expected to be String:
Infinispan 6.0
Infinispan 6.0
scala> localCache.size()
res13: Int = 1
scala> localCache.stop()
scala> localCache.start()
scala> localCache.size()
res16: Int = 0
Infinispan 6.0
Infinispan 6.0
Note how this example shows a very interesting characteristic of the Scala console. Every operation's return
value is stored in a temporary variable which can be referenced at a later stage, even if the user forgets to
assign the result of a operation when the code was executed.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
4 Upgrade Guide
4.1 Upgrading from 5.0 to 5.1
Please find below tips and recommendations when upgrading from Infinispan 5.0 to 5.1:
API
Eviction and Expiration
Transactions
State transfer
Configuration
Flags and ClassLoaders
JGroups Bind Address
Infinispan 6.0
4.1.1 API
1. The cache and cache manager hierarchies have changed slightly in 5.1 with the introduction of
BasicCache and BasicCacheContainer, which are parent classes of existing Cache and
CacheContainer classes respectively. What's important is that Hot Rod clients must now code
against BasicCache and BasicCacheContainer rather than Cache and CacheContainer. So
previous code that was written like this will no longer compile.
import org.infinispan.Cache;
import org.infinispan.manager.CacheContainer;
import org.infinispan.client.hotrod.RemoteCacheManager;
...
CacheContainer cacheContainer = new RemoteCacheManager();
Cache cache = cacheContainer.getCache();
Instead, if Hot Rod clients want to continue using interfaces higher up the hierarchy from the remote
cache/container classes, they'll have to write:
import org.infinispan.BasicCache;
import org.infinispan.manager.BasicCacheContainer;
import org.infinispan.client.hotrod.RemoteCacheManager;
...
BasicCacheContainer cacheContainer = new RemoteCacheManager();
BasicCache cache = cacheContainer.getCache();
Previous code that interacted against the RemoteCache and RemoteCacheManager should work as it used
to:
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
...
RemoteCacheManager cacheContainer = new RemoteCacheManager();
RemoteCache cache = cacheContainer.getCache();
Infinispan 6.0
2. Eviction's maxEntries is used as guide for the entire cache, but eviction happens on a per cache
segment, so when the segment is full, the segment is evicted. That's why maxEntries is a
theoretical limit but in practical terms, it'll be a bit less than that. This is done for performance reasons.
4.1.3 Transactions
1. A cache marked as TRANSACTIONAL cannot be accessed outside of a transaction, and a
NON_TRANSACTIONAL cache cannot be accessed within a transaction. In 5.0, a transactional cache
would support non-transactional calls as well. This change was done to be in-line with expectations
set out in JSR-107 as well as to provide more consistent behavior.
2. In 5.0, commit and rollback phases were asynchronous by default. Starting with 5.1, these are now
synchronous by default, to provide the guarantees required by a single lock-owner model.
4.1.5 Configuration
If you use XML to configure Infinispan, you shouldn't notice any change, except a much faster startup,
courtesy of the Stax based parser. However, if you use programmatic configuration, read on for the
important differences.
Configuration is now packaged in org.infinispan.configuration, and you must use a builder style:
Infinispan 6.0
The old bean style configuration is now deprecated and will be removed in a later version.
Configuration properties which can be safely changed at runtime are mutable, and all others are immutable.
To copy a configuration, use the read() method on the builder, for example:
This completely replaces the old system of defining a set of overrides on bean properties. Note that this
means the behaviour of Infinispan configuration is somewhat different when used programmatically. Whilst
before, you could define a default configuration, and any overrides would be applied on top of your defaults
when defined, now you must explicitly read in your defaults to the builder. This allows for much greater
flexibility in your code (you can have a as many "default" configurations as you want), and makes your code
more explicit and type safe (finding references works).
The schema is unchanged from before. Infinispan 4.0 configurations are currently not being parsed. To
upgrade, just change the schema definition from:
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:4.1
http://www.infinispan.org/schemas/infinispan-config-4.1.xsd"
xmlns="urn:infinispan:config:4.1">
to
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:5.1
http://www.infinispan.org/schemas/infinispan-config-5.1.xsd"
xmlns="urn:infinispan:config:5.1">
Infinispan 6.0
The schema documentation has changed format, as it is now produced using the standard tool xsddoc. This
should be a significant improvement, as better navigation is offered. Some elements and attributes are
missing docs right now, we are working on adding this. As an added benefit, your IDE should now show
documentation when an xsd referenced (as above)
We are in the process of adding in support for this configuration style for modules (such as cache stores). In
the meantime, please use the old configuration or XML if you require support for cache store module
configuration.
The above pattern has always been the intention of this API anyway.
Infinispan 6.0
The old bean style configuration is now deprecated and will be removed in a later version.
Configuration properties which can be safely changed at runtime are mutable, and all others are immutable.
To copy a configuration, use the read() method on the builder, for example:
This completely replaces the old system of defining a set of overrides on bean properties. Note that this
means the behaviour of Infinispan configuration is somewhat different when used programmatically. Whilst
before, you could define a default configuration, and any overrides would be applied on top of your defaults
when defined, now you must explicitly read in your defaults to the builder. This allows for much greater
flexibility in your code (you can have a as many "default" configurations as you want), and makes your code
more explicit and type safe (finding references works).
The schema is unchanged from before. Infinispan 4.0 configurations are currently not being parsed. To
upgrade, just change the schema definition from:
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:4.1
http://www.infinispan.org/schemas/infinispan-config-4.1.xsd"
xmlns="urn:infinispan:config:4.1">
to
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:5.1
http://www.infinispan.org/schemas/infinispan-config-5.1.xsd"
xmlns="urn:infinispan:config:5.1">
Infinispan 6.0
The schema documentation has changed format, as it is now produced using the standard tool xsddoc. This
should be a significant improvement, as better navigation is offered. Some elements and attributes are
missing docs right now, we are working on adding this. As an added benefit, your IDE should now show
documentation when an xsd referenced (as above)
We are in the process of adding in support for this configuration style for modules (such as cache stores). In
the meantime, please use the old configuration or XML if you require support for cache store module
configuration.
Infinispan 6.0
<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:5.2
http://www.infinispan.org/schemas/infinispan-config-5.2.xsd" xmlns="urn:infinispan:config:5.2">
...
</infinispan>
4.2.2 Transaction
The default transaction enlistment model has changed (ISPN-1284) from XAResounce to Synchronization
. Also now, if the XAResounce enlistment is used, then recovery is enabled by default.
In practical terms, if you were using the default values, this should not cause any backward compatibility
issues but an increase in performance of about 5-7%. However in order to use the old configuration defaults,
you need to configure the following:
<transaction useSynchronization="false">
<recovery enabled="false"/>
</transaction>
Infinispan 6.0
Infinispan 6.0
5 Glossary
5.1 Glossary
2-phase commit
Atomicity, Consistency, Isolation, Durability (ACID)
Basically Available, Soft-state, Eventually-consistent (BASE)
Cache Aside
Consistency, Availability and Partition-tolerance (CAP) Theorem
Consistent Hash
Data grid
Deadlock
Distributed Hash Table (DHT)
Externalizer
Hot Rod
In-memory data grid
Isolation level
JTA synchronization
Livelock
Memcached
Multiversion Concurrency Control (MVCC)
Near Cache
Network partition
NoSQL
Optimistic locking
Pessimistic locking
Read Ahead
READ COMMITTED
Relational Database Management System (RDBMS)
REPEATABLE READ
Representational State Transfer (REST)
Split brain
Structured Query Language (SQL)
Write-behind
Write skew
Write-through
XA resource
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
5.9 Deadlock
TODO
5.11 Externalizer
An Externalizer is a class that knows how to marshall a given object type to a byte array, and how to
unmarshall the contents of a byte array into an instance of the object type. Externalizers are effectively an
Infinispan extension that allows users to specify how their types are serialized. The underlying Infinispan
marshalling infrastructure builds on JBoss Marshalling, and offers efficient payloads and stream caching.
This provides much better performance than standard Java serialization.
Infinispan 6.0
Infinispan 6.0
5.16 Livelock
TODO
5.17 Memcached
Memcached is an in-memory caching system, often used to speed-up database-driven websites.
Memcached also defines a text based, client/server, caching protocol, known as the Memcached protocol.
Infinispan offers a server which speaks the Memcached protocol, allowing Memcached itself to be replaced
by Infinispan. Thanks to Infinispan's clustering capabilities, it can offer data failover capabilities not present in
original Memcached systems.
5.21 NoSQL
TODO
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
5.31 Write-behind
Write-behind is a cache store update mode. When this mode is used, updates to the cache are
asynchronously written to the cache store. Normally this means that updates to the cache store are not
performed in the client thread.
An alternative cache store update mode is Write-through.
5.33 Write-through
Write-through is a cache store update mode. When this mode is used, clients update a cache entry, e.g. via
a Cache.put() invocation, the call will not return until Infinispan has updated the underlying cache store.
Normally this means that updates to the cache store are done in the client thread.
An alternative mode in which cache stores can be updated is Write-behind.
5.34 XA resource
An XA resource is a participant in an XA transaction (also known as a distributed transaction). For example,
given a distributed transaction that operates over a database and Infinispan, XA defines both Infinispan and
the database as XA resources.
Java's API for XA transactions is JTA and XAResource is the java interface that describes an XA resource.
Infinispan 6.0
6 Extending Infinispan
Infinispan has a highly extensible architecture, making it easy to add extensions wherever needed. This
guide walks you through how to create extensions.
Target Audience
This guide is only for those who are looking to extend Infinispan beyond it's core use cases.
Infinispan 6.0
https://github.com/infinispan/infinispan/raw/master/query/src/main/resources/META-INF/services/org.infinispan.commands
status code: 404.
For a full, working example of a sample module that makes use of custom commands and visitors, check out
Infinispan Sample Module.
100 - 119
Infinispan 6.0
https://github.com/infinispan/infinispan/raw/master/query/src/main/resources/META-INF/services/org.infinispan.commands
status code: 404.
For a full, working example of a sample module that makes use of custom commands and visitors, check out
Infinispan Sample Module.
100 - 119
Infinispan 6.0
7 Contributing to Infinispan
AuthorsAnna Manukyan , Galder Zamarreo , Guillaume Scheibel , Kevin Pollet , Manik Surtani , Mircea
Markus , Navin Surtani , Pete Muir , Prabhat Jha , Radoslav Husar , Ray Tsang , Sanne Grinovero , Tristan
Tarrant
Target Audience
This guide shows you how to contribute to the Infinispan project. It contains useful information for
anyone from a casual contributors, wishing to submit a bug report, to full time developers.
The Basics
Pre-requisites
Issue Management - JIRA
Versioning Guidelines
Source control - Git
Setting up your IDE
Eclipse
Build - Maven
Continuous Integration - TeamCity
Testing - TestNG
Communicating with other Infinispan contributors
Style Requirements
Spelling
License header
Check-in comments
Configuration
Logging
Infinispan 6.0
Source Control
Pre-requisites
Repositories
Roles
Occasional Contributor
Frequent Contributor
Project Admin
Contributor License Agreement (CLA)
Committing your work
Release branches
Topic branches
Comments
Commits
Keeping your repo in sync with upstream
If you have cloned upstream
If you have forked upstream
Tips on enhancing git
Auto-completions
Terminal colours
Aliases
Visual History
Visual diff and merge tools
Choosing an Editor
Shell prompt
Building Infinispan
Requirements
Quick command reference
Publishing releases to Maven
Publishing snapshots
Publishing releases
The Maven Archetypes
Starting a new project
Writing a test case for Infinispan
Versions
Source Code
API, Commons and Core
API
Commons
Core
Infinispan 6.0
Running and Writing Tests
Running the tests
Specifying which tests to run
Skipping the test run
Running tests using @Parameters
Enabling TRACE in test logs
Enabling code coverage generation
Test groups
Which group should I use?
Test permutations
Running permutations manually or in an IDE
The Parallel Test Suite
Tips for writing and debugging parallel tests
Helping Others Out
Adding Configuration
Adding a property
Adding a group
Don't forget to update the XSD and XSD test
Bridging to the old configuration
Writing Documentation and FAQs
Introduction
What goes where?
Wiki markup or rich text
Markup guide
Headers, Page Structure and the Table of Contents
Marking up text
Lists and tables
Links
Admonitions
Images and other media
Code samples
Voice and grammar guide
Glossary
Screencasts
Managing this confluence instance.
Infinispan's Architecture
Interested in reading more about Infinispan's architecture? Check out the Architectural Overview.
Infinispan 6.0
7.1.1 requisites
Java 1.6
Infinispan is baselined on Java 6.0, and is built and tested using Sun Java 6.0.
Maven 3
Git
The Infinispan sources are stored in Git. If you don't wish to install Git, you can download
(optional)
source bundles
Infinispan 6.0
Versioning Guidelines
Only Infinispan contributors should set the Fix Version field.
When setting the Fix Version field for bugs and issues in JIRA, the following guidelines apply:
Version numbers are defined as MAJOR.MINOR.MICRO.MODIFIER. For example, 4.1.0.BETA1 would be:
MAJOR
MINOR
MICRO
MODIFIER BETA1
If the issue relates to a Task or Feature Request, please ensure that the .FINAL version is included in the
Fixed In field. For example, a new feature should contain 4.1.0.BETA1, 4.1.0.FINAL if it is new for 4.1.0 and
was first made public in BETA1. For example, see ISPN-299.
If the issue relates to a bug which affected a previous FINAL version, then the Fixed In field should also
contain the .FINAL version which contains the fix, in addition to any ALPHA, BETA or CR release. For
example, see ISPN-546.
If the issue pertains to a bug in the current release, then the .FINAL version should not be in the Fixed In
field. For example, a bug found in 4.1.0.ALPHA2 (but not in 4.1.0.ALPHA1) should be marked as fixed in
4.1.0.ALPHA3, but not in 4.1.0.FINAL. For example, see ISPN-416.
Infinispan 6.0
Eclipse
1. Install the m2eclipse plugin if you have not already installed it. Eclipse is including it since version
"Indigo" 3.7, for older versions follow instructions at http://eclipse.org/m2e/.
2. Import the Infinispan maven project. Select File -> Import in your eclipse workbench. Select the
Existing Maven Project importer.
Infinispan 6.0
4. Select Infinispan modules that you want to import.
5. Finally, from Infinispan 5.0 onwards, annotation processing is used to allow log messages to be
internationalized. This processing can be done directly from Eclipse as part of compilation but it
requires some set up:
1. Open the properties for infinispan-core and locate Annotation Processing
2. Tick Enable project specific settings
3. Enter target/generated-sources/annotations as the Generated source
directory
Code Formatting. From the menu Window->Preferences-> select Java -> Code Style -> Formatter. Import
formatter.xml
Code template. From the menu Window->Preferences-> select Java -> Code Style -> Code Templates.
Import codetemplates.xml
Some modules use Scala, if you plan contributing to one of these modules it's worth installing the Scala tools
.
Infinispan 6.0
IntelliJ IDEA
Importing
When you start IntelliJ, you will be greeted by a screen as shown below:
Infinispan 6.0
If you have already obtained a copy of the Infinispan sources via Github (see 'Source Control'), then
simply follow: Import Project -> /directory/to/downloaded/sources. IntelliJ will automatically make
use of maven to import the project since it will detect a pom.xml file in the base directory.
If you have not obtained the sources already, you can simply use the Git integration provided within
IntelliJ 12. Click on Check out from Version Control -> Github. After entering your Github
credentials, you will then be prompted to enter the git repository URL along with the location that you
want to check out the source code to.
Infinispan 6.0
Compiler settings
From Infinispan 5.0 onwards, annotation processing is used to allow log messages to be
internationalized. This processing can be done directly from IntelliJ as part of compilation but it
requires some set up:
Go to "Preferences/Compiler/Annotation Processor" and click on Enable annotation processing
Add an annotation processor with "Processor FQN Name" as
org.jboss.logging.LoggingToolsProcessor
In "Processed Modules", add all modules except the root and the parent modules.
There can sometimes be issues with the generated logging classes on rebuild (particularly when you
switch Git branches). If these issues do crop up then simply run mvn clean install -DskipTests=true
on the command line to clear them out.
EXTRA: If you are running a multi-core environment (e.g. quad-core or above) then you can follow the
instructions on making use of parallelized compilation in IntelliJ 12. Information on how to do this can
be found here.
Infinispan 6.0
Scala Plugin
You will need to download the Scala plugin for IntelliJ as well. This can be done by: Project Settings
-> Plugins -> Browse Repositories. Then run a search for 'Scala'. JetBrains themselves are the
vendor for this plugin and more information on it can be found here.
You also have to configure the Scala plugin to use the Scala compiler for Scala files and the Java
compiler for Java files. You can do this by going into Settings -> Compiler -> Scala Compiler. Be
sure to add the scala compiler bundle as shown in the screenshot below.
Code Style
You can find the code style .jar file for IntelliJ in the Infinispan source download. It is located in
/path/to/infinispan/home/ide-settings/intellij.
Infinispan 6.0
Infinispan 6.0
Spelling
Ensure correct spelling in code, comments, Javadocs, etc. (use American English spelling). It is
recommended that you use a spellchecker plugin for your IDE.
License header
All source files must have up-to-date license headers as described in Copyright Ownership and Licenses.
Never remove existing headers or copyrights.
Check-in comments
Please ensure any commit comments use this format if related to a task or issue in JIRA. This helps JIRA
pick out these checkins and display them on the issue, making it very useful for back/forward porting fixes. If
your comment does not follow this format, your commit may not be merged into upstream.
7.1.8 Configuration
Infinispan offers both programmatic configuration and XML configuration. For more information read the
Configuration chapter.
7.1.9 Logging
Infinispan follows the JBoss logging standards, which can be found here.
From Infinispan 5.0 onwards, Infinispan uses JBoss Logging to abstract over the logging backend. Infinispan
supports localization of log message for categories of INFO or above as explained in the JBoss Logging
guidelines. As a developer, this means that for each INFO, WARN, ERROR, FATAL message your code emits,
you need to modify the Log class in your module and add an explicit method for it with the right annotations.
For example:
Infinispan 6.0
@LogMessage(level = INFO)
@Message(value = "An informative message: %s - %s", id = 600)
void anInformativeMessage(String param1, String param2);
And then, instead of calling log.info(...), you call the method, for example
log.anInformativeMessage(param1, param2). If what you're trying to log is an error or similar
message and you want an exception to be logged as cause, simply use @Cause annotation, example:
@LogMessage(level = ERROR)
@Message(value = "An error message: %s", id = 600)
void anErrorMessage(String param1, @Cause IllegalStateException e);
The last thing to figure out is which id to give to the message. Each module that logs something in
production code that could be internationalized has been given an id range, and so the messages should
use an available id in the range for the module where the log call resides. Here are the id range assignments
per module:
Infinispan 6.0
Module name
Id range
core
1 - 1000
tree
2001 - 3000
2001 - 3000
3001 - 4000
hotrod client
4001 - 5000
server core
5001 - 6000
server hotrod
6001 - 7000
7001 - 8000
8001 - 9000
9001 - 10000
10001 - 11000
server memcached
11001 - 12000
server rest
12001 - 13000
server websocket
13001 - 14000
query
14001 - 15000
lucene directory
15001 - 16000
rhq plugin
16001 - 17000
cdi integration
17001 - 18000
18001 - 19000
cli interpreter
19001 - 20000
cli client
20001 - 21000
21001 - 22000
22001 - 23000
23001 - 24000
When editing the above table, remember to update the README-i18n.txt file in the project sources!
Infinispan 6.0
You will need to enable annotation processing in order to be able to compile Infinispan and have
the logger implementation generated.
7.2.1 requisites
This document assumes some working knowledge of git. We recommend Scott Chacon's excellent Pro Git
as a valuable piece of background reading. The book is released under the Creative Commons license and
can be downloaded in electronic form for free. At very least, we recommend that Chapter 2, Chapter 3 and
Chapter 5 of Pro Git are read before proceeding.
7.2.2 Repositories
Infinispan uses http://github.com/infinispan/infinispan as its canonical repository, and this repository contains
the stable code on master (currently Infinispan 5.x) as well as the maintenance branches for 4.2.x, 4.1.x and
4.0.x.
Typically, only Project Admins would be able to push to this repo while all else may clone or fork this repo.
7.2.3 Roles
The project assumes one of 3 roles an individual may assume when interacting with the Infinispan
codebase. The three roles here are:
Project Admin (typically, no more than 3 or 4 people)
Frequent Contributor
Occasional Contributor
Infinispan 6.0
None of the roles assume that you are a Red Hat employee. All it assumes is how much
responsibility over the project has been granted to you. Typically, someone may be in more than
one role at any given time, and puts on a different "hats" based on the task at hand.
Occasional Contributor
This role defines a user who browses through the source code of the project and occasionally submits
patches. Patches may be submitted in one of two ways:
Attach a patch file to the JIRA issue
Creating a pull request on GitHub
The approach a contributor chooses to use depends entirely his/her personal preference, but usually is tied
to how the contributor accesses Infinispan's source code. If the contributor directly clones the upstream
repository, they should submit patch files. If the contributor instead uses their personal GitHub account to
fork the upstream repository, then they are should issue a pull request.
Infinispan 6.0
In this workflow, the contributor directly clones the upstream repository, makes changes to his local clone,
adequately tests and commits his work with proper comments (more on commit comments later), and
generates a patch. The patch should then be attached to the JIRA issue.
More information on generating patches suitable for attaching to a JIRA can be found in Chapter 5, Section 2
of Pro Git, under the section titled Public Large Project .
Rather than emailing the patches to a developer mail list, please attach your patch to the JIRA
issue.
Infinispan 6.0
In this workflow, the contributor forks the Infinispan upstream repository on GitHub, clones their fork, and
makes changes to this private fork. When changes have been tested and are ready to be contributed back to
the project, a pull request is issued via GitHub so that one of the Project Administrators can pull in the
change.
Topic Branches
It is desirable to work off a topic branch, even when using your own, forked repository. A topic
branch is created for every feature or bug fix you do. Typically you would create one topic branch
per issue, but if several patches are related it's acceptable to have several commits in the same
branch; however different changes should always be identified by different commits.
Before you push your work onto your fork of the repository, it is often a good idea to review your commits.
Consolidating them (squashing) or breaking them up as necessary and cleaning up commit messages
should all be done while still working off your local clone. Also, prior to issuing a pull request, you should
make sure you rebase your branch against the upstream branch you expect it to be merged into. Also, only
submit pull requests for your branch - not for your master!
The section on Public Small Project in Chapter 5, Section 2 of Pro Git has more information on this style of
workflow.
A worked example
1. Make sure your master is synced up with upstream. See this section for how to do this
2. Create new branch for your topic and switch to it. For the example issue, ISPN-1234:
8. Sync with upstream again so that your changes now appear in your master branch
If your topic branch has been open for a while and you are afraid changes upstream may clash with your
changes, it makes sense to rebase your topic branch before you issue a pull request. To do this:
Infinispan 6.0
If you are sharing your forked Infinispan repo with others, then do not rebase! Use a merge instead.
Infinispan 6.0
A worked example
This example assumes that developer A and B have added each others Infinispan forked repositories with
the git add remote command. For example, developer B would add developer A's personal Infinispan
fork repository with the command
1. Developer A starts implementing feature ISPN-244 and works on a local topic branch ispn244
Developer A pushes ispn244 to personal Infinispan fork. For example:
5. Developer B sends pull request to developer A to integrate changes from my_ispn244 to ispn244
Infinispan 6.0
Frequent Contributor
A frequent contributor will only ever submit patches via a pull requests. The pull request will be submitted via
GitHub.
Frequent contributors should always fork the upstream project on GitHub and work off a clone of this fork.
This is very similar to Creating a pull request on GitHub workflow used by a Occasional Contributor.
All Infinispan core developers are considered frequent contributors and work off personal forks of
the upstream repository. This allows for complex features to be developed in parallel without
tripping up over one another. This process is certainly not restricted to just Infinispan core
developers; any contributor is welcome to also participate in this manner.
Project Admin
Project Admins have a very limited role. Only Project Admins are allowed to push to upstream, and Project
Admins never write any code directly on the upstream repository. All Project Admins do is pull in and merge
changes from contributors (even if the "contributor" happens to be themselves) into upstream, perform code
reviews and either commit or reject such changes.
All Contributors who are also Project Admins are encouraged to not merge their own changes, to
ensure that all changes are reviewed.
This approach ensures Infinispan maintains quality on the main code source tree, and allows for important
code reviews to take place again ensuring quality. Further, it ensures clean and easily traceable code history
and makes sure that more than one person knows about the changes being performed.
Infinispan 6.0
Merging in patches
Patches submitted via JIRA are audited and promoted to the upstream repository as detailed above. A
Project Admin would typically create a working branch to which the patch is applied and tested. The patch
can be further modified, cleaned up, and commit messages made clearer if necessary. The branch should
then be merged to the master or one of the maintenance branches before being pushed.
More information on applying patches can be found in Chapter 5, Section 3 of Pro Git, under Applying
Patches From Email.
Project Admins are also responsible for responding to pull requests. The process is similar to applying a
patch directly, except that when pulling in changes from a forked repository, more than a single commit may
be pulled in. Again, this should be done on a newly created working branch, code reviewed, tested and
cleaned up as necessary.
Infinispan 6.0
If commits need to be altered - e.g., rebasing to squash or split commits, or to alter commit messages - it is
often better to contact the Contributor and ask the Contributor to do so and re-issue the pull request, since
doing so on the upstream repo could cause update issues for contributors later on. If commits were altered
or three-way merge was performed during a merge instead of fast-forward, it's also a good idea to check the
log to make sure that the resulting repository history looks OK:
$ git log --pretty=oneline --graph --abbrev-commit # History messed up due to a bad merge
*
3005020 Merge branch 'ISPN-786' of git://github.com/Sanne/infinispan
|\
| * e757265 ISPN-786 Make dependency to log4j optional <-- Same with cb4e5d6 - unnecessary
* | cb4e5d6 ISPN-786 Make dependency to log4j optional <-- Cherry-picked commit by other admin
|/
* ...
$ git reset cb4e5d6
It is therefore strongly recommended that you use the handle_pull_request script that ensures a clean
merge. If you still wish to do this manually, please consider reading through the script first to get an idea of
what needs to happen.
More information on pulling changes from remote, forked repos can be found in Chapter 5, Section 3 of Pro
Git, under Checking Out Remote Branches .
Cutting releases
Releases can only me cut by Project Admins, and must be done off a recently updated (git fetch and git pull
origin) clone of the upstream repo. Infinispan's release.py script takes care of the rest.
Infinispan 6.0
Infinispan 6.0
Topic branches
Some of the biggest features of git are speed and efficiency of branching, and accuracy of merging. As a
result, best practices involve making frequent use of branches. Creating several topic branches a day, even,
should not be considered excessive, and working on several topic branches simultaneously again should be
commonplace.
Chapter 3, Section 4 of Pro Git has a detailed discussion of topic branches. For Infinispan, it makes sense to
create a topic branch and name it after the JIRA it corresponds to. (if it doesn't correspond to a JIRA, a
simple but descriptive name should be used).
Infinispan 6.0
Comments
It is extremely important that comments for each commit are clear and follow certain conventions. This
allows for proper parsing of logs by git tools. Read this article on how to format comments for git and adhere
to them. Further to the recommendations in the article, the short summary of the commit message should be
in the following format:
This can optionally be followed by a detailed explanation of the commit. Why it was done, how much of it
was completed, etc. You may wish to express this as a list, for example:
*
*
*
*
Make sure however to split separate concerns - especially if they are unrelated - in separate commits.
It might happen that a single commit fixes multiple JIRAs. This shouldn't be the norm, but if it happens, it's
recommended that all JIRA ids are specified in the title of commit, followed by a more detailed explanation
following the example above e.g.
Commits
Sometimes work on your topic branch may include several commits. For example, committing a test. Then
committing another test. Then perhaps committing a fix. And perhaps fixing your own fix in the next commit...
Before issuing a pull request for this topic branch, consider cleaning up these commits. Interactive rebasing
helps you squash several commits into a single commit, which is often more coherent to deal with for others
merging in your work. Chapter 6, Section 4 of Pro Git has details on how to squash commits and generally,
clean up a series of commits before sharing this work with others. Note that you can also easily reorder
them, just change the order of lines during the interactive rebase process.
Also, it is important to make sure you don't accidentally commit files for which no real changes have
happened, but rather, whitespace has been modified. This often happens with some IDEs. git diff
--check should be run before you issue such a pull request, which will check for such "noise" commits and
warn you accordingly. Such files should be reverted and not be committed to the branch.
Adhering to Infinispan's code style guidelines will help minimise "noise" commits. Project Admins are going
to ask contributors to reformat their code if necessary.
Infinispan 6.0
will often do the trick. You could then pull the specific branches you would need to update:
$
$
$
$
git
git
git
git
checkout master
pull origin master
checkout 4.2.x
pull origin 4.2.x
and/or
Infinispan 6.0
You should now be able to fetch and pull changes from upstream into your local repository, though you
should make sure you have no uncommitted changes. (You do use topic branches, right?)
$
$
$
$
$
$
$
$
git
git
git
git
git
git
git
git
fetch upstream
fetch upstream --tags
checkout master
pull upstream master
push origin master
checkout 4.2.x
pull upstream 4.2.x
push origin 4.2.x
and/or
The sync_with_upstream script can do this for you if your topic branch naming conventions match the script.
Infinispan 6.0
After logging out and back in again, typing git <TAB> will give you a list of git commands, as would git
c<TAB>, etc. This even works for options, e.g. git commit --<TAB>. The completions are even aware of
your refs, so even git checkout my_br<TAB> will complete to git checkout my_branch!
Note that you get git autocompletion for free if you use zsh instead of bash.
Terminal colours
Add the following to your ~/.gitconfig
[color]
ui = yes
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "diff"]
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
added = yellow
changed = green
untracked = cyan
Infinispan 6.0
Aliases
Some git commands are pretty long to type, especially with various switches. Aliases help you to map
shortcuts to more complex commands.; Again, For example, add the following to ~/.gitconfig:
[alias]
co = checkout
undo = reset --hard
cb = checkout -b
br = branch
cp = cherry-pick
st = status
l = log --pretty=oneline --decorate --abbrev-commit
lg = log --decorate --abbrev-commit
last = log --decorate -1 -p --abbrev-commit
ci = commit -a
pom = push origin master
graph = log --pretty=oneline --graph --abbrev-commit
dt = difftool
Visual History
Git ships with gitk, a GUI that visually represents a log. If you use Mac OS X, GitX is a good alternative. Try
typing gitk or gitx in a git project directory.
For Linux users, there are lots of alternatives: gitk, gitg, giggle, ... up to egit for Eclipse.
Choosing an Editor
You can customise the editor used by git editing ~/.gitconfig. The following fires up MacVIM instead of
the default vi editor:
[core]
editor = mvim -f
Infinispan 6.0
Shell prompt
You can change your Bash shell prompt to print the current repository's branch name. Add the following to
your ~/.bashrc:
function git_current_branch {
git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1]/'
}
if [ "$PS1" ]; then
PS1='[\u@\h:\W]$(git_current_branch)\$ '
fi
trustin@matrix:infinispan-4.2][4.2.x]$
If you're a ZSH user, you can get even more interesting branch information thanks to this blog post, such as:
whether your branch is dirty ()
whether it's ahead of the remote()
whether it diverges with the remote ()
whether it's behind ()
For example, the following prompt indicates that the current branch is 't_ispn775_master' and that the
branch is dirty:
[~/Go/code/infinispan.git]% (t_ispn775_master)
7.3.1 Requirements
Java 6.0 or above
Maven 3 or above
Infinispan 6.0
Make sure you follow the steps outlined in Maven Getting Started - Users to set up your JBoss
repository correctly. This step is crucial to ensure your Maven setup can locate JBoss artifacts! If
you also want to test the EAP integration modules you should also add the appropriate Enterprise
Red Hat Maven Repository.
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd" >
<localRepository/>
<interactiveMode/>
<usePluginRegistry/>
<offline/>
<proxies/>
<profiles>
<profile>
<id>jboss-public-repository</id>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url> https://repository.jboss.org/nexus/content/groups/public-jboss/ </url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url> https://repository.jboss.org/nexus/content/groups/public-jboss/ </url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
Infinispan 6.0
<!-- Include early access of application server and other products -->
<profile>
<id>redhat-earlyaccess-repository</id>
<repositories>
<repository>
<id>redhat-earlyaccess-repository-group</id>
<name>Red Hat early access repository</name>
<url> http://maven.repository.redhat.com/earlyaccess/all/ </url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>jboss-public-repository</activeProfile>
<activeProfile>redhat-earlyaccess-repository</activeProfile>
</activeProfiles>
</settings>
Infinispan 6.0
mvn clean
mvn compile
mvn test
Runs the TestNG unit test suite on the compiled code. Will also
compile the tests. See the testing section below for more
information on running different test groups. The default test group
run is the "unit" group.
mvn package
Packages the module as a JAR file, the resulting JAR file will be in
target/
mvn package
-Dmaven.test.skip.exec=true
mvn package
distribution
mvn deploy
mvn -Pgenerate-schema-doc
install -DskipTests=true
-pl core && firefox
core/target/xsd_doc
mvn install -P-extras
For non-snapshot releases (e.g., alphas, betas, release candidates and final releases) you should
use the bin/release.py script.
Infinispan 6.0
<settings>
...
<servers>
...
<server>
<id>jboss-snapshots-repository</id>
<username>your JBoss.org username</username>
<password>your JBoss.org password</password>
</server>
<server>
<id>jboss-releases-repository</id>
<username>your JBoss.org username</username>
<password>your JBoss.org password</password>
</server>
...
</servers>
...
</settings>
Publishing snapshots
Simply running
Publishing releases
Use the bin/release.py script.
Infinispan 6.0
You don't need to have any experience with or knowledge of Maven's Archetypes to use this! Just
follow the simple steps below.
These archetypes have only been tested with Maven 3. Please report back if you have any
success with using Maven 2.
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=newproject-archetype \
-DarchetypeVersion=1.0.5 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
You will be prompted for a few things, including the artifactId , groupId and version of your new
project. And that's it - you're ready to go!
in your newly generated project. This runs the main() method in the generated application class.
Infinispan 6.0
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=testcase-archetype \
-DarchetypeVersion=1.0.5 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
As above, this will prompt you for project details and again as above, you should open this project in your
IDE. Once you have done so, you will see some sample tests written for Infinispan making use of
Infinispan's test harness and testing tools along with extensive comments and links for further reading.
$ mvn test
Available profiles
The profiles available in the generated sample project are:
udp: use UDP for network communications rather than TCP
tcp: use TCP for network communications rather than UDP
jbosstm: Use the embedded JBoss Transaction Manager rather than Infinispan's dummy test
transaction manager
Want to know how best to work with the repositories and contribute code? Read
[Infinispan and Git]
Infinispan 6.0
Versions
The archetypes generate poms with dependencies to specific versions of Infinispan. You should edit these
generated poms by hand to point to other versions of Infinispan that you are interested in.
Source Code
The source code used to generate these archetypes are on GitHub. If you wish to enhance and contribute
back to the project, fork away!
7.4.1 API
The infinispan-api module should only contain the public interfaces which can be used in any context (local,
remote, etc). Any additions and/or modifications to this module must be discussed and approved by the
team beforehand. Ideally it should not contain any concrete classes: rare exceptions may be made for small,
self-contained classes which need to be referenced from the API interfaces and for which the introduction of
an interface would be deemed cumbersome.
7.4.2 Commons
The infinispan-commons module contains utility classes which can be reused across other modules. Classes
in infinispan-commons should be self-contained and not pull in any dependencies (apart from the existing
jboss-logging and infinispan-api). They should also make no reference to configuration aspects specific to a
particular environment.
7.4.3 Core
The infinispan-core module contains the actual implementation used for local/embedded mode. When
adding new functionality to the APIs, it is generally safe to start by putting them in infinispan-core and
promoting them to infinispan-api only when it is deemed to do so and it makes sense across the various
use-cases.
Infinispan 6.0
The default run executes all tests in the functional and unit groups. To just run the tests with txt and xml
output the command is:
$ mvn test
Alternatively, you can execute the tests and generate a report with:
$ mvn surefire-report:report
If you are running the tests on a Unix-like operating system, the default limits per user are typically
low. The Infinispan test suite creates a lot of processes/threads, thus you will have to increase your
user's limits and reboot the system to pick up the new values. Open up
/etc/security/limits.conf and add the following lines replacing the user name with your
username.
rhusar
rhusar
rhusar
rhusar
soft
hard
soft
hard
nofile
nofile
nproc
nproc
16384
16384
16384
16384
Infinispan 6.0
Alternatively, if there is more than one test with a given classname in your test suite, you could provide the
path to the test.
Alternatively, you can always pass your own Log4j configuration file via -Dlog4.configuration with your
own logging settings.
Patterns are also supported:
Note that you should never use -Dmaven.test.skip=true since modules' test classes depend on other
module test classes, and this will cause compilation errors.
Infinispan 6.0
Executing this will generate a GZIP file called trace-infinispan.log.gz. This file is not fully closed, so
to extract the log file, execute:
Please note, that -Dmaven.test.failure.ignore=true is used for generating JaCoCo code coverage
report, even if there are test failures.
Executing this will generate jacoco.exec file in each module's target/ directory. These are the JaCoCo
execution data files, which contain full data about the specific module's coverage.
As soon as the coverage execution command is finished, you will need to generate the JaCoCo report,
which will merge the generated jacoco.exec files as well as will create the code coverage report.
For having the report in place, run the following command from your Infinispan home directory:
The jacoco-html/ directory will be generated in Infinispan Home directory, which will contain the code
coverage report.
Infinispan 6.0
unit
Unit tests using stubs to isolate and test each major class in Infinispan. This is the default
group run if no test group is specified
functional
jgroups
Tests used for manual profiling, not meant for automated test runs
manual
Every test (except those not intended to be run by Hudson) should at least be in the functional or
unit groups, since these are the default test groups executed by Maven, and are run when
preparing a release.
Infinispan 6.0
Each permutation uses its own report directory, and its own html output file name. This allows you to execute
multiple permutations without wiping the results from the previous run. Note that due to the way Maven
operates, only one permutation can be executed per mvn command. So automating multiple runs requires
shell scripting, or some other execution framework to make multiple calls to Maven.
Infinispan 6.0
MyTest.java
package org.infinispan.mypackage;
@Test (testName = "mypackage.MyTest")
public class MyTest { ... }
Thread.sleep(10) may not work in certain OS/JRE combos (e.g. Windows XP/Sun JRE 1.5)
Use values grater than 10 for these statements, e.g. 50. Otherwise, a System.currentTimeMillis()
might return same value when called before and after such a sleep statement.
JMX
For each cache that is create with TestCacheManagerFactory.createXyzCacheManager() the test
harness will allocate a unique JMX domain name which can be obtained through
CacheManager.getJmxDomain(). This ensures that no JMX collisions will takes place between any tests
executed in parallel. If you want to enforce a JMX domain name, this can be done by using one of the
TestCacheManagerFactory.createCacheManagerEnforceJmxDomain methods. These methods
must be used with care, and you are responsible for ensuring no domain name collisions happen when the
parallel suite is executed.
Use obscure words
Insert uncommon or obscure words into the cache that has been generated with a random word generator.
In a multi-threaded environment like Infinispan's testsuite, grepping for these words can greatly help the
debugging process. You may find this random word generator useful.
Infinispan 6.0
Use the test method name as the key
Grab the test method and use it as part of the cached key. You can dynamically grab the test method using
code like this:
Thread.currentThread().getStackTrace()(1).getMethodName()
Even though we've tried to reduce them to a min, intermittent failures might still appear from time to time. If
you see such failures in existing code please report them in the issue tracker.
Note, these guides assume you are adding an element to the cache configuration, but apply equally to the
global configuration.
Before you start adding a configuration property, identify whether you want to add a property to an existing
configuration group/element, or whether you need to create a child object. We call the configuration group
XXX in the steps below.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Tutorials for using Infinispan This will be developed into a Getting Started Guide, where
Started Guide
User Guide
Glossary
An explanation of the
terminology used by
Infinispan
Frequently
Asked
technical FAQs
Questions
Editing and adding pages on Confluence is restricted to regular contributors to Infinispan (if you think you
should have access, or want to become a regular contributor to the documentation, then please email
infinispan-dev@lists.jboss.org.
Infinispan 6.0
Once the final set of guides (as described in the table above) is complete, there will be additional
guidance here to describe how to decide which guide to place content in.
Infinispan 6.0
The include macro is not automatically updated if you change a page name!
Confluence auto-generates the table of contents (using the toc macro) for the various guides, based on the
headings used in the guide. As the include macro does not print the title of the page you are including, it is
necessary to add the title above the include macro. You should not use the toc macro except on the main
guide page.
h1 headers should only be used to name sections of guide, h2 headers to name sub-sections and so on.
You should not skip header levels. Headings should follow the same capitalization rules as a sentence - only
capitalize the first letter and proper nouns.
For an example, take a look at the wiki markup for the Contributing to Infinispan guide.
Infinispan 6.0
Marking up text
You will likely want to introduce some inline formatting for text. Here are the various styles you should use.
Style
Use
bold
Bold should be used for emphasis only. You should never use another style to give
emphasis.
italic
Italic should be used when you introduce a new piece of terminology. For example
"Infinispan is a data grid". Further uses of the term do not need to be italicised.
underline
A fixed width font should be used whenever you refer to a class, variable, method by name,
font
code block
Should be used whenever you have a multi-line code example, or are expressing an
instruction for a user to do something
quotation
Should be used whenever you refer to text someone, or something, else has written, for
example the "Help Tips" on the right hand side of the edit page. You may wish to quote a
statement to indicate that your text is not overly precise. Quotes should not be used to refer
to a variable, class or method name, or a filesystem path or command
blockquote
Color
Infinispan 6.0
Links
Links should be used as normal!
Admonitions
Confluence supports three admonition styles, and you are encouraged to use them in your documentation as
they allow the flow of information to the reader to be controlled, by moving orthogonal information out of the
main body of text.
tip
A tip should be used when you want to convey useful information to the user. If the user does not
read the tip, it will have no impact on them understanding your documentation, however they will
gain useful extra information by reading the tip
note
A note should be used when you wish to convey extra information to the user. Without the
information the user may struggle to completely understand your documentation
warning A warning should be used when the there is some counter-intuitive information to be called out to
the user. For example, that the following information is out of date.
You can use the title attribute to give the admonition a title
Infinispan 6.0
{widget:url=http://au.youtube.com/watch?v=-dnL00TdmLY}
This produces
You can also embed Google Docs documents, Twitter searches, slide decks from SlideShare, and
presentations from SlideRocket. Just follow the above example, substituting the URL for your media.
Infinispan 6.0
Code samples
Confluence includes a code macro, but unfortunately it is not very advanced. This Confluence instance also
supports the snippet macro which can be used to include text from other sites. The use of the snippet
macro is strongly recommended as it ensures that code samples do not get out of date. It is critical that you
add a title to the your snippet, and it is also recommended you enable linenumbers and trim the text.
For example
{snippet:title=My Code
Sample|language=none|linenumbers=true|first=2|last=5|url=github.com/infinispan/infinispan/raw/master/README.mk
The snippet macro doesn't like the default "raw" link that GitHub provides. Instead, craft a URL
like github.com/infinispan/infinispan/raw/master/README.mkdn; to do this, take the
URL from your browser, and insert raw/master after the project name and before the path to the
file.
If you want to indicate that the user needs to substitute a variable in a code sample with their own,
then use < and > around the variable name. For example, to indicate the user needs to checkout a
topic branch from git:
Infinispan 6.0
Always write in the second or third person, never the first (plural or singular forms). Use the second
person to emphasize you are giving instructions to the user.
Naturally, most people write in the first person, and, typically find it the easiest form to write,
however without a lot of care it can produce the most "unprofessional" text. Conversely,
writing in the third person is trickier, but will produce text that feels well written almost
without fail. The first person can be used for emphasis but in general it is recommended to
avoid it unless you feel confident!
Writing entirely in the third person can produce quite "dry" text, so it is recommended that
you use the second person when you are giving instructions to the user. This could be when
you are walking through a sequence of steps they should perform, or could be when you are
stating that they must do something in order for them to succeed.
So, are there any tricks to reformulate a sentence so the first person is not used?
Use the passive voice "I recommend" can become "It is recommended". However,
extensive use of the can produce boring, dry and indefinite text, so don't do this too
much!
Change the subject. For example you can change "Here we discuss" to "This section
discusses"
Use a "chatty" style. Although the use of the first person is avoided, the documentation shouldn't be
too dry. Use the second person as needed. Short sentences and good use of punctuation help too!
If you define a list, keep the ordering of the list the same whenever you express the list. For example,
if you say "In this section you will learn about interceptors, commands and factories" do not go on to
say "First, let's discuss factories". This will subconsciously confuse the user
You should only capitalize proper nouns only. For example "data grid" is lower case (it's a concept),
whilst "Infinispan" is capitalized (it's a project/product name)
You should always use American spelling. Enable a spell checker!
Use the definite article when discussing a specific instance or the indefinite article when describing a
generalization of something; generally you omit the article when using a name for a project or product.
Infinispan 6.0
Keep the tense the same. It's very easy to slip between the present, past and future tenses, but this
produces text that is feels "unnatural" to the reader. Here's an example:
Data is collected from Infinispan every hour. Upon analysis the data showed that
Infinispan is 2 million times faster than it's nearest competitor
You may not have noticed, but the phrase starts using the present tense ( is) and slips into
the past tense (showed). This is clearly not actually the order in which the events
happened!
Of course, if you are actually describing the progression of time, then changing tenses is
fine. For example:
In the last section you were shown how to configure Infinispan using XML, and in the
next section you will be shown how to configure Infinispan programmatically.
If you are telling the user about a procedure they can follow, do be explicit about this, and enumerate
the steps clearly
7.8.6 Glossary
When writing a glossary entry, you should follow the Basically Available, Soft-state, Eventually-consistent
(BASE) as a template.
If the entry is commonly referred to using an acronym, then the title should consistent of the fully
expanded name, with the acronym in brackets. You can then use the acronym always within the main
text body
If you want to refer to other glossary articles using links in the text body, then just link them with no
alternative text
If you want to make external links (e.g. wikipedia, user guide), then add a h2 header "More
resources", and list them there. This clearly indicates to users when they are moving outside of our
definitions
7.8.7 Screencasts
TODO
Infinispan 6.0
7.10.1 requisites
Java 1.6
Infinispan is baselined on Java 6.0, and is built and tested using Sun Java 6.0.
Maven 3
Git
The Infinispan sources are stored in Git. If you don't wish to install Git, you can download
(optional)
source bundles
Infinispan 6.0
1. Choose between
Feature Request if you want to request an enhancement or new feature for Infinispan
Bug if you have discovered an issue
Task if you wish to request a documentation, sample or process (e.g. build system)
enhancement or issue
2. Then enter a Summary, describing briefly the problem - please try to be descriptive!
3. You should not set Priority.
4. Now, enter the version you are reporting an issue against in the Affects Version field, and leave the
Fix Version field blank.
5. In the Environment text area, describe in as much detail as possible your environment (e.g. Java
runtime and version, operating system, any network topology which is relevant).
6. In the Description field enter a detailed description of your problem or request.
7. If the issue has been discussed on the forums or the mailing list, enter a reference in the Forum
Reference field
8. Finally, hit Create
Versioning Guidelines
Only Infinispan contributors should set the Fix Version field.
When setting the Fix Version field for bugs and issues in JIRA, the following guidelines apply:
Version numbers are defined as MAJOR.MINOR.MICRO.MODIFIER. For example, 4.1.0.BETA1 would be:
MAJOR
MINOR
MICRO
MODIFIER BETA1
If the issue relates to a Task or Feature Request, please ensure that the .FINAL version is included in the
Fixed In field. For example, a new feature should contain 4.1.0.BETA1, 4.1.0.FINAL if it is new for 4.1.0 and
was first made public in BETA1. For example, see ISPN-299.
If the issue relates to a bug which affected a previous FINAL version, then the Fixed In field should also
contain the .FINAL version which contains the fix, in addition to any ALPHA, BETA or CR release. For
example, see ISPN-546.
If the issue pertains to a bug in the current release, then the .FINAL version should not be in the Fixed In
field. For example, a bug found in 4.1.0.ALPHA2 (but not in 4.1.0.ALPHA1) should be marked as fixed in
4.1.0.ALPHA3, but not in 4.1.0.FINAL. For example, see ISPN-416.
Infinispan 6.0
Eclipse
1. Install the m2eclipse plugin if you have not already installed it. Eclipse is including it since version
"Indigo" 3.7, for older versions follow instructions at http://eclipse.org/m2e/.
2. Import the Infinispan maven project. Select File -> Import in your eclipse workbench. Select the
Existing Maven Project importer.
Infinispan 6.0
3. Select the root directory of your Infinispan checkout.
Infinispan 6.0
5. Finally, from Infinispan 5.0 onwards, annotation processing is used to allow log messages to be
internationalized. This processing can be done directly from Eclipse as part of compilation but it
requires some set up:
1. Open the properties for infinispan-core and locate Annotation Processing
2. Tick Enable project specific settings
3. Enter target/generated-sources/annotations as the Generated source
directory
Code Formatting. From the menu Window->Preferences-> select Java -> Code Style -> Formatter. Import
formatter.xml
Code template. From the menu Window->Preferences-> select Java -> Code Style -> Code Templates.
Import codetemplates.xml
Some modules use Scala, if you plan contributing to one of these modules it's worth installing the Scala tools
.
Infinispan 6.0
IntelliJ IDEA
Importing
When you start IntelliJ, you will be greeted by a screen as shown below:
Infinispan 6.0
If you have already obtained a copy of the Infinispan sources via Github (see 'Source Control'), then
simply follow: Import Project -> /directory/to/downloaded/sources. IntelliJ will automatically make
use of maven to import the project since it will detect a pom.xml file in the base directory.
If you have not obtained the sources already, you can simply use the Git integration provided within
IntelliJ 12. Click on Check out from Version Control -> Github. After entering your Github
credentials, you will then be prompted to enter the git repository URL along with the location that you
want to check out the source code to.
Infinispan 6.0
Compiler settings
From Infinispan 5.0 onwards, annotation processing is used to allow log messages to be
internationalized. This processing can be done directly from IntelliJ as part of compilation but it
requires some set up:
Go to "Preferences/Compiler/Annotation Processor" and click on Enable annotation processing
Add an annotation processor with "Processor FQN Name" as
org.jboss.logging.LoggingToolsProcessor
In "Processed Modules", add all modules except the root and the parent modules.
There can sometimes be issues with the generated logging classes on rebuild (particularly when you
switch Git branches). If these issues do crop up then simply run mvn clean install -DskipTests=true
on the command line to clear them out.
EXTRA: If you are running a multi-core environment (e.g. quad-core or above) then you can follow the
instructions on making use of parallelized compilation in IntelliJ 12. Information on how to do this can
be found here.
Infinispan 6.0
Scala Plugin
You will need to download the Scala plugin for IntelliJ as well. This can be done by: Project Settings
-> Plugins -> Browse Repositories. Then run a search for 'Scala'. JetBrains themselves are the
vendor for this plugin and more information on it can be found here.
You also have to configure the Scala plugin to use the Scala compiler for Scala files and the Java
compiler for Java files. You can do this by going into Settings -> Compiler -> Scala Compiler. Be
sure to add the scala compiler bundle as shown in the screenshot below.
Code Style
You can find the code style .jar file for IntelliJ in the Infinispan source download. It is located in
/path/to/infinispan/home/ide-settings/intellij.
Infinispan 6.0
Infinispan 6.0
Spelling
Ensure correct spelling in code, comments, Javadocs, etc. (use American English spelling). It is
recommended that you use a spellchecker plugin for your IDE.
License header
All source files must have up-to-date license headers as described in Copyright Ownership and Licenses.
Never remove existing headers or copyrights.
Check-in comments
Please ensure any commit comments use this format if related to a task or issue in JIRA. This helps JIRA
pick out these checkins and display them on the issue, making it very useful for back/forward porting fixes. If
your comment does not follow this format, your commit may not be merged into upstream.
7.10.8 Configuration
Infinispan offers both programmatic configuration and XML configuration. For more information read the
Configuration chapter.
7.10.9 Logging
Infinispan follows the JBoss logging standards, which can be found here.
From Infinispan 5.0 onwards, Infinispan uses JBoss Logging to abstract over the logging backend. Infinispan
supports localization of log message for categories of INFO or above as explained in the JBoss Logging
guidelines. As a developer, this means that for each INFO, WARN, ERROR, FATAL message your code emits,
you need to modify the Log class in your module and add an explicit method for it with the right annotations.
For example:
Infinispan 6.0
@LogMessage(level = INFO)
@Message(value = "An informative message: %s - %s", id = 600)
void anInformativeMessage(String param1, String param2);
And then, instead of calling log.info(...), you call the method, for example
log.anInformativeMessage(param1, param2). If what you're trying to log is an error or similar
message and you want an exception to be logged as cause, simply use @Cause annotation, example:
@LogMessage(level = ERROR)
@Message(value = "An error message: %s", id = 600)
void anErrorMessage(String param1, @Cause IllegalStateException e);
The last thing to figure out is which id to give to the message. Each module that logs something in
production code that could be internationalized has been given an id range, and so the messages should
use an available id in the range for the module where the log call resides. Here are the id range assignments
per module:
Infinispan 6.0
Module name
Id range
core
1 - 1000
tree
2001 - 3000
2001 - 3000
3001 - 4000
hotrod client
4001 - 5000
server core
5001 - 6000
server hotrod
6001 - 7000
7001 - 8000
8001 - 9000
9001 - 10000
10001 - 11000
server memcached
11001 - 12000
server rest
12001 - 13000
server websocket
13001 - 14000
query
14001 - 15000
lucene directory
15001 - 16000
rhq plugin
16001 - 17000
cdi integration
17001 - 18000
18001 - 19000
cli interpreter
19001 - 20000
cli client
20001 - 21000
21001 - 22000
22001 - 23000
23001 - 24000
When editing the above table, remember to update the README-i18n.txt file in the project sources!
Infinispan 6.0
You will need to enable annotation processing in order to be able to compile Infinispan and have
the logger implementation generated.
7.11.1 requisites
This document assumes some working knowledge of git. We recommend Scott Chacon's excellent Pro Git
as a valuable piece of background reading. The book is released under the Creative Commons license and
can be downloaded in electronic form for free. At very least, we recommend that Chapter 2, Chapter 3 and
Chapter 5 of Pro Git are read before proceeding.
7.11.2 Repositories
Infinispan uses http://github.com/infinispan/infinispan as its canonical repository, and this repository contains
the stable code on master (currently Infinispan 5.x) as well as the maintenance branches for 4.2.x, 4.1.x and
4.0.x.
Typically, only Project Admins would be able to push to this repo while all else may clone or fork this repo.
7.11.3 Roles
The project assumes one of 3 roles an individual may assume when interacting with the Infinispan
codebase. The three roles here are:
Project Admin (typically, no more than 3 or 4 people)
Frequent Contributor
Occasional Contributor
Infinispan 6.0
None of the roles assume that you are a Red Hat employee. All it assumes is how much
responsibility over the project has been granted to you. Typically, someone may be in more than
one role at any given time, and puts on a different "hats" based on the task at hand.
Occasional Contributor
This role defines a user who browses through the source code of the project and occasionally submits
patches. Patches may be submitted in one of two ways:
Attach a patch file to the JIRA issue
Creating a pull request on GitHub
The approach a contributor chooses to use depends entirely his/her personal preference, but usually is tied
to how the contributor accesses Infinispan's source code. If the contributor directly clones the upstream
repository, they should submit patch files. If the contributor instead uses their personal GitHub account to
fork the upstream repository, then they are should issue a pull request.
Infinispan 6.0
In this workflow, the contributor directly clones the upstream repository, makes changes to his local clone,
adequately tests and commits his work with proper comments (more on commit comments later), and
generates a patch. The patch should then be attached to the JIRA issue.
More information on generating patches suitable for attaching to a JIRA can be found in Chapter 5, Section 2
of Pro Git, under the section titled Public Large Project .
Rather than emailing the patches to a developer mail list, please attach your patch to the JIRA
issue.
Infinispan 6.0
In this workflow, the contributor forks the Infinispan upstream repository on GitHub, clones their fork, and
makes changes to this private fork. When changes have been tested and are ready to be contributed back to
the project, a pull request is issued via GitHub so that one of the Project Administrators can pull in the
change.
Topic Branches
It is desirable to work off a topic branch, even when using your own, forked repository. A topic
branch is created for every feature or bug fix you do. Typically you would create one topic branch
per issue, but if several patches are related it's acceptable to have several commits in the same
branch; however different changes should always be identified by different commits.
Before you push your work onto your fork of the repository, it is often a good idea to review your commits.
Consolidating them (squashing) or breaking them up as necessary and cleaning up commit messages
should all be done while still working off your local clone. Also, prior to issuing a pull request, you should
make sure you rebase your branch against the upstream branch you expect it to be merged into. Also, only
submit pull requests for your branch - not for your master!
The section on Public Small Project in Chapter 5, Section 2 of Pro Git has more information on this style of
workflow.
A worked example
1. Make sure your master is synced up with upstream. See this section for how to do this
2. Create new branch for your topic and switch to it. For the example issue, ISPN-1234:
8. Sync with upstream again so that your changes now appear in your master branch
If your topic branch has been open for a while and you are afraid changes upstream may clash with your
changes, it makes sense to rebase your topic branch before you issue a pull request. To do this:
Infinispan 6.0
If you are sharing your forked Infinispan repo with others, then do not rebase! Use a merge instead.
Infinispan 6.0
A worked example
This example assumes that developer A and B have added each others Infinispan forked repositories with
the git add remote command. For example, developer B would add developer A's personal Infinispan
fork repository with the command
1. Developer A starts implementing feature ISPN-244 and works on a local topic branch ispn244
Developer A pushes ispn244 to personal Infinispan fork. For example:
5. Developer B sends pull request to developer A to integrate changes from my_ispn244 to ispn244
Infinispan 6.0
Frequent Contributor
A frequent contributor will only ever submit patches via a pull requests. The pull request will be submitted via
GitHub.
Frequent contributors should always fork the upstream project on GitHub and work off a clone of this fork.
This is very similar to Creating a pull request on GitHub workflow used by a Occasional Contributor.
All Infinispan core developers are considered frequent contributors and work off personal forks of
the upstream repository. This allows for complex features to be developed in parallel without
tripping up over one another. This process is certainly not restricted to just Infinispan core
developers; any contributor is welcome to also participate in this manner.
Project Admin
Project Admins have a very limited role. Only Project Admins are allowed to push to upstream, and Project
Admins never write any code directly on the upstream repository. All Project Admins do is pull in and merge
changes from contributors (even if the "contributor" happens to be themselves) into upstream, perform code
reviews and either commit or reject such changes.
All Contributors who are also Project Admins are encouraged to not merge their own changes, to
ensure that all changes are reviewed.
This approach ensures Infinispan maintains quality on the main code source tree, and allows for important
code reviews to take place again ensuring quality. Further, it ensures clean and easily traceable code history
and makes sure that more than one person knows about the changes being performed.
Infinispan 6.0
Merging in patches
Patches submitted via JIRA are audited and promoted to the upstream repository as detailed above. A
Project Admin would typically create a working branch to which the patch is applied and tested. The patch
can be further modified, cleaned up, and commit messages made clearer if necessary. The branch should
then be merged to the master or one of the maintenance branches before being pushed.
More information on applying patches can be found in Chapter 5, Section 3 of Pro Git, under Applying
Patches From Email.
Project Admins are also responsible for responding to pull requests. The process is similar to applying a
patch directly, except that when pulling in changes from a forked repository, more than a single commit may
be pulled in. Again, this should be done on a newly created working branch, code reviewed, tested and
cleaned up as necessary.
Infinispan 6.0
If commits need to be altered - e.g., rebasing to squash or split commits, or to alter commit messages - it is
often better to contact the Contributor and ask the Contributor to do so and re-issue the pull request, since
doing so on the upstream repo could cause update issues for contributors later on. If commits were altered
or three-way merge was performed during a merge instead of fast-forward, it's also a good idea to check the
log to make sure that the resulting repository history looks OK:
$ git log --pretty=oneline --graph --abbrev-commit # History messed up due to a bad merge
*
3005020 Merge branch 'ISPN-786' of git://github.com/Sanne/infinispan
|\
| * e757265 ISPN-786 Make dependency to log4j optional <-- Same with cb4e5d6 - unnecessary
* | cb4e5d6 ISPN-786 Make dependency to log4j optional <-- Cherry-picked commit by other admin
|/
* ...
$ git reset cb4e5d6
It is therefore strongly recommended that you use the handle_pull_request script that ensures a clean
merge. If you still wish to do this manually, please consider reading through the script first to get an idea of
what needs to happen.
More information on pulling changes from remote, forked repos can be found in Chapter 5, Section 3 of Pro
Git, under Checking Out Remote Branches .
Cutting releases
Releases can only me cut by Project Admins, and must be done off a recently updated (git fetch and git pull
origin) clone of the upstream repo. Infinispan's release.py script takes care of the rest.
Infinispan 6.0
Infinispan 6.0
Topic branches
Some of the biggest features of git are speed and efficiency of branching, and accuracy of merging. As a
result, best practices involve making frequent use of branches. Creating several topic branches a day, even,
should not be considered excessive, and working on several topic branches simultaneously again should be
commonplace.
Chapter 3, Section 4 of Pro Git has a detailed discussion of topic branches. For Infinispan, it makes sense to
create a topic branch and name it after the JIRA it corresponds to. (if it doesn't correspond to a JIRA, a
simple but descriptive name should be used).
Infinispan 6.0
Comments
It is extremely important that comments for each commit are clear and follow certain conventions. This
allows for proper parsing of logs by git tools. Read this article on how to format comments for git and adhere
to them. Further to the recommendations in the article, the short summary of the commit message should be
in the following format:
This can optionally be followed by a detailed explanation of the commit. Why it was done, how much of it
was completed, etc. You may wish to express this as a list, for example:
*
*
*
*
Make sure however to split separate concerns - especially if they are unrelated - in separate commits.
It might happen that a single commit fixes multiple JIRAs. This shouldn't be the norm, but if it happens, it's
recommended that all JIRA ids are specified in the title of commit, followed by a more detailed explanation
following the example above e.g.
Commits
Sometimes work on your topic branch may include several commits. For example, committing a test. Then
committing another test. Then perhaps committing a fix. And perhaps fixing your own fix in the next commit...
Before issuing a pull request for this topic branch, consider cleaning up these commits. Interactive rebasing
helps you squash several commits into a single commit, which is often more coherent to deal with for others
merging in your work. Chapter 6, Section 4 of Pro Git has details on how to squash commits and generally,
clean up a series of commits before sharing this work with others. Note that you can also easily reorder
them, just change the order of lines during the interactive rebase process.
Also, it is important to make sure you don't accidentally commit files for which no real changes have
happened, but rather, whitespace has been modified. This often happens with some IDEs. git diff
--check should be run before you issue such a pull request, which will check for such "noise" commits and
warn you accordingly. Such files should be reverted and not be committed to the branch.
Adhering to Infinispan's code style guidelines will help minimise "noise" commits. Project Admins are going
to ask contributors to reformat their code if necessary.
Infinispan 6.0
will often do the trick. You could then pull the specific branches you would need to update:
$
$
$
$
git
git
git
git
checkout master
pull origin master
checkout 4.2.x
pull origin 4.2.x
and/or
Infinispan 6.0
You should now be able to fetch and pull changes from upstream into your local repository, though you
should make sure you have no uncommitted changes. (You do use topic branches, right?)
$
$
$
$
$
$
$
$
git
git
git
git
git
git
git
git
fetch upstream
fetch upstream --tags
checkout master
pull upstream master
push origin master
checkout 4.2.x
pull upstream 4.2.x
push origin 4.2.x
and/or
The sync_with_upstream script can do this for you if your topic branch naming conventions match the script.
Infinispan 6.0
After logging out and back in again, typing git <TAB> will give you a list of git commands, as would git
c<TAB>, etc. This even works for options, e.g. git commit --<TAB>. The completions are even aware of
your refs, so even git checkout my_br<TAB> will complete to git checkout my_branch!
Note that you get git autocompletion for free if you use zsh instead of bash.
Terminal colours
Add the following to your ~/.gitconfig
[color]
ui = yes
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "diff"]
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
added = yellow
changed = green
untracked = cyan
Infinispan 6.0
Aliases
Some git commands are pretty long to type, especially with various switches. Aliases help you to map
shortcuts to more complex commands.; Again, For example, add the following to ~/.gitconfig:
[alias]
co = checkout
undo = reset --hard
cb = checkout -b
br = branch
cp = cherry-pick
st = status
l = log --pretty=oneline --decorate --abbrev-commit
lg = log --decorate --abbrev-commit
last = log --decorate -1 -p --abbrev-commit
ci = commit -a
pom = push origin master
graph = log --pretty=oneline --graph --abbrev-commit
dt = difftool
Visual History
Git ships with gitk, a GUI that visually represents a log. If you use Mac OS X, GitX is a good alternative. Try
typing gitk or gitx in a git project directory.
For Linux users, there are lots of alternatives: gitk, gitg, giggle, ... up to egit for Eclipse.
Choosing an Editor
You can customise the editor used by git editing ~/.gitconfig. The following fires up MacVIM instead of
the default vi editor:
[core]
editor = mvim -f
Infinispan 6.0
Shell prompt
You can change your Bash shell prompt to print the current repository's branch name. Add the following to
your ~/.bashrc:
function git_current_branch {
git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1]/'
}
if [ "$PS1" ]; then
PS1='[\u@\h:\W]$(git_current_branch)\$ '
fi
trustin@matrix:infinispan-4.2][4.2.x]$
If you're a ZSH user, you can get even more interesting branch information thanks to this blog post, such as:
whether your branch is dirty ()
whether it's ahead of the remote()
whether it diverges with the remote ()
whether it's behind ()
For example, the following prompt indicates that the current branch is 't_ispn775_master' and that the
branch is dirty:
[~/Go/code/infinispan.git]% (t_ispn775_master)
7.12.1 Requirements
Java 6.0 or above
Maven 3 or above
Infinispan 6.0
Make sure you follow the steps outlined in Maven Getting Started - Users to set up your JBoss
repository correctly. This step is crucial to ensure your Maven setup can locate JBoss artifacts! If
you also want to test the EAP integration modules you should also add the appropriate Enterprise
Red Hat Maven Repository.
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd" >
<localRepository/>
<interactiveMode/>
<usePluginRegistry/>
<offline/>
<proxies/>
<profiles>
<profile>
<id>jboss-public-repository</id>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url> https://repository.jboss.org/nexus/content/groups/public-jboss/ </url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url> https://repository.jboss.org/nexus/content/groups/public-jboss/ </url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
Infinispan 6.0
<!-- Include early access of application server and other products -->
<profile>
<id>redhat-earlyaccess-repository</id>
<repositories>
<repository>
<id>redhat-earlyaccess-repository-group</id>
<name>Red Hat early access repository</name>
<url> http://maven.repository.redhat.com/earlyaccess/all/ </url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>jboss-public-repository</activeProfile>
<activeProfile>redhat-earlyaccess-repository</activeProfile>
</activeProfiles>
</settings>
Infinispan 6.0
mvn clean
mvn compile
mvn test
Runs the TestNG unit test suite on the compiled code. Will also
compile the tests. See the testing section below for more
information on running different test groups. The default test group
run is the "unit" group.
mvn package
Packages the module as a JAR file, the resulting JAR file will be in
target/
mvn package
-Dmaven.test.skip.exec=true
mvn package
distribution
mvn deploy
mvn -Pgenerate-schema-doc
install -DskipTests=true
-pl core && firefox
core/target/xsd_doc
mvn install -P-extras
For non-snapshot releases (e.g., alphas, betas, release candidates and final releases) you should
use the bin/release.py script.
Infinispan 6.0
<settings>
...
<servers>
...
<server>
<id>jboss-snapshots-repository</id>
<username>your JBoss.org username</username>
<password>your JBoss.org password</password>
</server>
<server>
<id>jboss-releases-repository</id>
<username>your JBoss.org username</username>
<password>your JBoss.org password</password>
</server>
...
</servers>
...
</settings>
Publishing snapshots
Simply running
Publishing releases
Use the bin/release.py script.
Infinispan 6.0
You don't need to have any experience with or knowledge of Maven's Archetypes to use this! Just
follow the simple steps below.
These archetypes have only been tested with Maven 3. Please report back if you have any
success with using Maven 2.
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=newproject-archetype \
-DarchetypeVersion=1.0.5 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
You will be prompted for a few things, including the artifactId , groupId and version of your new
project. And that's it - you're ready to go!
in your newly generated project. This runs the main() method in the generated application class.
Infinispan 6.0
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=testcase-archetype \
-DarchetypeVersion=1.0.5 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
As above, this will prompt you for project details and again as above, you should open this project in your
IDE. Once you have done so, you will see some sample tests written for Infinispan making use of
Infinispan's test harness and testing tools along with extensive comments and links for further reading.
$ mvn test
Available profiles
The profiles available in the generated sample project are:
udp: use UDP for network communications rather than TCP
tcp: use TCP for network communications rather than UDP
jbosstm: Use the embedded JBoss Transaction Manager rather than Infinispan's dummy test
transaction manager
Want to know how best to work with the repositories and contribute code? Read
[Infinispan and Git]
Infinispan 6.0
Versions
The archetypes generate poms with dependencies to specific versions of Infinispan. You should edit these
generated poms by hand to point to other versions of Infinispan that you are interested in.
Source Code
The source code used to generate these archetypes are on GitHub. If you wish to enhance and contribute
back to the project, fork away!
You don't need to have any experience with or knowledge of Maven's Archetypes to use this! Just
follow the simple steps below.
These archetypes have only been tested with Maven 3. Please report back if you have any
success with using Maven 2.
Infinispan 6.0
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=newproject-archetype \
-DarchetypeVersion=1.0.5 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
You will be prompted for a few things, including the artifactId , groupId and version of your new
project. And that's it - you're ready to go!
in your newly generated project. This runs the main() method in the generated application class.
$ mvn archetype:generate \
-DarchetypeGroupId=org.infinispan.archetypes \
-DarchetypeArtifactId=testcase-archetype \
-DarchetypeVersion=1.0.5 \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
As above, this will prompt you for project details and again as above, you should open this project in your
IDE. Once you have done so, you will see some sample tests written for Infinispan making use of
Infinispan's test harness and testing tools along with extensive comments and links for further reading.
Infinispan 6.0
$ mvn test
Available profiles
The profiles available in the generated sample project are:
udp: use UDP for network communications rather than TCP
tcp: use TCP for network communications rather than UDP
jbosstm: Use the embedded JBoss Transaction Manager rather than Infinispan's dummy test
transaction manager
Want to know how best to work with the repositories and contribute code? Read
[Infinispan and Git]
Versions
The archetypes generate poms with dependencies to specific versions of Infinispan. You should edit these
generated poms by hand to point to other versions of Infinispan that you are interested in.
Source Code
The source code used to generate these archetypes are on GitHub. If you wish to enhance and contribute
back to the project, fork away!
Infinispan 6.0
The default run executes all tests in the functional and unit groups. To just run the tests with txt and xml
output the command is:
$ mvn test
Alternatively, you can execute the tests and generate a report with:
$ mvn surefire-report:report
If you are running the tests on a Unix-like operating system, the default limits per user are typically
low. The Infinispan test suite creates a lot of processes/threads, thus you will have to increase your
user's limits and reboot the system to pick up the new values. Open up
/etc/security/limits.conf and add the following lines replacing the user name with your
username.
rhusar
rhusar
rhusar
rhusar
soft
hard
soft
hard
nofile
nofile
nproc
nproc
16384
16384
16384
16384
Infinispan 6.0
Alternatively, if there is more than one test with a given classname in your test suite, you could provide the
path to the test.
Alternatively, you can always pass your own Log4j configuration file via -Dlog4.configuration with your
own logging settings.
Patterns are also supported:
Note that you should never use -Dmaven.test.skip=true since modules' test classes depend on other
module test classes, and this will cause compilation errors.
Infinispan 6.0
Executing this will generate a GZIP file called trace-infinispan.log.gz. This file is not fully closed, so
to extract the log file, execute:
Please note, that -Dmaven.test.failure.ignore=true is used for generating JaCoCo code coverage
report, even if there are test failures.
Executing this will generate jacoco.exec file in each module's target/ directory. These are the JaCoCo
execution data files, which contain full data about the specific module's coverage.
As soon as the coverage execution command is finished, you will need to generate the JaCoCo report,
which will merge the generated jacoco.exec files as well as will create the code coverage report.
For having the report in place, run the following command from your Infinispan home directory:
The jacoco-html/ directory will be generated in Infinispan Home directory, which will contain the code
coverage report.
Infinispan 6.0
unit
Unit tests using stubs to isolate and test each major class in Infinispan. This is the default
group run if no test group is specified
functional
jgroups
Tests used for manual profiling, not meant for automated test runs
manual
Every test (except those not intended to be run by Hudson) should at least be in the functional or
unit groups, since these are the default test groups executed by Maven, and are run when
preparing a release.
Infinispan 6.0
Each permutation uses its own report directory, and its own html output file name. This allows you to execute
multiple permutations without wiping the results from the previous run. Note that due to the way Maven
operates, only one permutation can be executed per mvn command. So automating multiple runs requires
shell scripting, or some other execution framework to make multiple calls to Maven.
Infinispan 6.0
MyTest.java
package org.infinispan.mypackage;
@Test (testName = "mypackage.MyTest")
public class MyTest { ... }
Thread.sleep(10) may not work in certain OS/JRE combos (e.g. Windows XP/Sun JRE 1.5)
Use values grater than 10 for these statements, e.g. 50. Otherwise, a System.currentTimeMillis()
might return same value when called before and after such a sleep statement.
JMX
For each cache that is create with TestCacheManagerFactory.createXyzCacheManager() the test
harness will allocate a unique JMX domain name which can be obtained through
CacheManager.getJmxDomain(). This ensures that no JMX collisions will takes place between any tests
executed in parallel. If you want to enforce a JMX domain name, this can be done by using one of the
TestCacheManagerFactory.createCacheManagerEnforceJmxDomain methods. These methods
must be used with care, and you are responsible for ensuring no domain name collisions happen when the
parallel suite is executed.
Use obscure words
Insert uncommon or obscure words into the cache that has been generated with a random word generator.
In a multi-threaded environment like Infinispan's testsuite, grepping for these words can greatly help the
debugging process. You may find this random word generator useful.
Infinispan 6.0
Use the test method name as the key
Grab the test method and use it as part of the cached key. You can dynamically grab the test method using
code like this:
Thread.currentThread().getStackTrace()(1).getMethodName()
Even though we've tried to reduce them to a min, intermittent failures might still appear from time to time. If
you see such failures in existing code please report them in the issue tracker.
Note, these guides assume you are adding an element to the cache configuration, but apply equally to the
global configuration.
Before you start adding a configuration property, identify whether you want to add a property to an existing
configuration group/element, or whether you need to create a child object. We call the configuration group
XXX in the steps below.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Tutorials for using Infinispan This will be developed into a Getting Started Guide, where
Started Guide
User Guide
Glossary
An explanation of the
terminology used by
Infinispan
Frequently
Asked
technical FAQs
Questions
Editing and adding pages on Confluence is restricted to regular contributors to Infinispan (if you think you
should have access, or want to become a regular contributor to the documentation, then please email
infinispan-dev@lists.jboss.org.
Infinispan 6.0
Once the final set of guides (as described in the table above) is complete, there will be additional
guidance here to describe how to decide which guide to place content in.
Infinispan 6.0
The include macro is not automatically updated if you change a page name!
Confluence auto-generates the table of contents (using the toc macro) for the various guides, based on the
headings used in the guide. As the include macro does not print the title of the page you are including, it is
necessary to add the title above the include macro. You should not use the toc macro except on the main
guide page.
h1 headers should only be used to name sections of guide, h2 headers to name sub-sections and so on.
You should not skip header levels. Headings should follow the same capitalization rules as a sentence - only
capitalize the first letter and proper nouns.
For an example, take a look at the wiki markup for the Contributing to Infinispan guide.
Infinispan 6.0
Marking up text
You will likely want to introduce some inline formatting for text. Here are the various styles you should use.
Style
Use
bold
Bold should be used for emphasis only. You should never use another style to give
emphasis.
italic
Italic should be used when you introduce a new piece of terminology. For example
"Infinispan is a data grid". Further uses of the term do not need to be italicised.
underline
A fixed width font should be used whenever you refer to a class, variable, method by name,
font
code block
Should be used whenever you have a multi-line code example, or are expressing an
instruction for a user to do something
quotation
Should be used whenever you refer to text someone, or something, else has written, for
example the "Help Tips" on the right hand side of the edit page. You may wish to quote a
statement to indicate that your text is not overly precise. Quotes should not be used to refer
to a variable, class or method name, or a filesystem path or command
blockquote
Color
Infinispan 6.0
Links
Links should be used as normal!
Admonitions
Confluence supports three admonition styles, and you are encouraged to use them in your documentation as
they allow the flow of information to the reader to be controlled, by moving orthogonal information out of the
main body of text.
tip
A tip should be used when you want to convey useful information to the user. If the user does not
read the tip, it will have no impact on them understanding your documentation, however they will
gain useful extra information by reading the tip
note
A note should be used when you wish to convey extra information to the user. Without the
information the user may struggle to completely understand your documentation
warning A warning should be used when the there is some counter-intuitive information to be called out to
the user. For example, that the following information is out of date.
You can use the title attribute to give the admonition a title
Infinispan 6.0
{widget:url=http://au.youtube.com/watch?v=-dnL00TdmLY}
This produces
You can also embed Google Docs documents, Twitter searches, slide decks from SlideShare, and
presentations from SlideRocket. Just follow the above example, substituting the URL for your media.
Infinispan 6.0
Code samples
Confluence includes a code macro, but unfortunately it is not very advanced. This Confluence instance also
supports the snippet macro which can be used to include text from other sites. The use of the snippet
macro is strongly recommended as it ensures that code samples do not get out of date. It is critical that you
add a title to the your snippet, and it is also recommended you enable linenumbers and trim the text.
For example
{snippet:title=My Code
Sample|language=none|linenumbers=true|first=2|last=5|url=github.com/infinispan/infinispan/raw/master/README.mk
The snippet macro doesn't like the default "raw" link that GitHub provides. Instead, craft a URL
like github.com/infinispan/infinispan/raw/master/README.mkdn; to do this, take the
URL from your browser, and insert raw/master after the project name and before the path to the
file.
If you want to indicate that the user needs to substitute a variable in a code sample with their own,
then use < and > around the variable name. For example, to indicate the user needs to checkout a
topic branch from git:
Infinispan 6.0
Always write in the second or third person, never the first (plural or singular forms). Use the second
person to emphasize you are giving instructions to the user.
Naturally, most people write in the first person, and, typically find it the easiest form to write,
however without a lot of care it can produce the most "unprofessional" text. Conversely,
writing in the third person is trickier, but will produce text that feels well written almost
without fail. The first person can be used for emphasis but in general it is recommended to
avoid it unless you feel confident!
Writing entirely in the third person can produce quite "dry" text, so it is recommended that
you use the second person when you are giving instructions to the user. This could be when
you are walking through a sequence of steps they should perform, or could be when you are
stating that they must do something in order for them to succeed.
So, are there any tricks to reformulate a sentence so the first person is not used?
Use the passive voice "I recommend" can become "It is recommended". However,
extensive use of the can produce boring, dry and indefinite text, so don't do this too
much!
Change the subject. For example you can change "Here we discuss" to "This section
discusses"
Use a "chatty" style. Although the use of the first person is avoided, the documentation shouldn't be
too dry. Use the second person as needed. Short sentences and good use of punctuation help too!
If you define a list, keep the ordering of the list the same whenever you express the list. For example,
if you say "In this section you will learn about interceptors, commands and factories" do not go on to
say "First, let's discuss factories". This will subconsciously confuse the user
You should only capitalize proper nouns only. For example "data grid" is lower case (it's a concept),
whilst "Infinispan" is capitalized (it's a project/product name)
You should always use American spelling. Enable a spell checker!
Use the definite article when discussing a specific instance or the indefinite article when describing a
generalization of something; generally you omit the article when using a name for a project or product.
Infinispan 6.0
Keep the tense the same. It's very easy to slip between the present, past and future tenses, but this
produces text that is feels "unnatural" to the reader. Here's an example:
Data is collected from Infinispan every hour. Upon analysis the data showed that
Infinispan is 2 million times faster than it's nearest competitor
You may not have noticed, but the phrase starts using the present tense ( is) and slips into
the past tense (showed). This is clearly not actually the order in which the events
happened!
Of course, if you are actually describing the progression of time, then changing tenses is
fine. For example:
In the last section you were shown how to configure Infinispan using XML, and in the
next section you will be shown how to configure Infinispan programmatically.
If you are telling the user about a procedure they can follow, do be explicit about this, and enumerate
the steps clearly
7.16.6 Glossary
When writing a glossary entry, you should follow the Basically Available, Soft-state, Eventually-consistent
(BASE) as a template.
If the entry is commonly referred to using an acronym, then the title should consistent of the fully
expanded name, with the acronym in brackets. You can then use the acronym always within the main
text body
If you want to refer to other glossary articles using links in the text body, then just link them with no
alternative text
If you want to make external links (e.g. wikipedia, user guide), then add a h2 header "More
resources", and list them there. This clearly indicates to users when they are moving outside of our
definitions
7.16.7 Screencasts
TODO
Infinispan 6.0
7.17.1 API
The infinispan-api module should only contain the public interfaces which can be used in any context (local,
remote, etc). Any additions and/or modifications to this module must be discussed and approved by the
team beforehand. Ideally it should not contain any concrete classes: rare exceptions may be made for small,
self-contained classes which need to be referenced from the API interfaces and for which the introduction of
an interface would be deemed cumbersome.
7.17.2 Commons
The infinispan-commons module contains utility classes which can be reused across other modules. Classes
in infinispan-commons should be self-contained and not pull in any dependencies (apart from the existing
jboss-logging and infinispan-api). They should also make no reference to configuration aspects specific to a
particular environment.
7.17.3 Core
The infinispan-core module contains the actual implementation used for local/embedded mode. When
adding new functionality to the APIs, it is generally safe to start by putting them in infinispan-core and
promoting them to infinispan-api only when it is deemed to do so and it makes sense across the various
use-cases.
Infinispan 6.0
Infinispan 6.0
Transaction FAQs
When using Atomikos transaction manager, distributed caches are not distributing data, what is
the problem?
Eviction and Expiration FAQs
Cache's number of entries never reaches configured maxEntries, why is that?
Expiration does not work, what is the problem?
Why is cache size sometimes even higher than specified maxEntries of the eviction
configuration element?
Why isn't there a notification for the expiration of a cache entry?
Cache Manager FAQs
Can I create caches using different cache modes using the same cache manager?
Can transactions span different Cache instances from the same cache manager?
How does multi-tenancy work?
Infinispan allows me to create several Caches from a single CacheManager. Are there any
reasons to create separate CacheManagers?
Cache Mode FAQs
What is the difference between a replicated cache and a distributed cache?
Does DIST support both synchronous and asynchronous communications?
I have caches configured with asynchronous replication or distribution, but these caches
appear to be behaving synchronously (waiting for responses), what is going on?
I notice that when using DIST, the cache does a remote get before a write command. Why is
this?
I use a clustered cache. I want the guarantees of synchronous replication with the parallelism
of asynchronous replication. What can I do?
Is buddy replication supported?
What is the L1 cache?
What consistency guarantees do I have with different Asynchronous processing settings ?
Listener FAQs
In a cache entry modified listener, can the modified value be retrieved via Cache.get() when
isPre=false?
When annotating a method with CacheEntryCreated, how do I retrieve the value of the cache
entry added?
Cloud FAQs
How do you make Infinispan send replication traffic over a specific network when you don't
know the IP address?
Demo FAQs
When using the GUI Demo, I've just put an entry in the cache with lifespan of -1. Why do I see
it as having a lifespan of 60,000?
Query Module FAQs
When I run an application based on the Query module, I get a ClassNotFoundException for
org.slf4j.impl.StaticLoggerBinder. How do I solve it?
JBoss Application Server Integration FAQs
Can I run my own Infinispan cache within JBoss Application Server 5 or 4?
Can I run my own Infinispan cache within JBoss Application Server 6?
Logging FAQs
How can I enable logging?
Infinispan 6.0
Third Party Container FAQs
Can I use Infinispan on Google App Engine for Java?
When running on Glassfish or Apache, creating a cache throws an exception saying "Unable to
construct a GlobalComponentRegistry", what is it wrong?
Language FAQs
Can I use Infinispan with Groovy? What about Jython, Clojure, JRuby or Scala etc.?
Marshalling & Unmarshalling
Best practices implementing java.io.Externalizable
Does Infinispan support storing Non-Serializable objects?
Do Externalizer implementations need to access internal Externalizer implementations?
Do I need to register an application cacheloader when using an isolated deployment?
During state transfer, the state receiver logs an EOFException when applying state saying
"Read past end of file". Should I worry about this?
How do I get more information on marshalling & unmarshalling exceptions?
Why am I getting invalid data passed to readExternal?
Tuning FAQs
When running Infinispan under load, I see RejectedExecutionException, how can I fix it?
JNDI FAQs
Can I bind Cache or CacheManager to JNDI?
Hibernate 2nd Level Cache FAQs
Can I use Infinispan as a remote JPA or Hibernate second level cache?
I'm adding the Infinispan 2nd level cache provider to existing servers that already use JGroups.
Should I set Infinispan to use the same JGroups cluster, or should I use two separate cluster
names?
Is it possible to use the Infinispan 2nd level cache outside of a J2EE server, and if so how do I
set up the transaction manager lookup?
What are the pitfalls of not using a non-JTA transaction factory such as
JDBCTransactionFactory with Hibernate when Infinispan is used as 2nd level cache provider?
Cache Server FAQs
After running a Hot Rod server for a while, I get a NullPointerException in
HotRodEncoder.getTopologyResponse(), how can I get around it?
Is there a way to do a Bulk Get on a remote cache?
What is the startServer.sh script used for? What is the startServer.bat script used for?
Debugging FAQs
How can I get Infinispan to show the full byte array? The log only shows partial contents of byte
arrays...
Clustering Transport FAQs
How do I retrieve the clustering physical address?
CLI FAQs
Can data stored via CLI be read using Infinispan remote clients (Hot Rod, Memcached,
REST)?
Infinispan 6.0
Infinispan 6.0
Massive heap and high availability - If you have 100 blade servers, and each node has 2GB of
space to dedicate to a replicated cache, you end up with 2 GB of total data. Every server is just a
copy. On the other hand, with a distributed grid - assuming you want 1 copy per data item - you get a
100 GB memory backed virtual heap that is efficiently accessible from anywhere in the grid. If a
server fails, the grid simply creates new copies of the lost data, and puts them on other servers.
Applications looking for ultimate performance are no longer forced to delegate the majority of their
data lookups to a large single database server - the bottleneck that exists in over 80% of enterprise
applications!
Scalability - Since data is evenly distributed there is essentially no major limit to the size of the grid,
except group communication on the network - which is minimised to just discovery of new nodes. All
data access patterns use peer-to-peer communication where nodes directly speak to each other,
which scales very well. Infinispan does not require entire infrastructure shutdown to allow scaling up
or down. Simply add/remove machines to your cluster without incurring any down-time.
Data distribution - Infinispan uses consistent hash algorithm to determine where keys should be
located in the cluster. Consistent hashing allows for cheap, fast and above all, deterministic location
of keys with no need for further metadata or network traffic. The goal of data distribution is to maintain
enough copies of state in the cluster so it can be durable and fault tolerant, but not too many copies to
prevent Infinispan from being scalable.
Persistence - Innispan exposes a CacheStore interface, and several high-performance
implementations - including JDBC cache stores, lesystem-based cache stores, Amazon S3 cache
stores, etc. CacheStores can be used for "warm starts", or simply to ensure data in the grid survives
complete grid restarts, or even to overow to disk if you really do run out of memory.
Language bindings (PHP, Python, Ruby, C, etc.) - Infinispan offers support for both the popular
memcached protocol - with existing clients for almost every popular programming language - as well
as an optimised Infinispan-specific protocol called HotRod. This means that Infinispan is not just
useful to Java. Any major website or application that wants to take advantage of a fast data grid will
be able to do so.
Management - When you start thinking about running a grid on several hundred servers,
management is no longer an extra, it becomes a necessity. The preferred way to manage multiple
Infinispan instances spread accross different servers is to use RHQ which is JBoss' enterprise
management solution. Thanks to RHQ's agent and auto discovery capabilities, monitoring both Cache
Manager and Cache instances is a very simple.
Support for Compute Grids - Infinispan 5 adds the ability to pass a Runnable around the grid. This
allows you to push complex processing towards the server where data is local, and pull back results
using a Future. This map/reduce style paradigm is common in applications where a large amount of
data is needed to compute relatively small results.
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Cache Loaders and Cache Store FAQs
Cache loaders and cache stores - what's the difference?
Are modifications to asynchronous cache stores coalesced or aggregated?
In JBoss Cache, the JDBC and File CacheLoaders had restrictions such as only being able to
use Strings in Fqns. Is this still the case in Infinispan?
What does the passivation flag do?
What if I get IOException "Unsupported protocol version 48" with
JdbcStringBasedCacheStore?
Is there any way I can boost cache store's performance? SKIP_CACHE_LOAD
Locking FAQs
Does Infinispan support distributed eager locking?
How does Infinispan support explicit eager locking?
How does Infinispan support implicit eager locking?
JBoss Cache exposed several different locking schemes - pessimistic, optimistic and MVCC. I
don't see a way to specify locking scheme in Infinispan. Why is this?
What isolation levels does Infinispan support?
Transaction FAQs
When using Atomikos transaction manager, distributed caches are not distributing data, what is
the problem?
Eviction and Expiration FAQs
Cache's number of entries never reaches configured maxEntries, why is that?
Expiration does not work, what is the problem?
Why is cache size sometimes even higher than specified maxEntries of the eviction
configuration element?
Why isn't there a notification for the expiration of a cache entry?
Cache Manager FAQs
Can I create caches using different cache modes using the same cache manager?
Can transactions span different Cache instances from the same cache manager?
How does multi-tenancy work?
Infinispan allows me to create several Caches from a single CacheManager. Are there any
reasons to create separate CacheManagers?
Cache Mode FAQs
What is the difference between a replicated cache and a distributed cache?
Does DIST support both synchronous and asynchronous communications?
I have caches configured with asynchronous replication or distribution, but these caches
appear to be behaving synchronously (waiting for responses), what is going on?
I notice that when using DIST, the cache does a remote get before a write command. Why is
this?
I use a clustered cache. I want the guarantees of synchronous replication with the parallelism
of asynchronous replication. What can I do?
Is buddy replication supported?
What is the L1 cache?
What consistency guarantees do I have with different Asynchronous processing settings ?
Infinispan 6.0
Listener FAQs
In a cache entry modified listener, can the modified value be retrieved via Cache.get() when
isPre=false?
When annotating a method with CacheEntryCreated, how do I retrieve the value of the cache
entry added?
Cloud FAQs
How do you make Infinispan send replication traffic over a specific network when you don't
know the IP address?
Demo FAQs
When using the GUI Demo, I've just put an entry in the cache with lifespan of -1. Why do I see
it as having a lifespan of 60,000?
Query Module FAQs
When I run an application based on the Query module, I get a ClassNotFoundException for
org.slf4j.impl.StaticLoggerBinder. How do I solve it?
JBoss Application Server Integration FAQs
Can I run my own Infinispan cache within JBoss Application Server 5 or 4?
Can I run my own Infinispan cache within JBoss Application Server 6?
Logging FAQs
How can I enable logging?
Third Party Container FAQs
Can I use Infinispan on Google App Engine for Java?
When running on Glassfish or Apache, creating a cache throws an exception saying "Unable to
construct a GlobalComponentRegistry", what is it wrong?
Language FAQs
Can I use Infinispan with Groovy? What about Jython, Clojure, JRuby or Scala etc.?
Marshalling & Unmarshalling
Best practices implementing java.io.Externalizable
Does Infinispan support storing Non-Serializable objects?
Do Externalizer implementations need to access internal Externalizer implementations?
Do I need to register an application cacheloader when using an isolated deployment?
During state transfer, the state receiver logs an EOFException when applying state saying
"Read past end of file". Should I worry about this?
How do I get more information on marshalling & unmarshalling exceptions?
Why am I getting invalid data passed to readExternal?
Tuning FAQs
When running Infinispan under load, I see RejectedExecutionException, how can I fix it?
JNDI FAQs
Can I bind Cache or CacheManager to JNDI?
Infinispan 6.0
Hibernate 2nd Level Cache FAQs
Can I use Infinispan as a remote JPA or Hibernate second level cache?
I'm adding the Infinispan 2nd level cache provider to existing servers that already use JGroups.
Should I set Infinispan to use the same JGroups cluster, or should I use two separate cluster
names?
Is it possible to use the Infinispan 2nd level cache outside of a J2EE server, and if so how do I
set up the transaction manager lookup?
What are the pitfalls of not using a non-JTA transaction factory such as
JDBCTransactionFactory with Hibernate when Infinispan is used as 2nd level cache provider?
Cache Server FAQs
After running a Hot Rod server for a while, I get a NullPointerException in
HotRodEncoder.getTopologyResponse(), how can I get around it?
Is there a way to do a Bulk Get on a remote cache?
What is the startServer.sh script used for? What is the startServer.bat script used for?
Debugging FAQs
How can I get Infinispan to show the full byte array? The log only shows partial contents of byte
arrays...
Clustering Transport FAQs
How do I retrieve the clustering physical address?
CLI FAQs
Can data stored via CLI be read using Infinispan remote clients (Hot Rod, Memcached,
REST)?
Infinispan 6.0
Coming Soon
An API for fine-grained replication is planned. This will provide the same benefits of JBoss Cache's
POJOCache variant, but far simpler and more robust. It will not rely on bytecode weaving or AOP,
and present users with a much more familiar JPA-style session interface. When released, the
fine-grained API will sacrifice performance, but give you cache data organization and fine-grained
replication. This organisation inevitably involves heavy use of reflection, proxies and comparisons,
and isn't nearly as efficient as more explicit use of the Cache API.
Infinispan 6.0
Infinispan 6.0
In JBoss Cache, the JDBC and File CacheLoaders had restrictions such
as only being able to use Strings in Fqns. Is this still the case in
Infinispan?
No. We have completely re-written these implementations with a much better design which allows us to use
arbitrary keys (or Fqn elements if using the TreeCache API), provided they are serializable. For details, see
the BucketBasedCacheStore.
Infinispan 6.0
Note that in this case the value returned by cache.put is not reliable.
This optimisation skips a cache store read and can have very significant performance improvement effects.
More flags are described at Per-Invocation Flags
tx.begin()
cache.lock(K)
cache.put(K,V5)
tx.commit()
Infinispan 6.0
tx.begin()
cache.put(K,V)
cache.put(K2,V2)
cache.put(K,V5)
tx.commit()
//
//
//
//
Implicit eager locking locks cache keys across cluster nodes only if it is necessary to do so. In a nutshell, if
implicit eager locking is turned on then for each modification Infinispan checks if cache key is locked locally.
If it is then a global cluster wide lock has already been obtained, otherwise a cluster wide lock request is sent
and lock is acquired.
Implicit eager locking is enabled as follows:
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Can I create caches using different cache modes using the same cache
manager?
Yes. You can create caches using different cache modes, both synchronous and asynchronous, using the
same cache manager.
Can transactions span different Cache instances from the same cache
manager?
Yes. Each cache behaves as a separate, standalone JTA resource. Internally though, components may be
shared as an optimization but this in no way affects how the caches interact with a JTA manager.
Infinispan 6.0
Infinispan 6.0
I notice that when using DIST, the cache does a remote get before a
write command. Why is this?
Certain methods, such as Cache.put(), are supposed to return the previous value associated with the
specified key according to the java.util.Map contract. If this is performed on an instance that does not
own the key in question and the key is not in L1 cache, the only way to reliably provide this return value is to
do a remote GET before the put. This GET is always sync (regardless of whether the cache is configured to
be sync or async) since we need to wait for that return value.
Infinispan 6.0
Infinispan 6.0
Description
Mode of
usage
Usage ofAsynchronous API, i.e. methods of the Cache interface like e.g. putAsync(key, val)
API
Sync
Sync
Sync
Sync
Async
Sync
Sync
Async
Async
1, 2
3 - Calling order of sync API method might not be preserved
depends on which operation finishes marshalling first in the
asyncExecutor
4 - Replication of put operation can be applied on different nodes in
different order this may result in inconsistent values
Async Sync
Sync
Async Async
Sync
1, 2, 3
Async Async
Async
1, 2, 3, 4
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
Infinispan 6.0
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>org.jgroups</pattern>
<shadedPattern>org.shaded.jgroups</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
Infinispan 6.0
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
Infinispan 6.0
Can I use Infinispan with Groovy? What about Jython, Clojure, JRuby or
Scala etc.?
While we haven't extensively tested Infinispan on anything other than Java, there is no reason why it cannot
be used in any other environment that sits atop a JVM. We encourage you to try, and we'd love to hear your
experiences on using Infinispan from other JVM languages.
Infinispan 6.0
End user externalizers should not need to fiddle with Infinispan internal externalizer classes. Instead, this
code should have been written as:
Infinispan 6.0
This exception is basically saying that the state generator was not able to generate the transaction log and
so the output to which it was writing is closed. In this situation, it's common to see the state receiver log an
EOFException, as shown below, when trying to read the transaction log because the sender did not write
the transaction log:
Infinispan 6.0
The current logic is for the state receiver to back off in these scenarios and retry after a few seconds. Quite
often, after the retry the state generator might have already finished dealing with the other node and hence
the state receiver will be able to fully receive the state.
Read More
You can read more about this issue in this forum thread.
Infinispan 6.0
java.util.concurrent.RejectedExecutionException
at
java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1759)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:767)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:658)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:92)
at
org.infinispan.remoting.transport.jgroups.CommandAwareRpcDispatcher.invokeRemoteCommands(CommandAwareRpcDispat
Infinispan 6.0
Infinispan 6.0
I'm adding the Infinispan 2nd level cache provider to existing servers
that already use JGroups. Should I set Infinispan to use the same
JGroups cluster, or should I use two separate cluster names?
TODO
What are the pitfalls of not using a non-JTA transaction factory such as
JDBCTransactionFactory with Hibernate when Infinispan is used as 2nd
level cache provider?
The problem is that Hibernate will create a Transaction instance via java.sql.Connection and Infinispan
will create a transaction via whatever TransactionManager returned by
hibernate.transaction.manager_lookup_class. If
hibernate.transaction.manager_lookup_class has not been populated, it will default to the
dummy transaction manager.
So, any work on the 2nd level cache will be done under a different transaction to the one used to commit the
stuff to the database via Hibernate. In other words, your operations on the database and the 2LC are not
treated as a single unit. Risks here include failures to update the 2LC leaving it with stale data while the
database committed data correctly.
Infinispan 6.0
Infinispan 6.0
And here's a log message where the full byte array is shown:
Infinispan 6.0
Infinispan 6.0
9 Videos
Monitoring
Geographic failover
9.1 Monitoring
Monitoring Infinispan with Jopr console (screencast)
How to install Jopr, the Jopr agent and the Infinispan Jopr plugin (video)
Montoring an Infinispan instance that was automatically discovered (video)
Montoring an Infinispan instance that was manually added (video)
Infinispan 6.0
10 Contributor Dashboard
Could not access the content at the URL because it is not from an allowed source.
https://issues.jboss.org/activity?maxResults=10&streams=key+IS+ISPN&os_authType=basic&title=Activity%20on%20Infin
You may contact your site administrator and request that this URL be added to the list of allowed sources.