ELResolver не может обрабатывать объект с нулевой базой - Weblogic 10.3.x, Facelets 1.1.14, RichFaces 3.3.2

У меня проблемы с использованием RichFaces 3.3.2 и Facelets 1.1.14 в Weblogic 10.3.4 и 10.3.5 (также известный как 11g). У меня есть файл xhtml с выражением #{empty messages}, и на консоли я получаю следующее исключение:

SEVERE: Error Rendering View[/index.xhtml]
javax.el.ELException: //media/DADOS/data/java/wl1034/user_projects/domains/wlrep1034/autodeploy/SimpleJSFa/index.xhtml:

  ELResolver cannot handle a null base Object with identifier 'messages'

    at com.sun.facelets.compiler.TextInstruction.write(TextInstruction.java:48)
    at com.sun.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:39)
    at com.sun.facelets.compiler.UILeaf.encodeAll(UILeaf.java:149)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:889)
    at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
    at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
    at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:108)

Переменная messages на данный момент действительно не существует, но поэтому я использовал оператор empty. Он отлично работает на Tomcat 5.5 и Websphere 6.1.

Полный файл xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:rich="http://richfaces.org/rich">

<body>

    <h1>Bean Message: #{TestBean.greeting}</h1>

    Are there messages pending? #{messages == null || empty messages} .

</body>
</html>

TestBean.java:

package eg.bean;

import java.util.ArrayList;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

public class TestBean {

    private String greeting = "Hello, World!";

    public TestBean() {
        // Uncommenting the following line puts an object in the session, under the
        // key "messages", and then the page displays properly.
        // addSomeMessages();
    }

    public String getGreeting() {
        return greeting;
    }

    public void setGreeting( String message ) {
        this.greeting = message;
    }

    public void addSomeMessages() {
        // This method is not being called for this example, but this is where
        // I would add a list of messages to be displayed to the user, and place it
        // on session scope (not advisable, I know, but bear with me)
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        List<String> messages = new ArrayList<String>();
        messages.add( "A message.");
        request.getSession().setAttribute( "messages", messages );
    }

}

Я могу только догадываться, что каким-то образом Weblogic использует другую реализацию ELResolver, что может быть вызвано конфликтами загрузчика классов, но я какое-то время возился с ней и ничего не добился.

У меня в WEB-INF / lib есть следующие банки:

commons-beanutils-1.7.0.jar
commons-digester-1.8.jar
commons-logging-1.1.1.jar
jsf-api.jar
jsf-facelets.jar
jsf-impl.jar
richfaces-api-3.3.2.SR1.jar
richfaces-impl-3.3.2.SR1.jar
richfaces-ui-3.3.2.SR1.jar
SimpleJSF.jar

Мой файл faces-config.xml выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xi="http://www.w3.org/2001/XInclude"
 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_1_2.xsd">

 <managed-bean>
  <managed-bean-name>TestBean</managed-bean-name>
  <managed-bean-class>eg.bean.TestBean</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
 </managed-bean>

 <application>
  <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
  <resource-bundle>
   <base-name>RepositoryBundle</base-name>
   <var>bundle</var>
  </resource-bundle>
 </application>
</faces-config>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" xmlns="http://java.sun.com/xml/ns/j2ee" 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">

    <!-- Use Documents Saved as *.xhtml -->
    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
    </context-param>

    <context-param>
      <param-name>com.sun.faces.disableVersionTracking</param-name>
      <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.LIBRARIES</param-name>
        <param-value>/WEB-INF/sense.taglib.xml</param-value>
    </context-param>

    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
        <param-value>com.sensedia.repository.web.startup.SensediaFaceletViewHandler</param-value>
    </context-param>

    <context-param>
        <param-name>com.prime.facestrace.DISABLE_TRACE</param-name>
        <param-value>false</param-value>
    </context-param>

    <!-- ********************** SERVLETS ********************** -->

    <!-- Faces Servlet -->
    <servlet>
        <servlet-name>FacesServlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- ********************** FILTERS ********************** -->
    <filter>
        <filter-name>richfaces</filter-name>
        <filter-class>org.ajax4jsf.Filter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>richfaces</filter-name>
        <servlet-name>FacesServlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

    <!-- Faces Servlet Mapping -->
    <servlet-mapping>
        <servlet-name>FacesServlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
    </listener>

    <welcome-file-list>
        <welcome-file>index.jsf</welcome-file>
    </welcome-file-list>

</web-app>

РЕДАКТИРОВАТЬ: я развертывал как отдельный файл войны, но я также пробовал упаковывать его как модуль EAR. Проблема не устранена. При развертывании в виде файла EAR я добавил weblogic.xml jar помимо моего собственного web.xml со следующим содержимым:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <container-descriptor>
        <prefer-web-inf-classes>true</prefer-web-inf-classes>
    </container-descriptor>
