[
https://jira.jboss.org/jira/browse/JBSEAM-4411?page=com.atlassian.jira.pl...
]
Tony Herstell updated JBSEAM-4411:
----------------------------------
Workaround Description:
Since the original user just pops back every time (even if you forcibly set it to null)
then you have to use the one provided regardless.
/**
* Copyright Software Factory - 2009
*/
package nz.co.softwarefactory.risingstars.controller.user;
import javax.ejb.Remove;
import javax.persistence.EntityManager;
import nz.co.softwarefactory.risingstars.mode.CrudsController;
import nz.co.softwarefactory.risingstars.mode.CRUDSMode.Mode;
import nz.co.softwarefactory.risingstars.model.User;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.Renderer;
import org.jboss.seam.international.StatusMessages;
import org.jboss.seam.international.StatusMessage.Severity;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.RunAsOperation;
import org.jboss.seam.security.management.IdentityManager;
/**
* @author Tony Herstell
*/
@SuppressWarnings("serial")
@Name("risingstars.registrationController")
@Scope(ScopeType.CONVERSATION)
public class RegistrationControllerImpl implements RegistrationController {
/**
* Inject and leverage the Seam Logger.
*/
@Logger
private Log log;
@In
private Identity identity;
@In
private IdentityManager identityManager;
@In
private EntityManager entityManager;
/**
* Inject the Renderer for Email purposes.
*/
@In(create=true)
private Renderer renderer;
@In
private Credentials credentials;
/**
* Outject a user for pages to act on.
*/
@In(create=true) @Out(required=true)
private User user;
/**
* Outject a mode of operation for pages to act on.
*/
// HACK HACK as for some reason we lose a Mode mode; but don't "lose"
and injected bean that simply contains the Mode mode.
@In(create=true) @Out(required=true)
private CrudsController crudsController;
/**
* Inject the Status Messages component so that messages (errors and info)
* can be sent to the View
*/
@In(create = true)
private transient StatusMessages statusMessages;
private boolean isValidSuppliedDetails = false;
private boolean isUserCreated = false;
@Override
@Begin(pageflow="create_registration_details_pageflow")
public String createRegistrationDetails() {
log.info("> " + this.getClass().getName()+ " createRegistrationDetails
");
crudsController.setMode(Mode.CREATE);
log.info("< " + this.getClass().getName()+ " createRegistrationDetails
");
return "start";
}
@Override
@Begin(pageflow="update_registration_details_pageflow")
public String updateRegistrationDetails() {
log.info("> " + this.getClass().getName()+ " updateRegistrationDetails
");
crudsController.setMode(Mode.UPDATE);
log.info("< " + this.getClass().getName()+ " updateRegistrationDetails
");
return "start";
}
@Override
public void initUpdateRegistrationDetails() {
log.info("> " + this.getClass().getName()+ "
initUpdateRegistrationDetails ");
// HACK HACK as cannot just point the User at the user just returned from the Datastore
User this_user = (User) entityManager.createQuery("from User u where u.email =
:email").setParameter("email",
credentials.getUsername()).getSingleResult();
updateUser(this_user, this.user);
log.info("< " + this.getClass().getName()+ " enter ");
}
// Hack
private void updateUser(User from, User to) {
to.setId(from.getId());
to.setVersion(from.getVersion());
to.setLastname(from.getLastname());
to.setFirstname(from.getFirstname());
to.setEmail(from.getEmail());
to.setPasswordHash(from.getPasswordHash());
to.setEnabled(from.isEnabled());
to.setRoles(from.getRoles());
}
@Override
public boolean isValidSuppliedDetails() {
boolean theResultToReturn = true;
log.info("> " + this.getClass().getName()+ " validSuppliedDetails
");
if (crudsController.getMode() == Mode.CREATE) {
new RunAsOperation() {
public void execute() {
setIsValidSuppliedDetails(!(identityManager.userExists(user.getEmail())));
}
}.addRole("admin")
.run();
if (getIsValidSuppliedDetails())
{
log.info ("Passed on unique user Check for email: " + user.getEmail());
} else {
log.info("Failed on unique user Check for email: " + user.getEmail());
statusMessages.addToControlFromResourceBundle("registration_email",
Severity.ERROR, "user_email_already_exists_in_system");
}
theResultToReturn = getIsValidSuppliedDetails();
} else if (crudsController.getMode() == Mode.UPDATE) {
} else {
throw new IllegalArgumentException(this.getClass().getName() +
"isValidSuppliedDetails called with disallowed Mode type");
}
log.info("< " + this.getClass().getName()+ " validSuppliedDetails
");
return theResultToReturn;
}
private void setIsValidSuppliedDetails(boolean isValid) {
this.isValidSuppliedDetails = isValid;
}
private boolean getIsValidSuppliedDetails() {
return this.isValidSuppliedDetails;
}
@Override
public void saveNewUser() {
log.info("> " + this.getClass().getName()+ " saveNewUser ");
if (crudsController.getMode() == Mode.CREATE) {
new RunAsOperation() {
public void execute() {
setIsUserCreated(identityManager.createUser(user.getEmail(), user.getPasswordHash(),
user.getFirstname(), user.getLastname()));
identityManager.enableUser(user.getEmail());
}
}.addRole("admin")
.run();
if (getIsUserCreated()) {
credentials.setUsername(user.getEmail());
credentials.setPassword(user.getPasswordHash());
identity.login();
statusMessages.addFromResourceBundle(Severity.INFO,
"registration_user_successfully_registered", user.getLastname() + ","
+ user.getFirstname());
try {
renderer.render("/WEB-INF/pages/user/registerSuccessfulEmailWrapper.xhtml");
log.info("Welcome Email sent!");
} catch (Exception e) {
log.info("Email sending failed: "+e);
}
} else {
log.error("failed to create new user " + user.getLastname() + ", "
+ user.getFirstname());
}
} else {
throw new IllegalArgumentException(this.getClass().getName() + "saveNewUser called
with disallowed Mode type");
}
log.info("< " + this.getClass().getName()+ " saveNewUser ");
}
@Override
public void updateUser() {
log.info("> " + this.getClass().getName()+ " updateUser ");
if (crudsController.getMode() == Mode.UPDATE) {
// Update the user. HACK HACK
User this_user = (User) entityManager.createQuery("from User u where u.id =
:id").setParameter("id", user.getId()).getSingleResult();
updateUser(this.user, this_user);
entityManager.persist(this_user);
final User final_user = this_user;
new RunAsOperation() {
public void execute() {
identityManager.changePassword(final_user.getEmail(), final_user.getPasswordHash());
}
}.addRole("admin")
.run();
Credentials credentials = identity.getCredentials();
credentials.setUsername(this_user.getEmail());
statusMessages.addFromResourceBundle(Severity.INFO,
"registration_user_successfully_updated", user.getLastname() + "," +
user.getFirstname());
} else {
throw new IllegalArgumentException(this.getClass().getName() + "updateUser called
with disallowed Mode type");
}
log.info("< " + this.getClass().getName()+ " updateUser ");
}
private void setIsUserCreated(boolean isUserCreated) {
this.isUserCreated = isUserCreated;
}
private boolean getIsUserCreated() {
return this.isUserCreated;
}
@Remove
@Destroy
@Override
public void destroy() {
log.info("> destory");
log.info("< destory");
}
}
A really sub optimal solution as if the object is complex you have to do a deep copy
(possibly linking to other objects) and then problem with merge/commit etc.
and Another one....
/**
* Outject a mode of operation for pages to act on.
*/
// HACK HACK as for some reason we lose a Mode mode; but don't "lose"
and injected bean that simply contains the Mode mode.
@In(create=true) @Out(required=true)
private CrudsController crudsController;
@Local
public interface CrudsController extends Serializable {
public void setMode(Mode mode);
public Mode getMode();
public void destroy();
}
@SuppressWarnings("serial")
@Name("risingstars.crudsController")
@Stateful
public class CrudsControllerImpl implements CrudsController, Serializable {
/**
* Inject and leverage the Seam Logger.
*/
@Logger
private Log log;
public Mode mode;
public void setMode(Mode mode) {
this.mode = mode;
}
public Mode getMode() {
return this.mode;
}
@Remove
@Destroy
@Override
public void destroy() {
log.info("> destory");
log.info("< destory");
}
}
Finally.. Status Messages don't show up either.
:/
---
<pageflow-definition
xmlns="http://jboss.com/products/seam/pageflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.com/products/seam/pageflow
http://jboss.com/products/seam/pageflow-2.2.xsd"
name="create_registration_details_pageflow">
<start-state name="entry">
<transition name="start" to="getUsersDetails" />
</start-state>
<page name="getUsersDetails"
view-id="/pages/user/createUserDetails.xhtml" redirect="true"
no-conversation-view-id="/home.xhtml">
<description>Registering of new User</description>
<transition name="cancel" to="end" />
<transition name="next" to="evaluateDetails"/>
</page>
<decision name="evaluateDetails"
expression="#{risingstars.registrationController.isValidSuppliedDetails()}">
<transition name="true" to="reviewDetails" />
<transition name="false" to="getUsersDetails" />
</decision>
<page name="reviewDetails"
view-id="/pages/user/reviewCreateUserDetails.xhtml" redirect="true"
no-conversation-view-id="/home.xhtml">
<description>Confirm details registering a new User (#{risingstars.user.lastname},
#{risingstars.user.firstname})</description>
<transition name="cancel" to="end" />
<transition name="back" to="getUsersDetails" />
<transition name="create" to="end">
<action expression="#{risingstars.registrationController.saveNewUser}"/>
</transition>
</page>
<page name="end" view-id="/home.xhtml"
redirect="true">
<end-conversation before-redirect="true"/>
</page>
</pageflow-definition>
<pageflow-definition
xmlns="http://jboss.com/products/seam/pageflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.com/products/seam/pageflow
http://jboss.com/products/seam/pageflow-2.2.xsd"
name="update_registration_details_pageflow">
<start-state name="entry">
<transition name="start" to="getUsersDetails">
<action
expression="#{risingstars.registrationController.initUpdateRegistrationDetails}"></action>
</transition>
</start-state>
<page name="getUsersDetails"
view-id="/pages/user/updateUserDetails.xhtml" redirect="true"
no-conversation-view-id="/home.xhtml">
<description>Updating of User (#{risingstars.user.lastname},
#{risingstars.user.firstname})</description>
<transition name="cancel" to="end" />
<transition name="next" to="evaluateDetails"/>
</page>
<decision name="evaluateDetails"
expression="#{risingstars.registrationController.isValidSuppliedDetails()}">
<transition name="true" to="reviewDetails" />
<transition name="false" to="getUsersDetails" />
</decision>
<page name="reviewDetails"
view-id="/pages/user/reviewUpdateUserDetails.xhtml" redirect="true"
no-conversation-view-id="/home.xhtml">
<description>Confirm details updating (#{risingstars.user.lastname},
#{risingstars.user.firstname})</description>
<transition name="cancel" to="end" />
<transition name="back" to="getUsersDetails" />
<transition name="update" to="end">
<action expression="#{risingstars.registrationController.updateUser}"/>
</transition>
</page>
<page name="end" view-id="/home.xhtml"
redirect="true">
<end-conversation before-redirect="true"/>
</page>
</pageflow-definition>
was:
Since the original user just pops back every time (even if you forcibly set it to null)
then you have to use the one provided regardless.
/**
* Copyright Software Factory - 2009
*/
package nz.co.softwarefactory.risingstars.controller.user;
import javax.ejb.Remove;
import javax.persistence.EntityManager;
import nz.co.softwarefactory.risingstars.mode.CrudsController;
import nz.co.softwarefactory.risingstars.mode.CRUDSMode.Mode;
import nz.co.softwarefactory.risingstars.model.User;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.Renderer;
import org.jboss.seam.international.StatusMessages;
import org.jboss.seam.international.StatusMessage.Severity;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.RunAsOperation;
import org.jboss.seam.security.management.IdentityManager;
/**
* @author Tony Herstell
*/
@SuppressWarnings("serial")
@Name("risingstars.registrationController")
@Scope(ScopeType.CONVERSATION)
public class RegistrationControllerImpl implements RegistrationController {
/**
* Inject and leverage the Seam Logger.
*/
@Logger
private Log log;
@In
private Identity identity;
@In
private IdentityManager identityManager;
@In
private EntityManager entityManager;
/**
* Inject the Renderer for Email purposes.
*/
@In(create=true)
private Renderer renderer;
@In
private Credentials credentials;
/**
* Outject a user for pages to act on.
*/
@In(create=true) @Out(required=true)
private User user;
/**
* Outject a mode of operation for pages to act on.
*/
// HACK HACK as for some reason we lose a Mode mode; but don't "lose"
and injected bean that simply contains the Mode mode.
@In(create=true) @Out(required=true)
private CrudsController crudsController;
/**
* Inject the Status Messages component so that messages (errors and info)
* can be sent to the View
*/
@In(create = true)
private transient StatusMessages statusMessages;
private boolean isValidSuppliedDetails = false;
private boolean isUserCreated = false;
@Override
@Begin(pageflow="create_registration_details_pageflow")
public String createRegistrationDetails() {
log.info("> " + this.getClass().getName()+ " createRegistrationDetails
");
crudsController.setMode(Mode.CREATE);
log.info("< " + this.getClass().getName()+ " createRegistrationDetails
");
return "start";
}
@Override
@Begin(pageflow="update_registration_details_pageflow")
public String updateRegistrationDetails() {
log.info("> " + this.getClass().getName()+ " updateRegistrationDetails
");
crudsController.setMode(Mode.UPDATE);
log.info("< " + this.getClass().getName()+ " updateRegistrationDetails
");
return "start";
}
@Override
public void initUpdateRegistrationDetails() {
log.info("> " + this.getClass().getName()+ "
initUpdateRegistrationDetails ");
// HACK HACK as cannot just point the User at the user just returned from the Datastore
User this_user = (User) entityManager.createQuery("from User u where u.email =
:email").setParameter("email",
credentials.getUsername()).getSingleResult();
updateUser(this_user, this.user);
log.info("< " + this.getClass().getName()+ " enter ");
}
// Hack
private void updateUser(User from, User to) {
to.setId(from.getId());
to.setVersion(from.getVersion());
to.setLastname(from.getLastname());
to.setFirstname(from.getFirstname());
to.setEmail(from.getEmail());
to.setPasswordHash(from.getPasswordHash());
to.setEnabled(from.isEnabled());
to.setRoles(from.getRoles());
}
@Override
public boolean isValidSuppliedDetails() {
boolean theResultToReturn = true;
log.info("> " + this.getClass().getName()+ " validSuppliedDetails
");
if (crudsController.getMode() == Mode.CREATE) {
new RunAsOperation() {
public void execute() {
setIsValidSuppliedDetails(!(identityManager.userExists(user.getEmail())));
}
}.addRole("admin")
.run();
if (getIsValidSuppliedDetails())
{
log.info ("Passed on unique user Check for email: " + user.getEmail());
} else {
log.info("Failed on unique user Check for email: " + user.getEmail());
statusMessages.addToControlFromResourceBundle("registration_email",
Severity.ERROR, "user_email_already_exists_in_system");
}
theResultToReturn = getIsValidSuppliedDetails();
} else if (crudsController.getMode() == Mode.UPDATE) {
} else {
throw new IllegalArgumentException(this.getClass().getName() +
"isValidSuppliedDetails called with disallowed Mode type");
}
log.info("< " + this.getClass().getName()+ " validSuppliedDetails
");
return theResultToReturn;
}
private void setIsValidSuppliedDetails(boolean isValid) {
this.isValidSuppliedDetails = isValid;
}
private boolean getIsValidSuppliedDetails() {
return this.isValidSuppliedDetails;
}
@Override
public void saveNewUser() {
log.info("> " + this.getClass().getName()+ " saveNewUser ");
if (crudsController.getMode() == Mode.CREATE) {
new RunAsOperation() {
public void execute() {
setIsUserCreated(identityManager.createUser(user.getEmail(), user.getPasswordHash(),
user.getFirstname(), user.getLastname()));
identityManager.enableUser(user.getEmail());
}
}.addRole("admin")
.run();
if (getIsUserCreated()) {
credentials.setUsername(user.getEmail());
credentials.setPassword(user.getPasswordHash());
identity.login();
statusMessages.addFromResourceBundle(Severity.INFO,
"registration_user_successfully_registered", user.getLastname() + ","
+ user.getFirstname());
try {
renderer.render("/WEB-INF/pages/user/registerSuccessfulEmailWrapper.xhtml");
log.info("Welcome Email sent!");
} catch (Exception e) {
log.info("Email sending failed: "+e);
}
} else {
log.error("failed to create new user " + user.getLastname() + ", "
+ user.getFirstname());
}
} else {
throw new IllegalArgumentException(this.getClass().getName() + "saveNewUser called
with disallowed Mode type");
}
log.info("< " + this.getClass().getName()+ " saveNewUser ");
}
@Override
public void updateUser() {
log.info("> " + this.getClass().getName()+ " updateUser ");
if (crudsController.getMode() == Mode.UPDATE) {
// Update the user. HACK HACK
User this_user = (User) entityManager.createQuery("from User u where u.id =
:id").setParameter("id", user.getId()).getSingleResult();
updateUser(this.user, this_user);
entityManager.persist(this_user);
final User final_user = this_user;
new RunAsOperation() {
public void execute() {
identityManager.changePassword(final_user.getEmail(), final_user.getPasswordHash());
}
}.addRole("admin")
.run();
Credentials credentials = identity.getCredentials();
credentials.setUsername(this_user.getEmail());
statusMessages.addFromResourceBundle(Severity.INFO,
"registration_user_successfully_updated", user.getLastname() + "," +
user.getFirstname());
} else {
throw new IllegalArgumentException(this.getClass().getName() + "updateUser called
with disallowed Mode type");
}
log.info("< " + this.getClass().getName()+ " updateUser ");
}
private void setIsUserCreated(boolean isUserCreated) {
this.isUserCreated = isUserCreated;
}
private boolean getIsUserCreated() {
return this.isUserCreated;
}
@Remove
@Destroy
@Override
public void destroy() {
log.info("> destory");
log.info("< destory");
}
}
A really sub optimal solution as if the object is complex you have to do a deep copy
(possibly linking to other objects) and then problem with merge/commit etc.
and Another one....
/**
* Outject a mode of operation for pages to act on.
*/
// HACK HACK as for some reason we lose a Mode mode; but don't "lose"
and injected bean that simply contains the Mode mode.
@In(create=true) @Out(required=true)
private CrudsController crudsController;
@Local
public interface CrudsController extends Serializable {
public void setMode(Mode mode);
public Mode getMode();
public void destroy();
}
@SuppressWarnings("serial")
@Name("risingstars.crudsController")
@Stateful
public class CrudsControllerImpl implements CrudsController, Serializable {
/**
* Inject and leverage the Seam Logger.
*/
@Logger
private Log log;
public Mode mode;
public void setMode(Mode mode) {
this.mode = mode;
}
public Mode getMode() {
return this.mode;
}
@Remove
@Destroy
@Override
public void destroy() {
log.info("> destory");
log.info("< destory");
}
}
Finally.. Status Messages don't show up either.
:/
added more info in workaround area.
jPDL re-installing its first seam object
----------------------------------------
Key: JBSEAM-4411
URL:
https://jira.jboss.org/jira/browse/JBSEAM-4411
Project: Seam
Issue Type: Bug
Components: Core
Affects Versions: 2.2.0.GA
Environment: WinXP64 MyEclipse JBoss latest RF
Reporter: Tony Herstell
Priority: Critical
Given this snippit
<start-state name="entry">
<transition name="start" to="getUsersDetails">
<action
expression="#{risingstars.registrationController.initUpdateRegistrationDetails}"></action>
</transition>
</start-state>
<page name="getUsersDetails"
view-id="/pages/user/updateUserDetails.xhtml" redirect="true"
no-conversation-view-id="/home.xhtml">
<description>Updating of User (#{risingstars.user.lastname},
#{risingstars.user.firstname})</description>
<transition name="cancel" to="end" />
<transition name="next" to="evaluateDetails"/>
</page>
I enter the jPDL and the bean has a User in scope... say (say id 123) auto created by
@In(create=true) @Out(required=true)
private User user;
I then do this in initUpdateRegistrationDetails :
this.user = (User) entityManager.createQuery("from User u where u.email =
:email").setParameter("email",
credentials.getUsername()).getSingleResult();
Which forces the user in scope to now point to this new user (say id 456)
What happens if by the time we get to the next page we have switched back to the original
User (123).
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira