Converter in p:selectOneMenu - jsf

I have problem with my converter - it stops working and nothing happened.
I have Entity class "Group":
#Entity
#Table(name="users_group")
public class Group implements Serializable {
private int id;
private String name;
private boolean active = true;
private String code;
private List<User> users = new ArrayList<User>();
// getters, setters
#Override
public String toString() {
return "Group.id="+getId();
}
#Override
public boolean equals(Object obj){
System.out.println("OBJ :"+obj);
if(obj == null )return false;
if(obj instanceof String){
if(obj.toString().equals(this.toString())){
return true;
}
}
if(obj instanceof Group){
Group objGroup = (Group) obj;
if(objGroup.getId() == this.getId()){
System.out.println("EUREKA! Found");
return true;
}
}
return false;
}
}
here is my jsf view code:
<p:selectOneMenu id="group" value="#{priviligeMB.groupPrivilige.group}" converter="#{groupConverter}" >
<f:selectItems value="#{priviligeMB.groups}"
var="group" itemLabel="#{group.name}" itemValue="#{group}" />
</p:selectOneMenu >
And of course GroupConverter class:
#Component("groupConverter")
public class GroupConverter implements Converter {
#Autowired
GroupService groupService;
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
// arg2 is "Group.id=x" where x is just an id, for example "Group.id=2"
try {
System.out.println("getasObj: "+arg2);
return groupService.getGroupById(Integer.parseInt(arg2.split("=")[1]));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
// arg2 is object with toString() method that prints: "Group.id=x"
System.out.println("getAsString: "+arg2);
return arg2.toString();
}
}
Here is my log:
> getAsString: Group.id=1
> getAsString: Group.id=2
> Hibernate: SELECT locale.code from messages_locale locale left join users_user u sers on
> users.locale_id = locale.id where users.username =?
> getasObj: Group.id=1
> Hibernate: select group0_.id as id0_0_, group0_.active as
> active0_0_, group0_.co de as code0_0_, group0_.name as name0_0_ from
> users_group group0_ where group0_. id=?
> OBJ :Group.id=1 EUREKA! Found
> OBJ :Group.id=1 EUREKA! Found
> OBJ :Group.id=2
And after that... nothing happened! No errors, no actions, no page reload, no messages...

I got the similar problem and finally it's solved.
In such case, you need to make sure the object returned by "getAsObject" can match one of the objects in "#{priviligeMB.groups}", here "match" means the same object.

Related

Primefaces OrderList and Converter: getAsObject() called with "[object Object]" String

This can be seen as a continuation of my other question.
In my backend view, I have a list of some POJO. The POJO is converted to JSON with its toString() method:
BackingView.java
#Getter #Setter private List<SomePOJO> pojoList = ...
SomePojo.java
#EqualsAndHashCode(callSuper = false, of = {"id"})
public class SomePOJO implements Serializable {
private static final long serialVersionUID = 1L;
#Getter #Setter private Long id;
#Getter #Setter private Long date;
#Getter #Setter private Date name;
....
#Override
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
//making a readable string-representation of the object to display on the orderList
public String toStringOrderlistDisplay() {
return "Pojo with id " + id + "and so on... "
}
In my frontend, I want to allow the user to sort this pojo-list using Primefaces orderList :
<p:orderList id="ordList" widgetVar="ordList"
value="#{backingview.pojoList }" var="rfg"
controlsLocation="left" responsive="true" itemValue="#{rfg}"
itemLabel="#{rfg.toStringOrderlistDisplay()}" converter="#{pojoConverter}">
</p:orderList>
PojoConverter.java
#Named
#FacesConverter(value = "pojoConverter")
public class PojoConverter implements Converter {
#Override
public Pojo getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && value.trim().length() > 0) {
try {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(value, RechtsaktFallgeschichte.class);
}
catch (NumberFormatException | IOException ex) {
ex.printStackTrace();
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid Pojo."));
}
}
else { return null; }
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
SomePOJO r = (SomePOJO) value;
if (r != null) {
return r.toString();
}
else { return null; }
}
}
Converting to JSON seems to work just fine, if I print the output of the getAsString() method, everything looks as you would expect. However, when the getAsObject() method is called, the value-String-parameter always contains "[object Object]" instead of the POJOs JSON representation. What am I doing wrong here?
I don't know if it is possible to achieve what you are trying to do, but a better way (and the working one) is to pass the POJO id in the getAsString() method, and convert it back to Pojo using a cache map Map<Long, Pojo> pojoCache.
The converter should look like this:
PojoConverter.java
#Named
#FacesConverter(value = "pojoConverter")
public class PojoConverter implements Converter<Pojo> {
#Inject
private PojoService pojoService;
#Override
public Pojo getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && value.trim().length() > 0) {
return pojoService.getPojoCache().get(Long.valueOf(value));
} else {
return null;
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Pojo value) {
if (value != null) {
return String.valueOf(value.getId());
} else {
return null;
}}
}
For a more detailed explanation check this: p:orderList converter getAsObject() doesn't call Object.toString()

