Conversation (Old Seam vs CDI/EJB)
tony.herstell1 Jul 5, 2013 2:17 AMI have a very clean JEE 6 project (No Seam3/CODI addons etc.).
In "old" Seam 2 a conversation was "transactional". If the conversation was not ended then all updates were rolled back.
Brillaint, simple to understand and use and basically "easy".
I have been struggling with CDI/EJB to replicate the same thing and pobably am confused.
Let me explain...
I set up my bean:
Make it stateful (to get Transactions
Make it conversational
//Tell prettyfaces to use this bean when the pattern matches and show the manage Organisations page. Also support a Query Param (cid). @URLMappings(mappings = { @URLMapping(id = "manageOrganisations", pattern = "/organisation/manage", viewId = "/pages/organisation/manageOrganisations.xhtml"), @URLMapping(id = "createOrganisation", pattern = "/organisation/create", viewId = "/pages/organisation/CRUDOrganisation.xhtml"), @URLMapping(id = "readOrganisation", pattern = "/organisation/view", viewId = "/pages/organisation/CRUDOrganisation.xhtml"), @URLMapping(id = "updateOrganisation", pattern = "/organisation/update", viewId = "/pages/organisation/CRUDOrganisation.xhtml"), @URLMapping(id = "deleteOrganisation", pattern = "/organisation/delete", viewId = "/pages/organisation/CRUDOrganisation.xhtml") }) // Leverage EJB to get Transactional Support @Stateful // Lets be long running (multiple client-server round trips) - Needs Extended on // PersistanceContext too to hold onto my objects and not get LIEs. @ConversationScoped // EL Can can find me... @Named public class OrganisationManagementController extends BaseController { @URLQueryParameter("cid") private String cid; // DON'T let any Entities be Proxied by WELD so just use class local. // According to this definition, JPA entities are technically managed beans. // However, entities have // their own special lifecycle, state and identity model and are usually // instantiated by JPA or using // new. Therefore we don't recommend directly injecting an entity class. We // especially recommend // against assigning a scope other than @Dependent to an entity class, since // JPA is not able to // persist injected CDI proxies. private List<Organisation> organisations; ... // Access to the persistence store so we can read from the DB with Long // Running extension to go with Conversation Scope above. @PersistenceContext(type = PersistenceContextType.EXTENDED) private EntityManager em; // Inject this to make conversation magic happen @Inject private Conversation conversation; ...
I enter the conversation like this:
// A good place to START a conversation from. ** land here off a menu // click... public String init() { this.logger.info(">>>init"); if (!this.conversation.isTransient()) { this.logger.info("Existing conversation found:" + this.conversation.getId() + " Ending it..."); this.conversation.end(); } this.logger.info("+++CONVERSATION START"); this.conversation.begin(); // START THE LONG RUNNING CONVERSATION this.logger.info("conversation:" + this.conversation.getId()); this.logger.info("<<<init"); return "pretty:manageOrganisations"; }
and ping-pong through user requests and responses.
Now...
Create and Update take effect immediately in the DB.
public String updateOrganisation(Organisation organisation) { this.logger.info(">>> updateOrganisation " + organisation.getName()); this.logger.info("conversation:" + this.conversation.getId()); this.em.merge(organisation); this.updateEvent.fire(organisation); this.logger.info("Updated " + organisation.getName()); // Clear the organisation this.organisationToBeAffected = null; String[] params = { organisation.getName() }; this.postGlobalMessage("organisation_updated_successfully", params, null, null, FacesMessage.SEVERITY_INFO); this.logger.info("<<< updateOrganisation " + organisation.getName()); return "pretty:manageOrganisations"; }
Delete has no effect in the DB.
public String deleteOrganisation(Organisation organisation) { String navigationToReturn = null; this.logger.info(">>> Deleting " + organisation.getName()); this.logger.info("conversation:" + this.conversation.getId()); this.deleteEvent.fire(organisation); this.organisations.remove(organisation); this.em.remove(organisation); navigationToReturn = "pretty:manageOrganisations"; this.logger.info("<<< Deleting " + organisation.getName()); return navigationToReturn; }
I expected nothing to get perisited until I ended the conversation (and stuff to never get perisited if I didnt!)...
public String finished() { // land on here when finished up to return to // Main Page (a "done" button). this.logger.info(">>>finished"); this.logger.info("+++CONVERSATION END for conversation:" + this.conversation.getId()); if (!this.conversation.isTransient()) { // May have been an error (don't // get trapped on the page). this.conversation.end(); // END THE LONG RUNNING CONVERSATION } this.logger.info("<<<finished"); return "pretty:home"; }
I know that CDI Conversations are subtely differnt to Seam conversations.
Please can you suggest how to get the simple Seam2 Conversation capability back.