Unit tests in JUnit failing when I run update/delete commands - spring

I am currently working on an API implementation in Java with spring and hibernate.
I have two tables in my Model package
User and UserDetail which has a OneToMany mapping
#Entity
public class User {
private Long id;
private String userId;
private Set<UserDetail> userDetails;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "user")
public Set<UserDetail> getUserDetails() {
return userDetails;
}
public void setUserDetail(Set<UserDetail> userDetails) {
this.userDetails = userDetails;
}
}
#Entity
public class User {
private Long id;
private String key;
private String value;
private User user;
#ManyToOne
#JoinColumn(name = "USER_ID", nullable = false)
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
My API looks like this
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void addUserDetail(AddUserDetailRequest request) {
//... adds the user detail for the userId as request.getUserId()
}
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void deleteUserDetail(DeleteUserDetailRequest request) {
//... deletes a particular value for a user with userId as request.getUserId() and userDetail key as request.getDeleteKey()
}
I have written Junit test cases to test the addition and deletion of UserDetails for a user, My addUserDetail is working as it should, but when I call the delete the changes are not reflected and they fail.
Below is my test case
#Test
public void testDeletUserDetail() throws Exception {
//GIVEN
String userId = client.newUser().call(getCreateUserRequest()).getId();
client.newAddUserDetail().call(getAddUserDetailRequest(userId, "key1", "value1"));
client.newAddUserDetail().call(getAddUserDetailRequest(userId, "key2", "value2"));
//WHEN
client.newDeteteUserDetail().call(getDeleteUserDetailRequest(userId, "key2"));
//THEN
List<UserDetail> userDetails = client.newGetUserDetail().call(getGetUserDetailRequest(userId));
assertEquals(userDetails.size(), 1); // This check fails and says it has a size of 2 instead of 1.
}
I am using HSQL for testing purposes
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.iiitd.myAPI.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="HSQL" />
<property name="generateDdl" value="true" />
<property name="showSql" value="false" />
</bean>
</property>
</bean>
<jdbc:embedded-database id="dataSource" type="HSQL" />
I have two implementation for deleteUserDetail and one of them fails.
// This one works in both jUnit and manual testing
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void deleteUserDetail(DeleteUserDetailRequest request) {
User user = userRepository.findByUserId(request.getUserId());
if(!CollectionUtils.isEmpty(user.getUserDetail())) {
UserDetail toRemove = null;
for(UserDetail userDetail : user.getUserDetail()) {
if(StringUtils.equals(userDetail.getKey(), request.getDeleteKey())) {
toRemove = userDetail;
}
}
Assert.notNull(toRemove, "Detail user doesn't exist.");
user.getUserDetail().remove(toRemove);
userRepository.save(user);
}
}
//This one doesn't and unit tests fails but manual tests are OK
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void deleteUserDetail(DeleteUserDetailRequest request) {
UserDetail userDetail = userDetailRepository.getUserDetail();
Assert.notNull(userDetail, "Detail doesn't exists");
userDetailRepository.delete(userDetail);
}
All the repositories extends JpaRepository
Could anyone explain how to circumvent this issue ?
Any help would be appreciated.

Related

Hibernate Creating an already created table even if property <name="hibernate.hbm2ddl.auto" value="update"> is set to update.(Db is postgres)

I am using Hibernate as an ORM for a Spring Boot Application to write values to my Postgres Database.I have configured the properties in my persistence.xml
Persistence.xml
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/ImageHoster" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="postgres" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
I have created an entity called Movie
Movie
#Entity
#Table(name = "Movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
public String id;
#Column(name = "movie")
public String movie;
#Column(name = "updatedDate")
public Date updatedDate;
#Lob
#Column(name = "image")
public String image;
public String getMovie() {
return movie;
}
public void setMovie(String movie) {
this.movie = movie;
}
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
At the first time when there is no movie table in my postgres database the table is getting created and there is no error.But as i am running the application once the table is created it is trying to create the table again which is causing the below error
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement.
My Configuration for the JPA goes like this
JPAConfig
#Configuration
public class JpaConfig {
#Bean
public EntityManagerFactory entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf =new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceXmlLocation("classpath:META-INF/persistence.xml");
emf.afterPropertiesSet();
return emf.getObject();
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.postgresql.Driver");
ds.setUrl("jdbc:postgresql://localhost:5432/ImageHoster");
ds.setUsername("postgres");
ds.setPassword("postgres");
return ds;
}
}
Any idea where i am going wrong as I have another entity called User which is working fine and is not getting created everytime the application runs.
Once i changed the table name from Movie to movie in my entity everything was working as expected.
#Entity
#Table(name = "movie"){
}
This made everything fine..any idea why this happened? as i am not able to understand why it is a problem.

