CDI ViewScope & PrettyFaces: Multiple calls to @PostConstruct (JSF 2.2)
Asked Answered
K

1

3

I'v already check similar questions which declare that JSF 2.1 had this bug, but I'm using JSF 2.2 Let's detail:

My environment:

  • CDI: 1.1
  • Dynamic Web Module: 3.0
  • Java: 1.7
  • JSF: 2.2
  • PrettyFaces: 2.0.12.Final

My Bean:

@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
  }
}

That controller, right now is just a mock which returns a one-element list.

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

I'm using pretty faces, the pretty-config.xml is the following:

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

In the home.xhtml I'm going to omit irrelevant code but say that I call N times the homeBean; for example #{home.buttonClicked()}


OK; Now the problem.


Each one of those references to the HomeBean, creates a new HomeBean instance; If I debug it with a breakpoint at the @PostConstruct it's called N times; so the controller is called N times and the log line "HomeBean: initialized" is printed N times.

It's a @ViewScopped, so I assume it will be alive for the entire view isn't it?

Let's say, finally it renders the home page correctly... but the controller is going to be a DB access... I don't want a new DB access per image! O_O

[EDITED] It's definitely related with pretty-faces because if I remove it, it works perfectly fine. I've configured Pretty faces as the following in the 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>

And the Pom dependencies are (prettyfaces.version is 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>

What's going on there? Thx very much.

Koslo answered 21/5, 2015 at 16:4 Comment(9)
Are you implying that the problem disappears when you remove PrettyFaces? I'm namely not seeing why that would ever be relevant to the question in its current form, yet you made (implicitly) a mention of it.Australian
@mantero: Could you check if this also happens if your change the pattern to <pattern value="/home" />Rollerskate
@Australian yes, I tried removing pretty faces and it seems to work fine again.Koslo
@Rollerskate Yes, it still happens.Koslo
Since definitely it's related with PrettyFaces I'm going to edit the question adding configuration detailsKoslo
Could you add "Thread.dumpStack()" to your @PostConstruct method and include the results in the question. It would be interesting to see the results for one if the CSS files for example.Rollerskate
@Rollerskate I've created a public gist to show the results: gist.github.com/manutero/609f23fb2c979c4d1f60Koslo
You have a pattern <pattern value="/#{provinceName}" />. This pattern will also match URLs like /style.css or /image.css. That's why PrettyFaces is forwarding these requests to the home page. That's what is causing this problem.Rollerskate
@Rollerskate is there anyway to solve that? If answer I can vote and check it :)Koslo
R
3

The problem is caused by this mapping:

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

This mapping is basically matching every URL beginning with a /. So it doesn't just match /foobar but also /style.css and /scripts.js and /jquery.min.js and so on.

There are basically two ways to fix this. First you could try to use a custom regular expression to restrict what the path parameter is allowed to contain. You could for example use something like this:

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

This tells PrettyFaces that the province name must only contain letters, but no number, periods, etc. This was something like style.css won't be matched any more.

The second option is to use some kind of URL prefix like this:

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

That's what I usually recommend as it is the most simply and straight forward way. :)

Rollerskate answered 25/5, 2015 at 7:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.