javax.el.PropertyNotFoundException: itemLabel="#{projet.nomProjet}": Property 'nomProjet' not found on type java.lang.String

I'm trying to apply a JSF converter to an Entity inside a selectOneMenu,
but the converter is not recognized, I get this warning in my xhtml file,
<<"nomProjet" cannot be resolved>>
and when I run the application I'm getting Error HTTP 500 :
itemLabel="#{projet.nomProjet}": Property 'nomProjet' not found on type java.lang.String
Here is my code:
The selectOneMenu in my view
<p:selectOneMenu id="projet" converter="projetConverter" value="# {affectation.selectedProjet}" >
<f:selectItems var="projet" itemValue="#{projet}" itemLabel="#{projet.nomProjet}" value="#{affectation.projetsAffectablesCollaborateur()}" />
</p:selectOneMenu>
The converter
#Component
#FacesConverter("projetConverter")
public class ProjetConverter implements Converter {
#Autowired
private ProjetRepository projetRepository;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || value.isEmpty()) {
return null;
}
try {
Projet projet = projetRepository.findByIdProjet(Long.valueOf(value));
return projet;
} catch (NumberFormatException exception) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de conversion", "ID de projet invalide"));
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
if (value instanceof Projet) {
return String.valueOf(((Projet) value).getIdProjet());
} else {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de conversion", "Instance de projet invalide"));
}
}
}
And my Entity :
#Entity
#NamedQuery(name = "Projet.findAll", query = "SELECT p FROM Projet p")
public class Projet implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long idProjet;
private String nomProjet;
#Transient
private List<Role> listRoles = new ArrayList<Role>();
public List<Role> getListRoles() {
return listRoles;
}
public void setListRoles(List<Role> listRoles) {
this.listRoles = listRoles;
}
// bi-directional many-to-one association to AffectationProjetRole
#OneToMany(mappedBy = "projet")
private List<AffectationProjetRole> affectationProjetRoles;
public Projet() {
}
public Projet(String nomProjet) {
this.nomProjet = nomProjet;
}
public long getIdProjet() {
return this.idProjet;
}
public void setIdProjet(long idProjet) {
this.idProjet = idProjet;
}
public String getNomProjet() {
return this.nomProjet;
}
public void setNomProjet(String nomProjet) {
this.nomProjet = nomProjet;
}
public List<AffectationProjetRole> getAffectationProjetRoles() {
return this.affectationProjetRoles;
}
public void setAffectationProjetRoles(List<AffectationProjetRole> affectationProjetRoles) {
this.affectationProjetRoles = affectationProjetRoles;
}
public AffectationProjetRole addAffectationProjetRole(AffectationProjetRole affectationProjetRole) {
getAffectationProjetRoles().add(affectationProjetRole);
affectationProjetRole.setProjet(this);
return affectationProjetRole;
}
public AffectationProjetRole removeAffectationProjetRole(AffectationProjetRole affectationProjetRole) {
getAffectationProjetRoles().remove(affectationProjetRole);
affectationProjetRole.setProjet(null);
return affectationProjetRole;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (idProjet ^ (idProjet >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Projet other = (Projet) obj;
if (idProjet != other.idProjet)
return false;
return true;
}
}
How is this caused and how can I solve it?
itemLabel="#{projet.nomProjet}": Property 'nomProjet' not found on type java.lang.String
This error message tells that #{projet} is during runtime actually a java.lang.String. Let's look where's #{projet} is coming from.
<f:selectItems value="#{affectation.projetsAffectablesCollaborateur()}"
var="projet" itemValue="#{projet}" itemLabel="#{projet.nomProjet}" />
Thus, #{affectation.projetsAffectablesCollaborateur()} actually returned a List<String>. If this is unexpected, then beware of generic type erasure and doublecheck all unchecked casts that the generic type is not incorrectly assumed. Generally, the mistake is in the persitence layer. For example, when you mistakenly execute the query SELECT p.nomProject FROM Project p instead of SELECT p FROM Project p and then performed an unchecked cast against List<Projet> instead of List<String>.
Do note that rendering item labels doesn't involve the converter at all, so showing and blaming it is unnecessary. The converter is only used on item values.

p:orderList converter getAsObject() doesn't call Object.toString()

I've written a custom converter as follows:
#FacesConverter(value = "orderListConverter")
public class OrderListConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Object ret = null;
if (component instanceof OrderList) {
Object list = ((OrderList) component).getValue();
ArrayList<ExampleEntity> al = (ArrayList<ExampleEntity>) list;
for (Object o : al) {
String name = "" + ((ExampleEntity) o).getName();
if (value.equals(name)) {
ret = o;
break;
}
}
}
return ret;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
String str = "";
if (value instanceof ExampleEntity) {
str = "" + ((ExampleEntity) value).getNumber();
}
return str;
}
}
My ExampleEntity is implemented as follows:
public class ExampleEntity {
private String name;
private int number;
public ExampleEntity(String name, int number) {
this.name = name;
this.number = number;
}
#Override
public String toString() {
return "toString(): [name=" + name + ", number=" + number + "]";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
the orderList-Component from Primefaces looks like that:
<p:orderList value="#{orderListBean.exampleList}"
var="exampleEntity" itemValue="#{exampleEntity}"
converter="orderListConverter">
<p:column style="width:25%">
#{exampleEntity.number}
</p:column>
<p:column style="width:75%;">
#{exampleEntity.name}
</p:column>
</p:orderList>
and the bean is implemented as follows:
#SessionScoped
#ManagedBean(name = "orderListBean")
public class OrderListBean {
private List<ExampleEntity> exampleList;
#PostConstruct
public void init() {
exampleList = new ArrayList<ExampleEntity>();
exampleList.add(new ExampleEntity("nameOne", 1));
exampleList.add(new ExampleEntity("nameTwo", 2));
exampleList.add(new ExampleEntity("nameThree", 3));
exampleList.add(new ExampleEntity("nameFour", 4));
exampleList.add(new ExampleEntity("nameFive", 5));
}
public List<ExampleEntity> getExampleList() {
return exampleList;
}
public void setExampleList(List<ExampleEntity> exampleList) {
this.exampleList = exampleList;
}
}
1) when debugging, the value Parameter of getAsObject() contains
the number of the ExampleEntity, but I had expected the
toString() method of ExampleEntity to be called!
2) What is the correct content for itemValue attribute?
Is it a kind of convention over configuration? Or how does the component
'know', to use the whole object, when inserting exampleEntity into itemValue
Hope everything is clear! Tanks a lot for any explanation!
Converters basically serve to transform values in 2 directions:
Server to client, when the value is rendered.
Client to server, when the value is submitted.
In your getAsString you established, that the string representation, the one which client uses, is exampleEntity's number. So that's what gets rendered to client as a value. And later, when the client submits its value, that value is number. To convert it to the object (server) representation, the getAsObject called with the number as a parameter.
The server can't possibly call getAsObject with exampleEntity.toString(), because it doesn't have the exampleEntity instance at that point, only the submitted number.
To illustrate, this should hold:
obj.equals(conv.getAsObject(ctx, comp, conv.getAsString(ctx, comp, obj)));
getAsObject and getAsString should be inversive in their input and output.
To answer your 2nd question: that depends on your needs. You could say itemValue="#{exampleEntity.number}", but that would make sense only if you're not interested in the exampleEntity itself, i.e. on submit you would get the number from the client and that's all you need for your server-side logic.
#FacesConverter(value = "EntityConverter")
public class EntityConverter implements Converter, Serializable {
private static final long serialVersionUID = 1L;
public EntityConverter() {
super();
}
#Override
public Object getAsObject(final FacesContext context, final UIComponent component, final String value) {
if (value == null) {
return null;
}
return fromSelect(component, value);
}
/**
* #param currentcomponent
* #param objectString
* #return the Object
*/
private Object fromSelect(final UIComponent currentcomponent, final String objectString) {
if (currentcomponent.getClass() == UISelectItem.class) {
final UISelectItem item = (UISelectItem) currentcomponent;
final Object value = item.getValue();
if (objectString.equals(serialize(value))) {
return value;
}
}
if (currentcomponent.getClass() == UISelectItems.class) {
final UISelectItems items = (UISelectItems) currentcomponent;
final List<Object> elements = (List<Object>) items.getValue();
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
if (!currentcomponent.getChildren().isEmpty()) {
for (final UIComponent component : currentcomponent.getChildren()) {
final Object result = fromSelect(component, objectString);
if (result != null) {
return result;
}
}
}
if (currentcomponent instanceof OrderList) {
Object items = ((OrderList) currentcomponent).getValue();
List<Object> elements = (List<Object>) items;
for (final Object element : elements) {
if (objectString.equals(serialize(element))) {
return element;
}
}
}
return null;
}
/**
* #param object
* #return the String
*/
private String serialize(final Object object) {
if (object == null) {
return null;
}
return object.getClass() + "#" + object.hashCode();
}
#Override
public String getAsString(final FacesContext arg0, final UIComponent arg1, final Object object) {
return serialize(object);
}
}

JSF: No validator could be found for type when adding a converter and a validator to a p:selectOneMenu

I'm currently encountering the problem specified above when trying to add a converter and a validator to a single field. I know how these 2 works because I've used them before, but this is the first time I've tried both of them on a single field. Here are my codes:
<p:selectOneMenu id="bussProgram"
value="#{signupWizardBean.subscription.businessProgram}">
<f:converter binding="#{membershipProgramConverter}"></f:converter>
<f:validator binding="#{dropdownValidator}"></f:validator>
<f:selectItems value="#{signupWizardBean.membershipPrograms}"
var="plan" itemValue="#{plan}"
itemLabel="#{plan.description}" />
</p:selectOneMenu>
Converter
#Named
#ApplicationScoped
public class MembershipProgramConverter implements Converter {
#PersistenceContext
private transient EntityManager em;
#Inject
private Logger log;
#Override
public Object getAsObject(FacesContext ctx, UIComponent component,
String value) {
if (StringUtils.isBlank(value) || value.equals("0"))
return null;
return em.find(MembershipProgram.class, new Long(value));
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object o) {
MembershipProgram mp = (MembershipProgram) value;
return mp.getId() != null ? String.valueOf(mp.getId()) : null;
}
}
Validator:
#Named
#ApplicationScoped
public class DropdownValidator implements Validator, Serializable {
private static final long serialVersionUID = -456545939475878299L;
#Inject
private ResourceBundle bundle;
#Inject
private FacesContext facesContext;
#Inject
private Logger log;
#Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
log.debug("[dropship-web] validating value={}", value);
if (value == null) {
FacesMessage msg = new FacesMessage(
bundle.getString("error.requiredField"),
bundle.getString("error.requiredField"));
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
facesContext.addMessage("promoCode", msg);
throw new ValidatorException(msg);
}
}
}
Entity Class:
#Entity
#Table(name = "CRM_MEMBERSHIP_PROGRAMS", uniqueConstraints = #UniqueConstraint(columnNames = { "code" }))
#SequenceGenerator(name = "ID_GENERATOR", sequenceName = "CRM_MEMBERSHIP_PROGRAM_SEQ")
public class MembershipProgram extends BaseEntity {
private static final long serialVersionUID = -7796298586810386239L;
#Size(max = 25)
#Column(name = "CODE", nullable = false)
private String code;
#Size(max = 100)
#Column(name = "DESCRIPTION", nullable = true)
private String description;
public MembershipProgram() {
}
public MembershipProgram(long id, String description) {
setId(id);
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((code == null) ? 0 : code.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
MembershipProgram other = (MembershipProgram) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
return true;
}
}
Note that on debug: both the MembershipProgramConverter.getAsObject/getAsString, DropdownValidator.validate methods are called.
I also found out that with or without selected item from the dropdown list, I'm encountering:
.validation.UnexpectedTypeException: HV000030: No validator could be found for type: com.czetsuya.models.membership.MembershipProgram.
javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: com.czetsuya.models.membership.MembershipProgram.
Finally I was able to figure out the problem, I've added #Size annotation on the target entity, just removed the #Size:
#Size(max = 25)
#OneToOne(optional = false)
#JoinColumn(name = "BUSINESS_PROGRAM", nullable = false)
private MembershipProgram businessProgram;
When I removed the #Size, the problem was solved but I have encountered a new one, on submit it the form always throw:
Validation Error: Value is not valid
To fixed the Value is not valid, make sure that you have properly implemented Model.equals method. My fault was that I rely on eclipse generate hashcode and equals feature, I failed to notice that it calls the equals method from my BaseEntity.

selectOneMenu do not render/display value

Made a post earlier about this topic (Display values in drill-down SelectOneMenus). The problem that have is not connected to the Object converters as I first thought.
I have two selectOneMenu depending on each other, Sector -> Category. When I persist the background business object that holds a Sector and Category, everything works as expected. Even after the current user session terminates and the user log on again and edit the previous saved business object.
The problem occur when and the entity manager flushes the objects and user wants to display the Sector, Category again from the database. The Sector selectOneMenu displays its value as it should, but the Category selectOneMenu value is not displayed. Although the backing bean has the correct value from the database.
What makes the selectOneMenuto not display certain persisted values/objects when they are loaded from database instead from in-memory?
Edit.xhtml
<h:outputLabel value="Sector:" />
<h:selectOneMenu id="sectorSelector" value="#{activityController.selected.category.sector}" title="#{bundle.CreateSectorLabel_sectorName}" valueChangeListener="#{activityController.changeSectorMenu}" immediate="true">
<a4j:ajax event="change" execute="#this categoryMenu" render="categoryMenu"/>
<f:selectItems value="#{sectorController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>
<h:outputLabel value="Category:" />
<h:selectOneMenu id="categoryMenu" value="#{activityController.selected.category}" title="#{bundle.CreateSectorLabel_sectorName}"
binding="#{activityController.categoryMenu}"
required="true" requiredMessage="#{bundle.CreateCategoryRequiredMessage_sector}">
<f:selectItems value="#{activityController.categorySelection}"/>
</h:selectOneMenu>
Controller bean for Category
#ManagedBean(name = "categoryController")
#SessionScoped
public class CategoryController implements Serializable{
....
#FacesConverter(forClass = Category.class)
public static class CategoryControllerConverter implements Converter {
#Override
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
CategoryController controller = (CategoryController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "categoryController");
return controller.ejbFacade.find(getKey(value));
}
java.lang.Integer getKey(String value) {
java.lang.Integer key;
key = Integer.valueOf(value);
return key;
}
String getStringKey(java.lang.Integer value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
#Override
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Category) {
Category o = (Category) object;
return getStringKey(o.getIdCategory());
}
else {
throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + CategoryController.class.getName());
}
}
}
Part of POJO object
...
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idCategory")
private Integer idCategory;
...
#Override
public boolean equals(Object object) {
if (!(object instanceof Category)) {
return false;
}
Category other = (Category) object;
if ((this.idCategory == null && other.idCategory != null) || (this.idCategory != null && !this.idCategory.equals(other.idCategory))) {
return false;
}
return true;
}
Functon for creating the SelectItem[] array
public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) {
int size = entities.size();
SelectItem[] items;
int i = 0;
if (selectOne) {
items = new SelectItem[size + 1];
items[0] = new SelectItem("", ResourceBundle.getBundle("/resources/Bundle").getString("Select_item"));
i++;
} else {
items = new SelectItem[size];
}
for (Object x : entities) {
items[i++] = new SelectItem(x, x.toString());
}
return items;
}
The problem was that I didn't have the right collection of SelectItems when the user edited a business object. Plus that I added the <f:converter> to explicitly invoke the converter, where I did some changes in the getAsString() (the else part).
Thank you for your time, and hope the post can be useful to someone else.
SelectMenuOne
public String prepareEditOrganisationActivity() {
current = (Activity) organisationActivityItems.getRowData();
Sector sector = current.getCategory().getSector();
CategoryController categoryBean = JsfUtil.findBean("categoryController", CategoryController.class);
categorySelection = categoryBean.categoryItemsBySector(sector);
return "EditActivity";
}
CategoryControllerConverter
...
#Override
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Category) {
Category o = (Category) object;
return getStringKey(o.getIdCategory());
}
else {
Category tmp = new Category();
return getStringKey(tmp.getIdCategory());
}
}

Resources