JSF 2.2整合Spring 4+Spring Data JPA遇Target Unreachable异常
解决JSF 2.2 + Spring 4 + Spring Data JPA集成时的
PropertyNotFoundException问题 这个异常Target Unreachable, identifier [registerEmployee] resolved to null的核心原因是JSF无法找到你定义的registerEmployee Bean,本质是JSF和Spring的Bean生命周期管理冲突,加上一些配置和注解使用错误导致的。下面是一步步的解决方案:
1. 统一Bean管理方式:把JSF托管Bean交给Spring管理
你现在混合使用了JSF的@ManagedBean和Spring的@Autowired,这会导致Bean的管理混乱。推荐把所有业务相关的Bean都交给Spring管理,这样能更好地集成Spring Data JPA。
修正RegisterEmployee类
替换JSF的注解为Spring的注解,同时移除@ManagedProperty改用Spring的@Autowired:
import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.annotation.SessionScope; @Component("registerEmployee") // 用Spring的@Component定义Bean,指定名称对应JSF中的EL @SessionScope // Spring的会话作用域,替代JSF的@SessionScoped public class RegisterEmployee implements Serializable { @Autowired private EmployeeService employeeService; // 注意:不要用@Autowired注入Employee实体!实体类是JPA映射对象,不是Spring管理的Bean private Employee employee = new Employee(); // 直接实例化,或者用@ModelAttribute // Getters & Setters public EmployeeService getEmployeeService() { return employeeService; } public void setEmployeeService(EmployeeService employeeService) { this.employeeService = employeeService; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public String register() { employeeService.register(employee); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("The Employee "+this.employee.getEmployeeName()+" Is Registered Successfully")); // 注册完成后重置Employee对象,避免下次复用旧数据 this.employee = new Employee(); return ""; } }
修正Employee实体类
实体类是JPA用来映射数据库的对象,不需要添加@Component注解,去掉这个错误的配置:
import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "employee") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "EMP_ID") private long employeeId; @Column(name = "EMP_NAME") private String employeeName; @Column(name = "EMP_HIRE_DATE") private Date employeeHireDate; @Column(name = "EMP_SALARY") private double employeeSalary; // 保留原有的Getters和Setters public long getEmployeeId() { return employeeId; } public void setEmployeeId(long employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public Date getEmployeeHireDate() { return employeeHireDate; } public void setEmployeeHireDate(Date employeeHireDate) { this.employeeHireDate = employeeHireDate; } public double getEmployeeSalary() { return employeeSalary; } public void setEmployeeSalary(double employeeSalary) { this.employeeSalary = employeeSalary; } }
2. 配置JSF从Spring获取Bean
在faces-config.xml中添加Spring的EL解析器,让JSF能够识别Spring管理的Bean:
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" version="2.2"> <application> <!-- 配置Spring的EL解析器,让JSF能找到Spring管理的Bean --> <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> </application> </faces-config>
3. 检查Spring核心配置
确保你的Spring配置类(或XML)包含以下关键配置:
- 开启组件扫描,覆盖
RegisterEmployee、EmployeeService所在的包:
@Configuration @ComponentScan(basePackages = "com.your.package") // 替换成你的实际包路径 @EnableJpaRepositories(basePackages = "com.your.package.repository") // 开启Spring Data JPA @EnableTransactionManagement // 开启事务管理 public class SpringConfig { // 配置DataSource、LocalContainerEntityManagerFactoryBean、PlatformTransactionManager等Bean @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); em.setPackagesToScan("com.your.package.entity"); // 指定JPA实体类所在包 em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); // 可选:添加Hibernate属性配置 Properties props = new Properties(); props.setProperty("hibernate.hbm2ddl.auto", "update"); props.setProperty("hibernate.show_sql", "true"); em.setJpaProperties(props); return em; } // 其他必要配置:DataSource、TransactionManager等 }
为什么之前的方案无效?
- 混合JSF和Spring的Bean管理:JSF的
@ManagedBean默认不会识别Spring的@Autowired,必须配置Spring EL解析器才能打通两者 Employee实体加@Component是错误的:实体类是JPA的映射对象,不需要被Spring作为单例Bean管理,注入会导致复用同一个实例,数据混乱- 仅替换
@Autowired为@ManagedProperty没用:JSF的@ManagedProperty只能注入JSF托管的Bean,无法直接获取Spring的Bean
内容的提问来源于stack exchange,提问作者Norman87
相关产品推荐
相关产品推荐

