Custom enum marshaling with JAXB and moxy - jaxb

I am having some trouble with custom enum marshaling with Moxy and JSON. My use case is that I have a large object model that includes enumerations that normally should provide a normal enumerated value, a "code", and a description. The source of this data has only the "code", so I need to be able to unmarshal instances of these enums using only the code (e.g.
{"companyCode":{"code":"PI"}}.
However, I should also be able to marshal and unmarshal all three fields:
{"companyCode":
{"value":"Private",
"code":"PI","description":
"Private Ins"
}
}
I am using an adapter that looks like this:
public class CodeEnumXmlAdapter<E extends Enum<E> & CodeEnum> extends XmlAdapter<CodeEnumImpl,E> {
public static <T extends Enum<T> & CodeEnum> T getFromName(Class<T> clazz, String name) {
if (name == null) return null;
T[] values = clazz.getEnumConstants();
for (T t : values) {
if (name.equals(t.name())) {
return t;
}
}
return null;
}
public static <T extends Enum<T> & CodeEnum> T getFromCode(Class<T> clazz, String code) {
if (code == null) return null;
T[] values = clazz.getEnumConstants();
for (T t : values) {
if (code.equals(t.getCode())) {
return t;
}
}
return null;
}
public static <T extends Enum<T> & CodeEnum> T getFromString(Class<T> clazz, String aString) {
if (aString == null) return null;
T[] values = clazz.getEnumConstants();
for (T t : values) {
if (aString.equals(t.getCode()) || aString.equals(t.name()) || aString.equals(t.getDescription())) {
return t;
}
}
return null;
}
#Override
public E unmarshal(CodeEnumImpl value) throws Exception {
if (value == null) return null;
String valueString = value.getValue();
if (valueString == null)
valueString = value.getCode();
if (valueString == null)
valueString = value.getDescription();
if (valueString == null)
return null;
Type generic = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
return getFromString((Class<E>)generic, valueString);
}
#Override
public CodeEnumImpl marshal(E value) throws Exception {
return value == null ? null : new CodeEnumImpl(value);
}
}
This converts from a an enum like this:
import org.apache.commons.lang3.StringUtils;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(CompanyCode.Adapter.class)
public enum CompanyCode implements CodeEnum {
// Changed "Commmercial" to "Client" based on inputs from ...Greg, Tamil
Client("CM", "Client"), Medicare("MC", "Medicare"), Medicaid("MD",
"Medicaid"), Private("PI", "Private Ins"), Patient("PT", "Patient");
private String code;
private String description;
private CompanyCode(String code, String label) {
this.code = code;
this.description = label;
}
public String getDescription() {
return description;
}
public String getCode() {
return code;
}
public static CompanyCode fromCode(String code) {
if (StringUtils.isEmpty(code)) {
return null;
}
for (CompanyCode freq : values()) {
if (freq.getCode().equalsIgnoreCase(code)) {
return freq;
}
}
throw new IllegalArgumentException("Invalid CompanyCode code: " + code);
}
public String toString() {
return description;
}
public static class Adapter extends CodeEnumXmlAdapter<CompanyCode> {}
}
and uses and intermediate type like this:
import javax.xml.bind.annotation.XmlElement;
/**
* Created by Jeffrey Hoffman on 6/24/2015.
*/
public class CodeEnumImpl {
String value;
String description;
String code;
public CodeEnumImpl() {
}
public <E extends Enum<E> & CodeEnum> CodeEnumImpl(E value) {
if (value != null) {
this.value = value.name();
this.description = value.getDescription();
this.code = value.getCode();
}
}
#XmlElement
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#XmlElement
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#XmlElement
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public String toString() {
return value == null ? null : value.toString();
}
}
This is working fine with straight XML and JAXB. However, when I try to use Moxy, I get an exception like this:
Exception Description: The object [Private Ins], of class [class
com.labcorp.phoenix.biz.enums.CompanyCode], could not be converted to
[class java.lang.Object]. Internal Exception: Exception
[EclipseLink-115] (Eclipse Persistence Services -
2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DescriptorException Exception
Description: No conversion value provided for the attribute [Private].
Mapping:
org.eclipse.persistence.oxm.mappings.XMLDirectMapping[companyCode-->companyCode/text()]
Descriptor: XMLDescriptor(com.labcorp.phoenix.eligibility.Root -->
[DatabaseTable(root)]) at
org.eclipse.persistence.exceptions.ConversionException.couldNotBeConverted(ConversionException.java:87)
at
org.eclipse.persistence.internal.jaxb.XMLJavaTypeConverter.convertObjectValueToDataValue(XMLJavaTypeConverter.java:178)
at
org.eclipse.persistence.oxm.mappings.XMLDirectMapping.convertObjectValueToDataValue(XMLDirectMapping.java:511)
at
org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getFieldValue(XMLDirectMapping.java:330)
at
org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.marshalSingleValue(XMLDirectMappingNodeValue.java:62)
at
org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.marshal(XMLDirectMappingNodeValue.java:58)
at
org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
at
org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
at
org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:393)
at
org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:368)
at
org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:238)
at
org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
at
org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
at
org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:743)
at
org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:1124)
at
org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:869)
... 7 more Caused by: Exception [EclipseLink-115] (Eclipse
Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.DescriptorException
It seems like a bug in moxy, because my adapter converts to a non-enum type, so there should not be a nestedConverter that deals with enums.

I managed to reproduce your issue with 2.5.0. It's most probably bug which has been fixed already. Unable to find the bug in Eclipse Bugzilla, but the same code works correctly with 2.6.0. Are you able to upgrade to latest MOXy?

Related

Model mapper mapping Map<String,Object> to class which extends another generic class not working for list field

I am trying to create my custom configuration object from Map using model mapper. Everything gets mapped properly excepts the fields property which is coming fro Generic super class.
My target object is
public class ADParserConfig extends CustomParserConfig<ADParserConfigField> {
private String pattern;
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
}
This extends generic class CustomParserConfig
public class CustomParserConfig<T extends CustomParserConfigField> {
protected List<T> fields;
protected String timeStampField;
public List<T> getFields() {
return fields;
}
public void setFields(List<T> fields) {
this.fields = fields;
}
public String getTimeStampField() {
return timeStampField;
}
public void setTimeStampField(String timeStampField) {
this.timeStampField = timeStampField;
}
}
Where CustomParserConfigField is
public class CustomParserConfigField {
protected String name;
protected Integer index;
protected String type;
protected String format;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
}
I am trying to map Map using below function
ADParserConfig adParserConfig = getConfig(map,ADParserConfig.class);
public <T extends CustomParserConfig> T getConfig(Map<String,Object> configObject, Class<T> classType){
ModelMapper modelMapper = new ModelMapper();
return modelMapper.map(configObject,classType);
}
Everything excepts fields gets mapped properly for the below map.
{fields=[{name=timeStamp, type=timestamp, format=dd/mm/yyyy HH:MM:SS a}, {name=logName, type=string}], pattern=(?<timeStamp>\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2}:\d{2}\s[AMPMampm]{2})?\s(LogName=(?<logName>[\w\s\W]+))?\sSourceName=(?<sourceName>[\w\s\W]+)\sEventCode=(?<eventCode>[0-9]*), timeStampField=timestamp}
Please help. Why is issue happens only for fields object ? Do I need to specify something else in mapper configurations ?
It looks like a bug and it had been fixed by #370

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.

