Этот фрагмент пропускает глобальный список testContainerCommand.testContainerLocationList
. Для каждого местоположения он увидит, присутствует ли он в списке местоположений основного объекта testContainerCommand.testContainer.testContainerLocationList
.Пользовательская функция JSTL всегда возвращает значение false
В обоих классах это свойство, которое выглядит так: private Set<TestContainerLocation> testContainerLocationList = new HashSet<TestContainerLocation>(0);
.
Текущая отладка показывает, что testContainerCommand.testContainer.testContainerLocationList
имеет два элемента
form.jsp
<p>Number of locations: ${fn:length(testContainerCommand.testContainer.testContainerLocationList)}</p>
<!-- currently shows 2 -->
<c:forEach items="${testContainerCommand.testContainerLocationList}" var="loc" varStatus="status">
<!-- ${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)} -->
<c:choose>
<c:when test="${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)}">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
</c:forEach>
Мой custom.tld файл:
<function>
<name>containsSet</name>
<function-class>org.test.utils.Compare</function-class>
<function-signature>boolean containsSet(java.util.Set,java.lang.Object)
</function-signature>
</function>
Мой Custom.java файл:
public class Compare {
public static boolean containsSet(Set s, Object o){
return s.contains(o);
}
}
TestContainer XML Hibernate отображения:
...
<set name="testContainerLocationList" table="test_container_location_lookup"
inverse="false" lazy="false" fetch="select" cascade="all">
<key>
<column name="id" not-null="true"/>
</key>
<many-to-many entity-name="org.test.vto.TestContainerLocation">
<column name="location_id" not-null="true" />
</many-to-many>
</set>
...
Почему это всегда возвращение ложным? Должен ли я бросать объекты перед их сравнением?
Update # 1
Я побежал следующий тестовый код:
public class Main {
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().openSession();
try{
List<TestContainerLocation> testContainerLocationList = session.createQuery("from TestContainerLocation").list();
TestContainer testContainer = (TestContainer)session.createQuery("from TestContainer where id = 12").list().get(0);
for(TestContainerLocation l: testContainerLocationList){
System.out.println(Compare.containsSet(testContainer.getTestContainerLocationList(), l));
}
}
catch(RuntimeException e){
e.printStackTrace();
}
session.close();
}
}
Какой выход (как и ожидалось):
true
true
false
false
false
Update # 2
Web Fl ow file:
<view-state id="form" view="/dbtest/form" model="testContainerCommand">
<on-entry>
<evaluate
expression="testContainerAction.getTestContainer(testContainerCommand, flowRequestContext)" />
<evaluate
expression="testContainerAction.getTestContainerLocationList(testContainerCommand, flowRequestContext)" />
</on-entry>
<transition on="submit" to="saveForm" />
<transition on="display" to="display" />
</view-state>
TestContainerAction.Java
public void getTestContainer(TestContainerCommand cmd, RequestContext requestContext) throws Exception{
HttpServletRequest request = (HttpServletRequest) requestContext.getExternalContext().getNativeRequest();
//get param
String id = request.getParameter("id");
//param present
if(! StringUtils.isEmpty(id) && StringUtils.isNumeric(id)){
cmd.setTestContainer(testContainerDao.getTestContainerById(Long.parseLong(id)));
}
//no param
else{
TestContainer t = new TestContainer();
t.setTestContainerType(new TestContainerType());
t.setTestContainerLocationList(new HashSet<TestContainerLocation>(0));
cmd.setTestContainer(t);
}
cmd.setTestContainerTypeList(testContainerTypeDao.getTestContainerTypeList());
cmd.setTestContainerLocationList(testContainerLocationDao.getTestContainerLocationList());
}
public List<TestContainerLocation> getTestContainerLocationList(TestContainerCommand cmd, RequestContext requestContext) throws Exception{
cmd.setTestContainerLocationList(testContainerLocationDao.getTestContainerLocationList());
return cmd.getTestContainerLocationList();
}
Update # 3
TestContainerLocation класс:
public class TestContainerLocation implements Serializable {
/**
*
*/
private static final long serialVersionUID = -1381290537575465609L;
private Integer locationId;
private String locationName;
private Set<TestContainer> testContainer = new HashSet<TestContainer>(0);
public Integer getLocationId() {
return locationId;
}
public void setLocationId(Integer locationId) {
this.locationId = locationId;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public Set<TestContainer> getTestContainer() {
return testContainer;
}
public void setTestContainer(Set<TestContainer> testContainer) {
this.testContainer = testContainer;
}
}
Я нашел сайт, который, кажется, говорить о том, что ДПМ говорил: http://javarevisited.blogspot.ca/2011/02/how-to-write-equals-method-in-java.html
Вот содержание моего ранее сокращенного для каждого:
<ul>
<c:forEach items="${testContainerCommand.testContainerLocationList}" var="loc" varStatus="status">
<!-- ${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)} -->
<c:choose>
<c:when test="${cfn:containsSet(testContainerCommand.testContainer.testContainerLocationList,loc)}">
<li><input type="checkbox" id="location${loc.locationId}" name="location"
value="${loc.locationId}"
checked="checked" />
<label for="location${loc.locationId}">${loc.locationName}</label></li>
</c:when>
<c:otherwise>
<li><input type="checkbox" id="location${loc.locationId}" name="location"
value="${loc.locationId}" />
<label for="location${loc.locationId}">${loc.locationName}</label></li>
</c:otherwise>
</c:choose>
</c:forEach>
</ul>
Update # 4
Новая функция сравнения, делая простой ToString() на входящих объектов:
public class Compare {
private static Logger logger = Logger.getLogger(Compare.class);
public static boolean containsSet(Set s, Object o){
logger.info(s.toString()+":"+o.toString());
return s.contains(o);
}
}
Выход указанного каротаж:
INFO : org.test.utils.Compare - [[email protected], [email protected]]:[email protected]
INFO : org.test.utils.Compare - [[email protected], [email protected]]:org.test.vto.TestCo[email protected]
INFO : org.test.utils.Compare - [[email protected], [email protected]]:[email protected]
INFO : org.test.utils.Compare - [[email protected], [email protected]]:[email protected]
INFO : org.test.utils.Compare - [[email protected], [email protected]]:[email protected]
Решение :
В соответствии с принятым решением мне просто пришлось переопределить методы equals и hashCode в моем классе TestContainerLocation.
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
TestContainerLocation in = (TestContainerLocation) obj;
return getLocationId() == in.getLocationId()
&& (getLocationName() == in.getLocationName()
|| (getLocationName() != null && getLocationName().equals(in.getLocationName())));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getLocationId() == null) ? 0 : Long.valueOf(getLocationId()).hashCode());
result = prime * result + ((getLocationName() == null) ? 0 : getLocationName().hashCode());
return result;
}
Откуда вы знаете, что оно возвращает false? Вы ничего не делаете внутри c: когда тег. Как определяются значения equals и hashCode? Каковы объекты в наборе и какой объект вы передаете в containsSet()? –
Вы исключали JSTL/EL из подозреваемого, выполнив 's.contains (o)' как обычное Java-приложение? Есть одна довольно очевидная базовая ошибка начинающих Java, которая может вызвать эту проблему, но вы нигде в вопросе явно не исключили ее из-за причины. – BalusC
@ Первый параметр jb-nizet - это Set, второй - один экземпляр TestContainerLocation. Я также добавил вывод HTML-комментариев, который показывает, что это ложь ... вот что я основал. –
TekiusFanatikus