I know this question has been asked many times before but i couldn't find any answer to my problem.
I have a Webapp that uses wildfly 8 as container. The problem is that if I throw an exception within my ejb the transaction is not rolled back.
I know if I annotate my ejb with @stateless and @localbean it is per default transactional.
I have tried the following things:
checked if the db does roll back a transaction if i write sql code in the workbench
begin;
INSERT INTO `bookservicewebapp`.`author` (`firstname`, `lastname`) VALUES ('firstname1', 'lastname1');
SELECT * FROM bookservicewebapp.author;
INSERT INTO `bookservicewebapp`.`author` (`firstname`, `lastname`) VALUES ('firstname2', 'lastname2');
rollback; //worked!
turn off autocommit in mysql //in my.ini
@Transactional(rollbackOn = Exception.class)
myself@ApplicationException(rollback=true)
@TransactionTimeout(unit=TimeUnit.SECONDS,value=5)
and wait 6 seconds within the method.The code under discussion is:
public List<Long> saveBooks(List<Book> books){
List<Long> savedBooksIds = new ArrayList<>(books.size());
for (Book book : books) {
// are these authors in the db?
List<Author> fetchedAuthors = new ArrayList<Author>();
if (book.getAuthors() == null || book.getAuthors().size() == 0) {
throw new RuntimeException("no authors");
}
for (Author a : book.getAuthors()) {
//select all authors with given attributes
List<Author> buf = getAuthorsByStuff(a.getFirstname(),
a.getLastname(), a.getBirthday());
if (buf.size() != 1) {
throw new RollbackException("author " + a.getFirstname()
+ " does not exist");
} else {
fetchedAuthors.add(buf.get(0));
}
}
book.setAuthors(fetchedAuthors);
// is the publisher in the db?
if (book.getPublisher() != null) {
Publisher pub = book.getPublisher();
//select all publishers with given attributes
List<Publisher> buf = getPublishersByStuff(pub.getName(),
pub.getPostcode(), pub.getCountrycode());
if (buf.size() != 1) {
throw new RollbackException("publisher " + pub.getName()
+ " does not exist");
} else {
book.setPublisher(buf.get(0));
}
}
//em.persist(book);
savedBooksIds.add(em.merge(book).getId());
}
return savedBooksIds;
}
The selection code:
public List<Author> getAuthorsByStuff(String firstname, String lastname,
Date date) {
return em.createNamedQuery("Author.getAuthorsByStuff", Author.class)
.setParameter("firstname", firstname)
.setParameter("lastname", lastname)
.setParameter("birthday", date).getResultList();
}
The error was that wildfly was misconfigured. JTA had to be enabled and a isolationlevel has to be configured.
<datasource jta="true" jndi-name="java:jboss/datasources/BookServiceWebAppDS" pool-name="BookServiceWebAppDS" enabled="true" use-ccm="false">
<connection-url>jdbc:mysql://localhost:3306/bookservicewebapp</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver>mysql</driver>
<transaction-isolation>TRANSACTION_REPEATABLE_READ</transaction-isolation>
<security>
<user-name>username</user-name>
<password>password</password>
</security>
<validation>
<validate-on-match>false</validate-on-match>
<background-validation>false</background-validation>
</validation>
<statement>
<share-prepared-statements>false</share-prepared-statements>
</statement>
</datasource>