0
votes

Let's assume a simple Jsf example with a xhtml page, a ManagedBean, a service and an JPA entityClass. I have a lot of usecases with the following structure:

  • Hold an entity in my bean
  • Do actions on the entity
  • Do rendering on the updated entity

Some easy example, so everyone will understand

Entity:

public class Entity {
     private long id;
     private boolean value;
     ...
     // Getter and Setter
}

Dao:

public class EntityService {

    // Entity Manger em and other stuff

    public void enableEntity(long id) {
        Entity e = em.find(id);
        e.value = true;
        em.persist(e);
    }
}

Managed Bean:

@ManagedBean
@RequestScoped/ViewScoped
public class EntityBean() {

    @EJB
    private EntityService entityService;

    private Entity entity;

    @PostConstruct
    public void init() {
        // here i fetch the data, to provide it for the getters and setters
        entity = entityService.fetchEntity();
    }

    public void enableEntity() {
        entityService.enableEntity(entity.getId);
    }

    // Getter and Setter
}

and finally a simple xhtml:

<html>
    // bla bla bla

    <h:panelGroup id="parent">
         <h:panelGroup id="disabled" rendered="#{not EntityBean.entity.value}>
              <p:commandButton value="action" action="#{EntityBean.enableEntity}" update="parent" />
         </h:panelGroup>

         <h:panelGroup id="enabled" rendered="#{EntityBean.entity.value}>
               // other stuff that should become visible
         </h:panelGroup>             
    </h:panelGroup>
</html>

What i want to achieve:

  • Always show the up to date entity in every request!

What i already tried

  • I tried with a dao-fetch in my getter. But you can read everywhere that this is bad practice, because jsf will call the getter more than once (but for now the only way i can keep them really up to date).
  • I tried RequestScoped Beans. But the Bean will be created before the action is done, and is not recreated on the update call and the value will be outdated (Makes sense, since this is one request, and the request starts with the click on the button).
  • I tried ViewScoped Beans and added an empty String return value to my method. My hope was, that this redirection will recreate the Bean after the action was processed. But this was not the case.
  • I tried to call the refetch function manually after every method i used. But I have some cross bean actions on the same entity (My real entities are way more complex than this example). So the different Beans do not always know, if and when the entity has changed.

My Questions:

  • Can this be done with any kind of Scope? Let's say that every request will fetch the data from my PostConstruct again.
  • There must be a better solution than the dao-fetch in the getter method

This seems to be a fundamental problem for me, because getting the up to date data is essential for my app (data is changed often).

Using Primefaces 6.1 and Wildfly 10.x

1
What ORM tool do you use?basamoahjnr
JPA entities and hibernate to save to MySQL databasekaiser

1 Answers

1
votes

What do you think about this? A request scoped bean which will be created for update, too and does only one fetchEntity() per request.

<f:metadata>
  <f:viewAction action="#{entityBean.load()}" onPostback="true"/>
</f:metadata>

@ManagedBean
@RequestScoped
public class EntityBean() {

  @EJB
  private EntityService entityService;

  private Entity entity = null;

  public void load() {}
  public Entity getEntity() {
    if(entity == null) {
      entity = entityService.fetchEntity();
    }
    return entity;
  }
  public void enableEntity() {
    entityService.enableEntity(getEntity().getId);
  }

  // Getter and Setter
}