neo4j null pointer exception while saving via #Repository - java

The sample project i'm working with can be found attached here -
Spring Jira
This is my configuration
#EnableNeo4jRepositories(basePackages = "com.graph.repository")
public class DBConfig extends Neo4jConfiguration{
#Value("${neo4j.location}")
private String neo4jDatabaseLocation;
#Override
public SessionFactory getSessionFactory() {
return new SessionFactory(getConfiguration(), "com.graph.entity");
}
#Bean
public Configuration getConfiguration() {
Configuration configuration = new Configuration();
configuration.driverConfiguration()
.setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver")
.setURI(neo4jDatabaseLocation);
return configuration;
}
#Bean
#Override
public Session getSession() throws Exception {
return getSessionFactory().openSession();
}
}
Abstract Entity
public abstract class Entity {
#GraphId
private Long id;
public Long getId() {
return id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || id == null || getClass() != o.getClass()) return false;
Entity entity = (Entity) o;
if (!id.equals(entity.id)) return false;
return true;
}
#Override
public int hashCode() {
return (id == null) ? -1 : id.hashCode();
}
}
This is my Entity
#NodeEntity(label = "Patient")
public class Patient extends Entity {
private String patientId;
private String patientName;
private String otherPatientId;
private String sex;
private String dateOfBirth;
private String patientIdIssuer;
#Relationship(type = "STUDY", direction = Relationship.UNDIRECTED)
private Set<Study> studies;
Getters and Setters...
}
Study has nested entity/relationship and that has another nested entity/relationship. 1:N relationship
This is my repository
#Repository
public interface PatientRepository extends GraphRepository<Patient> {
}
And this is the calling method
public class Test() {
#Autowired
private PatientRepository patientRepository;
public void test() {
Patient patient = new Patient();
// set fields
patientRepository.save(patient); -> This is where I get NPE
}
}
Stack Trace :
Caused by: java.lang.NullPointerException: null
at org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver.nativeTransaction(EmbeddedDriver.java:180) ~[neo4j-ogm-embedded-driver-2.0.4.jar:na]
at org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver.newTransaction(EmbeddedDriver.java:148) ~[neo4j-ogm-embedded-driver-2.0.4.jar:na]
at org.neo4j.ogm.session.transaction.DefaultTransactionManager.openTransaction(DefaultTransactionManager.java:57) ~[neo4j-ogm-core-2.0.4.jar:na]
at org.neo4j.ogm.session.delegates.TransactionsDelegate.beginTransaction(TransactionsDelegate.java:37) ~[neo4j-ogm-core-2.0.4.jar:na]
at org.neo4j.ogm.session.Neo4jSession.beginTransaction(Neo4jSession.java:441) ~[neo4j-ogm-core-2.0.4.jar:na]
at org.neo4j.ogm.session.request.RequestExecutor.executeSave(RequestExecutor.java:84) ~[neo4j-ogm-core-2.0.4.jar:na]
at org.neo4j.ogm.session.delegates.SaveDelegate.save(SaveDelegate.java:75) ~[neo4j-ogm-core-2.0.4.jar:na]
at org.neo4j.ogm.session.delegates.SaveDelegate.save(SaveDelegate.java:44) ~[neo4j-ogm-core-2.0.4.jar:na]
at org.neo4j.ogm.session.Neo4jSession.save(Neo4jSession.java:425) ~[neo4j-ogm-core-2.0.4.jar:na]
Can someone please tell me what I'm doing wrong??
Note : I had this working earlier with sdn.3.x with GraphDatabaseService

