Im stumped. I declare my set thusly:
private Set<Long> applicationIds;
Then I populate it like this:
public void setApplicationIds( Set<Long> applicationIds ) {
this.applicationIds = new TreeSet<Long>( applicationIds );
this.applications = null;
}
Then I attempt to use it:
public List<Application> getApplications() {
if ( applications == null ) {
applications = new ArrayList<Application>();
if ( applicationIds != null ) {
for ( Application application : availableApplications ) {
if ( applicationIds.contains( Long.valueOf( application.getId() ) ) ) {
applications.add( application );
}
}
}
}
return applications;
}
And I end up with this:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
at java.lang.Long.compareTo(Long.java:50)
at java.util.TreeMap.getEntry(TreeMap.java:346)
at java.util.TreeMap.containsKey(TreeMap.java:227)
at java.util.TreeSet.contains(TreeSet.java:234)
at org.mitre.asias.pf.pnp.viewmodel.Subscription.getApplications(Subscription.java:84)
The line causing the exception (line 84 from the stack trace) is this one:
if ( applicationIds.contains( Long.valueOf( application.getId() ) ) ) {
Perhaps I am missing something, but if the declaration is Set<Long>
and I am calling the contains
method passing in a Long.valueOf
value, how can I be getting this exception?
This is a model bean for a JSF application. I am using Java 6, Tomcat 6.0.32, mojarra 2.1.14, but none of that should really matter as the Generics are supposed to prevent this kind of problem compile time...
-------------- EDIT -----------------
Its actually the JSF... I threw together a super simplified example with this setter:
public void setSelectedValues(Set<Long> selectedValues) {
this.selectedValues = selectedValues;
if (logger.isTraceEnabled()) {
StringBuilder message = new StringBuilder("Selected values:");
for (Object value : selectedValues) {
message.append("\n\t'").append(value.getClass().getName())
.append("': '").append(value.toString()).append("'");
}
logger.trace(message.toString());
}
this.selections = null;
}
bound to this component:
<p:selectManyCheckbox id="numbers"
value="#{controller.selectedValues}" layout="pageDirection">
<f:selectItems value="#{controller.availableValues}" />
</p:selectManyCheckbox>
which writes this to the log:
15:45:16.887 [http-bio-8080-exec-9] TRACE com.pastdev.learn.debug.Controller - Selected values:
'java.lang.String': '1'
'java.lang.String': '5'
So, the simple answer is the correct one (thank you @PaulTomblin for emphasizing this). The setter is getting called with a Set
that contains String
s. So now, what is the best process for conversion? Will I need to iterate through the list casting each value to a Long?
As a side note, I tested this on Tomcat 7 using Java 7 and the ClassCastException went away, however, the contains
method always returns false
as should be expected.
-------------- EDIT 2 -----------------
I found an answer with the correct way to bind my component here.
-------------- EDIT 3 -----------------
And here is a better explanation of the problem.