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!