Looks like the only thing missing is the #Configuration annotation on your Neo4jConfiguration class:
#org.springframework.context.annotation.Configuration
#EnableTransactionManagement
#EnableNeo4jRepositories(basePackages = "com.seyfert.matrix.graph.repository")
public class DBConfig extends Neo4jConfiguration{
...

Related

How to create custom auditing entity listener that extends AuditingEntityListener

I have implemented auditing through Sping Data JPA but now I want to be able to control the update and create timestamps with custom logic. So I want to write a custom auditing entity listener that extends the Auditingentitylistener.
I have the following generic entity class where I register the custom auditing entity listener:
#MappedSuperclass
#Audited
#EntityListeners(CustomAuditingEntityListener.class)
public class AuditableEntity extends BaseEntity {
#CreatedDate
#Column(name = "created", nullable = false)
private Date created;
#CreatedBy
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "created_by_id", foreignKey = #ForeignKey(name = "fk_entity_created_by_id"))
private Account createdBy;
#LastModifiedDate
#Column(name = "last_updated", nullable = false)
private Date lastUpdated;
#LastModifiedBy
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "last_updated_by_id", foreignKey = #ForeignKey(name = "fk_entity_last_updated_by_id"))
private Account lastUpdatedBy;
protected AuditableEntity() {
}
...
}
The CustomAuditingEntityListener class is defined as
#Configurable
public class CustomAuditingEntityListener extends AuditingEntityListener {
public CustomAuditingEntityListener() {
super();
}
#Override
#PrePersist
public void touchForCreate(Object target) {
if (//custom logic) {
super.touchForCreate(target);
}
}
#Override
#PreUpdate
public void touchForUpdate(Object target) {
if (//custom logic) {
super.touchForUpdate(target);
}
}
}
The custom auditing entity listener is called correctly but when the super.touchForCreate(target) or super.touchForUpdate(target) gets called the timestamps are not set because the handler in the AuditingEntityListener class is null.
This is the code of the AuditingEntityListener class:
package org.springframework.data.jpa.domain.support;
#Configurable
public class AuditingEntityListener implements ConfigurableObject {
private ObjectFactory<AuditingHandler> handler;
public AuditingEntityListener() {
JoinPoint var2 = Factory.makeJP(ajc$tjp_1, this, this);
JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);
if (this != null && this.getClass().isAnnotationPresent(Configurable.class) && AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class))) {
AnnotationBeanConfigurerAspect.aspectOf().ajc$before$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$1$e854fa65(this);
}
if ((this == null || !this.getClass().isAnnotationPresent(Configurable.class) || !AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class))) && this != null && this.getClass().isAnnotationPresent(Configurable.class) && AbstractDependencyInjectionAspect.ajc$if$6f1(var1)) {
AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
}
if (!AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class)) && AbstractDependencyInjectionAspect.ajc$if$6f1(var2)) {
AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
}
}
public void setAuditingHandler(ObjectFactory<AuditingHandler> auditingHandler) {
Assert.notNull(auditingHandler, "AuditingHandler must not be null!");
this.handler = auditingHandler;
}
#PrePersist
public void touchForCreate(Object target) {
if (this.handler != null) {
((AuditingHandler)this.handler.getObject()).markCreated(target);
}
}
#PreUpdate
public void touchForUpdate(Object target) {
if (this.handler != null) {
((AuditingHandler)this.handler.getObject()).markModified(target);
}
}
static {
ajc$preClinit();
}
}
Can someone explain how I can ensure that the AuditingHandler is not null and is set like it happens for the default AuditingEntityListener class?
With Spring 5.1 there is a rather straightforward way to autowire Spring components in the custom entity listener, so that the AuditingHandler can be used.
1. Declare the customer entity listener as a Spring component. Use constructor injection.
#Component
public class CustomAuditingEntityListener {
private ObjectFactory<AuditingHandler> handler;
public CustomAuditingEntityListener(ObjectFactory<AuditingHandler> auditingHandler) {
this.handler = auditingHandler;
}
#Override
#PrePersist
public void touchForCreate(Object target) {
if (//custom logic) {
AuditingHandler object = handler.getObject();
if (object != null) {
object.markCreated(target);
}
}
}
#Override
#PreUpdate
public void touchForUpdate(Object target) {
if (//custom logic) {
AuditingHandler object = handler.getObject();
if (object != null) {
object.markModified(target);
}
}
}
}
2. Tell Hibernate to use Spring as the bean provider by setting the appropriate configuration property:
#Configuration
public class JpaConfig extends JpaBaseConfiguration {
#Autowired
private ConfigurableListableBeanFactory beanFactory;
protected JpaConfig(DataSource dataSource, JpaProperties properties,
ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
super(dataSource, properties, jtaTransactionManager);
}
#Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
#Override
protected Map<String, Object> getVendorProperties() {
Map<String, Object> properties = new HashMap<>();
// This is the important line
properties.put(org.hibernate.cfg.AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
return properties;
}
}
--Edit-- Variation of 2. Alternatively the SpringBeanContainer can be configured this way, with the benefit of not losing the Hibernate properties that Spring Boot populates:
#Configuration
public class JpaConfig {
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
EntityManagerFactoryBuilder builder, ConfigurableListableBeanFactory beanFactory) {
return builder.dataSource(dataSource) //
.packages(BaseEntity.class) //
.persistenceUnit("myunit") //
.properties(Map.of(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory))) //
.build();
}
}

