CDI ViewScope и PrettyFaces: множественные вызовы @PostConstruct (JSF 2.2)

Я уже проверял подобные вопросы, которые заявляют, что в JSF 2.1 была эта ошибка, но я использую JSF 2.2. Давайте подробнее:

Моя среда:

  • CDI: 1.1
  • Динамический веб-модуль: 3.0
  • Ява: 1.7
  • JSF: 2.2
  • PrettyFaces: 2.0.12.Финал

Моя фасоль:

@Named(value = "home")
@javax.faces.view.ViewScoped
public class HomeBean implements Serializable {

  @Inject
  private HomeController controller;

  private List<Store> myPopularStores;

   @PostConstruct
   public void postConstruct() {
    myPopularStores = controller.getStores();
    LOG.log(Level.FINE, "HomeBean: initialized");
  }

  public String buttonClicked() {
     // whatever
  }
}

Этот контроллер прямо сейчас является просто макетом, который возвращает список из одного элемента.

@Named
public class HomeController implements Serializable {
  public List<Store> getStores() {
    // mocked
  }
}

Я использую красивые лица, pretty-config.xml выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
                      http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">

 <url-mapping id="Home">
    <pattern value="/" />
    <view-id value="/home.xhtml" />
  </url-mapping>

 <url-mapping id="cityIndex">
    <pattern value="/#{provinceName}" />
    <view-id value="/home.xhtml" />
 </url-mapping>

</pretty-config>

В home.xhtml я собираюсь опустить ненужный код, но скажу, что вызываю N раз homeBean; например #{home.buttonClicked()}


OK; Теперь проблема.


Каждая из этих ссылок на HomeBean создает новый экземпляр HomeBean; Если я отлаживаю его с точкой останова на @PostConstruct, он вызывается N раз; поэтому контроллер вызывается N раз, и строка журнала "HomeBean: инициализирована" печатается N раз.

Это @ViewScopped, поэтому я предполагаю, что он будет активен для всего представления, не так ли?

Скажем, наконец, он правильно отображает домашнюю страницу... но контроллер будет доступом к БД... Я не хочу новый доступ к БД для каждого изображения! О_О

[EDITED] Это определенно связано с pretty-faces, потому что если я удалю его, он будет работать отлично. Я настроил красивые лица следующим образом в web.xml

<filter>
    <filter-name>OCPsoft Rewrite Filter</filter-name>
    <filter-class>org.ocpsoft.rewrite.servlet.RewriteFilter</filter-class>
    <async-supported>true</async-supported>
</filter>
<filter-mapping>
    <filter-name>OCPsoft Rewrite Filter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ASYNC</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

И зависимости Pom (prettyfaces.version — 2.0.12.Final):

<dependency>
   <groupId>org.ocpsoft.rewrite</groupId>
   <artifactId>rewrite-servlet</artifactId>
   <version>${prettyfaces.version}</version>
</dependency>
<dependency>
   <groupId>org.ocpsoft.rewrite</groupId>
   <artifactId>rewrite-integration-faces</artifactId>
   <version>${prettyfaces.version}</version>
</dependency>
<dependency>
   <groupId>org.ocpsoft.rewrite</groupId>
   <artifactId>rewrite-config-prettyfaces</artifactId>
   <version>${prettyfaces.version}</version>
</dependency>

Что там происходит? Большое спасибо.


person Manu    schedule 21.05.2015    source источник
comment
Вы подразумеваете, что проблема исчезнет, ​​когда вы удалите PrettyFaces? Я не понимаю, почему это когда-либо имело бы отношение к вопросу в его нынешней форме, но вы (неявно) упомянули об этом.   -  person BalusC    schedule 22.05.2015
comment
@mantero: Не могли бы вы проверить, произойдет ли это, если вы измените шаблон на ‹pattern value=/home /›   -  person chkal    schedule 22.05.2015
comment
@BalusC да, я пытался удалить красивые лица, и, кажется, это снова работает нормально.   -  person Manu    schedule 22.05.2015
comment
@chkal Да, это все еще происходит.   -  person Manu    schedule 22.05.2015
comment
Поскольку это определенно связано с PrettyFaces, я собираюсь отредактировать вопрос, добавив детали конфигурации.   -  person Manu    schedule 22.05.2015
comment
Не могли бы вы добавить Thread.dumpStack() в свой метод @PostConstruct и включить результаты в вопрос. Было бы интересно увидеть результаты, например, для файлов CSS.   -  person chkal    schedule 22.05.2015
comment
@chkal Я создал публичный список, чтобы показать результаты: gist.github.com/manutero/609f23fb2c979c4d1f60< /а>   -  person Manu    schedule 22.05.2015
comment
У вас есть шаблон ‹значение шаблона=/#{provinceName} /›. Этот шаблон также будет соответствовать URL-адресам, таким как /style.css или /image.css. Вот почему PrettyFaces перенаправляет эти запросы на домашнюю страницу. Вот что вызывает эту проблему.   -  person chkal    schedule 22.05.2015
comment
@chkal это как-то решить? Если ответ, я могу проголосовать и проверить его :)   -  person Manu    schedule 24.05.2015


Ответы (1)


Проблема вызвана этим сопоставлением:

<url-mapping id="cityIndex">
   <pattern value="/#{provinceName}" />
   <view-id value="/home.xhtml" />
</url-mapping>

Это сопоставление в основном соответствует каждому URL-адресу, начинающемуся с /. Таким образом, он соответствует не только /foobar, но и /style.css, и /scripts.js, и /jquery.min.js, и так далее.

В основном есть два способа исправить это. Сначала вы можете попробовать использовать настраиваемое регулярное выражение для ограничения того, что может содержать параметр пути. Например, вы можете использовать что-то вроде этого:

<url-mapping id="cityIndex">
   <pattern value="/#{ /[a-z]+/ provinceName }" />
   <view-id value="/home.xhtml" />
</url-mapping>

Это сообщает PrettyFaces, что название провинции должно содержать только буквы, но не числа, точки и т. д. Это было что-то вроде style.css, которое больше не будет совпадать.

Второй вариант — использовать какой-то префикс URL, например:

<url-mapping id="cityIndex">
   <pattern value="/province/#{provinceName}" />
   <view-id value="/home.xhtml" />
</url-mapping>

Это то, что я обычно рекомендую, так как это самый простой и прямой путь. :)

person chkal    schedule 25.05.2015