Converter only in one direction?
quilian Sep 10, 2008 11:26 PMHi!
short version: Is it somehow possible to have a Converter accepting an MyEntity Instance as input and get only instance.getId (String) out of it to store in the model?
long version:
I'm trying to write my own converter. I have a the two classes User and Employee:
USER is managed by Hibernate and therefore an Entity :
@Entity(optimisticLock = OptimisticLockType.DIRTY, dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@javax.persistence.Entity
@Table(name = "MB_USER", uniqueConstraints = @UniqueConstraint(columnNames = "KENNUNG"))
public class Benutzer
implements
java.io.Serializable,
HibernateManagedEntity {
private static final long serialVersionUID = 1L;
protected BigDecimal id;
protected String kennung;
protected String kennwort;
protected String employeeid;
...EMPLOYEE is just a dummy class which gets filled with proper values from 'external' (actually it's the same db, but it could be any other system):
public class Employee extends ExternalEntity implements java.io.Serializable {
protected String id;
protected String label;
// Getters and Setters
...
The property User.employeeid is semantically a foreign key but without the db constraint for technical reasons.
When editing a User, I want to select the Employees like this:
<h:selectOneMenu id="xy" value="userManager.instance.employeeid">
<s:selectItems id="select" value="employeeManager.resultList" var="emp" label="#{emp.label}"/>
<mb:convertEntity managerName="employeeManager"/>
</h:selectOneMenu>where the mb:convertEntity is my own implementation similiar to s:convertEntity:
Name("com.mobilanten.mowita.werkbank.converter.EntityConverter")
@Scope(CONVERSATION)
@Converter
@BypassInterceptors
public class EntityConverter
implements
javax.faces.convert.Converter,
Serializable {
private static final long serialVersionUID = 1L;
private String managerName;
private EntityStore store;
@Create
public void create() {
store = EntityStore.instance();
}
private void init() {
if (getManager() != null) {
store.setManager(getManager());
} else
throw new IllegalStateException(
"manager not defined. you must define the attribute 'managerName' for tag mb:entityConverter!");
}
@SuppressWarnings("unchecked")
@Transactional
public String getAsString(FacesContext facesContext, UIComponent cmp,
Object value) throws ConverterException {
init();
if (value == null) {
return null;
}
if (value instanceof String) {
return value.toString();
} else
if (value instanceof Entity) {
return ((Entity) value).getId().toString();
} else
throw new ClassCastException(
"Value to convert is not a derivative of com.mobilanten.mowita.werkbank.Entity but "
+ value.getClass().getName());
}
@Transactional
public Object getAsObject(FacesContext facesContext, UIComponent cmp,
String value) throws ConverterException {
init();
if (value == null) {
return null;
}
return value; // instead of store.get(value), which would give me the real entity; i want the id only
}
@SuppressWarnings("unchecked")
public Manager<Entity> getManager() {
return (Manager<Entity>) Component.getInstance(getManagerName());
}
public String getManagerName() {
return managerName;
}
public void setManagerName(String aManagerName) {
managerName = aManagerName;
}
This gives me the expected html output with employee.id as value and label as label:
.. <option value="287">Kilian,Tobias</option> ...
Now there is no Employee member in User, only the String.
So I changed getAsObject(..) to only return the id. This gives me a facelets error with the content of
javax.faces.component.UISelectOne.INVALID
As a workaround i thought about extending User with something like
public setEmployeeByInstance( Employee employee) {
setEmployee( employee.getId());
}
but I hope this can be avoided....
Thanks in advance for any help!