</weblogic-web-app>

Я также добавил application.xml в каталог META-INF уха, просто ссылаясь на военный модуль. Я также добавил файл weblogic-application.xml помимо этого, чтобы дополнительно указать изоляцию загрузчика классов:

<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <application-param>
        <param-name>webapp.encoding.default</param-name>
        <param-value>UTF-8</param-value>
    </application-param>

    <prefer-application-packages>
        <package-name>org.mozilla.*</package-name>
        <package-name>javax.jws.*</package-name>
        <package-name>com.sun.*</package-name>
        <package-name>javax.xml.rpc.*</package-name>
        <package-name>javax.xml.soap.*</package-name>
    </prefer-application-packages>

</weblogic-application>

person st.never    schedule 10.05.2011    source источник


Ответы (2)


Собственно, реализация EL должна быть предоставлена ​​самим контейнером. Конфликт пути к классам приведет только к ошибкам определения класса / метода, таким как LinkageError, NoClassDefFoundError, AbstractMethodError и т. Д. Это не тот случай, но это действительно очень похоже на ошибку в реализации EL Weblogic. Поскольку я не использую WebLogic, я не могу это проверить / подтвердить.

Вместо этого вы можете попробовать использовать следующее выражение

#{messages == null || empty messages}

Или вы можете попытаться полностью заменить реализацию EL, например JBoss (который позволяет передавать аргументы метода). Просто опустите jboss-el.jar в /WEB-INF/lib и добавьте следующее в web.xml

<context-param>     
    <param-name>com.sun.faces.expressionFactory</param-name>
    <param-value>org.jboss.el.ExpressionFactoryImpl</param-value>   
</context-param>
person BalusC    schedule 10.05.2011
comment
Спасибо за ваш вклад! К сожалению, проблема не устранена. Я также пробовал использовать Sun EL Resolver, помещая el-api-1.0.jar и el-impl-1.0.jar и используя com.sun.el.ExpressionFactoryImpl в качестве выражения Factory. Те же симптомы. Я на самом деле подозреваю, что это вообще не имеет никакого эффекта - я попытаюсь отладить и посмотреть, действительно ли эти классы вызываются. Спасибо, в любом случае! - person st.never; 10.05.2011
comment
Интересный. Как насчет альтернативного выражения EL #{messages == null || empty messages}? - person BalusC; 10.05.2011
comment
Фактически, использование #{messages == null || empty messages} или даже просто #{messages == null} вызывает ту же проблему ... Я могу подтвердить, что изменения происходят (если я полностью удалю оператор, страница будет отображаться нормально). Странный. - person st.never; 10.05.2011
comment
Что такое #{messages}? Это определяется <ui:param> или чем-то еще? Думаю, будет полезен минимальный фрагмент представления (xhtml) и модели (управляемый компонент), которая воспроизводит точную проблему. - person BalusC; 10.05.2011
comment
Я обновил вопрос, включив в него файлы xhtml и java. Это просто очень простой пример для воспроизведения проблемы. Но messages предназначен для ArrayList<String>, помещенного в область сеанса (см. Файл управляемого компонента). - person st.never; 10.05.2011
comment
Выглядит нормально, хотя я бы использовал FacesContext#addMessage() с null идентификатором клиента и <h:messages globalOnly="true"> для этого. Попробуйте случайный идентификатор, например #{empty foo}. Если это тоже не удается, скорее всего, это ошибка в преобразователе Weblogic EL. - person BalusC; 10.05.2011

В конце концов, это проблема с загрузчиком классов. Я упаковал jar-файлы JSF 1.2 в папку WEB-INF / lib моего приложения:

jsf-api.jar
jsf-impl.jar

Weblogic 10.3.x имеет собственную реализацию, расположенную в MW_HOME/wlserver/common/deployable-libraries/jsf-1.2.war (а версия 2.0 в jsf-2.0.war). Я заменил указанные выше банки в моем собственном веб-приложении следующими банками из jsf-1.2.war!/WEB-INF/lib:

glassfish.jsf_1.0.0.0_1-2-15.jar
glassfish.jstl_1.2.0.1.jar
javax.jsf_1.1.0.0_1-2.jar
wls.jsf.di.jar

Мне также пришлось удалить все пакеты в элементе prefer-application-packages в weblogic.xml:

<!--
<prefer-application-packages>
    <package-name>org.mozilla.*</package-name>
    <package-name>javax.jws.*</package-name>
    <package-name>com.sun.*</package-name>
    <package-name>javax.xml.rpc.*</package-name>
    <package-name>javax.xml.soap.*</package-name>
</prefer-application-packages>
-->

После этого страница отображалась правильно. (Это действительно вызвало другие проблемы, такие как ViewExpiredException на каждой странице, но это, я думаю, другая проблема ...)

person st.never    schedule 11.05.2011