BrunoPires
BrunoPires

Reputation: 383

After a single element is removed from DB, it is still rendered in p:tree, until I either change another element or refresh the page

I'm having trouble trying to update the list of elements contained in a Primefaces p:tree through ajax. The problem I'm facing is: after a single element is removed from the database it is still rendered in the tree, until I either change another element (causing another update of the p:tree component) or refresh the page.

There are two managed beans involved in the process:

1- The first is responsible for populating the tree with entites contained in a database, here's the relevant code:

@Named
@RequestScoped
public class CredentialProvider {

    @Inject
    private UserFacadeLocal userFacade;

    private TreeNode userCredentials;

    @PostConstruct
    public void init() {
        /* Uses facade to populate TreeNode with entities */
    }        

    public TreeNode getUserCredentials(){
        return userCredentials;
    }

    /* Other getters and setters */

}

2- The second is responsible for updating / deleting the entities, here's the code:

@Named
@RequestScoped
public class CredentialManager {

    @Inject
    private UserFacadeLocal userFacade;

    public void deleteCredential(String userId){
        User user = userFacade.find(userId);
        userFacade.remove(user);
    }

    /* Other entitie handling methods */
}

The action of remvoing an element is triggered by:

<p:commandButton value="Delete" update=":treeContainer" actionListener="#{credentialManager.deleteCredential(node.login)}"

When I click the button I see the @PostConstructof the CredentialProvider bean being called first, and right after it the getUserCredentials() method, and only after that the deleteCredential() is called.

So my tree contents are being generated before they're updated, how can I solve this?

Upvotes: 1

Views: 39

Answers (1)

BalusC
BalusC

Reputation: 1109695

The CredentialProvider is being constructed first because that's needed in order to let JSF find the item to delete so that it can supply the right ID to deleteCredential() method.

Just explicitly reinitialize the model after update.

@Named
@RequestScoped
public class CredentialManager {

    @Inject
    private UserFacadeLocal userFacade;

    @Inject
    private CredentialProvider credentialProvider;

    public void deleteCredential(String userId){
        User user = userFacade.find(userId);
        userFacade.remove(user);
        credentialProvider.init();
    }

    /* Other entitie handling methods */
}

You might want to change the scope of CredentialProvider to @ViewScoped to keep it alive across postbacks so that you can ensure integrity across postbacks even when the database is been manipulated by other requests in the meanwhile. Additional bonus is, it saves you from unnecessary queries to DB.

Upvotes: 1

Related Questions