Posted at

JSFでビューにデータベースの情報を表示できない時にやったこと

ビューにデータベースの情報を表示しようとしたらjavax.ejb.EJBExceptionが出てしまう問題について。

解決までにやったことを備忘録としてまとめてみた。



使っているもの


  • mac PC

  • NetBeans 11.0

  • GlassFish Server 4.1.1

  • JSF(Java Server Faces) 2.2


やりたいこと&問題

①入力した値をデータベースに保存

②データベースに保存した情報をページに表示する


問題

②を以下のコードで実行するとjavax.ejb.EJBExceptionとエラーになった。


index.xhtml (bodyタグ以下)

        <h2>データの作成</h2>

<h:form>
<h:panelGrid columns="2">
番号:
<h:inputText value ="#{backigBean.number}" />
名前:
<h:inputText value ="#{backigBean.name}" />
<h:commandButton value="作成" action="#{backigBean.create}" />
<h:commandButton value="取消" type="reset" />
</h:panelGrid>
<br/>
<br/>
<h2>作成した情報一覧</h2>
<h:dataTable value="#{backigBean.getAll}" var="item">
<h:column>#{item.number}</h:column>
<h:column>#{item.name}</h:column>
<h:column><h:commandLink value="編集" action="#{backigBean.toReturn}" /></h:column>
<h:column><h:commandButton value="削除" action="#{backigBean.delete(item)}" /></h:column>
</h:dataTable>
<h:commandButton value="戻る" action="#{backigBean.toReturn}" />
</h:form>


BackingBean.java (ビジネスロジックのコード)

package backingBeans;

import ejb.DataManager;
import entity.Data;
import java.io.Serializable;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@SessionScoped
@ManagedBean
public class BackingBean implements Serializable{
private Integer number;
private String name;
@EJB
private DataManager dm;

//データの保存
public String create(){
Data data = new Data();
data.setNumber(number);
data.setName(name);
if(number == null) return null;
try{
dm.create(data);
}catch(javax.ejb.EJBException e){}
clear();
return null;
}

//全データをDBから取得
public List<Data> getAll(){
return dm.getAll();
}

//データの削除
public String delete(Data data){
dm.delete(data);
return null;
}

//ブラウザをクリア
public void clear(){
number = null;
name = null;
}

//同じページに戻る
public String toReturn(){
return null;
}

//ゲッター&セッター
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}



Data.java (データクラス)

package entity;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Data implements Serializable{
@Id
private Integer number;
private String name;
public Data(){}
public Data(Integer number, String name){
this.number = number;
this.name = name;
}

//ゲッター&セッター
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}



DataManager.java (DBとデータの仲介をするコード)

package ejb;

import entity.Data;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class DataManager {
@PersistenceContext
private EntityManager em;

//DBに入力値を保存
public void create(Data data){
em.persist(data);
}
//DB上のデータを削除
public void delete(Data data){
em.remove(em.merge(data));
}
//DB上のデータを全て取得
public List<Data> getAll(){
return em.createNamedQuery("backingBean.getAll").getResultList();
}

}



解決すべく試したこと3つ


1. キャッシュをクリア


ターミナル

$ ~/Library/Caches

$ rm -rf NetBeans

そして、NetBeans再起動。...が、何も変わらなかった。

(参考サイト: http://d.hatena.ne.jp/tkrd/20140818/1408315483)


2. glassfish-resources.xhtml内のresourcesタグを1コに絞る


glassfish-resources.xhtml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="org.apache.derby.jdbc.ClientDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="derby_net_test_appPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="serverName" value="localhost"/>
<property name="portNumber" value="1527"/>
<property name="databaseName" value="test"/>
<property name="User" value="testuser"/>
<property name="Password" value="test"/>
<property name="URL" value="jdbc:derby://localhost:1527/test"/>
<property name="driverClass" value="org.apache.derby.jdbc.ClientDriver"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" jndi-name="java:app/jdbc/test" object-type="user" pool-name="derby_net_test_appPool"/>
</resources>

おそらくこのresourceタグの中では、「このプロジェクトでは、サーバーがこのデータベースと接続するよ」っていう設定をしてくれている。

複数のデータベースに繋ぎかえると、いくつものデータベース情報が自動で生成されるから、サーバーはどのデータベースに接続していいか分からなくなってしまった...のだと思う。

だから、resourceタグはこのファイル中に1回だけ登場させるように編集する。

これでサーバーの問題は解決!


3. 使う関数を変更

今度は別のエラーが出た。



getAllじゃダメと言われてるっぽいのでビューファイルの該当箇所をallに変更。


index.xhtml

...(省略)

<h2>作成した情報一覧</h2>
<h:dataTable value="#{backigBean.all}" var="item">

すると、またjavax.ejb.EJBExceptionが出てくる。

そこで、DataManagerのコードを以下の関数に変更。


DataManager

 //...(省略)

//DB上のデータを全て取得
public List<Data> getAll(){
//return em.createNamedQuery("backingBean.getAll").getResultList(); ここを以下に変更
return em.createQuery("SELECT c FROM Data c").getResultList();
}

動いた!!


まとめ


  • サーバー、Model(データベース)、View(フロント)、そしてController(内部システム)それぞれを関連づける設定をするファイルがある。「あれっ、おかしいな」と思ったら、それらファイルの整合性がとれているかを確認しよう。

  • エラーの字面だけ見てると一生解決しないこともある。よく分からずに使っているコードがあるなら、それを疑うのも一つ。