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.

Manu Artero
  • 9,238
  • 6
  • 58
  • 73
  • 1
    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. – BalusC May 21 '15 at 21:57
  • @mantero: Could you check if this also happens if your change the pattern to – chkal May 22 '15 at 04:42
  • @BalusC yes, I tried removing pretty faces and it seems to work fine again. – Manu Artero May 22 '15 at 07:03
  • @chkal Yes, it still happens. – Manu Artero May 22 '15 at 07:04
  • Since definitely it's related with PrettyFaces I'm going to edit the question adding configuration details – Manu Artero May 22 '15 at 07:29
  • 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. – chkal May 22 '15 at 08:41
  • @chkal I've created a public gist to show the results: https://gist.github.com/manutero/609f23fb2c979c4d1f60 – Manu Artero May 22 '15 at 09:00
  • 1
    You have a pattern . 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. – chkal May 22 '15 at 18:47
  • @chkal is there anyway to solve that? If answer I can vote and check it :) – Manu Artero May 24 '15 at 10:07

1 Answers1

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. :)

chkal
  • 5,598
  • 21
  • 26