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)
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";
}
}
My experience is largely with seam-2 but should be equally applicable here.
The conversation and JPA session is decoupled in seam for the simple reason that a conversation ending may not result in the entity being saved.
For example, a cancel action on a long running conversation would end the conversation (since there is no reason to maintain the conversation anymore)
Considering that you are doing a rollback on the cancel in your example, it would also seem logical that you would need to call a flush as suggested by @user1187037 (theoretically a commit but I don't think that's allowed)
I think there might have been a configuration you could set so that it did flush on conversation end but I may be mistaken.
In any case, http://javalangblog.blogspot.co.uk/2010/04/flush-mode-conversation.html seems to suggest a solution
Hope that helps.
EDIT: You can configure the flush mode per conversation using xml
<begin-conversation join="true" flush-mode="COMMIT" />
and using annotations
@Begin(flushMode=COMMIT)
Bear in mind though that a conversation can @End without it being explicitly defined. If a user is partway through the conversation, made changes to entities and then abandons the conversation, it will get automatically closed after a timeout. If I remember correctly, this will cause any changes to get committed in the above case.
References:
http://docs.jboss.org/seam/3/persistence/3.0.0.Alpha1/reference/en-US/html_single/#d0e249 http://docs.jboss.org/seam/3/latest/api/org/jboss/seam/persistence/FlushModeType.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With