Own SpringSecurity UserDetailsService dont load User - Could not obtain transaction-synchronized Session for current thread

I wrote my own SpringSecurity UserDetailsService. I used this tutorial for it.
The only differents between my configuration and that tutorial is, that I have a xml file for spring framework. But my application didn't work:
The problem is, that userDao.load(email); (watch UserDetailsService below) returns null and not an userObject. But if I switch the configuration of SpringSecurity to an inMemoryAuthentication and use userDao.load(email); in another context, the service returns the right user.
Stacktrace:
SCHWERWIEGEND: An internal error occurred while trying to authenticate the user.
org.springframework.security.authentication.InternalAuthenticationServiceException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:110)
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:132)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Caused by: org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at de.nak.cars.dao.UserDAO.load(UserDAO.java:61)
at de.nak.cars.service.impl.UserDetailsServiceImpl.loadUserByUsername(UserDetailsServiceImpl.java:34)
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:102)
... 39 more
UserDetailsService:
#Component
#Qualifier("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserDAO userDao;
#Transactional(readOnly=true)
#Override
public UserDetails loadUserByUsername(final String email)
throws UsernameNotFoundException {
de.name.cars.model.User user = userDao.load(email); //load returns null, saw in debug mode
List<GrantedAuthority> authorities = buildUserAuthority(user.getRoles());
return buildUserForAuthentication(user, authorities);
}
private UserDetails buildUserForAuthentication(de.name.cars.model.User user,
List<GrantedAuthority> authorities) {
return new User(user.getEmail(), user.getPassword(), true, true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> roles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
for (UserRole role : roles){
setAuths.add(new SimpleGrantedAuthority(role.getRoleName()));
}
List<GrantedAuthority> result = new ArrayList<GrantedAuthority>(setAuths);
return result;
}
}
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="de.nak.cars" />
<!-- The data source -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url"
value="jdbc:h2:Y:/db/nak"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<!-- The session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="de.nak.cars.model"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.hbm2ddl.import_files">initial-sql.sql</prop>
</props>
</property>
</bean>
<!-- The transaction manager -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- The advice -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- The pointcut definition -->
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(* de.nak.cars.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
</beans>
User.java
#Entity
public class User implements Serializable {
/** Generated version id. */
private static final long serialVersionUID = -5464675373969471720L;
/** The identifier. */
private Long id;
/** The user's firstname. */
private String firstName;
/** The user's lastname. */
private String lastName;
/** The user's student identification number. */
private String email;
/** The user's roles. */
private Set<UserRole> roles;
/** The user's password. */
private String password;
/** Set of user-exam combinations. */
private Set<ExamKey> examKeys = new HashSet<ExamKey>(0);
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "FIRST_NAME", length = 100, nullable = false)
public String getFirstname() {
return firstName;
}
public void setFirstname(String firstName) {
this.firstName = firstName;
}
#Column(name = "LAST_NAME", length = 100, nullable = false)
public String getlastName() {
return lastName;
}
public void setlastName(String lastName) {
this.lastName = lastName;
}
#ManyToMany(fetch = FetchType.LAZY, cascade= CascadeType.ALL)
#JoinTable(name="USER_USERROLE", joinColumns = {
#JoinColumn(name="USER_ID", nullable = false, updatable = false)},
inverseJoinColumns = { #JoinColumn(name="ROLE_ID", nullable = false, updatable = false)})
public Set<UserRole> getRoles() {
return roles;
}
public void setRoles(Set<UserRole> roles) {
this.roles = roles;
}
#Column(name = "EMAIL", nullable = false, unique = true)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name="PASSWORD", nullable = false)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "examKeyId.user")
public Set<ExamKey> getExamKeys() {
return examKeys;
}
public void setExamKeys(Set<ExamKey> examKeys) {
this.examKeys = examKeys;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.hashCode());
result = prime * result + ((lastName == null) ? 0 : email.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
if (!email.equals(other.email))
return false;
return true;
}
#Override
public String toString() {
return "User [id=" + id + ", firstName=" + firstName + ", lastName="
+ lastName + ", email=" + email + ", password=" + password + ", examKeys=" + examKeys
+ "]";
}
}
you need to enable transaction management support. In the guide you followed it was done with #EnableTransactionManagement annotation over AppConfig class. In your case you use xml configuration, so you should add <tx:annotation-driven transaction-manager="txManager" /> inside your spring-config.xml

JPA no session when calling child

I am using spring-data-jpa and JPA repositories
here is my source code
<beans:bean id="producerService" class="cz.services.RepositoryProducerService" />
<jpa:repositories base-package="cz.repository" />
<beans:bean id="myEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="packagesToScan" value="cz.models" />
<beans:property name="jpaVendorAdapter">
<beans:bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</beans:property>
<beans:property name="jpaProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<beans:property name="entityManagerFactory" ref="myEmf" />
</beans:bean>
<beans:bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="url"
value="jdbc:mysql://localhost:3306/mydb?zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8" />
<beans:property name="username" value="root" />
<!--<property name="password" value="test" /> -->
<beans:property name="password" value="test"></beans:property>
</beans:bean>
and here is my entity and repository classes:
package cz.models;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the users database table.
*
*/
#Entity
#Table(name="users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private int enabled;
private String password;
private String username;
//bi-directional many-to-one association to Authority
#OneToMany(mappedBy="user")
private List<Authority> authorities;
//bi-directional many-to-one association to Room
#OneToMany(mappedBy="user")
private List<Room> rooms;
//bi-directional many-to-one association to UsersData
#OneToMany(mappedBy="user")
private List<UsersData> usersData;
public User() {
}
....
public List<Room> getRooms() {
return this.rooms;
}
and here are User Repository:
public void setRooms(List<Room> rooms) {
this.rooms = rooms;
}
public Room addRoom(Room room) {
getRooms().add(room);
room.setUser(this);
return room;
}
public Room removeRoom(Room room) {
getRooms().remove(room);
room.setUser(null);
return room;
}
public List<UsersData> getUsersData() {
return this.usersData;
}
public void setUsersData(List<UsersData> usersData) {
this.usersData = usersData;
}
public UsersData addUsersData(UsersData usersData) {
getUsersData().add(usersData);
usersData.setUser(this);
return usersData;
}
public UsersData removeUsersData(UsersData usersData) {
getUsersData().remove(usersData);
usersData.setUser(null);
return usersData;
}
}
and userRepository:
public interface UserRepository extends JpaRepository<User, Integer> {
#Transactional
#Query("select u from User u WHERE u.enabled = 1 ")
public List<User> findAllactiveUsers();
#Transactional
#Query("select u from User u WHERE u.username = :username ")
public User findByUsername(#Param("username")String username);
}
and my service for spring security:
#Service
public class MyUserDetailsService implements UserDetailsService {
#Resource
UserRepository repositoryUser;
#Resource
AuthorityRepository repositoryAuthority;
public UserDetails loadUserByUsername(String username) {
System.out.println("start");
cz.models.User userModel = null;
UserDetails userDetail = null;
try{
userModel = repositoryUser.findByUsername(username);
// User user = userModel;
System.out.println(userModel.getUsername());
List<Authority> authorities = repositoryAuthority.findAllByUser(userModel);
// repositoryUserData.findAll();
System.out.println(userModel.getAuthorities().size());
Collection<SimpleGrantedAuthority> collectionAuthorities = new ArrayList<SimpleGrantedAuthority>();
for (int i = 0; i < authorities.size(); i++) {
collectionAuthorities.add(new SimpleGrantedAuthority(authorities
.get(i).getAuthority()));
}
userDetail = new User(userModel.getUsername(),
userModel.getUsername(), collectionAuthorities);
}catch(Exception e){
e.printStackTrace();
}
return userDetail;
}
}
The problem is: when I want call - this peace of code:
userModel.getAuthorities()
which call child (fk in db). I have exception :
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
When I add second repository Authorities I do not have this no session problem. But I do not want create every time method in my repository.
List<Authority> authorities = repositoryAuthority.findAllByUser(userModel);
I have to use hibernate.LazyInitialization instead of eanger.(and some stable)
I saw a lot of post with this problem with JPA, but nothing work for me :(
Use a query that fetches the data you want so that it is there when you need it.
#Query("select u from User u left join fetch u.authorities WHERE u.username = :username ")
public User findByUsernameFetchAuthorities(#Param("username")String username);
Using findByUsernameFetchAuthorities when you want to access the authorities will cause them to be pre-fetched, avoiding the error and keeping them lazily fetched for every other query.

Getting the error NoSuchMethodError: org.apache.cassandra.thrift.TBinaryProtocol when using Apache Cassandra,Kundera,Spring MVC

I keep getting the message
java.lang.NoSuchMethodError: org.apache.cassandra.thrift.TBinaryProtocol: method <init>(Lorg/apache/thrift/transport/TTransport;)V not found
at com.impetus.client.cassandra.schemamanager.CassandraSchemaManager.initiateClient(CassandraSchemaManager.java:446)
at com.impetus.kundera.configure.schema.api.AbstractSchemaManager.exportSchema(AbstractSchemaManager.java:101)
at com.impetus.client.cassandra.schemamanager.CassandraSchemaManager.exportSchema(CassandraSchemaManager.java:138)
at com.impetus.kundera.configure.SchemaConfiguration.configure(SchemaConfiguration.java:172)
at com.impetus.kundera.configure.ClientMetadataBuilder.buildClientFactoryMetadata(ClientMetadataBuilder.java:45)
at com.impetus.kundera.persistence.EntityManagerFactoryImpl.configureClientFactories(EntityManagerFactoryImpl.java:352)
at com.impetus.kundera.persistence.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:116)
at com.impetus.kundera.KunderaPersistence.createEntityManagerFactory(KunderaPersistence.java:83)
at com.impetus.kundera.KunderaPersistence.createContainerEntityManagerFactory(KunderaPersistence.java:65)
Whenever I try to run my Java Spring MVC 3.2 Project. I am trying to connect to Apache Cassandra 1.2.8 that I have installed on my machine from the Spring WebApp using Kundera. I have included the following dependencies in the pom.xml file of the project:
scale7-pelops(1.3-1.1.x)
cassandra-all & cassandra-clientutil (1.2.8)
kundera-core & kundera-cassandra (2.6)
My Spring Project uses XML-less configuration (Java Config) and JPA apart from kundera's persistence.xml which is under {PROJECT}/src/main/resources/META-INF so as to be at the base of the classpath during deployment. My persistence.xml looks like:
<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_2_0.xsd"
version="2.0">
<persistence-unit name="cassandra_pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<class>org.tutiworks.orm.Role</class>
<class>org.tutiworks.orm.User</class>
<properties>
<property name="kundera.nodes" value="localhost"/>
<property name="kundera.port" value="9160"/>
<property name="kundera.keyspace" value="afrikana"/>
<property name="kundera.dialect" value="cassandra"/>
<property name="kundera.ddl.auto.prepare" value="update"/>
<property name="kundera.client.lookup.class" value="com.impetus.client.cassandra.pelops.PelopsClientFactory" />
<property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider"/>
<property name="kundera.cache.config.resource" value="/ehcache-cassandra.xml"/>
</properties>
</persistence-unit>
</persistence>
And the configuration class creating the entityManager looks like:
#Configuration
public class SpringDataConfig extends WebMvcConfigurerAdapter{
#Autowired
private Environment env;
#Value("${kundera.nodes}") private String node;
#Value("${kundera.port}") private String port;
#Value("${kundera.keyspace}") private String keyspace;
#Value("${kundera.dialect}") private String dialect;
#Value("${kundera.ddl.auto.prepare}") private String dbGenerator;
#Value("${kundera.cache.provider.class}") private String cacheClass;
#Value("${kundera.client.lookup.class}") private String lookupClass;
#Value("${kundera.cache.config.resource}") private String configResource;
#Value("${persistence.unit.name}") private String persistenceUnitName;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitName(persistenceUnitName);
return em;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
The following class shows how the persistence context is used.
public abstract class GenericDAO< T extends Serializable > {
private Class<T> clazz;
#PersistenceContext
EntityManager entityManager;
protected void setClazz( Class<T> clazzToSet ){
this.clazz = clazzToSet;
}
public T findOne( String id ){
return this.entityManager.find( this.clazz, id );
}
#SuppressWarnings("unchecked")
public List< T > findAll(){
return this.entityManager.createQuery( "from " + this.clazz.getName() )
.getResultList();
}
public void save( T entity ){
this.entityManager.persist( entity );
}
public void update( T entity ){
this.entityManager.merge( entity );
}
public void delete( T entity ){
this.entityManager.remove( entity );
}
public void deleteById( String entityId ){
T entity = this.findOne( entityId );
this.delete( entity );
}
}
A sample of the ORM that is mapped to a column family in Apache Cassandra installation looks like the following.
#XmlRootElement(name = "Role")
#Entity(name="Role")
#Table(name = "roles", schema = "afrikana#cassandra_pu")
public class Role implements Serializable {
private static final long serialVersionUID = 9127322651789683331L;
#Id
#Column(name="id")
#XmlID
private String id;
#Column(name = "role_name")
#XmlElement(name = "role_name")
private String roleName;
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Where would I be going wrong with my configuration? What I'm I missing? How do I fix the error?
Kundera cassandra libraries are running on 1.2.4 version. Ideally 1.2.8 or higher versions should always be backward compatible, but in this case unfortunately they are not!

Error in entity retrieval

I am attempting to handle an 'entity' through annotation instead of a hibernate xml mapping.
I face a situation where addition succeeds but retrieval fails - help is appreciated.
Model class:
#Entity
#Table(name = "PERSON")
public class Person implements Serializable {
private static final long serialVersionUID = -5527566248002296042L;
#Id
#Column(name = "ID")
#GeneratedValue
private Integer id;
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
#Column(name = "MONEY")
private Double money;
.....setters and getters
}
spring configuration:
<context:annotation-config />
<context:component-scan base-package="org.spring.entity,org.spring.service" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
....
</bean>
<!-- Hibernate session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
...
<property name="packagesToScan">
<list>
<value>org.spring.entity</value>
<value>org.spring.service</value>
</list>
</property>
<property name="hibernateProperties">
...
</property>
</bean>
Service class:
public void add(String firstName, String lastName, Double money) {
// Retrieve session from Hibernate
Session session = sessionFactory.openSession();
try{
// Create a new person
Person person = new Person();
person.setFirstName(firstName);
person.setLastName(lastName);
person.setMoney(money);
// Save
session.save(person);
}
finally{
session.close();
}
}
public void edit(Integer id, String firstName, String lastName, Double money) {
// Retrieve session from Hibernate
Session session = sessionFactory.openSession();
try{
// Retrieve existing person via id
Query query = session.createQuery("FROM Person WHERE ID=?");<=FAILS HERE
query.setInteger(0, id);
Person person = (Person)query.list().get(0);
......
}
The error is as below:
Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException:
person is not mapped [from person where ID=?]
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClass
Persister(SessionFactoryHelper.java:180)
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement
(FromElementFactory.java:110)
at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromCla
use.java:93)
at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlW
alker.java:324)
Your HQL is wrong, Do this way:
(in case of multiple results, their might be some syntax left right, please check.)
Query query = session.createQuery("FROM Person WHERE ID=:ID")
List list=query.setParameter("ID",ID).list();
or
(in case of Single result)
Person person =new Person ();
person =(Person ) session.get(Person .class, ID);

Resources