a.neo4j.mapping.Neo4jPersistentProperty: 73 - Owning ClassInfo is null for field

what does this error message mean?
2016-01-23 19:07:24,914 WARN ta.neo4j.mapping.Neo4jPersistentProperty: 73 - Owning ClassInfo is null for field: private java.lang.Long com.xenoterracide.rpf.AbstractPersistable.id and propertyDescriptor: org.springframework.beans.GenericTypeAwarePropertyDescriptor[name=id]
here's this class
public abstract class AbstractPersistable implements Identified<Long> {
private Long id;
#Override
public Long getId() {
return this.id;
}
}
I restructured my packages, and the component scan for Neo4j as defined in my config, was no longer correct. So if you get this error make sure that the class is within the scan path of the neo4j session.
#Configuration
#Profile( Strings.Profiles.EMBEDDED )
class EmbeddedConfig extends Neo4jConfiguration {
#Bean
#Override
#Scope( value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )
public Session getSession() throws Exception {
return super.getSession();
}
#Bean
#Override
public Neo4jServer neo4jServer() {
return new InProcessServer();
}
#Bean
#Override
public SessionFactory getSessionFactory() {
return new SessionFactory( Strings.PackagePaths.getModelPackages() );
}
}

Hibernate Lazy Load is Recursively Loading Set or Referencing data

