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";
    }
}