Spring и IceFaces: непредвиденная ошибка 404 на `http://‹hostname›/‹projectname›/WEB-INF/views/‹filename›.xhtml`

Я разрабатываю программное обеспечение на основе Spring и ICEFaces.
У меня есть файл по адресу <project directory>/src/main/webapp/WEB-INF/views/<filename>.xhtml, доступ к которому осуществляется по следующему URL-адресу: http://<hostname>/<projectname>/<filename>.xhtml

Файл содержит <h:form id="formId">, который отображается как <form action="/<projectname>/WEB-INF/views/<filename>.xhtml" [.. some other stuff ..]>.

Это означает, что когда я нажимаю на ввод отправки, содержащийся в форме, браузер пытается открыть URL-адрес http://<hostname>/<projectname>/WEB-INF/views/<filename>.xhtml и, как я сказал в заголовке, показывает страницу с ошибкой 404.

Я бы хотел, чтобы к файлу .xhtml можно было получить доступ и по «более длинному» URL-адресу. Я почти уверен, что в настоящее время не могу этого добиться из-за ошибки конфигурации.

Это мой web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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-app_2_5.xsd"
  version="2.5">

<web-app>
    <display-name>SIGLO</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <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>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Это файл applicationContext.xml, указанный в предыдущем файле:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns="http://www.springframework.org/schema/beans"
    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/aop
                        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" >

    <context:component-scan base-package="com.infoone.siglo" />
    <!--
         map all requests to /resources/** to the container default servlet 
        (ie, don't let Spring handle them)
    -->
    <bean id="defaultServletHttpRequestHandler" class="org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler" />
    <bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
        <property name="urlMap" >
            <map>
                <entry key="/resources/**" value-ref="defaultServletHttpRequestHandler" />
            </map>
        </property>
    </bean>
    <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
    <mvc:annotation-driven />

    <!-- JSF for representation layer. All JSF files under /WEB-INF/views directory -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver" >
        <property name="cache" value="false" />
        <property name="viewClass" value="org.springframework.faces.mvc.JsfView" />
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean name="icefacesResourceHandler" class="org.springframework.faces.webflow.JsfResourceRequestHandler" />

    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
      <property name="order" value="0" />
      <property name="mappings">
        <value>
          /javax.faces.resource/**=icefacesResourceHandler
        </value>
      </property>
    </bean>
    </beans>

И, наконец, это мой faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" 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">
    <application>
        <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
        <locale-config></locale-config>
        <resource-bundle>
            <base-name>MessageResources</base-name>
            <var>msg</var>
        </resource-bundle>
    </application>
</faces-config>

Позвольте мне отметить, что эта конфигурация по-прежнему не позволяет мне успешно открыть более короткий URL. Действительно, мне нужно создать правильный контроллер или, лучше, правильный @RequestMapping внутри @Controller:

@RequestMapping(value = "<filename>", method = RequestMethod.GET)
public String creaBlocco()
{
    return "<filename>";
}

@RequestMapping(value = "<filename>", method = RequestMethod.POST)
public String creaBlocco([.. parameters ..]) {
    [.. stuff ..]
    return "<filename>";
}

Да, значение @RequestMapping равно "<filename>" без расширения .xhtml. Я уже убедился методом проб и ошибок, что такое сопоставление необходимо для успешного выполнения GET. С другой стороны, я понимаю, что такая конфигурация очень хрупкая. Что мне нужно изменить в моих файлах конфигурации, чтобы сделать <filename>.xhtml доступным, используя также более длинный URL?

Заранее спасибо за внимание.


person iccuta    schedule 13.08.2012    source источник
comment
Спасибо за Ваш ответ. Мое приложение развернуто на VMware vFabric tc Server Developer Edition v2.6. При использовании Servlet 3.0 он также не загружает дескриптор. При использовании Servlet 2.5 приложение загружается на сервер, но продолжает вести себя так, как я описал в своем исходном посте. В любом случае, я обновлю свой пост новым файлом web.xml.   -  person iccuta    schedule 13.08.2012
comment
Без проблем. Это был просто комментарий, а не ответ. Я уже удалил его, теперь вы исправили свой вопрос, чтобы исключить возможную причину.   -  person BalusC    schedule 13.08.2012
comment
Попробуйте изменить ‹имя свойства=значение суффикса=.jsp /› на ‹имя свойства=значение суффикса=.xhtml /›   -  person Ravi Kadaboina    schedule 14.08.2012


Ответы (1)


После некоторых исследований я пришел к выводу, что я использовал эти технологии не так, как они должны были использоваться. Если вы столкнулись с той же проблемой в том же контексте, вы, вероятно, делаете ту же ошибку, поэтому вам нужно немного изменить архитектуру вашего приложения, чтобы решить ее. Действительно, кажется, что использование JSF/ICEFaces и Spring MVC в сочетании с Spring WebFlow является наиболее удобным и простым подходом.

Я попытаюсь объяснить причину.
Ваш сайт/домашняя страница пользователя заполнена ссылками на сценарии использования (или, лучше сказать, потоки), которые можно активировать с его/ее привилегиями. Эти ссылки выглядят как http://<page-url>?<flow-id>. Поток в Spring WebFlow определяется как граф состояний в XML-файле. Переходы между состояниями помечаются строками, называемыми действиями или условиями. Некоторые состояния являются view-state s, что означает, что есть что показать пользователю, когда такое состояние достигнуто. Следовательно, для каждого состояния просмотра с именем <state-id> должен быть файл .xhtml с именем <state-id>.xhtml.

Кнопки, предоставляемые JSF и ICEFaces, всегда будут отображаться как <input type="submit" [..]>, а действие содержащей формы всегда будет указывать на тот же URL-адрес, что и содержащая страница (т. е. http://<page-url>?<flow-id>). Это факт.
Разница в том, что в данном случае такой URL поддерживается не реальным файлом (как в моем вопросе), а, если приложение правильно настроено, обработчиком потока будет отвечать и управлять всеми состояниями и переходами, определенными в файле xml, выбирая правильный вид для отображения.

Кроме того, кнопки, предоставляемые JSF и ICEFaces, имеют атрибут action. Как вы можете себе представить, они соответствуют действиям, определенным в файле определения потока: поэтому нажатие кнопки с определенным значением атрибута action вызовет переход из текущего состояния, помеченного точно эту строку.
Говоря более конкретно, если вы нажмете на кнопку, браузер отправит запрос POST на http://<page-url>?<flow-id>, тело которого содержит все необходимые параметры. Обработчик потока получает этот запрос POST и вычисляет следующее состояние, возможно, выбирая, какое представление должно быть показано пользователю.

Если вы все еще читаете этот ответ, я думаю, вам нужен конкретный пример, на который можно сослаться. Я предоставлю вам тот, который я использовал, чтобы изучить все, что я написал здесь: http://wiki.icesoft.org/display/ICE/Spring+Web+Flow+2.3.1 Это отличная отправная точка, потому что она простая, но исчерпывающая.

person iccuta    schedule 17.08.2012