Reputation: 45
I am trying to set Apache Ignite as the second level Hibernate cache provider in my project but i am getting a strange exception.
Configurations are as below:
Added
<spring.version>4.3.0.RELEASE</spring.version>
<hibernate.version>4.3.8.Final</hibernate.version>
<ignite.version>1.6.0</ignite.version>
<repositories>
<repository>
<id>GridGain External Repository</id>
<url>http://www.gridgainsystems.com/nexus/content/repositories/external</url>
</repository>
</repositories>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-core</artifactId>
<version>${ignite.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-spring</artifactId>
<version>${ignite.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-hibernate</artifactId>
<version>${ignite.version}</version>
</dependency>
Spring Hibernate Configuration file
<!-- Hibernate SessionFactory -->
<bean id="sessionFactoryHibernate" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.apache.ignite.cache.hibernate.HibernateRegionFactory</prop>
<prop key="org.apache.ignite.hibernate.grid_name">hibernate-grid</prop>
<prop key="org.apache.ignite.hibernate.default_access_type">READ_ONLY</prop>
</props>
</property>
<property name="packagesToScan" value="com.entity"></property>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Basic configuration for atomic cache. --> <bean id="atomic-cache" class="org.apache.ignite.configuration.CacheConfiguration" abstract="true"> <property name="cacheMode" value="PARTITIONED"/> <property name="atomicityMode" value="ATOMIC"/> <property name="writeSynchronizationMode" value="FULL_SYNC"/> </bean> <!-- Basic configuration for transactional cache. --> <bean id="transactional-cache" class="org.apache.ignite.configuration.CacheConfiguration" abstract="true"> <property name="cacheMode" value="PARTITIONED"/> <property name="atomicityMode" value="TRANSACTIONAL"/> <property name="writeSynchronizationMode" value="FULL_SYNC"/> </bean> <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> <!-- Specify the name of the caching grid (should correspond to the one in Hibernate configuration). --> <property name="gridName" value="hibernate-grid"/> <!-- Specify cache configuration for each L2 cache region (which corresponds to a full class name or a full association name). --> <property name="cacheConfiguration"> <list> <!-- Configurations for entity caches. --> <!-- <bean parent="transactional-cache"> <property name="name" value="com.mycompany.MyEntity1"/> </bean> <bean parent="transactional-cache"> <property name="name" value="com.mycompany.MyEntity2"/> </bean> <bean parent="transactional-cache"> <property name="name" value="com.mycompany.MyEntity1.children"/> </bean> --> <!-- Configuration for update timestamps cache. --> <bean parent="atomic-cache"> <property name="name" value="org.hibernate.cache.spi.UpdateTimestampsCache"/> </bean> <!-- Configuration for query result cache. --> <bean parent="atomic-cache"> <property name="name" value="org.hibernate.cache.internal.StandardQueryCache"/> </bean> </list> </property> </bean> </beans>
import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Index; import javax.persistence.Table; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Table(name = "USER_TYPE", indexes = { @Index(columnList = "TYPE_SHORT_NAME", name = "TYPE_SHORT_NAME_UNIQUE_idx", unique = true), }) @Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "userType") public class UserType implements Serializable { private static final long serialVersionUID = -628308304752474026L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "USER_TYPE_ID") private int userTypeId; @Column(name = "TYPE_SHORT_NAME", length = 20, nullable = false) private String typeShortName; @Column(name = "TYPE_LONG_NAME", length = 255) private String typeLongName; public UserType() { } public UserType(int userTypeId, String typeShortName, String typeLongName) { this.userTypeId = userTypeId; this.typeShortName = typeShortName; this.typeLongName = typeLongName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((typeLongName == null) ? 0 : typeLongName.hashCode()); result = prime * result + ((typeShortName == null) ? 0 : typeShortName.hashCode()); result = prime * result + userTypeId; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof UserType)) return false; UserType other = (UserType) obj; if (typeLongName == null) { if (other.typeLongName != null) return false; } else if (!typeLongName.equals(other.typeLongName)) return false; if (typeShortName == null) { if (other.typeShortName != null) return false; } else if (!typeShortName.equals(other.typeShortName)) return false; if (userTypeId != other.userTypeId) return false; return true; } @Override public String toString() { return "UserType [userTypeId=" + userTypeId + ", typeShortName=" + typeShortName + ", typeLongName=" + typeLongName + "]"; } public int getUserTypeId() { return userTypeId; } public void setUserTypeId(int userTypeId) { this.userTypeId = userTypeId; } public String getTypeShortName() { return typeShortName; } public void setTypeShortName(String typeShortName) { this.typeShortName = typeShortName; } public String getTypeLongName() { return typeLongName; } public void setTypeLongName(String typeLongName) { this.typeLongName = typeLongName; } }
public interface AlphaCacheManager { AlphaCache<?, ?> getCache(Class<?> cacheClass); } import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.Ignition; import org.springframework.stereotype.Repository; @Repository public class IgniteAlphaCacheManager implements AlphaCacheManager { private final Ignite ignite; private final Map<Class<?>, AlphaCache<?, ?>> caches; public IgniteAlphaCacheManager() { System.out.println("Init cache..."); ignite = Ignition.start("classpath:/spring/ignite-configuration.xml"); //ignite = Ignition.start(); caches = new ConcurrentHashMap<>(); initCaches(); } private void initCaches() { IgniteCache<Integer, BaseIdea> igniteCache = ignite.getOrCreateCache(BaseIdea.class.getName()); AlphaCache<Integer, BaseIdea> ideaCache = new IgniteAlphaCache<>(igniteCache); caches.put(BaseIdea.class, ideaCache); } @Override public AlphaCache<?, ?> getCache(Class<?> cacheClass) { return caches.get(cacheClass); } } }
The exception that i get it below on tomcat startup:
Jul 27, 2016 1:46:43 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'hibernateStatisticsFactoryBean': Unsatisfied dependency expressed through field 'sessionFactoryHibernate': Error creating bean with name 'sessionFactoryHibernate' defined in class path resource [spring/databaseContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cache is not started: userType; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactoryHibernate' defined in class path resource [spring/databaseContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cache is not started: userType
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:350)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:756)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4811)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5272)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1407)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1397)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactoryHibernate' defined in class path resource [spring/databaseContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cache is not started: userType
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:187)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1048)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1018)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:570)
... 24 more
Caused by: java.lang.IllegalArgumentException: Cache is not started: userType
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.publicCache(GridCacheProcessor.java:3143)
at org.apache.ignite.internal.IgniteKernal.getCache(IgniteKernal.java:2427)
at org.apache.ignite.cache.hibernate.HibernateRegionFactory.regionCache(HibernateRegionFactory.java:226)
at org.apache.ignite.cache.hibernate.HibernateRegionFactory.buildEntityRegion(HibernateRegionFactory.java:175)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:364)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 35 more
Upvotes: 1
Views: 1868
Reputation: 67
@Cache
annotation will be executed only if you use the entityManager.find()
method. That mean this will work only with primary keys. Another approach is to use query cache or ignite API.
Upvotes: 2
Reputation: 3026
Till now, annotations not supported in ignite-cache (as l2 cache for hibernate).
If you don't want to put configuration of each entity in cache configuration, follow below steps
Step 1. Create a new class HibernateRegionFactoryForIgnite as below
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.cache.CacheException;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.hibernate.HibernateCollectionRegionForIgnite;
import org.apache.ignite.cache.hibernate.HibernateEntityRegionForIgnite;
import org.apache.ignite.cache.hibernate.HibernateRegionFactory;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
import org.apache.log4j.Logger;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cfg.Settings;
@SuppressWarnings("deprecation")
public class HibernateRegionFactoryForIgnite extends HibernateRegionFactory {
private static final long serialVersionUID = 530290669748711933L;
public static Logger logger = Logger.getLogger(HibernateRegionFactoryForIgnite.class);
private IgniteKernal ignite;
private IgniteInternalCache<Object, Object> dfltCache;
private final Map<String, String> regionCaches = new HashMap<>();
@Override
public void start(SessionFactoryOptions settings, Properties properties) throws CacheException {
start(new Settings(settings), properties);
initializeVariables(properties);
}
public void initializeVariables(Properties props) {
ignite = (IgniteKernal) Ignition.ignite("hibernate-grid");
String dfltCacheName = props.getProperty(DFLT_CACHE_NAME_PROPERTY);
for (Map.Entry<Object, Object> prop : props.entrySet()) {
String key = prop.getKey().toString();
if (key.startsWith(REGION_CACHE_PROPERTY)) {
String regionName = key.substring(REGION_CACHE_PROPERTY.length());
String cacheName = prop.getValue().toString();
regionCaches.put(regionName, cacheName);
}
}
if (dfltCacheName != null) {
dfltCache = ((IgniteKernal) ignite).getCache(dfltCacheName);
}
}
private IgniteInternalCache<Object, Object> regionCache(String regionName) throws CacheException {
String cacheName = regionCaches.get(regionName);
if (cacheName == null) {
if (dfltCache != null)
return dfltCache;
cacheName = regionName;
}
IgniteInternalCache<Object, Object> cache = ((IgniteKernal) ignite).getCache(cacheName);
if (cache == null)
throw new CacheException("Cache '" + cacheName + "' for region '" + regionName + "' is not configured.");
return cache;
}
@Override
public EntityRegion buildEntityRegion(String regionName, Properties props, CacheDataDescription metadata)
throws CacheException {
EntityRegion entityRegion = null;
try {
entityRegion = new HibernateEntityRegion(this, regionName, ignite, regionCache(regionName),
metadata);
} catch (Exception e) {
}
if (entityRegion == null) {
ignite.createCache(cacheConfiguration(regionName));
try {
entityRegion = new HibernateEntityRegion(this, regionName, ignite, regionCache(regionName),
metadata);
} catch (Exception e) {
logger.debug("exception occurred");
}
}
return entityRegion;
}
@Override
public CollectionRegion buildCollectionRegion(String regionName, Properties props, CacheDataDescription metadata)
throws CacheException {
CollectionRegion collectionRegion = null;
try {
collectionRegion = new HibernateCollectionRegion(this, regionName, ignite, regionCache(regionName),
metadata);
} catch (Exception e) {
}
if (collectionRegion == null) {
ignite.createCache(cacheConfiguration(regionName));
try {
collectionRegion = new HibernateCollectionRegion(this, regionName, ignite,
regionCache(regionName), metadata);
} catch (Exception e) {
logger.debug("exception occurred");
}
}
return collectionRegion;
}
private CacheConfiguration<Object, Object> cacheConfiguration(String cacheName) {
CacheConfiguration<Object, Object> cfg = new CacheConfiguration<Object, Object>();
cfg.setName(cacheName);
cfg.setCacheMode(CacheMode.PARTITIONED);
cfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
return cfg;
}
}
Step 2. Use class HibernateRegionFactoryForIgnite as value for key hibernate.cache.region.factory_class in hibernate configuration properties
Upvotes: 1
Reputation: 8390
You have to configure caches for all your regions. For example, for userType
you can add this to the configuration:
<bean parent="transactional-cache">
<property name="name" value="userType"/>
</bean>
Upvotes: 1