Проблемы при работе моего веб-приложения JSF(Icefaces) для нескольких пользователей
Это мой первый вопрос на stackru, поэтому, пожалуйста, оставьте отзыв, если вы что-то упустили.
Я использую JPA (Hibernate 3), Spring 3.0.6 и JSF (Icefaces 3.0) для своего веб-приложения. Когда я пользуюсь приложением, на моей локальной машине проблем нет. Но если второй пользователь начинает кликать, иногда возникает следующее исключение:
"Обнаружено предварительно связанное соединение JDBC! JpaTransactionManager не поддерживает запуск в DataSourceTransactionManager, если указано управлять самим источником данных. Рекомендуется использовать один JpaTransactionManager для всех транзакций в одном источнике данных, независимо от того, доступен ли JPA или JDBC".
В моей ситуации это не имеет смысла, так как я использую только один JPATransactionManager и один EntityManager (см. Конфигурацию ниже). Единственная ситуация, это исключение следует выдавать при использовании нескольких менеджеров транзакций с одним источником данных.
(Я думаю) Из-за JSF у меня было много проблем с обработкой сеансов и транзакций, и я использовал это решение, чтобы оно заработало.
После недели множества различных конфигураций и бесконечных испытаний я не могу найти источник проблемы. Такое ощущение, что я что-то упустил в конфигурации.
Кстати: в настоящее время я регулярно получаю исключение
msgstr "нулевой идентификатор в записи xxxxx.xxxx.xxxx (не очищать сессию после возникновения исключения)"
после getAll() из совершенно другой таблицы. То есть трассировка стека содержит yyyy.getAll(), и вышеприведенное исключение выдается. Я понятия не имею, откуда это взялось.
Большое спасибо за Вашу помощь!
Вот мои текущие конфиги:
applicationContext.xml:
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
destroy-method="close">
<property name="driverClassName" value="${datasource.driverClassName}" />
<property name="url" value="${datasource.url}" />
<property name="username" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
<property name="removeAbandonedTimeout" value="180" />
<property name="removeAbandoned" value="true" />
<property name="defaultCatalog" value="${datasource.defaultCatalog}" />
<property name="testWhileIdle" value="true" />
<property name="validationQuery" value="Select 1" />
</bean>
<!-- Spring Data Access Exception Translator Defintion -->
<bean id="jdbcExceptionTranslator"
class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="HomeDao"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${hibernate.show_sql}" />
</bean>
</property>
</bean>
<util:properties id="hibernateProperties">
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<prop key="hibernate.hbm2ddl.auto">none</prop>
</util:properties>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="openEntityManagerInViewPhaseListener"
class="de.itcampus.endopdb.util.OpenEntityManagerInViewPhaseListener">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:annotation-config/>
<aop:aspectj-autoproxy />
<context:component-scan base-package="de.endopdb" />
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<!-- spring-security -->
<security:http realm="Sample Realm" entry-point-ref="authenticationEntryPoint"
auto-config="false">
<security:custom-filter ref="sessionManagementFilter"
before="SESSION_MANAGEMENT_FILTER" />
<security:intercept-url pattern="/ifpages/pages/administration/**"
access="ROLE_ADMIN" />
<security:intercept-url pattern="/ifpages/pages/**"
access="ROLE_ADMIN,
ROLE_USER" />
<security:access-denied-handler
error-page="/loginError.xhtml" />
<security:form-login login-page="/loginStart.xhtml" />
<security:logout logout-url="/j_spring_security_logout"
logout-success-url="/logoutSuccess.xhtml" invalidate-session="true" />
</security:http>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/loginStart.xhtml" />
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
user-service-ref="userDetailsService">
<security:password-encoder hash="md5" />
</security:authentication-provider>
</security:authentication-manager>
<bean id="userDetailsService" class="de.itcampus.endopdb.security.UserDetailsServiceImpl">
</bean>
<bean id="sessionManagementFilter"
class="org.springframework.security.web.session.SessionManagementFilter">
<constructor-arg name="securityContextRepository"
ref="httpSessionSecurityContextRepository" />
<property name="invalidSessionStrategy" ref="invalidSessionStrategy" />
</bean>
<bean id="httpSessionSecurityContextRepository"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
<bean id="invalidSessionStrategy"
class="org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy">
<constructor-arg name="invalidSessionUrl"
value="/ifpages/pages/loginStart.xhtml" />
</bean>
web.xml
<context-param>
<param-name>openEntityManagerInViewPhaseListenerBeanName</param-name>
<param-value>openEntityManagerInViewPhaseListener</param-value>
</context-param>
<filter>
<filter-name>MyJSFCompatibleOpenEntityManagerInViewFilter</filter-name>
<filter-class>de.itcampus.endopdb.util.myJSFCompatibleOpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyJSFCompatibleOpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
// Spring Listener for Request und Session-Scoped beans
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
// Spring Context Loader Listener
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
// SOAP-Servlet
<servlet>
<servlet-name>jaxws-servlet</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jaxws-servlet</servlet-name>
<url-pattern>/soap</url-pattern>
</servlet-mapping>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
//minutes
<session-timeout>30</session-timeout>
</session-config>
// tomcat basic auth
<security-constraint>
<web-resource-collection>
<web-resource-name>SOAP-Auth</web-resource-name>
<url-pattern>/soap</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>XXXXX</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>SOAP-Auth</realm-name>
</login-config>
<security-role>
<role-name>XXXXXXX</role-name>
</security-role>
//Java Faces
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/icefaces/*</url-pattern>
</servlet-mapping>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>false</param-value>
</context-param>
//Icefaces
<context-param>
<param-name>com.icesoft.faces.standardRequestScope</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>com.icesoft.faces.synchronousUpdate</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/xmlhttp/*</url-pattern>
</servlet-mapping>
Лица-config.xml
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
<lifecycle>
<phase-listener>de.itcampus.endopdb.util.OpenEntityManagerInViewPhaseListenerDelegator</phase-listener>
</lifecycle>