PrimeFaces Ajax调用总是返回302错误代码

时间:2012-07-31 20:03:55

标签: ajax spring jsf primefaces

我正在使用Spring 3.2.0,PrimeFaces 3.3.1,Mojarra 2.1.11和Spring Security 3.1.1创建一个项目。

我的问题是当PrimeFaces触发ajax调用时,例如在表格分页中,屏幕组件不会刷新。

编辑#4

每当调用ajax时,都会从服务器返回错误302并刷新页面

我认为问题与Spring安全有关,这是我的设置:

 <security:http entry-point-ref="authenticationEntryPoint" pattern="/spring/**">
    <security:anonymous />
    <security:http-basic />
    <security:custom-filter position="FORM_LOGIN_FILTER" ref="authenticationProcessingFilter" />
    <security:logout logout-url="/spring/logout" logout-success-url="/spring/login?logout=true" />
    <security:intercept-url pattern="/spring/login" access="ROLE_ANONYMOUS,ROLE_USER,ROLE_ADMIN" />
    <security:intercept-url pattern="/spring/logoutSuccess" access="ROLE_ANONYMOUS,ROLE_USER,ROLE_CLIENT" />
    <security:intercept-url pattern="/spring/intro" access="ROLE_ANONYMOUS,ROLE_USER"  />
    <security:intercept-url pattern="/spring/flows/admin_main_flow/**" access="ROLE_ADMIN" />
    <security:intercept-url pattern="/spring/flows/client_main_flow/**" access="ROLE_CLIENT" />
 </security:http>

 <security:http security="none" pattern="/javax.faces.resource/**" />
 <security:http security="none" pattern="/ajax/**" />
 <security:http security="none" pattern="/static/**" />
 <security:http security="none" pattern="/resources/**" />

这是在登录后发生的,所以我认为会话不应该已经过期。

编辑#4结束

我将应用程序剥离到最低限度并尝试使用此代码:

<h:form id="testAjax" >
    <h:panelGrid columns="4" cellpadding="5">  
        <h:outputLabel for="test" value="test:" style="font-weight:bold"/>  
    <p:inputText id="test" value="#{testBean.test}" />
    <p:commandButton value="Submit" update="@form"/>
    <h:outputText value="#{testBean.test}" id="display" />  
</h:panelGrid>  
</h:form>

请注意,我仔细检查过没有嵌套的表单,我尝试使用@form或元素id进行“处理”和“更新”。

会发生的是调用TestBean的setter,设置属性,但是再也不会再调用getter来显示新值。这是服务器端的日志:

org.springframework.web.servlet.DispatcherServlet  - DispatcherServlet with name 'Spring MVC Dispatcher Servlet' processing POST request for [/TryAjax/spring/WEB-INF/login.xhtml]
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping  - Mapping [/WEB-INF/login.xhtml] to HandlerExecutionChain with handler [org.springframework.web.servlet.mvc.UrlFilenameViewController@2f46ccac] and 1 interceptor
org.springframework.web.servlet.mvc.UrlFilenameViewController  - Returning view name 'WEB-INF/login' for lookup path [/WEB-INF/login.xhtml]
org.springframework.web.servlet.DispatcherServlet  - Rendering view [org.springframework.faces.mvc.JsfView: name 'WEB-INF/login'; URL [/WEB-INF/WEB-INF/login.xhtml]] in DispatcherServlet with name 'Spring MVC Dispatcher Servlet'
org.springframework.faces.support.RequestLoggingPhaseListener  - Entering JSF Phase: RESTORE_VIEW 1
org.springframework.faces.mvc.JsfView  - Asking faces lifecycle to render
org.springframework.faces.support.RequestLoggingPhaseListener  - Entering JSF Phase: RENDER_RESPONSE 6
org.springframework.faces.mvc.JsfView  - View rendering complete
org.springframework.web.servlet.DispatcherServlet  - Successfully completed request

