Netbeans を使用して JPA で JSF アプリケーションを開発しています。Entity クラスを作成し、Netbeans を介して Entity クラスから JSF ページを生成します。AbstractFacade、各エンティティの抽象ファサードを拡張するファサード、各エンティティのコントローラー Bean、および JSF ページを作成します。次に、これらの生成されたコードを変更して使用し、ロジックを作成します。
1 つの JSF ページ内で 2 つのコントローラー Bean を使用すると、断続的に ClassCastException が発生します。しかし、GLassFish サーバーを再起動すると、しばらくの間例外が消えて再び表示され、何が変更を開始したのかわかりません。たとえば、Atm というエンティティがある状況を考えてみましょう。このエンティティには、別のエンティティである MedicineGroup プロパティがあります。Atm エンティティからのオブジェクトが JSF ページを介して保存される場合、MedicineGroupController を呼び出すすべての MedicineGroups を取得し、それを Atm オブジェクトの選択された GenericName プロパティに割り当てます。このロジックは、ClassCastException が発生するまでうまく機能します。
(ほとんどの JSF ページで上記と同じ方法が使用されます。Atm エンティティには Vtm のプロパティがあります。Ampp には、Atm atm、MeasurmentUnit strengthUnit、Double strength、Double rol などのプロパティがあります。)
各 JSF ページに 1 つのコントローラーのみが存在するようにロジックを変更することで同じことを行うこともできますが、同じ JSF ページ内で複数のコントローラー Bean を参照できる場合は非常に簡単です。
ここで何が問題なのですか?
以下にいくつかの重要なコードをリストしました。
JSF ページの関連部分。
<h:selectOneListbox id="txtGroup" value="#{vtmController.current.medicineGroup}" size="5" >
<f:selectItems value="#{medicineGroupController.items}" var="gp" itemValue="#{gp}" itemLabel="#{gp.name}"/>
</h:selectOneListbox>
Entity クラスの例
@Entity
@Inheritance
public class Vtm extends PharmaceuticalItem implements Serializable {
@ManyToOne
MedicineGroup medicineGroup;
public MedicineGroup getMedicineGroup() {
return medicineGroup;
}
public void setMedicineGroup(MedicineGroup medicineGroup) {
this.medicineGroup = medicineGroup;
}
}
自動生成されたコンバーターを含むコントローラー クラスの例。
@ManagedBean
@SessionScoped
public final class VtmController {
@EJB
private VtmFacade ejbFacade;
SessionController sessionController = new SessionController();
List<Vtm> lstItems;
private Vtm current;
private DataModel<Vtm> items = null;
private int selectedItemIndex;
boolean selectControlDisable = false;
boolean modifyControlDisable = true;
String selectText = "";
public VtmController() {
}
public List<Vtm> getLstItems() {
return getFacade().findBySQL("Select d From Vtm d");
}
public void setLstItems(List<Vtm> lstItems) {
this.lstItems = lstItems;
}
public int getSelectedItemIndex() {
return selectedItemIndex;
}
public void setSelectedItemIndex(int selectedItemIndex) {
this.selectedItemIndex = selectedItemIndex;
}
public Vtm getCurrent() {
if (current == null) {
current = new Vtm();
}
return current;
}
public void setCurrent(Vtm current) {
this.current = current;
}
private VtmFacade getFacade() {
return ejbFacade;
}
public DataModel<Vtm> getItems() {
items = new ListDataModel(getFacade().findAll("name", true));
return items;
}
public static int intValue(long value) {
int valueInt = (int) value;
if (valueInt != value) {
throw new IllegalArgumentException(
"The long value " + value + " is not within range of the int type");
}
return valueInt;
}
public DataModel searchItems() {
recreateModel();
if (items == null) {
if (selectText.equals("")) {
items = new ListDataModel(getFacade().findAll("name", true));
} else {
items = new ListDataModel(getFacade().findAll("name", "%" + selectText + "%",
true));
if (items.getRowCount() > 0) {
items.setRowIndex(0);
current = (Vtm) items.getRowData();
Long temLong = current.getId();
selectedItemIndex = intValue(temLong);
} else {
current = null;
selectedItemIndex = -1;
}
}
}
return items;
}
public Vtm searchItem(String itemName, boolean createNewIfNotPresent) {
Vtm searchedItem = null;
items = new ListDataModel(getFacade().findAll("name", itemName, true));
if (items.getRowCount() > 0) {
items.setRowIndex(0);
searchedItem = (Vtm) items.getRowData();
} else if (createNewIfNotPresent) {
searchedItem = new Vtm();
searchedItem.setName(itemName);
searchedItem.setCreatedAt(Calendar.getInstance().getTime());
searchedItem.setCreater(sessionController.loggedUser);
getFacade().create(searchedItem);
}
return searchedItem;
}
private void recreateModel() {
items = null;
}
public void prepareSelect() {
this.prepareModifyControlDisable();
}
public void prepareEdit() {
if (current != null) {
selectedItemIndex = intValue(current.getId());
this.prepareSelectControlDisable();
} else {
JsfUtil.addErrorMessage(new MessageProvider().getValue("nothingToEdit"));
}
}
public void prepareAdd() {
selectedItemIndex = -1;
current = new Vtm();
this.prepareSelectControlDisable();
}
public void saveSelected() {
if (selectedItemIndex > 0) {
getFacade().edit(current);
JsfUtil.addSuccessMessage(new MessageProvider().getValue("savedOldSuccessfully"));
} else {
current.setCreatedAt(Calendar.getInstance().getTime());
current.setCreater(sessionController.loggedUser);
getFacade().create(current);
JsfUtil.addSuccessMessage(new MessageProvider().getValue("savedNewSuccessfully"));
}
this.prepareSelect();
recreateModel();
getItems();
selectText = "";
selectedItemIndex = intValue(current.getId());
}
public void addDirectly() {
JsfUtil.addSuccessMessage("1");
try {
current.setCreatedAt(Calendar.getInstance().getTime());
current.setCreater(sessionController.loggedUser);
getFacade().create(current);
JsfUtil.addSuccessMessage(new MessageProvider().getValue("savedNewSuccessfully"));
current = new Vtm();
} catch (Exception e) {
JsfUtil.addErrorMessage(e, "Error");
}
}
public void cancelSelect() {
this.prepareSelect();
}
public void delete() {
if (current != null) {
current.setRetired(true);
current.setRetiredAt(Calendar.getInstance().getTime());
current.setRetirer(sessionController.loggedUser);
getFacade().edit(current);
JsfUtil.addSuccessMessage(new MessageProvider().getValue("deleteSuccessful"));
} else {
JsfUtil.addErrorMessage(new MessageProvider().getValue("nothingToDelete"));
}
recreateModel();
getItems();
selectText = "";
selectedItemIndex = -1;
current = null;
this.prepareSelect();
}
public boolean isModifyControlDisable() {
return modifyControlDisable;
}
public void setModifyControlDisable(boolean modifyControlDisable) {
this.modifyControlDisable = modifyControlDisable;
}
public boolean isSelectControlDisable() {
return selectControlDisable;
}
public void setSelectControlDisable(boolean selectControlDisable) {
this.selectControlDisable = selectControlDisable;
}
public String getSelectText() {
return selectText;
}
public void setSelectText(String selectText) {
this.selectText = selectText;
searchItems();
}
public void prepareSelectControlDisable() {
selectControlDisable = true;
modifyControlDisable = false;
}
public void prepareModifyControlDisable() {
selectControlDisable = false;
modifyControlDisable = true;
}
@FacesConverter(forClass = Vtm.class)
public static class VtmControllerConverter implements Converter {
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
VtmController controller = (VtmController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "vtmController");
return controller.ejbFacade.find(getKey(value));
}
java.lang.Long getKey(String value) {
java.lang.Long key;
key = Long.valueOf(value);
return key;
}
String getStringKey(java.lang.Long value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Vtm) {
Vtm o = (Vtm) object;
return getStringKey(o.getId());
} else {
throw new IllegalArgumentException("object " + object + " is of type "
+ object.getClass().getName() + "; expected type: " + VtmController.class.getName());
}
}
}
}
ファサードの例
@Stateless
public class VtmFacade extends AbstractFacade<Vtm> {
@PersistenceContext(unitName = "HOPU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public VtmFacade() {
super(Vtm.class);
}
}
生成された抽象的なファサードと私が行った変更。
public abstract class AbstractFacade<T> {
protected Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll(boolean withoutRetired) {
return findAll(null, null, withoutRetired);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
javax.persistence.criteria.CriteriaQuery<T> cq = cb.createQuery(entityClass);
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findAll(String fieldName) {
return findAll(fieldName, "", false);
}
public List<T> findAll(String fieldName, boolean withoutRetired) {
return findAll(fieldName, "", withoutRetired);
}
public List<T> findAll(String fieldName, String fieldValue) {
return findAll(fieldName, fieldValue, false);
}
public List<T> findBySQL(String temSQL) {
TypedQuery<T> qry = getEntityManager().createQuery(temSQL, entityClass);
return qry.getResultList();
}
public List<T> findBySQL(String temSQL, Map<String, Date> parameters) {
TypedQuery<T> qry = getEntityManager().createQuery(temSQL, entityClass);
Set s=parameters.entrySet();
Iterator it=s.iterator();
while (it.hasNext()){
Map.Entry m=(Map.Entry)it.next();
Date pVal = (Date) m.getValue();
String pPara=(String) m.getKey();
qry.setParameter(pPara, pVal, TemporalType.DATE);
System.out.println("Parameter " + pPara + "\tVal" + pVal);
}
return qry.getResultList();
}
private void test(Class myClass, Object ob) {
}
public List<T> findAll(String fieldName, String fieldValue, boolean withoutRetired) {
javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
javax.persistence.criteria.CriteriaQuery<T> cq = cb.createQuery(entityClass);
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
ParameterExpression<String> p = cb.parameter(String.class);
Predicate predicateField = cb.like(rt.<String>get(fieldName), fieldValue);
Predicate predicateRetired = cb.equal(rt.<Boolean>get("retired"), false);
Predicate predicateFieldRetired = cb.and(predicateField, predicateRetired);
if (withoutRetired && !fieldValue.equals("")) {
cq.where(predicateFieldRetired);
} else if (withoutRetired) {
cq.where(predicateRetired);
} else if (!fieldValue.equals("")) {
cq.where(predicateField);
}
if (!fieldName.equals("")) {
cq.orderBy(cb.asc(rt.get(fieldName)));
}
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findExact(String fieldName, String fieldValue, boolean withoutRetired) {
javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
javax.persistence.criteria.CriteriaQuery<T> cq = cb.createQuery(entityClass);
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
ParameterExpression<String> p = cb.parameter(String.class);
Predicate predicateField = cb.equal(cb.upper(rt.<String>get(fieldName)), fieldValue.toLowerCase());
Predicate predicateRetired = cb.equal(rt.<Boolean>get("retired"), false);
Predicate predicateFieldRetired = cb.and(predicateField, predicateRetired);
if (withoutRetired && !fieldValue.equals("")) {
cq.where(predicateFieldRetired);
} else if (withoutRetired) {
cq.where(predicateRetired);
} else if (!fieldValue.equals("")) {
cq.where(predicateField);
}
if (!fieldName.equals("")) {
cq.orderBy(cb.asc(rt.get(fieldName)));
}
return getEntityManager().createQuery(cq).getResultList();
}
public T findByField(String fieldName, String fieldValue, boolean withoutRetired) {
List<T> lstAll = findExact(fieldName, fieldValue, true);
if (lstAll.isEmpty()) {
return null;
} else {
return lstAll.get(0);
}
}
public T findFirstBySQL(String temSQL) {
TypedQuery<T> qry = getEntityManager().createQuery(temSQL, entityClass);
try {
return qry.getResultList().get(0);
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
public <U> List<T> testMethod(U[] a, Collection<U> all) {
List<T> myList = new ArrayList<T>();
return myList;
}
public <U> List<T> findAll(String fieldName, int searchID, boolean withoutRetired) {
javax.persistence.criteria.CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
javax.persistence.criteria.CriteriaQuery<T> cq = cb.createQuery(entityClass);
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
if (withoutRetired) {
cq.where(cb.and(cb.equal(rt.get("retired"), false)),
(cb.equal(rt.get(fieldName).get("id"), searchID)));
} else {
cq.where(cb.equal(rt.get("retired"), false));
}
return getEntityManager().createQuery(cq).getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
public Double findAggregateDbl(String strJQL){
Query q= getEntityManager().createQuery(strJQL);
try{
return (Double) q.getSingleResult();
}catch (Exception e){
System.out.println(e.getMessage());
return 0.0;
}
}
}
これは、例外によって参照されるコードです。
AtmController controller = (AtmController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "atmController");
別の例では、これは同じ対応する場所ですが、別のコントローラーです。一度エラーが発生すると、JSF ページアクセスのあとがきにもかかわらず、同じ Controller でエラーが発生していますが、サーバーの再起動後、エラーが発生し始めたページによってコントローラーが異なります。
これは完全なスタック トレースです。(コントローラ クラスの名前は、アクセスに使用する JSF ページによって異なります。)
INFO: java.lang.ClassCastException: gov.sp.health.bean.VtmController cannot be cast to gov.sp.health.bean.AtmController
java.lang.ClassCastException: gov.sp.health.bean.VtmController cannot be cast to gov.sp.health.bean.AtmController
at gov.sp.health.bean.AtmController$VtmControllerConverter.getAsObject(AtmController.java:252)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(HtmlBasicInputRenderer.java:171)
at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectOneValue(MenuRenderer.java:202)
at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:319)
at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1030)
at javax.faces.component.UIInput.validate(UIInput.java:960)
at javax.faces.component.UIInput.executeValidate(UIInput.java:1233)
at javax.faces.component.UIInput.processValidators(UIInput.java:698)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:508)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1590)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIForm.visitTree(UIForm.java:344)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:376)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:252)
at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1170)
at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:722)
AtmController 内のコンバーター
@FacesConverter(forClass = Atm.class)
public static class AtmControllerConverter implements Converter {
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
AtmController controller = (AtmController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "atmController");
return controller.ejbFacade.find(getKey(value));
}
java.lang.Long getKey(String value) {
java.lang.Long key;
key = Long.valueOf(value);
return key;
}
String getStringKey(java.lang.Long value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Atm) {
Atm o = (Atm) object;
return getStringKey(o.getId());
} else {
throw new IllegalArgumentException("object " + object + " is of type "
+ object.getClass().getName() + "; expected type: " + AtmController.class.getName());
}
}
}
VtmController 内のコンバーター
@FacesConverter(forClass = Vtm.class)
public static class VtmControllerConverter implements Converter {
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
VtmController controller = (VtmController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "vtmController");
return controller.ejbFacade.find(getKey(value));
}
java.lang.Long getKey(String value) {
java.lang.Long key;
key = Long.valueOf(value);
return key;
}
String getStringKey(java.lang.Long value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Vtm) {
Vtm o = (Vtm) object;
return getStringKey(o.getId());
} else {
throw new IllegalArgumentException("object " + object + " is of type "
+ object.getClass().getName() + "; expected type: " + VtmController.class.getName());
}
}
}
MedicineGroupController 内のコンバーター
@FacesConverter(forClass = MedicineGroup.class)
public static class MedicineGroupControllerConverter implements Converter {
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
MedicineGroupController controller = (MedicineGroupController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "medicineGroupController");
return controller.ejbFacade.find(getKey(value));
}
java.lang.Long getKey(String value) {
java.lang.Long key;
key = Long.valueOf(value);
return key;
}
String getStringKey(java.lang.Long value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof MedicineGroup) {
MedicineGroup o = (MedicineGroup) object;
return getStringKey(o.getId());
} else {
throw new IllegalArgumentException("object " + object + " is of type "
+ object.getClass().getName() + "; expected type: " + MedicineGroupController.class.getName());
}
}
}