0

I have the following JSF 2.0 beans:

@ApplicationScoped
class GreedyBean {
  Result doGreedyStuff(String userId) {
    ... // Takes lots of machine resources and time.
  }
}

@SessionScoped
class MyPageBean {
  String userId;
  GreedyBean greedyBean;
  String getFirstGreedyStuffStat() {
    Result result = greedyBean.doGreedyStuff(userId);
    return result.getString();
  }
  int getSecondGreedyStuffStat() {
    Result result = greedyBean.doGreedyStuff(userId);
    return result.getInt();
  }
  void setGreedyBean(GreedyBean greedyBean) { this.greedyBean = greedyBean; }
}

Then in my JSF page:

<h:outputText value="#{myPageBean.firstGreedyStuffStat}"/>
<h:outputText value="#{myPageBean.secondGreedyStuffStat}"/>

How do I refactor this to have only one call to GreedyBean::doGreedyStuff without implementing a cache mechanism by myself? If JSF can't do that, saying so is a valid answer.

Notes:

  • I have barely any knowledge in JSF: I'm only fixing this one bug and then I resume my usual other tasks.
  • We use Spring for the injection, I tried to translate those in JSF annotation. If there's an error there, please indulge me.
  • As @JasperdeVries mentioned, I can't put the call in the @PostConstruct of MyPageBean because the data wouldn't be up to date. The result should be up to date at the moment of the request, not at the start of the session. I understand the principle and will enforce it, though it doesn't help me in this situation.
Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • Possible duplicate of [Performance issues when calling database in getter method for dataTable, getter is called multiple times](http://stackoverflow.com/questions/4669651/performance-issues-when-calling-database-in-getter-method-for-datatable-getter) – Jasper de Vries Mar 29 '17 at 11:44
  • @JasperdeVries One notable difference is the mention of the scopes, I guess. I can't put those in the `@PostConstruct` of my session bean because it'd take too much time at that moment, also the data may be outdated if the session lasts for too long... – Olivier Grégoire Mar 29 '17 at 11:49
  • If you need the data to be request scoped, why not move it to a request scoped bean? – Jasper de Vries Mar 29 '17 at 11:54
  • @JasperdeVries hmmm... Because I didn't know it existed (and there doesn't seem to be any request-scoped bean as example in the app I'm fixing). Thank you for that, I think I see the JSF under a better angle, now! – Olivier Grégoire Mar 29 '17 at 12:00
  • No problem, glad I could help – Jasper de Vries Mar 29 '17 at 12:01

1 Answers1

1

From @JasperdeVries' explanations, I need to add a new request-scoped bean:

GreedyBean.java

@ApplicationScoped
class GreedyBean {
  Result doGreedyStuff(String userId) {
    ... // Takes lots of machine resources and time.
  }
}

MyPageBean.java (should be renamed to something about the session, not the page)

@SessionScoped
class MyPageBean {
  String userId;
  String getUserId() { return userId; }
}

MyPageRequestBean.java

@RequestScoped
class MyPageRequestBean {
  // Beans
  MyPageBean myPageBean;
  GreedyBean greedyBean;

  // Data
  String firstGreedyStat;
  int secondGreedyStat;

  @PostConstruct
  public void init() {
    Result result = greedyBean.doGreedyStuff(myPageBean.getUserId());
    firstGreedyStat = result.getString();
    secondGreedyStat = result.getInt();
  }

  String getFirstGreedyStat() { return firstGreedyStat; }
  int getSecondGreedyStat() { return secondGreedyStat; }

  void setMyPageBean(MyPageBean myPageBean) { this.myPageBean = myPageBean; }
  void setGreedyBean(GreedyBean greedyBean) { this.greedyBean = greedyBean; }
}

myPage.xhtml

<h:outputText value="#{myPageRequestBean.firstGreedyStuffStat}"/>
<h:outputText value="#{myPageRequestBean.secondGreedyStuffStat}"/>
Community
  • 1
  • 1
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137