I have a Seam 3 sandbox application using JBoss 7, Hibernate as default JPA implementation and as JSF as web front end.
I have the problem, that the SQL UPDATE is swallowed by default.
My stateful EJB in conversation scope maintains an extended scoped EntityManager and one Entity, Container Managed Transactions (Requires new)
- The EntityManager gets injected
- The EJB uses the EM to load the Entity and keeps it in a field
- JSF application accesses the EJB and its entity, changes a String field
- JSF application calles "Save" method in EJB
- In save() I check, if the Entities field was changed -> it was changed properly
- I do nothing more, the container commits the transaction after save() is finished.
- Problem: No SQL update is performed against the DB.
If i extend save() by:
a) entityManager.contains(entity) the UPDATE is executed as expected (result is "true")
OR
b) entityManager.persist(entity) the UPDATE is executed as expected
Q: As far as I understand the specs neither of a) or b) should be required, because the Entity remains managed during the entire process. I dont understand, why a) has an effect on saving. I can imaging the b) has an effect on saving, but it should not be required, should it?
Any explanation is welcome.
Here is my EJB:
@Named
@ConversationScoped
@Stateful
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class LanguageBean {
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
@Inject
private UserTransaction transaction;
private Language value;
@Inject
Conversation conversation;
public LanguageBean() {
super();
}
@Begin
public void selectLanguage(Long anId) {
conversation.setTimeout(10 * 60 * 1000);
if (anId != null) {
value = em.find(Language.class, anId);
}
}
@BeforeCompletion
public void transactionComplete(){
System.out.println("transactionComplete");
}
public Language getValue() {
return value;
}
@Produces
@Named
@ConversationScoped
public Language getLanguage() {
return getValue();
}
public void setValue(Language aValue) {
value = aValue;
}
@End
public String save() {
// displays the changed attribute:
System.out.println("save code: "+value.getCode());
// why is either this required:
// boolean tempContains = em.contains(value);
// System.out.println("managed: "+tempContains);
// or: why is persist required:
em.persist(value);
return "languages?faces-redirect=true";
}
@End
public String cancel() throws SystemException {
transaction.setRollbackOnly();
return "languages?faces-redirect=true";
}
}