NCache is an in-memory distributed caching for .NET. But it also supports Java thanks to its 100% native client and third-party integrations. Let’s take a quick tour through the NCache Java client and two of its third-party integrations for Java applications.
Basic Caching Operation with Java Client
After installing NCache,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
try { // After having NCache up and running... // Connect to cache String cacheName = "demoCache"; Cache cache = CacheManager.getCache(cacheName); // Cache a product Product product = buildOrRetrieveProductToCache(); String key = "Product:" + product.getProductID(); cache.add(key, product); // Later in another part of our code... // Retrieve cached product Product foundProduct = cache.get(key, Product.class); if (foundProduct != null) { // Do something with the cached product here } else { // No product was found } } catch (OperationFailedException ex) { // Handle NCache-specific exceptions, like connection failures, here } catch (Exception ex) { // Handle generic exceptions, like IllegalArgumentException, here } |
With the Java client, we have more caching operations. Apart from adding and retrieving a single item, we have bulk operations to add, retrieve, update, and delete items; and an asynchronous API. For more details on more advanced caching operations, check CRUD Operations: An Overview. We can find Java examples in that guide too.
Also, inside our Java applications, we can use the SQL querying functionality and indexing strategies to retrieve and delete cached entries using a SQL-like syntax.
With these caching operations, we write our own caching mechanism inside our Java applications. But with NCache, we can take advantage of its existing third-party integration. Let’s take a look at two of them.
NCache as Hibernate Second-Level Cache
Hibernate is an object-relational mapping tool for Java. Probably, it doesn’t need too much introduction since it’s a widespread tool in the Java world.
To avoid excessive roundtrips to a database, Hibernate uses different caching mechanisms: first and second-level caches. And Hibernate fallbacks between them when retrieving objects from the database.
The first level cache is a per-session cache. It’s the first cache Hibernate checks when loading objects. Unlike the first-level cache, the second-level cache is optional. And it’s available for all sessions.
Hibernate doesn’t provide any implementations for the second-level cache. We have to rely on third-party caching providers instead. NCache works like a second-level cache.
We can make NCache work as a Hibernate second-level cache provider through configuration files without changing our production code.
The second-level cache is disabled by default. To enable it and use NCache as a second-level cache, we have to configure it in Hibernate configuration file. For example, this is a hibernate.cfg.xml
file,
1 2 3 4 5 6 7 8 9 10 11 |
<hibernate-configuration> <session-factory> <!-- It enables Hibernate second-level cache --><!-- It enables Hibernate second-level cache --> <property name="hibernate.cache.use_second_level_cache">true</property> <!-- It configures NCache as a second-level cache provider, for Hibernate 3.6 and above ---> <property name="hibernate.cache.region.factory_class">JCacheRegionFactory</property> <!-- It's NCache applicaton identifier --> <property name="ncache.application_id">myapp</property><!-- It configures NCache as a second-level cache provider, for Hibernate 3.6 and above ---> JCacheRegionFactory </session-factory> </hibernate-configuration> |
NCache as a second-level provider
NCacheHibernate.xml
.
Hibernate uses regions to group objects under a name. With NCache, we can have separate cache instances per region or a single cache instance for multiple regions. Even we can configure each region with different NCache caching features. We also specify all these configurations inside the NCacheHibernate.xml
1 2 3 4 5 6 7 8 |
<configuration> <application-config application-id="myapp" enable-cache-exception="true" default-region-name="DefaultRegion" key-case-sensitivity="false"> <cache-regions> <region name="MyCustomRegion" cache-name="myPartitionedcache" priority="default" expiration-type="sliding" expiration-period="8"/> <region name="DefaultRegion" cache-name="demoCache" priority="default" expiration-type="none" expiration-period="0" /> </cache-regions> </application-config> </configuration> |
For more details about the NCacheHibernate.xml
file, check Configure Cacheable Objects and Regions.
Even though we enable second-level caching, Hibernate doesn’t cache objects by default. We have to mark our objects as cacheable either through annotations or mapping files. For example, let’s annotate a Product
class,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@Entity @Table(name = "Products") @Cacheable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Product { @Id @GeneratedValue @Column(name = "ProductID") private int ProductID; @Column(name = "Name") private String Name; public Product() {} public int getProductID() { return ProductID; } public void setProductID(int productID) { this.ProductID = productID; } public String getName() { return Name; } public void setName(String name) { this.Name = name; } } |
That’s how we can use NCache as a second-level Hibernate cache. Also, we can use NCache to cache query results. We can improve the overall performance of our applications by caching the result of large, complex, and frequent queries. To learn how to use NCache for query caching with Hibernate, check Use Query Caching. We need small changes in our Hibernate configuration file and in our queries to cache.
NCache Spring Integration
NCache integrates with the Spring framework too. The Spring framework is an application framework and inversion of control container for the Java platform. We can plug NCache into the Spring caching module, making it scalable and distributed.
When we use NCache with Spring, we offload our database by reducing the number of database trips to serve data, giving us better performance.
To start using NCache with Spring, we need to annotate our configuration class. Like this,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Configuration @EnableCaching public class CachingConfiguration { @Bean public CacheManager cacheManager() { SpringConfigurationManager springConfigurationManager = new SpringConfigurationManager(); URL resource = getClass().getClassLoader().getResource("ncache-spring.xml"); springConfigurationManager.setConfigFile(resource.getPath()); NCacheCacheManager cacheManager = new NCacheCacheManager(); cacheManager.setSpringConfigurationManager(springConfigurationManager); return cacheManager; } } |
Instead of using annotations, we can also use an XML file. Although, we’re better off using annotations since we can find type errors at compile time.
After changing the Spring configuration via either annotations or an XML file, we need to configure the actual caches. Inside the ncache-spring.xml
file, we define our cache instances with their properties like expiration and eviction policy. For example,
1 2 3 4 5 6 |
<application-config default-cache-name="default"> <caches> <cache name="ProductsCache" ncache-instance="demoCache" priority="normal" expiration-type="absolute" expiration-period="10"/> </caches> </application-config> |
After configuring our Spring application and enabling caching, the next step is to annotate the methods we want to cache. For example, to cache a service we call from an API controller or other services in our application, we can write,
1 2 3 4 5 6 7 8 9 10 11 12 |
@Service public class ProductService { @Cacheable("ProductsCache") public String getProductNameByCode(String code) { return retrieveProductNameFromDatastore(code); } private String retrieveProductNameFromDatastore(String code) { // Image a query to retrieve a product name from a database return "Any name"; } } |
With all these steps, we’re ready to use NCache with Spring.
For more details about configuring NCache with Spring, check Configuring Applications for using NCache as a Spring Caching Provider.
Conclusion
That’s how we can use the NCache Java client to support basic caching operations. We can integrate NCache with Hibernate and Spring Framework with only configuration and minor coding changes.
Apart from Hibernate and Spring, NCache also supports JCache API. We can use NCache in our JCache application and use the same JCache API with a distributed solution. To learn how to integrate NCache with JCache, visit JCache Guide.
And for hybrid applications with Java and .NET backend sides, NCache supports Portable Data Types. We can use NCache to share data between the Java and .NET backend applications. For example, with Portable Data Types, we can implement a JSON storage with NCache sharing data between two .NET and Java applications.
If you want to benefit from a distributed, scalable, and performant caching solution in your Java applications, give NCache a try.