我担心是配置问题,我按照基本指令但是做了一些修改来纠正一些错误,这里的web.xml剥离了一些不相关的部分

<?xml version = '1.0'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
  version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee">
    <context-param>  
        <param-name>log4jConfigLocation</param-name>  
        <param-value>/WEB-INF/log4j.xml</param-value>  
    </context-param>  
    <listener>  
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
    </listener>  
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring_context.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener </listener-class>
    </listener>
    <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>*.faces</url-pattern>
    </servlet-mapping>
    <servlet-mapping> 
        <servlet-name>Faces Servlet</servlet-name> 
        <url-pattern>*.xhtml</url-pattern> 
    </servlet-mapping>
    <context-param>
        <param-name>facelets.LIBRARIES</param-name>
        <param-value>/WEB-INF/tags/synaptic.taglib.xml</param-value>
    </context-param>
    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>flushMode</param-name>
            <param-value>AUTO</param-value>
        </init-param>
    </filter>
    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</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>facelets.SKIP_COMMENTS</param-name>
        <param-value>true</param-value>
    </context-param>
    <servlet>
        <servlet-name>Resources Servlet</servlet-name>
        <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
            <servlet-name>Resources Servlet</servlet-name>
            <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>
</web-app>

面对配置

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee" 
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
              version="2.0"> 
    <application>
        <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
    </application>
</faces-config>

其他弹簧流配置

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx" 
       xmlns:mvc="http://www.springframework.org/schema/mvc" 
       xmlns:webflow="http://www.springframework.org/schema/webflow-config" 
       xmlns:faces="http://www.springframework.org/schema/faces"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/webflow-config 
        http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd 
        http://www.springframework.org/schema/faces 
        http://www.springframework.org/schema/faces/spring-faces-2.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
    <faces:resources />
    <context:annotation-config />
     <context:component-scan base-package="com.synaptic"/>
    <bean class="org.springframework.faces.webflow.JsfFlowHandlerAdapter">
        <property name="flowExecutor" ref="flowExecutor" />
    </bean>
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <value>
                /flows/*=flowController
            </value>
        </property>
        <property name="defaultHandler">
            <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
        </property>
    </bean>
    <bean  class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
    </bean>
    <bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
         <property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
         <property name="prefix" value="/WEB-INF/"/>
         <property name="suffix" value=".xhtml"/>
    </bean>
    <bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
      <property name="flowExecutor" ref="flowExecutor"/>
    </bean>
    <webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
        <webflow:flow-execution-listeners> 
            <webflow:listener ref="flowFacesContextLifecycleListener" /> 
            <!--  <webflow:listener ref="facesContextListener"/>-->
        </webflow:flow-execution-listeners> 
    </webflow:flow-executor> 
    <bean id="flowFacesContextLifecycleListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener" /> 
    <webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices">
        <webflow:flow-location-pattern value="/WEB-INF/flows/**/*.xml"/>
    </webflow:flow-registry>
    <bean id="conversionService" class="org.springframework.faces.model.converter.FacesConversionService"/>
    <bean id="expressionParser" class="org.springframework.webflow.expression.el.WebFlowELExpressionParser">
         <constructor-arg>
             <bean class="org.jboss.el.ExpressionFactoryImpl"/>    
         </constructor-arg>
         <property name="conversionService" ref="conversionService"/>
     </bean>        
    <faces:flow-builder-services id="facesFlowBuilderServices" expression-parser="expressionParser" conversion-service="conversionService"/>
</beans>

如果您发现任何错误或者您有任何想法可以帮助我,请解决这个问题。谢谢!

编辑#1

我添加了支持bean的代码和我声明它的webflow代码:

public class TestBean implements Serializable {
    private String test = "xxx";
    public String getTest() {
        return test;
    }
    public void setTest(String test) {
        this.test = test;
    }
}

