简单的 CDI 注入有问题... "Passivation" 在 SessionScoped Controller bean 中使用 @Inject 时出现相关错误
Trouble with simple CDI Injection... "Passivation" related error when using @Inject in SessionScoped Controller bean
好吧——我假设我在这里犯了一个非常明显的错误——但我似乎无法通过我所做的几次 Google/SO 搜索找到我的答案。我的 Java 编程背景主要基于 JSF,在工作中我只有使用 Faces 管理 bean 的经验(使用 @Managed
注释)。但是,我正在做一个个人项目,这是我第一次尝试使用 CDI。我在将服务 bean 注入到 SessionScoped
控制器 bean 时遇到问题……这很奇怪,因为我将相同的服务 bean 注入到不同的 RequestScoped
bean 没问题……我看不出我错过了什么。我有 SessionScoped
bean 实现 Serializable
,但是当我尝试部署时我仍然收到以下错误,ONLY 一旦我添加了 @Inject
bean 的变量(没有它,bean 将毫无用处……):Caused by: org.apache.webbeans.exception.WebBeansConfigurationException: Passivation capable beans must satisfy passivation capable dependencies.
这是我的一些服务和控制器 bean 代码:
UserService.java
import ds.nekotoba.model.User;
import java.util.Date;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import org.apache.deltaspike.jpa.api.transaction.Transactional;
import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.HashingPasswordService;
import org.apache.shiro.crypto.hash.Hash;
@Named
@Transactional//Makes all methods in bean transactional
public class UserService {
@Inject
private EntityManager em;
public User findById(Long id) {
return em.find(User.class, id);
}
public User findByUsername(String username) {
return em.createNamedQuery("User.findByUsername", User.class)
.setParameter("username", username)
.getSingleResult();
}
public User find(String username, String password) {
List<User> found = em.createNamedQuery("User.find", User.class)
.setParameter("username", username)
.setParameter("password", password)
.getResultList();
return found.isEmpty() ? null : found.get(0);
}
@Produces
@Named("users")
@RequestScoped
public List<User> list() {
return em.createNamedQuery("User.list", User.class).getResultList();
}
public Long create(User user) {
….
}
public void update(User user){
em.merge(user);
}
public void delete(User user){
em.remove(em.contains(user) ? user : em.merge(user));
}
}
LoginController.java 注意:这个 bean 中的 @Inject
调用没有问题!
import ds.nekotoba.model.User;
import ds.nekotoba.service.UserService;
import ds.nekotoba.util.Globals;
import java.io.IOException;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.omnifaces.util.Faces;
import org.omnifaces.util.Messages;
@Named(value="login")
@RequestScoped
public class LoginController {
public LoginController() {
}
@Inject ProfileController profile;
@Inject UserService userService;
//Variables
private String username;
private String password;
private boolean remember;
//<editor-fold desc="Getters/Setters">
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isRemember() {
return remember;
}
public void setRemember(boolean remember) {
this.remember = remember;
}
//</editor-fold>
public void submit() throws IOException {
try {//Attempt login
SecurityUtils.getSubject().login(new UsernamePasswordToken(username, password, remember));
} catch (AuthenticationException ae) {
Messages.addGlobalError("不明なユーザ、また試してみてください。");
ae.printStackTrace();
}
//If successful, set User in ProfileController, get full user info
if(SecurityUtils.getSubject().isAuthenticated()){
User user = new User();
user.setUsername(username);
user.setPassword(password);
profile.setUserInfo(user);
//profile.refreshUserInfo(); //COMMENTED OUT DUE TO ERROR INJECTED IN ProfileController.java
}
//Redirect to intended page
SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(Faces.getRequest());
Faces.redirect(savedRequest != null ? savedRequest.getRequestUrl() : Globals.HOME_URL);
}
}
ProfileController.java(一旦我在这个 bean 中使用任何 @Inject
调用就会出现上述错误...)
import ds.nekotoba.model.User;
import ds.nekotoba.service.UserService;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named(value="profile")
@SessionScoped
public class ProfileController implements Serializable {
@Inject UserService userService;//CAUSES ERROR MENTIONED ABOVE
//Variables
private User userInfo;
public ProfileController() {
}
public void refreshUserInfo() {
userInfo = userService.findByUsername(userInfo.getUsername());
}
//<editor-fold desc="Getters/Setters">
public User getUserInfo() {
return userInfo;
}
public void setUserInfo(User userInfo) {
this.userInfo = userInfo;
}
//</editor-fold>
}
就像我说的,我是 CDI 注入的新手,所以我确信我遗漏了一些明显的东西……我就是想不通。任何帮助将不胜感激。
其他项目信息:
JSF 2.2
JPA 2.0
TomEE 1.7.1
OmniFaces 1.8.1
Apache Shiro 1.3.0-SNAPSHOT
Apache DeltaSpike(这会是一个矛盾点吗?)
Foo implements Serializable
是必要的但不足以使 Foo
可序列化。 Foo
的所有成员也必须是可序列化的。
在你的例子中,ProfileController
是可序列化的,但它的 UserService
成员不是。
好吧——我假设我在这里犯了一个非常明显的错误——但我似乎无法通过我所做的几次 Google/SO 搜索找到我的答案。我的 Java 编程背景主要基于 JSF,在工作中我只有使用 Faces 管理 bean 的经验(使用 @Managed
注释)。但是,我正在做一个个人项目,这是我第一次尝试使用 CDI。我在将服务 bean 注入到 SessionScoped
控制器 bean 时遇到问题……这很奇怪,因为我将相同的服务 bean 注入到不同的 RequestScoped
bean 没问题……我看不出我错过了什么。我有 SessionScoped
bean 实现 Serializable
,但是当我尝试部署时我仍然收到以下错误,ONLY 一旦我添加了 @Inject
bean 的变量(没有它,bean 将毫无用处……):Caused by: org.apache.webbeans.exception.WebBeansConfigurationException: Passivation capable beans must satisfy passivation capable dependencies.
这是我的一些服务和控制器 bean 代码:
UserService.java
import ds.nekotoba.model.User;
import java.util.Date;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import org.apache.deltaspike.jpa.api.transaction.Transactional;
import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.HashingPasswordService;
import org.apache.shiro.crypto.hash.Hash;
@Named
@Transactional//Makes all methods in bean transactional
public class UserService {
@Inject
private EntityManager em;
public User findById(Long id) {
return em.find(User.class, id);
}
public User findByUsername(String username) {
return em.createNamedQuery("User.findByUsername", User.class)
.setParameter("username", username)
.getSingleResult();
}
public User find(String username, String password) {
List<User> found = em.createNamedQuery("User.find", User.class)
.setParameter("username", username)
.setParameter("password", password)
.getResultList();
return found.isEmpty() ? null : found.get(0);
}
@Produces
@Named("users")
@RequestScoped
public List<User> list() {
return em.createNamedQuery("User.list", User.class).getResultList();
}
public Long create(User user) {
….
}
public void update(User user){
em.merge(user);
}
public void delete(User user){
em.remove(em.contains(user) ? user : em.merge(user));
}
}
LoginController.java 注意:这个 bean 中的 @Inject
调用没有问题!
import ds.nekotoba.model.User;
import ds.nekotoba.service.UserService;
import ds.nekotoba.util.Globals;
import java.io.IOException;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.omnifaces.util.Faces;
import org.omnifaces.util.Messages;
@Named(value="login")
@RequestScoped
public class LoginController {
public LoginController() {
}
@Inject ProfileController profile;
@Inject UserService userService;
//Variables
private String username;
private String password;
private boolean remember;
//<editor-fold desc="Getters/Setters">
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isRemember() {
return remember;
}
public void setRemember(boolean remember) {
this.remember = remember;
}
//</editor-fold>
public void submit() throws IOException {
try {//Attempt login
SecurityUtils.getSubject().login(new UsernamePasswordToken(username, password, remember));
} catch (AuthenticationException ae) {
Messages.addGlobalError("不明なユーザ、また試してみてください。");
ae.printStackTrace();
}
//If successful, set User in ProfileController, get full user info
if(SecurityUtils.getSubject().isAuthenticated()){
User user = new User();
user.setUsername(username);
user.setPassword(password);
profile.setUserInfo(user);
//profile.refreshUserInfo(); //COMMENTED OUT DUE TO ERROR INJECTED IN ProfileController.java
}
//Redirect to intended page
SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(Faces.getRequest());
Faces.redirect(savedRequest != null ? savedRequest.getRequestUrl() : Globals.HOME_URL);
}
}
ProfileController.java(一旦我在这个 bean 中使用任何 @Inject
调用就会出现上述错误...)
import ds.nekotoba.model.User;
import ds.nekotoba.service.UserService;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named(value="profile")
@SessionScoped
public class ProfileController implements Serializable {
@Inject UserService userService;//CAUSES ERROR MENTIONED ABOVE
//Variables
private User userInfo;
public ProfileController() {
}
public void refreshUserInfo() {
userInfo = userService.findByUsername(userInfo.getUsername());
}
//<editor-fold desc="Getters/Setters">
public User getUserInfo() {
return userInfo;
}
public void setUserInfo(User userInfo) {
this.userInfo = userInfo;
}
//</editor-fold>
}
就像我说的,我是 CDI 注入的新手,所以我确信我遗漏了一些明显的东西……我就是想不通。任何帮助将不胜感激。
其他项目信息:
JSF 2.2
JPA 2.0
TomEE 1.7.1
OmniFaces 1.8.1
Apache Shiro 1.3.0-SNAPSHOT
Apache DeltaSpike(这会是一个矛盾点吗?)
Foo implements Serializable
是必要的但不足以使 Foo
可序列化。 Foo
的所有成员也必须是可序列化的。
在你的例子中,ProfileController
是可序列化的,但它的 UserService
成员不是。