I am having some strange issues with Hibenate lazy loading. I have 2 entities ProcessEntity and SectionEntity. A ProcessEntity can have many SectionEntity's and the SectionEntity should know which ProcessEntity it belongs to (#OneToMany). The problem I am having is when I load a ProcessEntity with hibernateTemplate.get(id) and then call my custom function fetchLazyCollections(entity, ...) which loops the entities methods until it finds a PersistentCollection and then forces a lazy load on that method.
When the ProcessEntity has its Set lazy loaded it recursively loads ALL the data in the SectionEntity meaning it loads the ProcessEntity which loads the SectionEntitys which load the ProcessEntity and so on! This causes a stack overflow when I try to serialize the data and must be terrible for performance. This doesn't happen when I make an HQL query etc.
Here is my setup for the Entities:
ProcessEntity:
#javax.persistence.Entity(name = "processes")
public class ProcessEntity extends Entity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id = Entity.UNSAVED_ID;
...
#OneToMany(fetch=FetchType.LAZY, mappedBy="process")
private Set<SectionEntity> sections = new HashSet<SectionEntity>();
...
public Set<SectionEntity> getSections() {
return sections;
}
public void setSections(Set<SectionEntity> sections) {
this.sections = sections;
}
...
}
SectionEntity:
#javax.persistence.Entity(name = "sections")
public class SectionEntity extends Entity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id = Entity.UNSAVED_ID;
...
#ManyToOne(fetch = FetchType.LAZY, targetEntity = ProcessEntity.class)
#JoinColumn(name="process", referencedColumnName="id")
private ProcessEntity process;
#Override
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
...
public ProcessEntity getProcess() {
return process;
}
public void setProcess(ProcessEntity process) {
this.process = process;
}
...
}
fetchLazyCollections:
public <E extends Entity> E fetchLazyCollections(E entity, String... specifiedCollections) {
if(getCurrentSession() == null) {
throw new SessionException("No session found for fetching collections.");
}
// Fetch the collections using reflection
Class<? extends Entity> clazz = entity.getClass();
for(Method method : clazz.getMethods()) {
Class<?> returnType = method.getReturnType();
if(ReflectUtils.isClassCollection(returnType)) {
// Check if the collection type is specified via the getter
List<String> specified = Arrays.asList(specifiedCollections);
if(!specified.isEmpty()) {
if(!specified.contains(method.getName())) {
continue;
}
}
try {
// Check that the collection is persistent
Collection collection = (Collection) method.invoke(entity);
if(collection instanceof PersistentCollection) {
collection.size(); // invokes lazy loading
}
}
catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
}
return entity;
}
I am using Spring on my back-end making use of #Transactional. Here is my Hibernate spring module (#Configuration):
#Configuration
#Import({
MappingModule.class
})
#ImportResource("classpath:nz/co/doltech/ims/properties.xml")
#EnableTransactionManagement
public class HibernateModule {
private static int statisticId = 0;
private #Value("#{app['root.path']}") String projectPath;
private #Value("#{app['database.jndiname']}") String databaseJndiName;
private #Value("#{app['hibernate.dialect']}") String hibernateDialect;
private #Value("#{app['hibernate.hbm2ddl']}") String hibernateHbm2dll;
private #Value("#{app['hibernate.show_sql']}") String hibernateShowSql;
private #Value("#{app['hibernate.format_sql']}") String hibernateFormatSql;
private #Value("#{app['hibernate.generate_statistics']}") String hibarnateStatistics;
private #Value("#{app['hibernate.cache.provider_class']}") String hibarnateCacheProviderClass;
private #Value("#{app['hibernate.cache.use_query_cache']}") String hibarnateQueryCache;
private #Value("#{app['hibernate.cache.use_second_level_cache']}") String hibarnateSecondLevelCache;
private #Value("#{app['hibernate.cache.use_structured_entries']}") String hibernateStructuredEntries;
private #Value("#{app['net.sf.ehcache.configurationResourceName']}") String hibernateEhcacheResource;
private #Value("#{app['flyway.enabled']}") String flywayEnabled;
private #Value("#{app['flyway.basePath']}") String flywayBasePath;
#Bean(name="dataSource")
public JndiObjectFactoryBean getDriverManagerDataSource() {
JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean();
dataSource.setJndiName(databaseJndiName);
dataSource.setCache(true);
return dataSource;
}
#Bean(name="sessionFactory")
#DependsOn({"dataSource", "flyway"})
public AnnotationSessionFactoryBean getAnnotationSessionFactoryBean() {
AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean();
sessionFactory.setDataSource((DataSource) getDriverManagerDataSource().getObject());
sessionFactory.setPackagesToScan(new String[] {
projectPath + ".server.entities",
projectPath + ".server.entities.joins"
});
Properties props = new Properties();
props.setProperty("hibernate.dialect", hibernateDialect);
props.setProperty("hibernate.show_sql", hibernateShowSql);
props.setProperty("hibernate.hbm2ddl.auto", hibernateHbm2dll);
props.setProperty("hibernate.format_sql", hibernateFormatSql);
props.setProperty("hibernate.generate_statistics", hibarnateStatistics);
props.setProperty("hibernate.cache.provider_class", hibarnateCacheProviderClass);
props.setProperty("hibernate.cache.use_query_cache", hibarnateQueryCache);
props.setProperty("hibernate.hibernate.cache.provider_configuration_file_resource_path", hibernateEhcacheResource);
props.setProperty("hibernate.use_second_level_cache", hibarnateSecondLevelCache);
props.setProperty("hibernate.cache.use_structured_entries", hibernateStructuredEntries);
props.setProperty("javax.persistence.validation.mode", "none");
// caching resource
//props.setProperty("net.sf.ehcache.configurationResourceName", hibernateEhcacheResource);
//props.setProperty("hibernate.transaction.manager_lookup_class", "nz.co.doltech.ims.server.persistence.TransactionManagerLookup");
//props.setProperty("hibernate.transaction.factory_class", "org.hibernate.transaction.JTATransactionFactory");
sessionFactory.setHibernateProperties(props);
return sessionFactory;
}
#Bean(name="transactionManager")
#DependsOn("sessionFactory")
public HibernateTransactionManager getHibernateTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getAnnotationSessionFactoryBean().getObject());
return transactionManager;
}
#Bean(name="hibernateTemplate")
#DependsOn("sessionFactory")
public HibernateTemplate getHibernateTemplate() {
HibernateTemplate hibernateTemplate = new HibernateTemplate();
hibernateTemplate.setSessionFactory(getAnnotationSessionFactoryBean().getObject());
return hibernateTemplate;
}
#Bean(name="jmxExporter")
#DependsOn("hibernateStatisticsBean")
public MBeanExporter getJmxExporter() {
MBeanExporter exporter = new MBeanExporter();
Map<String, Object> map = new HashMap<>();
Properties props = AppProperties.getProperties();
String name = props.getProperty(AppProperties.CLIENT_MODULE_NAME);
String type = props.getProperty(AppProperties.CLIENT_RELEASE_STAGE);
map.put("Hibernate:"+name+"[" + ++statisticId + "]-"+type+"=Statistics",
getHibernateStatisticsBean());
exporter.setBeans(map);
return exporter;
}
#Bean(name="hibernateStatisticsBean")
public StatisticsService getHibernateStatisticsBean() {
StatisticsService statsBean = new StatisticsService();
statsBean.setStatisticsEnabled(true);
statsBean.setSessionFactory(getAnnotationSessionFactoryBean().getObject());
return statsBean;
}
#Bean(name="incidentDao")
#DependsOn("hibernateDao")
public IncidentHibernateDao getIncidentDao() {
IncidentHibernateDao incidentDao = new IncidentHibernateDao();
//incidentDao.registerBroadcasterId(AtmosphereConst.UPDATE_ID_KEY);
return incidentDao;
}
#Bean(name="transactionTemplate")
#DependsOn({"transactionManager"})
#Scope("prototype")
public TransactionTemplate getTransactionTemplate() {
return new TransactionTemplate(getHibernateTransactionManager());
}
}
This is the Hibernate output:
hibernateDao.get(...) called:
Hibernate: select processent0_.id as id27_0_, processent0_.description as descript2_27_0_, processent0_.name as name27_0_, processent0_.nametoken as nametoken27_0_, processent0_.order_value as order5_27_0_, processent0_.removed as removed27_0_ from processes processent0_ where processent0_.id=?
hibernateDao.fetchLazyCollections(...) called:
Hibernate: select incidentjo0_.process_id as process3_27_1_, incidentjo0_.incident_id as incident2_1_, incidentjo0_.process_id as process3_1_, incidentjo0_.incident_id as incident2_21_0_, incidentjo0_.process_id as process3_21_0_, incidentjo0_.completed as completed21_0_ from incident_process incidentjo0_ where incidentjo0_.process_id=?
Hibernate: select sections0_.process as process27_1_, sections0_.id as id1_, sections0_.id as id29_0_, sections0_.description as descript2_29_0_, sections0_.name as name29_0_, sections0_.order_value as order4_29_0_, sections0_.process as process29_0_, sections0_.removed as removed29_0_ from sections sections0_ where sections0_.process=?
Nothing else is called from that point.
Does anyone have any idea what is going on here? I am out of ideas.
Appreciate any help I can get!
Cheers,
Ben

