延續 JBoss Tools 自動產生專案經驗,本文實作自訂 Seam 專案,解決 @PersistenceContext 注入失敗、@In 注入設定、增量式熱部署機制等核心議題。
public interface GenericDao {
Object get(Class clazz, Serializable id);
void save(Object object);
void update(Object object);
void remove(Class clazz, Serializable id);
void remove(Object obj);
// ... 其他查詢方法
}
@Name("genericDao")
public class GenericDaoImpl implements GenericDao {
// 錯誤:@PersistenceContext 僅適用 Session Bean
// @PersistenceContext
// 修正:使用 Seam 管理的 EntityManager
@In("entityManager")
private EntityManager em;
public Object get(Class clazz, Serializable id) {
if (id == null) return null;
return em.find(clazz, id);
}
// ... 其他實作
}
@Name("userService")
public class UserServiceImpl implements UserService, SecurityUserService {
// create=true 自動建立元件、required=true 強制注入
@In(create = true, required = true)
protected GenericDao genericDao;
private List<User> resultList = null;
public List<User> getResultList() {
if (resultList == null) findAllUsers();
return resultList;
}
public void findAllUsers() {
String hql = "from User order by userCode";
resultList = this.genericDao.query(hql);
}
}
@Entity
@Table(name = "USER")
public class User implements IUser, Serializable {
@Id
private String userCode;
private String userName;
// getter/setter 省略
}
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="https://www.w3.org/1999/xhtml"
xmlns:s="https://jboss.com/products/seam/taglib"
xmlns:ui="https://java.sun.com/jsf/facelets"
xmlns:f="https://java.sun.com/jsf/core"
xmlns:h="https://java.sun.com/jsf/html"
xmlns:rich="https://richfaces.org/rich"
template="layout/template.xhtml">
<ui:define name="body">
<rich:panel>
<f:facet name="header">User Search Results</f:facet>
<rich:dataTable id="userServiceTable" var="user" value="#{userService.resultList}">
<h:column>
<f:facet name="header"><h:outputText value="UserCode"/></f:facet>
<h:outputText value="#{user.userCode}"/>
</h:column>
<h:column>
<f:facet name="header"><h:outputText value="UserName"/></f:facet>
<h:outputText value="#{user.userName}"/>
</h:column>
</rich:dataTable>
</rich:panel>
</ui:define>
</ui:composition>
| 錯誤訊息 | 原因 | 解決方案 |
|---|---|---|
| @PersistenceContext may only be used on session bean | POJO 元件不支援 EJB 註解 | 改用 @In("entityManager") 注入 Seam 管理的持久化上下文 |
| @In attribute requires non-null value: userService.genericDao | 元件未自動建立且注入失敗 | 加上 @In(create=true, required=true) |
專案代碼分為 Action 與 Model 兩目錄:
WEB-INF/dev — 支援熱重載WEB-INF/classes — 標準類別路徑此機制加速「編輯-編譯-測試」循環,修改 Action 層代碼無需重啟伺服器。