Here's my experience with the SelectMany...
I'm adding a little "addUsers" implementation to the SWF-booking sample...
I'm trying to implement a form that allows entering new users with a SelectManyCheckBox group that would allow
CRUD on a OneToMany Roles. So a user could have "ROLE_USER" or "ROLE_SUPERVISOR"
which is saved in a separate table, CustPrivileges
for example. The User would be the controlling side of the relationship.
I spent a lot of time trying to figure out how to do this..
I thought it might resemble the Item/Bid anotation in the Hibernate CaveateEmptor so...
in the User class
Code:
//as a member..
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID", nullable = false)
private List<Privilege> privileges = new ArrayList<Privilege>();
// accessors....
public List<Privilege> getPrivileges() { return privileges; }
public void setPrivileges(List<Privilege> privileges){
this.privileges = privileges;
}
in the Privileges
@Entity
@Table(name = "CUSTPRIVILEGES",
uniqueConstraints = {@UniqueConstraint(columnNames={"USER_ID", "AUTHORITY"})}
)
// as a member
@ManyToOne
@JoinColumn(name = "USER_ID", nullable = false, updatable = false, insertable = false)
@org.hibernate.annotations.ForeignKey(name="FK_USERID")
private User user;
This all maps ok with a fk_userid in the custPrivileges table.
Problem is with JSF selectManyCheckBox on the page for the roles it's near impossible to
have these inputs updateable. If I use a converter for the Component it will create detached
objs when they should have the id from the db. ( Impossible to have the Converter activate the jpaFlowExecutionListener ).
The inputs from the component are String representations
of the objs (value submitted from inputs are String). So converting the form to an updatable one is a nightmare with.
all the logic involved to reconcile each case between what's in the form and what's potentially in the dbase.
for example....
Code:
in the facelet:
<c:choose>
<c:when test='${userFm.update == "true"}'>
<div class="field">
<div class="label">
<h:outputLabel for="enabled">Privileges:</h:outputLabel>
</div>
<div class="input">
<h:selectManyCheckbox id="privileges" value="#{userFm.privileges}" layout="pageDirection" required="true" converter="PrivilegeConverter" >
<c:choose>
<c:when test='${ fn:startsWith(userFm.privileges[0],"ROLE_SUPERVISOR") and userFm.privileges[1]==null }'>
<f:selectItem id="item1" itemLabel="Agent1" itemValue="ROLE_USER##{userFm.privileges[0]}" />
</c:when>
<c:when test='${ fn:startsWith(userFm.privileges[1],"ROLE_USER") and userFm.privileges[1]!=null }'>
<f:selectItem id="item1" itemLabel="Agent2" itemValue="#{userFm.privileges[1]}" />
</c:when>
<c:otherwise>
<f:selectItem id="item1" itemLabel="Agent3" itemValue="#{userFm.privileges[0]}"/>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test='${ fn:startsWith(userFm.privileges[0],"ROLE_USER") and userFm.privileges[1]==null }'>
<f:selectItem id="item2" itemLabel="Administrator1" itemValue="ROLE_SUPERVISOR##{userFm.privileges[0]}" />
</c:when>
<c:otherwise>
<f:selectItem id="item2" itemLabel="Administrator2" itemValue="#{userFm.privileges[0]}" />
</c:otherwise>
</c:choose>
</h:selectManyCheckbox>
</div>
</div>
</c:when>
<c:otherwise>
<div class="field">
<div class="label">
<h:outputLabel for="enabled">Privileges:</h:outputLabel>
</div>
<div class="input">
<!-- <sf:clientTextValidator required="true"> -->
<h:selectManyCheckbox id="privileges" value="#{userFm.privileges}" layout="pageDirection" required="true" >
<f:selectItem id="item1" itemLabel="Agent_new" itemValue="ROLE_USER"/>
<f:selectItem id="item2" itemLabel="Administrator_new" itemValue="ROLE_SUPERVISOR" />
</h:selectManyCheckbox>
<!-- </sf:clientTextValidator> -->
</div>
</div>
</c:otherwise>
</c:choose>
in the Service...
( forgive the patchy code after all I've tried but u get the drift... )
if(user.getUpdate()){
User userdb = user;
em.lock(userdb,LockModeType.READ);
pdbSize = userdb.getPrivileges().size();
if(false){
// something I tied wuz here...
}
else{
if(user.getPrivileges().get(0)!=null){
Privilege P0 = user.getPrivileges().get(0);
Privilege P0db = em.find(Privilege.class, P0.getId());
P0db.setAuthority(P0.getAuthority());
P0db.setUser(user);
user.getPrivileges().set(0, P0db);
}
if(pSize>1){
Privilege P1 = user.getPrivileges().get(1);
P1.setId(null);
P1.setUser(user);
user.getPrivileges().set(1, P1);
}
}
}
else{
String strP0 = user.getPrivileges().get(0)+"";
if(strP0.equals("ROLE_USER")){
user.getPrivileges().remove(0);
user.addPrivilege("ROLE_USER");
}
else if(strP0.equals("ROLE_SUPERVISOR")){
user.getPrivileges().remove(0);
user.addPrivilege("ROLE_SUPERVISOR");
}
if(pSize>1){
strP0 = user.getPrivileges().get(0)+"";
if(strP0.equals("ROLE_USER")){
user.getPrivileges().remove(0);
user.addPrivilege("ROLE_USER");
}
else if(strP0.equals("ROLE_SUPERVISOR")){
user.getPrivileges().remove(0);
user.addPrivilege("ROLE_SUPERVISOR");
}
}
}
if there's more than two ROLES or selections to the SelectMany.....fagetAboudit !!! (hehehe)
Has anyone done something that allows showing what is in the dbase while updating a SelectMany group situation?
Is there a cut and dry approach to getting this done using JSF-hibernate ( and SWF? )
The only alternative I can think of is to delete all entries for this user and overwriting the group each time u update the user.
Not such a user friendly approach, doesn't allow for seeing what's there before u update.
Do you know what I mean? What would be the easiest approach to adding users with roles to a website and have them updatable?
What JSF component(s) would u use? Surely this has already been done I'm just new at the game !
took a look at this but too much missing info, seems close to what I'm talking about. http://i-proving.ca/space/Technologi...ctManyCheckbox
Any help are suggestions appreciated !
P.S. anyone know why the Hibernate.org site has been down so long?
( hope everythings OK with them
)