2

I have a spring-based Java EE web application. there is a repository layer (data access object layer) that i am testing using junit. i use maven to build and test my project.

my problem is this: when i run the tests on windows, the automated/default rollback behavior of spring works, however, when i deploy to my linux development server and attempt to run the tests, the rollback behavior does not seem to work.

here is a sample table. notice that the user name field is specified to be unique.

create table user (
 id mediumint not null auto_increment,
 username varchar(50),
 passwd varchar(50),
 unique(username)
);

here is my plain-old-java-object (pojo) modeling this table.

@Entity
@Table(name="user")
public class User {
 @Column(name="id")
 public int id;
 @Column(name="username")
 public String username;
 @Column(name="passwd")
 public String passwd;

 public void User() { }

 public void User(String username, String passwd) {
  this.username = username;
  this.passwd = passwd;
 }
}

and then i have a JPA repository to persist a user as follows.

@Repository
public class JpaUserRepository {
 @PersistenceContext
 EntityManager em;

 public User find(int id) {
  User user = this.em.find(User.class, id);
  return user;
 }

 public void save(User user) {
  this.em.persist(user);
 }

 public void delete(User user) {
  this.em.remove(user);
 }
}

my unit tests using junit is as follows.

@ContextConfiguration(locations={"classpath:spring/business.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class JpaUserRepositoryTests {
 @AutoWired
 UserRepository userRepository;

 @Test
 @Transactional
 public void testSave() {
  User user = new User("user1","pw");
  userRepository.save(userRepository);

  user = userRepository.find(user.id);
  Assert.assertNotNull(user);
 }

 @Test
 @Transactional
 public void testDelete() {
  User user = new User("user1","pw");
  userRepository.save(userRepository);

  user = userRepository.find(user.id);
  Assert.assertNotNull(user);

  userRepository.delete(user);

  user = userRepository.find(user.id);
  Assert.assertNull(user);
 }
}

again, on windows, when i run "mvn clean test", i get no failures. however, when i run this on my linux (CentOS 6.4 x64) box, i get a org.hibernate.exception.ConstraintViolationException because of the "user1" value.

i did some searching on stackoverflow. here's what i tried.

  • used the @Rollback annotation to every method in the **Tests classes.
  • used @TransactionConfiguration(defaultRollback=true) at the class level on all **Tests classes.

however, neither of these modifications work.

note the versions and/or differences of my windows vs linux environment. i'm not sure they make a difference.

  • spring framework 3.2.2.RELEASE
  • spring jpa 1.3.1.RELEASE
  • maven surefire plugin 2.15
  • maven 3.0.5 (version 3.1.0 on linux)
  • junit 4.11
  • JDK 1.7
  • MySql 5.6.11 (version 5.1.69 on linux)

also, please note that after "mvn clean test", on windows, if i do a

select * from user;

then i get 0 results. but on linux, i do see that the user row/record is in the table. this is the reason why i think rollback is not working on linux.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Jane Wayne
  • 8,205
  • 17
  • 75
  • 120
  • Does both Systems (win and linux) use the SAME database? – Ralph Aug 05 '13 at 16:32
  • well, yes and no. yes, the same database MySQL, but not the same version. on windows, as noted above, it's 5.6.11 and on linux, it's 5.1.69. they are both 64-bit MySQL, however. but i can't imagine this problem of not rolling back is at the database level, can it be so? i'd think that the logic to rollback would be in spring. unless somehow, rollback isn't a supported operation on MySQL 5.1.69 on linux? – Jane Wayne Aug 05 '13 at 16:35
  • not sure what you mean by "same" database. same as in same versions? no. same as in same instance? no. – Jane Wayne Aug 05 '13 at 18:26
  • @Ralph thanks, for that pointer.. i decided to upgrade MySQL on my linux box to 5.6.11, now everything works. all i can say is WOW. i cannot believe it was a database issue. – Jane Wayne Aug 05 '13 at 18:45
  • My idea was more that one db is inno-db and the other one was myIsam, but anyway. If you fixed it, then it is done. – Ralph Aug 05 '13 at 20:33
  • @Ralph you may be right on that. thanks for that pointer. maybe with the later version of MySQL, myisam is not the default and it's innodb. i just read, per your last comment, that myisam does not support rollback operations. – Jane Wayne Aug 06 '13 at 00:24

1 Answers1

0

ok, so here's what was happening.

on my windows box, i was using MySQL v5.6.11. on my linux box, i was using MySQL v5.1.69.

according to this link, http://dev.mysql.com/doc/refman/5.5/en/innodb-default-se.html, innodb is the default storage engine starting with v5.5, and prior to v5.5, myisam was the default storage engine.

according to this link, http://dev.mysql.com/doc/refman/5.1/en/myisam-storage-engine.html, it reinforces that myisam is the default storage engine in v5.1.

so, on my linux box, i was on v5.1.69, and the default storage was myisam, thus, spring's automagic rollback mechanism never worked.

Jane Wayne
  • 8,205
  • 17
  • 75
  • 120
  • according to these links below, myisam does not support rollback/transactional operations. http://www.rackspace.com/knowledge_center/article/mysql-engines-myisam-vs-innodb http://stackoverflow.com/questions/3404467/mysql-rollback-on-the-myisam-engine – Jane Wayne Aug 07 '13 at 18:57