Hibernate - Spring MVC - llegal attempt to associate a collection with two open sessions

There are are many questions of same type, but none works for me.
I have Spring MVC hibernate application.
Here are my two model classes
Config.java
public class Config implements java.io.Serializable {
private Integer configId;
private String configName;
private Set<ConfigFields> ConfigFieldses = new HashSet<ConfigFields>(0);
//getters and setters
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="configuration")
public Set<ConfigFields> getConfigFieldses() {
return this.ConfigFieldses;
}
public void setConfigFieldses(Set<ConfigFields> ConfigFieldses) {
this.ConfigFieldses = ConfigFieldses;
}
}
ConfigFields.java
public class ConfigFields implements java.io.Serializable {
private Integer configFieldId;
private Confign config;
private String configFieldName;
//getteres and setters
#XmlTransient
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="ConfigId")
public Config getConfig() {
return this.config;
}
public void setConfig(Config configu) {
this.config = config;
}
}
Here is GenericHibernateDao.java
#Repository
#Transactional
public class GenericHibernateDao<T extends Serializable>
implements GenericDao<T>{
#Resource
protected SessionFactory sessionFactory;
#Override
public void insert(T transientInstance) {
sessionFactory.getCurrentSession().persist(transientInstance);
}
#Override
public void update(T instance) {
sessionFactory.getCurrentSession().saveOrUpdate(instance);
}
#Override
public void delete(T persistentInstance) {
sessionFactory.getCurrentSession().delete(persistentInstance);
}
#SuppressWarnings("unchecked")
#Override
public T merge(Serializable detachedInstance) {
return (T) sessionFactory.getCurrentSession().merge(detachedInstance);
}
#SuppressWarnings("unchecked")
#Override
public T findById(Class<?> clazz, Serializable id) {
T t= (T) sessionFactory.openSession().get(clazz, id);
return t;
}
#SuppressWarnings("unchecked")
public List<T> findByNamedQuery(Class<T> clazz, String queryName, Map<String, Object> queryParams) {
Query namedQuery = sessionFactory.getCurrentSession().getNamedQuery(queryName);
for (String s : queryParams.keySet()) {
namedQuery.setParameter(s, queryParams.get(s));
}
return namedQuery.list();
}
}
In my controller I have this method
#RequestMapping(value = "/deleteConfig/{configId}", method = RequestMethod.POST)
#ResponseBody
#Transactional
public String deleteConfiguration(#PathVariable Integer configId, HttpServletResponse response) throws IOException {
try {
Config config=configService.findById(configId);
logger.info("Deleting configuration...");
configService.delete(config);
} catch(Exception e) {
logger.debug(e.getMessage());
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
return "success";
}
My test case
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration("classpath:webapptest")
#ContextConfiguration(locations = {"classpath:test-applicationcontext.xml"})
public class ConfigurationsControllerTest {
private MockMvc springMvc;
#Autowired
WebApplicationContext wContext;
#Before
public void init() throws Exception {
springMvc = MockMvcBuilders.webAppContextSetup(wContext).build();
}
#Test
public void deleteConfiguration() throws Exception {
ResultActions resultActions=springMvc.perform(MockMvcRequestBuilders.post("/deleteConfig/117").accept(MediaType.APPLICATION_JSON));
resultActions.andDo(MockMvcResultHandlers.print());
resultActions.andExpect(MockMvcResultMatchers.status().isOk());
}
}
When I run the testcase in console, logger showing
Illegal attempt to associate a collection with two open sessions
And JUnit test case stacktrace is
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is bitronix.tm.internal.BitronixRollbackException: transaction was marked as rollback only and has been rolled back
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:932)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:66)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:168)
In Config class, I have Set which is set to CASCADE ALL. SO I am able to insert set of configfields while inserting config too. But now I want to delete by passing config object. So it should delete 1 row from config table and few rows from configfields table based on configId.
What is wrong here? And how to solve without affecting application(I mean insert)