#XmlAttribute/#XmlValue need to reference a Java type that maps to text in XML

how to pick the value of an attribute 'name' which is a PriceEventName class type in the below case, FYI if i put #XmlAttribute above it this is turn out to an exception "an error #XmlAttribute/#XmlValue need to reference a Java type that maps to text in XML"
I looking heavily on the internet but I didn't find something similar to my case
PriceEvent class
package somepackage
import ...
import
#XmlAccessorType(XmlAccessType.FIELD)
public class PriceEvent {
#XmlElement(name="Message",namespace="someValue")
private String color;
private PriceEventName name;// this is an attribute
.
.
}
PriceEventName class
Imports ...
public class PriceEventName {
public static final int PRICEUPDATE_TYPE = 0;
public static final PriceEventName PRICEUPDATE = new PriceEventName(PRICEUPDATE_TYPE, "X-mas");
private static java.util.Hashtable _memberTable = init();
private static java.util.Hashtable init() {
Hashtable members = new Hashtable();
members.put("X-mas", PRICEUPDATE);
return members;
}
private final int type;
private java.lang.String stringValue = null;
public PriceEventName(final int type, final java.lang.String value) {
this.type = type;
this.stringValue = value;
}
public static PriceEventName valueOf(final java.lang.String string) {
java.lang.Object obj = null;
if (string != null) {
obj = _memberTable.get(string);
}
if (obj == null) {
String err = "" + string + " is not a valid PriceEventName";
throw new IllegalArgumentException(err);
}
return (PriceEventName) obj;
}
}
This is how you declare the field as an attribute with an adapter:
#XmlJavaTypeAdapter(PenAdapter.class)
#XmlAttribute
protected PriceEventName name;
public PriceEventName getName() { return name; }
public void setName(PriceEventName value) { this.name = value; }
Add you'll need to add a getter to PriceEventName:
public String getStringValue(){ return stringValue; }
And here is the adapter class:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class PenAdapter extends XmlAdapter<String,PriceEventName> {
public PriceEventName unmarshal(String v) throws Exception {
return PriceEventName.valueOf( v );
}
public String marshal(PriceEventName v) throws Exception {
return v.getStringValue();
}
}

