0

I'm working with primefaces 4.0 and JSF 2.2 and I'm currently trying to update a form with a p:tree on it. The commandButton works correctly but it does not update the form or call the init() method until I manually refresh the page. I don't know what I'm doing wrong since the same code does work for a DataTable element.

Here's the code:

<h:form id="preferenciasForm">
 <div id="panelTree">
    <p:panel id="defTree" style="margin-bottom: 20px">
        <p:tree value="#{dtPreferencesBuilder.root}" var="node"
            selectionMode="checkbox"
            selection="#{dtPreferencesBuilder.selectedNodes}"
            style="width:100%; height:100%;" animate="true">
               <p:treeNode>
                    <h:outputText value="#{node.label}" />
               </p:treeNode>
        </p:tree>
        <p:commandButton value="Add preferences"
            icon="ui-icon-pencil"
            actionListener="#{dtPreferencesBuilder.insertPrefNodes()}"
            update=":preferenciasForm" ajax="true" />
    </p:panel>
 </div>
</h:form>

And here's is the java class.

@ManagedBean(name="dtPreferencesBuilder")
@ViewScoped //I've tried with or without the ViewScoped, neither work
public class PreferencesBuilderBean {
  private TreeNode root;
  private TreeNode prefRoot;
  private TreeNode[] selectedNodes;

 @PostConstruct
 public void init() {
    System.out.println("Building Tree");
    selectedNodes=null;
    root=null;
    prefRoot=null;
    root=getStandardTree();
    prefRoot=getPreferedTree();
 }

The init() is not called as the print is only show on manual reload so the tree is not updated nor the selectedNodes refreshed. Any ideas why it doesn't work?

Benjamin Jimenez
  • 984
  • 12
  • 26
  • Init() is not supposed to be called, only when the bean is created. So you need a RequestScoped bean if you want it called, but then it will be completely new. I think you would want to keep it ViewScoped and do your job in insertPrefNodes(), but I don't understand exactly what you are trying to do – Jaqen H'ghar Jul 13 '14 at 09:17
  • Using a `@PostConstruct` method... does the print get called when you access the page for the first time? Also, on the button, instead of an `actionListener` have you tried using `action`? – rion18 Jul 13 '14 at 17:04
  • @JaqenH'ghar I'm just tryind to add a new node and display it on the tree without having to manually refresh the webpage. I set the selectedNode = null and the new tree in the insertPrefNodes() method but it does not work. It's like the update is not working. – Benjamin Jimenez Jul 13 '14 at 20:32
  • @rion18 yes the print is called everytime I refresh the webpage (F5) so when I add a new node and refresh, the new node is shown in the tree however is not shown without manually refreshing the webpage. The button is working either with action or actionlistener but neither update the form. – Benjamin Jimenez Jul 13 '14 at 20:32
  • Can you try doing it programatically? As in, in your `insertPrefNodes` method, add a `RequestContext.getCurrentInstance().update("preferenciasForm")`; – rion18 Jul 13 '14 at 20:37
  • Actually now that I tried again @JaqenH'ghar solution worked fine, So can you post your comment as answer, also Do you know why the init() postconstruct is not called when I update the form? – Benjamin Jimenez Jul 13 '14 at 20:42
  • @rion18 It does not work, I dont know why the update on the form does not call the init() but it does with my datatable in another webpage, anyway with JaqenH'ghar solution I managed to get it working – Benjamin Jimenez Jul 13 '14 at 20:55
  • `@PostConstruct` only gets called after the constructor has been executed. If its scope is `request`, then its called on EVERY call to the bean, if it's `view`, it gets called after he initial page load (that's why it gets executed after every page refresh), if it's `session`, it'll be called ONLY when your session starts. If you wish to keep a `ViewScoped` bean, what you want to do (call the `init()` method at every ajax request) you might want to use ``. – rion18 Jul 13 '14 at 21:08
  • Great explanation!, everything is clearer for me now. Thanks a lot @rion18 – Benjamin Jimenez Jul 14 '14 at 21:10

1 Answers1

0

As I cannot describe bean scopes better than excellent answers already given for similar questions I'll just refer you to the answers by BalusC and Kishor P here.

The init-method (or any method with the @PostConstruct-annotation) will be called by the framework only when the bean is created, after injections and therefore after the constructor has run as rion18 said. It would not be normal to use the method for anything else than initializing work. So create other methods, and call those from actions and actionListeners.

If you want the bean to be the same when you call it with ajax (as you do) it needs to be at least ViewScoped. If you really do want to call the init() every time it should be RequestScoped, but then the bean will be new when you call it with ajax and not remember a thing.

Community
  • 1
  • 1
Jaqen H'ghar
  • 4,305
  • 2
  • 14
  • 26
  • The "not remember a thing" is the point I was trying to get to ;) I've never seen or heard about anyone using a `RequestScope` ONLY to have a `@PostConstruct` method executed... That's why the `preRenderView` method might be a good option for the OP. – rion18 Jul 14 '14 at 15:23
  • You're right, its gets called even with ajax requests, had to check :-) That probably has its place somewhere, but it looks as a more standard way is enough in this case – Jaqen H'ghar Jul 14 '14 at 15:37
  • If OP needs to keep variable data in his bean que should use ViewScope and preRenderView. If he doesn't RequestScope is the optimal solution... :) – rion18 Jul 14 '14 at 19:01
  • Thank you both guys you help me a lot, now I undestand a bit more how the beans works, I read the documentation but I didn't undestand it so well. – Benjamin Jimenez Jul 14 '14 at 21:13