0
votes

I use Myfaces CODI @ViewAccessScoped backing beans in my JSF application. One of the benefits is that I don't need to use view parameters to communicate information between views. For the record @ViewAccessScoped ensures that a bean is accessible until until the first request of a new view doesn't access it. Take this case where I want to pass a string value from page1 to page2:

Page1Bean.java (backing bean for page1.xhtml)

@Inject private Page2Bean page2Bean;
private String source = "Hello, World!";

...
page2Bean.setTarget(source);

Page2Bean.java (backing bean for page2.xhtml)

private String target;

If I navigate directly from page1 to page2, then when I access #{page2Bean.target} from page2 it has the value "hello, world!".

In effect I'm pushing the data from the page1 view to the page2 view. The other option is to pull the data from the page1 view into the page2 view, so in the page2Bean I @Inject Page1Bean and @ViewAccessScoped ensures that I can access page1Bean.getSource() (as long as it was in the previous view).

This is all well and good, but in the real world I may want to navigate from page1 to any one of a number of other pages, depending on user input. So Page1Bean.java ends up looking like this:

Page1Bean.java (revised)

@Inject private Page2Bean page2Bean;
@Inject private Page3Bean page3Bean;
@Inject private Page4Bean page4Bean;
@Inject private Page5Bean page5Bean;
@Inject private Page6Bean page6Bean;
@Inject private Page7Bean page7Bean;
@Inject private Page8Bean page8Bean;

Now for my question: does the memory footprint of page1Bean always include page2Bean- page8Bean? or will memory only be used if I access one of the @Inject'ed beans at runtime?

I hope this isn't too naive a question, but I'm not sure exactly how it will work and if the answer to the first question is yes, I'm more or less ending up using @SessionScoped!.

Thanks for any clarification.

2

2 Answers

0
votes

Well, I suppose it was pretty obvious really but having put some logging in the constructors of the beans that were being injected with @Inject, I could see that they were all being instantiated when the Page1Bean was instantiated, i.e. when navigating to page1. I found the solution in the JSR-299 CDI spec section 5.6 Programmatic lookup:

@Inject private Instance<Page2Bean> page2BeanDynamic;
...
if(someCondition) {
  Page2Bean page2Bean = page2BeanDynamic.get();
  page2Bean.setTarget(source);
}

so this is basically dynamic @Inject and ensures that I'm only instantiating the beans at runtime when needed.

Putting finalize() & @PreDestroy methods in Page2Bean I see them both called when navigating from page2 to page1, as expected.

0
votes

No real memory footprint. Only proxies are generated. That's the reason for the constructor calls. You don't need to resolve beans manually!

You don't have to inject all beans. You are using it in a wrong way. Just keeping state between _ independent _ pages should be done via @WindowScoped. If they aren't independent use the beans in the target page (if you don't need the view-controller callbacks in the target pages).