Nesting Maps in Java

I want to store many details (like name, email, country) of the particular person using the same key in hashtable or hashmap in java?
hashMap.put(1, "Programmer");
hashMap.put(2, "IDM");
hashMap.put(3,"Admin");
hashMap.put(4,"HR");
In the above example, the 1st argument is a key and 2nd argument is a value, how can i add more values to the same key?
You can achieve what you're talking about using a map in each location of your map, but it's a little messy.
Map<String, Map> people = new HashMap<String, Map>();
HashMap<String, String> person1 = new HashMap<String, String>();
person1.put("name", "Jones");
person1.put("email", "jones#jones.com");
//etc.
people.put("key", person1);
//...
people.get("key").get("name");
It sounds like what you might really want, though, is to define a Person class that has multiple properties:
class Person
{
private String name;
private String email;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
//plus getters and setters for other properties
}
Map<String, Person> people = new HashMap<String, Person>();
person1 = new Person();
person1.setName("Jones");
people.put("key", person1);
//...
people.get("key").getName();
That's the best I can do without any information about why you're trying to store values in this way. Add more detail to your question if this is barking up the wrong tree.
I think what you are asking
let us assume you we want to store String page, int service in the key and an integer in the value.
Create a class PageService with the required variables and define your HashMap as
Hashmap hmap = .....
Inside pageService, what you need to do is override the equals() and hashcode() methods. Since when hashmap is comparing it checks for hashcode and equals.
Generating hashcode and equals is very easy in IDEs. For example in eclipse go to Source -> generate hashcode() and equals()
public class PageService {
private String page;
private int service;
public PageService(String page, int service) {
super();
this.page = page;
this.service = service;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public int getService() {
return service;
}
public void setService(int service) {
this.service = service;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((page == null) ? 0 : page.hashCode());
result = prime * result + service;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PageService other = (PageService) obj;
if (page == null) {
if (other.getPage() != null)
return false;
} else if (!page.equals(other.getPage()))
return false;
if (service != other.getService())
return false;
return true;
}
}
The following class is very generic. You can nest ad infinitum. Obviously you can add additional fields and change the types for the HashMap. Also note that the tabbing in the toString method should be smarter. The print out is flat.
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HierarchicalMap
{
private String key;
private String descriptor;
private Map<String,HierarchicalMap>values=new HashMap<String,HierarchicalMap>();
public String getKey()
{
return key;
}
public void setKey(String key)
{
this.key = key;
}
public void addToSubMap(String key, HierarchicalMap subMap)
{
values.put(key, subMap);
}
public String getDescriptor()
{
return descriptor;
}
public void setDescriptor(String descriptor)
{
this.descriptor = descriptor;
}
public HierarchicalMap getFromSubMap(String key)
{
return values.get(key);
}
public Map<String,HierarchicalMap> getUnmodifiableSubMap()
{
return Collections.unmodifiableMap(values);
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("HierarchicalMap: ");
sb.append(key);
sb.append(" | ");
sb.append(descriptor);
Iterator<String> itr=values.keySet().iterator();
while(itr.hasNext())
{
String key= itr.next();
HierarchicalMap subMap=this.getFromSubMap(key);
sb.append("\n\t");
sb.append(subMap.toString());
}
return sb.toString();
}

selectOneMenu in dataTable, default value not getting set properly

When I place a selectOneMenu within a dataTable, it does not display the correct default value in the selectOneMenu. The datatable is bound to a list of POJO's. The POJO entity Badge references a POJO entity we will call Facility. This Facility should be the selected value of the selectOneMenu in the row (the row being each Badge).
The following is my simple example of a table:
<h:dataTable id="examp" value="#{managedBean.badges}" var="badge">
<h:column rowHeader="rowie">
<h:selectOneMenu value="#{badge.facility}" id="col1">
<f:converter converterId="facilityConverter" />
<f:selectItems value="#{managedBean.facilities}"
/>
</h:selectOneMenu>
</h:column>
</h:dataTable>
The selectItems are a List of SelectItem objects that are created at PostConstruct. These are within my managedbean that is in ViewScope.
public class ListBadges extends BaseBean {
private List<Badge> badges = new ArrayList<Badge>();
private List<SelectItem> facilities = new ArrayList<SelectItem>();
public ListBadges() {
getBadgesFromDatabase(true);
}
#PostConstruct
public void init() {
if (facilities.size() <= 0) {
try {
List<Facility> facilityBeans = FacilityHelper.getFacilities();
for (Facility fac : facilityBeans) {
facilities.add(new SelectItem(fac, fac.getFacilityName()));
}
} catch (tException e) {
log.error("ListBadges.init(): " + e.getMessage());
e.printStackTrace();
}
}
}
public void getBadgesFromDatabase(boolean forceRefresh) {
if (forceRefresh || badges == null || badges.isEmpty())
badges = BadgeHelper.getBadgeList();
}
///
/// Bean Properties
///
public List<Badge> getBadges() {
return badges;
}
public void setBadges(List<Badge> badges) {
this.badges = badges;
}
public List<SelectItem> getFacilities() {
return facilities;
}
public void setFacilities(List<SelectItem> facilities) {
this.facilities = facilities;
}
Stepping through the code I confirm that all of the data is correct. In my converter, I verified that the arguments passed to getAsString is correct, so it should have identified the correct item.
#FacesConverter("facilityConverter")
public class FacilityConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String from) {
try {
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
ListBadges neededBean =
(ListBadges) context.getApplication().getELResolver().getValue(elContext, null, "managedBean");
long id = Long.parseLong(from);
for (SelectItem sItem : neededBean.getFacilities()) {
Facility facility = (Facility)sItem.getValue();
if (facility.getFacilityId() == id)
return facility;
}
} catch (Exception e) {
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
try {
Facility facility = (Facility)value;
return facility.getFacilityId() + "";
} catch (Exception e) {
}
return null;
}
}
Here is the Facility class which has equals and hashCode implemented:
public class Facility implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private long facilityId;
private String facilityName;
private String address1;
private String address2;
private String city;
private String state;
private String postalCode;
private String url;
private String phone;
private String siteManager;
public Facility() {
}
public Facility(String facilityName) {
this.facilityName = facilityName;
}
public Facility(String facilityName,
String address1, String address2, String city, String state,
String postalCode, String url, String phone, String siteManager) {
this.facilityName = facilityName;
this.address1 = address1;
this.address2 = address2;
this.city = city;
this.state = state;
this.postalCode = postalCode;
this.url = url;
this.phone = phone;
this.siteManager = siteManager;
}
public long getFacilityId() {
return this.facilityId;
}
public void setFacilityId(long facilityId) {
this.facilityId = facilityId;
}
public String getFacilityName() {
return this.facilityName;
}
public void setFacilityName(String facilityName) {
this.facilityName = facilityName;
}
public String getAddress1() {
return this.address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return this.address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getPostalCode() {
return this.postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSiteManager() {
return siteManager;
}
public void setSiteManager(String siteManager) {
this.siteManager = siteManager;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof Facility) || (o == null))
return false;
if (o == this)
return true;
Facility obj = (Facility)o;
return obj.getFacilityId() == this.getFacilityId();
}
#Override
public int hashCode() {
return (new Long(this.getFacilityId()).hashCode()) ^
((this.getAddress1() == null) ? 0 : this.getAddress1().hashCode()) ^
((this.getAddress2() == null) ? 0 : this.getAddress2().hashCode()) ^
((this.getCity() == null) ? 0 : this.getCity().hashCode()) ^
((this.getFacilityName() == null) ? 0 : this.getFacilityName().hashCode()) ^
((this.getPhone() == null) ? 0 : this.getPhone().hashCode()) ^
((this.getPostalCode() == null) ? 0 : this.getPostalCode().hashCode()) ^
((this.getSiteManager() == null) ? 0 : this.getSiteManager().hashCode()) ^
((this.getUrl() == null) ? 0 : this.getUrl().hashCode());
}
}
I would greatly appreciate any feedback.
I found the problem and it is nothing to do with JSF.
Eclipse was loading an older version of the Facility bean class that had a programmatic mistake in its equals method. Even after fully cleaning, republishing, cleaning the working directory, restarting the web server, and restarting Eclipse this old class was still getting loaded. I restarted my computer and finally the correct class was being loaded and this problem went away.
Thanks for looking at this BalusC. Without this blog article you wrote I would be completely lost! http://balusc.blogspot.com/2007/09/objects-in-hselectonemenu.html

Resources