Spring dan IceFaces: kesalahan tak terduga 404 pada `http://‹hostname›/‹projectname›/WEB-INF/views/‹filename›.xhtml`

Saya sedang mengembangkan perangkat lunak berdasarkan Spring dan ICFaces.
Saya memiliki file di <project directory>/src/main/webapp/WEB-INF/views/<filename>.xhtml, yang dapat diakses dengan benar menggunakan URL berikut: http://<hostname>/<projectname>/<filename>.xhtml

File berisi <h:form id="formId"> yang diterjemahkan sebagai <form action="/<projectname>/WEB-INF/views/<filename>.xhtml" [.. some other stuff ..]>

Artinya, ketika saya mengklik input submit yang ada di formulir, browser mencoba membuka URL http://<hostname>/<projectname>/WEB-INF/views/<filename>.xhtml dan, seperti yang saya katakan di judul, muncul halaman error 404.

Saya ingin file .xhtml juga dapat dijangkau menggunakan URL yang "lebih panjang". Saya cukup yakin bahwa saat ini saya tidak dapat mencapainya karena kesalahan konfigurasi.

Ini adalah web.xml saya:

<?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>

Ini adalah applicationContext.xml yang dirujuk dalam file sebelumnya:

<?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>

Dan, pada akhirnya, inilah faces-config.xml saya:

<?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>

Izinkan saya menunjukkan bahwa konfigurasi ini masih tidak memungkinkan saya membuka URL yang lebih pendek dengan sukses. Memang benar, saya harus membuat pengontrol yang tepat atau, lebih baik lagi, @RequestMapping yang tepat di dalam @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>";
}

Ya, nilai @RequestMapping adalah "<filename>", tanpa ekstensi .xhtml. Saya sudah memastikan, melalui trial and error, bahwa pemetaan seperti itu diperlukan agar GET berhasil. Di sisi lain, saya menyadari bahwa konfigurasi seperti itu sangat rapuh. Apa yang harus saya ubah pada file konfigurasi saya, agar <filename>.xhtml dapat dijangkau juga menggunakan URL lebih panjang?

Terima kasih sebelumnya atas perhatian Anda.


person iccuta    schedule 13.08.2012    source sumber
comment
Terima kasih atas jawaban anda. Aplikasi saya diterapkan pada VMware vFabric tc Server Developer Edition v2.6. Saat menggunakan Servlet 3.0, deskriptornya juga tidak dimuat. Saat menggunakan Servlet 2.5, aplikasi dimuat ke server tetapi tetap berperilaku seperti yang saya jelaskan di postingan asli saya. Bagaimanapun, saya akan memperbarui posting saya dengan web.xml baru   -  person iccuta    schedule 13.08.2012
comment
Tidak masalah. Itu hanya komentar, bukan jawaban. Saya sudah menghapusnya, sekarang Anda telah memperbaiki pertanyaan Anda untuk mengecualikan kemungkinan penyebabnya.   -  person BalusC    schedule 13.08.2012
comment
Coba ubah ‹property name=suffix value=.jsp /› menjadi ‹property name=suffix value=.xhtml /›   -  person Ravi Kadaboina    schedule 14.08.2012


Jawaban (1)


Setelah beberapa penelitian, saya sampai pada kesimpulan bahwa saya tidak menggunakan teknologi tersebut sebagaimana mestinya. Jika Anda menghadapi masalah yang sama, dalam konteks yang sama, Anda mungkin membuat kesalahan yang sama, oleh karena itu Anda harus sedikit mengubah arsitektur aplikasi Anda untuk menyelesaikannya. Memang benar, tampaknya menggunakan JSF/ICEFaces dan Spring MVC bersama dengan Spring WebFlow adalah pendekatan yang paling nyaman dan mudah.

Saya akan mencoba menjelaskan alasannya.
Halaman beranda situs/pengguna Anda diisi dengan link ke kasus penggunaan (atau, lebih baik lagi, alur) yang dapat diaktifkan dengan hak istimewanya. Tautan tersebut terlihat seperti http://<page-url>?<flow-id>. Aliran di Spring WebFlow didefinisikan sebagai grafik status, dalam file xml. Transisi antar keadaan diberi label berdasarkan string, bernama tindakan, atau kondisi. Beberapa status adalah view-state, artinya ada sesuatu yang dapat ditampilkan kepada pengguna saat status tersebut tercapai. Oleh karena itu, untuk setiap status tampilan bernama <state-id>, harus ada file .xhtml bernama <state-id>.xhtml.

Tombol yang disediakan oleh JSF dan ICEFaces akan selalu dirender sebagai <input type="submit" [..]> dan tindakan formulir yang memuatnya akan selalu menunjuk ke URL yang sama dengan halaman yang memuatnya (yaitu http://<page-url>?<flow-id>). Itu faktanya.
Perbedaannya adalah, dalam kasus ini, URL tersebut tidak didukung oleh file asli (seperti dalam pertanyaan saya) namun, jika aplikasi dikonfigurasi dengan benar, sebuah flow-handler akan menjawab dan mengelola semua status dan transisi yang ditentukan dalam file xml, memilih tampilan yang tepat untuk ditampilkan.

Selain itu, tombol-tombol yang disediakan oleh JSF dan ICEFaces memiliki atribut action. Seperti yang dapat Anda bayangkan, tindakan tersebut sesuai dengan tindakan yang ditentukan dalam file definisi alur: oleh karena itu, klik pada tombol dengan nilai atribut action tertentu akan memicu transisi dari keadaan saat ini yang diberi label persis dengan string itu.
Secara lebih konkret, jika Anda mengklik tombol tersebut, browser mengirimkan permintaan POST ke http://<page-url>?<flow-id> yang tubuhnya berisi semua parameter yang diperlukan. Pengendali aliran menerima permintaan POST tersebut dan menghitung status berikutnya, mungkin memilih tampilan mana yang harus ditampilkan kepada pengguna.

Jika Anda masih membaca jawaban ini, saya rasa Anda memerlukan contoh nyata untuk dijadikan referensi. Saya akan memberi Anda yang saya gunakan untuk mempelajari semua hal yang saya tulis di sini: http://wiki.icesoft.org/display/ICE/Spring+Web+Flow+2.3.1 Ini adalah titik awal yang luar biasa, karena mudah namun lengkap.

person iccuta    schedule 17.08.2012