我制作了一个非常简单的JSF webapp,它运行良好。
然后我尝试添加Spring / Hibernate实体来管理业务逻辑并访问数据库。
该项目的构建工作正常,但应用程序的运行给我3天的错误。
以下是我最近尝试的设置:
我们测试成功: * JSF配置(通过更简单的webapp) * Dao部分和Spring部分的单元测试。 问题在于整合两个世界。
服务器: Apache 8.5.24
pom.xml。 “显示图表”不会显示依赖项版本中的任何冲突。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>zparkingb</groupId>
<artifactId>disquesapp2</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>disquesapp2</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework-version>3.1.1.RELEASE</org.springframework-version>
</properties>
<dependencies>
<!-- JSF + PrimeFace -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>5.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-shaded</artifactId>
<version>3.0.2.Final</version>
</dependency>
<!-- Swing + Hibernate -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework-version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.11.Final</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
<type>jar</type>
</dependency>
<dependency> <!--LVR: for the @NotNull, @Size, ...-->
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.7.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<id>default-copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}/</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources-webapp-common</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<url>http://repository.primefaces.org/</url>
<id>PrimeFaces-maven-lib</id>
<layout>default</layout>
<name>Repository for library PrimeFaces-maven-lib</name>
</repository>
</repositories>
</project>
在.war中添加了库:
antlr-2.7.7.jar
aopalliance-1.0.jar
classmate-1.3.1.jar
commons-logging-1.1.1.jar
dom4j-1.6.1.jar
hibernate-commons-annotations-4.0.5.Final.jar
hibernate-core-4.3.11.Final.jar
hibernate-entitymanager-4.3.11.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
hibernate-validator-6.0.7.Final.jar
jandex-1.1.0.Final.jar
javassist-3.18.1-GA.jar
javax.faces-2.3.3.jar
jboss-logging-3.1.3.GA.jar
jboss-logging-annotations-1.2.0.Beta1.jar
jboss-transaction-api_1.2_spec-1.0.0.Final.jar
jstl-1.2.jar
lib.txt
mysql-connector-java-5.1.6.jar
primefaces-5.0.jar
spring-aop-3.1.1.RELEASE.jar
spring-asm-3.1.1.RELEASE.jar
spring-beans-3.1.1.RELEASE.jar
spring-context-3.1.1.RELEASE.jar
spring-core-3.1.1.RELEASE.jar
spring-expression-3.1.1.RELEASE.jar
spring-jdbc-3.1.1.RELEASE.jar
spring-orm-3.1.1.RELEASE.jar
spring-tx-3.1.1.RELEASE.jar
spring-web-3.1.1.RELEASE.jar
validation-api-2.0.1.Final.jar
weld-servlet-shaded-3.0.2.Final.jar
xml-apis-1.0.b2.jar
META-INF / context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--<Context antiJARLocking="true" path="/disquesapp2"/> LVR: not supported anymore as of Tomcat 8-->
<Context path="/disquesapp2">
<!-- Utilisation de Weld pour les ManagedBean -->
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory" />
</Context>
WEB-INF / faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<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_3.xsd"
version="2.3"
>
<application>
<!-- Translation -->
<resource-bundle>
<base-name>
messages
</base-name>
<var>msg</var>
</resource-bundle>
<!-- This JSF variable resolver lets you reference JSF managed
beans from a Spring context, or a Spring bean from a managed bean -->
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
<locale-config />
</application>
<lifecycle />
<factory />
<managed-bean>
<managed-bean-name>requestBean</managed-bean-name>
<managed-bean-class>
zparkingb.disquesapp.controler.RequestBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>disqueService</property-name>
<value>#{disqueService}</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>changeLocal</managed-bean-name>
<managed-bean-class>
zparkingb.disquesapp.controler.ChangeLecal
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>showsearch</from-outcome>
<to-view-id>/search.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>error</from-outcome>
<to-view-id>/exception.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/search.xhtml</from-view-id>
<navigation-case>
<from-outcome>disquedetail</from-outcome>
<to-view-id>/disque.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>error</from-outcome>
<to-view-id>/exception.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/disque.xhtml</from-view-id>
<navigation-case>
<from-outcome>res</from-outcome>
<to-view-id>/search.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>error</from-outcome>
<to-view-id>/exception.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
WEB-INF / applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- Initialisation des beans Dao -->
<bean id="disqueDao" class="zparkingb.disquesapp.dao.DisqueDaoImpl" >
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="editeurDao" class="zparkingb.disquesapp.dao.EditeurDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="disqueService" class="zparkingb.disquesapp.bo.DisqueServiceImpl">
<property name="disqueDao" ref="disqueDao"/>
</bean>
<bean id="editeurService" class="zparkingb.disquesapp.bo.EditeurServiceImpl">
<property name="editeurDao" ref="editeurDao"/>
</bean>
<!-- Config de la base de données -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/properties/database.properties</value>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${dbconfig.jdbc_driverClassName}" />
<property name="url" value="${dbconfig.jdbc_url}" />
<property name="username" value="${dbconfig.jdbc_username}" />
<property name="password" value="${dbconfig.jdbc_password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<!-- Le dialecte de la db utilisée -->
<prop key="hibernate.dialect">${dbconfig.hibernate_dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<!--Indique où doivent tourner les sessions -->
<!--<prop key="hibernate.current_session_context_class">jta</prop>-->
<prop key="hibernate.current_session_context_class">thread</prop>
<!-- Ajouté de manière à pouvoir peupler les relations LAZY en dehors de la transation-->
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
</props>
</property>
<!-- Indique quelles classes il faut parser pour trouver les classe d'entités-->
<property name="packagesToScan" value="zparkingb.disquesapp.jpa" />
</bean>
<!-- Transactions management -->
<!-- TODO : to add later -->
<!-- Exception translation -->
<!--LVR: causes errors => in comments -->
<!--<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />-->
<!-- persistence -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>
因此,这是我在运行时获得的Apache日志文件:
03-Feb-2018 22:56:05.802 GRAVE [http-nio-8085-exec-8] org.apache.catalina.core.StandardContext.listenerStart Exception lors de l'envoi de l'évènement contexte initialisé (context initialized) à l'instance de classe d'écoute (listener) [com.sun.faces.config.ConfigureListener]
java.lang.RuntimeException: com.sun.faces.config.ConfigurationException: Factory 'javax.faces.lifecycle.ClientWindowFactory' was not configured properly.
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:315)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4745)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5207)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
...
Caused by: com.sun.faces.config.ConfigurationException: Factory 'javax.faces.lifecycle.ClientWindowFactory' was not configured properly.
at
... 48 more
Caused by: javax.faces.FacesException: Unable to find CDI BeanManager
at com.sun.faces.application.ApplicationImpl.isJsf23(ApplicationImpl.java:2718)
at com.sun.faces.application.ApplicationImpl.addELResolver(ApplicationImpl.java:553)
at javax.faces.application.ApplicationWrapper.addELResolver(ApplicationWrapper.java:611)
at org.jboss.weld.environment.servlet.jsf.WeldApplication.<init>(WeldApplication.java:72)
... 51 more
03-Feb-2018 23:04:15.230 INFOS [http-nio-8085-exec-2] org.apache.catalina.core.ApplicationContext.log Initializing Spring root WebApplicationContext
03-Feb-2018 23:04:18.053 GRAVE [http-nio-8085-exec-2] org.apache.catalina.core.StandardContext.listenerStart Exception lors de l'envoi de l'évènement contexte initialisé (context initialized) à l'instance de classe d'écoute (listener) [com.sun.faces.config.ConfigureListener]
java.lang.RuntimeException: java.lang.StackOverflowError
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:315)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4743)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5207)
JSF控制器:
package zparkingb.disquesapp.controler;
import java.util.List;
import javax.inject.Named;
import javax.inject.Singleton;
import zparkingb.disquesapp.bo.DisqueService;
import zparkingb.disquesapp.jpa.Disque;
import zparkingb.disquesapp.jpa.Editeur;
/**
*
* @author laurent
*/
@Singleton
@Named
public class RequestBean {
private List<Disque> disques;
private Disque currentDisque;
private int currentIndex;
private Editeur filterEditeur;
private DisqueService disqueService;
public Editeur getFilterEditeur() {
return filterEditeur;
}
// Filter
public void setFilterEditeur(Editeur pFilterEditeur) {
this.filterEditeur = pFilterEditeur;
}
// Disques
public List<Disque> getDisques() {
return disques;
}
public Disque getCurrentDisque() {
return currentDisque;
}
// Action
public String searchDisques() {
if (filterEditeur == null) {
disques = disqueService.getAllDisques();
}
else {
disques = disqueService.getAllDisques(filterEditeur);
}
if (!disques.isEmpty())
currentDisque = disques.get(0);
else
currentDisque = null;
currentIndex = 0;
return "";
}
public boolean hasNext() {
return (currentIndex < (disques.size() - 1));
}
public boolean hasPrevious() {
return (currentIndex > 0);
}
public String previous() {
if (currentIndex > 0) {
currentIndex = 0;
currentDisque = disques.get(currentIndex);
}
return null;
}
public String next() {
if (currentIndex < (disques.size() - 1)) {
currentIndex++;
currentDisque = disques.get(currentIndex);
}
return null;
}
public int getCurrentIndex() {
return currentIndex;
}
public void setCurrentIndex(int pCurrentIndex) {
this.currentIndex = pCurrentIndex;
}
// -- SPRING INJECTION --
public DisqueService getDisqueService() {
return disqueService;
}
public void setDisqueService(DisqueService pDisqueService) {
this.disqueService = pDisqueService;
}
}
主要对象Service bean:
package zparkingb.disquesapp.bo;
import java.util.List;
import zparkingb.disquesapp.dao.DisqueDaoImpl;
import zparkingb.disquesapp.jpa.Disque;
import zparkingb.disquesapp.jpa.Editeur;
/**
*
* @author laurent
*/
public class DisqueServiceImpl implements DisqueService {
private DisqueDaoImpl disqueDao;
public void setDisqueDao(DisqueDaoImpl pDisqueDao) {
this.disqueDao = pDisqueDao;
}
@Override
public List<Disque> getAllDisques() {
return disqueDao.getAllDisques();
}
@Override
public List<Disque> getAllDisques(Editeur pEditeur) {
return disqueDao.getAllDisques(pEditeur);
}
@Override
public Disque getDisqueById(Integer pId) {
return disqueDao.getDisqueById(pId);
}
@Override
public Disque getDisqueByName(String pName) {
return disqueDao.getDisqueByName(pName);
}
@Override
public void save(Disque disque) {
disqueDao.save(disque);
}
@Override
public void update(Disque disque) {
disqueDao.update(disque);
}
@Override
public void delete(Disque disque) {
disqueDao.delete(disque);
}
}
主要对象Dao bean
package zparkingb.disquesapp.dao;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.transaction.annotation.Transactional;
import zparkingb.disquesapp.exceptions.*;
import zparkingb.disquesapp.jpa.Disque;
import zparkingb.disquesapp.jpa.Editeur;
//@Transactional
public class DisqueDaoImpl implements DisqueDao, Serializable {
private static final long serialVersionUID = 1L;
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public List<Disque> getAllDisques() {
try {
return sessionFactory.getCurrentSession().createQuery("FROM Disque").list();// "Disque" = le nom de la classe
} catch (Throwable th) {
throw new DisquesException(1, th);
}
}
@Override
public List<Disque> getAllDisques(Editeur pEditeur) {
try {
Query query = sessionFactory.getCurrentSession().getNamedQuery("findDisquesByEditeur").setLong(
"idEditeur", pEditeur.getId());
return query.list();
} catch (Throwable th) {
throw new DisquesException(3, th);
}
}
@Override
public Disque getDisqueById(Integer pId) {
try {
return (Disque) sessionFactory.getCurrentSession().get(Disque.class, pId);
} catch (Throwable th) {
throw new DisquesException(4, th);
}
}
@Override
public Disque getDisqueByName(String pName) {
try {
Criteria crit = sessionFactory.getCurrentSession().createCriteria(Disque.class);
crit.add(Restrictions.eq("title", pName));
return (Disque) crit.uniqueResult();
} catch (Throwable th) {
throw new DisquesException(5, th);
}
}
@Override
public void save(Disque disque) {
sessionFactory.getCurrentSession().save(disque);
}
@Override
public void update(Disque disque) {
sessionFactory.getCurrentSession().update(disque);
}
@Override
public void delete(Disque disque) {
sessionFactory.getCurrentSession().delete(disque);
}
}