<view-state id="home" view="../views/adminHome.xhtml">
    <on-entry>
        <evaluate expression="textManager.getTest()" result="viewScope.test"/>
    </on-entry>
</view-state>

现在这个testBean只是我可以做的最简单的测试用例,它不起作用,我遇到的主要问题是没有ajax调用,例如表的分页,添加或删除或修改数据表的元素,tabView等。

我通常为页面创建bean并将它们放在viewScope或flowScope中,这也适用于来自数据库的数据列表。我尝试使用Spring管理的bean使用范围Session,但它既不起作用也不起作用。另一个注意事项是页面上的默认值显示正确。

编辑#2

使用firebug和eclipse调试我看到了:

TestBean.test的初始值为“xxx”,我更改为aaa并按提交。

ajax post请求被发送到服务器:

javax.faces.ViewState   e2s1
javax.faces.partial.ajax    true
javax.faces.partial.execu...    @all
javax.faces.partial.rende...    testAjax testAjax:display
javax.faces.source  testAjax:testButton
testAjax    testAjax
testAjax:test   aaa
testAjax:testButton testAjax:testButton

当发送POST时,我首先调试对TestBean.getTest()的调用,然后调用具有正确值的TestBean.setTest(“aaa”)。

此时我希望在构建响应时再次调用TestBean.getTest(),但调用没有发生且响应不包含正确的值,而是旧值“xxx”。

如果现在我刷新页面,则调用getter并正确显示新值“aaa”。

编辑#3

我仍然可以解决这个问题。我现在注意到了萤火虫出乎意料的行为:

当我单击命令按钮时,2请求被发送到服务器,POST和GET。

首先发送POST并返回错误“302 Moved Temporarily”,然后GET启动并返回没有更新数据的响应。任何人都知道在这种情况下302意味着什么,可能是什么原因?

以相同的方式调试primefaces演示只触发POST请求,返回无错误

谢谢

3 个答案:

答案 0 :(得分:1)

您需要向flow-executor添加一个参数,以禁止重定向到相同的状态。配置变为:

<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
    <webflow:flow-execution-listeners> 
        <webflow:listener ref="flowExecutionListener" /> 
        <webflow:listener ref="facesContextListener"/>
        <!--  <webflow:listener ref="flowFacesContextLifecycleListener" />-->
    </webflow:flow-execution-listeners> 
    <webflow:flow-execution-attributes>
        <webflow:redirect-in-same-state value="false"/>
    </webflow:flow-execution-attributes>
</webflow:flow-executor> 

这可以防止流执行程序在发送ajax请求后完全刷新页面。

答案 1 :(得分:0)

当您将JSF与Spring集成时,您的JSF托管bean将成为Spring bean。这就是为什么Spring包含他们自己的ELResolver实现的原因,这样你就可以从EL表达式中引用这些Spring bean。

不幸的是,虽然Spring支持的唯一范围是@Request,@ Session和@Application。

幸运的是,可以将与Spring集成的ViewScope的简单实现集成到您的应用程序中。 PrimeFaces的首席开发人员Cagatay Civici撰写了一篇博客文章,展示了一个简单的ViewScope实现示例,该实现可以轻松集成到您的应用程序中。

http://cagataycivici.wordpress.com/2010/02/17/port-jsf-2-0s-viewscope-to-spring-3-0/

使用视图作用域的托管bean,您的bean将具有足够的持久性,以便在ajax更新上动态呈现页面元素。

答案 2 :(得分:0)

<webflow:flow-execution-attributes>
<webflow:redirect-in-same-state value="false"/>
</webflow:flow-execution-attributes>

解决了我的问题。 我使用 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping 与 JSF 1.x RichFaces 3.x 导航。 当转移到 JSF 2.x 和 PrimeFaces/RichFaces 4 时,DataTables 的 ajax 方面不起作用(例如显示但不会排序) 添加这个 xml 就像魔法一样(因为我不知道我在做什么,所以需要这样做)