LazyInitializationException encountered when using load instead of get with Hibernate

I am using JPA, Hibernate and Spring MVC. In the controller class all the methods works greatly. When I test them in the web browser the public String getModuleFormation(long id) method, that returns an object, and it gives me the following error:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
as a root cause, but yesterday I tried it, and it worked without problem in the localhost:45045/GestionModules/detail/xx URL.
What could cause this problem?
My detail.jsp:
<c:if test="${!empty detailModule}">
${detailModule.idModule}
${detailModule.libModule}
</c:if>
POJO Class + JPA :
#Entity
#Table(name="ModuleFormation")
public class ModuleFormation {
private long idModule;
private String libModule;
public ModuleFormation() {
// TODO Auto-generated constructor stub
}
public ModuleFormation(String libModule) {
this.libModule = libModule;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seqModule")
#SequenceGenerator(name="seqModule", sequenceName = "seqModuleFormation")
#Column(name="idModule")
public long getIdModule() {
return this.idModule;
}
public void setIdModule(long idModule) {
this.idModule = idModule;
}
#Column(name="libModule", nullable=false, length = 100)
public String getLibModule() {
return this.libModule;
}
public void setLibModule(String libModule) {
this.libModule = libModule;
}
}
DAO Class :
#Repository
public class ModuleFormationDAOImpl implements ModuleFormationDAO {
#Autowired
private SessionFactory sessionFactory;
public void ajouterModuleFormation(ModuleFormation module) {
sessionFactory.getCurrentSession().save(module);
}
public void supprimerModuleFormation(long idModule) {
ModuleFormation module = (ModuleFormation) sessionFactory.getCurrentSession().load(ModuleFormation.class, idModule);
if(module != null)
sessionFactory.getCurrentSession().delete(module);
}
public List<ModuleFormation> listModuleFormation() {
return sessionFactory.getCurrentSession().createQuery("from ModuleFormation")
.list();
}
public ModuleFormation getModuleFormation(long idModule) {
return (ModuleFormation) sessionFactory.getCurrentSession().load(ModuleFormation.class, idModule);
}
public void majModuleFormation(ModuleFormation module) {
sessionFactory.getCurrentSession().merge(module);
}
}
Service Class :
#Service
public class ModuleFormationServiceImpl implements ModuleFormationService {
#Autowired
private ModuleFormationDAO moduleDao;
#Transactional
public void ajouterModuleFormation(ModuleFormation module) {
moduleDao.ajouterModuleFormation(module);
}
#Transactional
public void supprimerModuleFormation(long idModule) {
moduleDao.supprimerModuleFormation(idModule);
}
#Transactional
public List<ModuleFormation> listModuleFormation() {
return moduleDao.listModuleFormation();
}
#Transactional
public ModuleFormation getModuleFormation(long idModule) {
return moduleDao.getModuleFormation(idModule);
}
#Transactional
public void majModuleFormation(ModuleFormation module) {
moduleDao.majModuleFormation(module);
}
}
Controller Class :
#Controller
public class ModuleFormationController {
#Autowired
private ModuleFormationService moduleService;
#RequestMapping("/module")
public String listModulesFormations(Map<String, Object> map) {
map.put("module", new ModuleFormation());
map.put("moduleList", moduleService.listModuleFormation());
return "module";
}
#RequestMapping(value = "/ajouter", method = RequestMethod.POST )
public String ajouterModuleFormation(#ModelAttribute("module")
ModuleFormation module,BindingResult result) {
moduleService.ajouterModuleFormation(module);
return "redirect:/module";
}
#RequestMapping(value = "/supprimer/{idModule}")
public String supprimerModuleFormation(#PathVariable("idModule")
long idModule) {
moduleService.supprimerModuleFormation(idModule);
return "redirect:/module";
}
#RequestMapping(value= "/detail/{idModule}")
public String getModuleFormation(#PathVariable("idModule")
long idModule,Map<String, Object> map) {
map.put("detailModule", moduleService.getModuleFormation(idModule));
return "/detail";
}
#RequestMapping(value= "/detail/modifier", method = RequestMethod.POST )
public String majModuleFormation(#ModelAttribute("detailModule")
ModuleFormation module, BindingResult result) {
moduleService.majModuleFormation(module);
return "detail/{idModule}";
}
}
The Javadoc on the Hibernate Session#load(Class, Serializable) method says:
Return the persistent instance of the given entity class with the given identifier,
assuming that the instance exists. This method might return a proxied instance that
is initialized on-demand, when a non-identifier method is accessed.
When you access a property on the object in your JSP the session which loaded the object has been closed.
Use Session#get(Class, Serializable) to ensure that you don't load a proxy.
Instead of sessionFactory.getCurrentSession().load(ModuleFormation.class, idModule), have you tried sessionFactory.getCurrentSession().get(ModuleFormation.class, idModule)?

Categories