Ginkgochris
Ginkgochris

Reputation: 465

Most elegant way to update data from a user POST in a SessionScoped bean (CDI, JSF)

I have a SessionScoped CDI-bean holding user data.

@SessionScoped
public class UserData {
  private String name;
  private String city;
  .. several other attributes
}

The user wants to update his data in a form (JSF). Therefore I use a "FrontendModel" to encapsulate all the attributes.

FrontendModel

@RequestScoped
@Named
public class UserDataFrontendModel {
  private String name;
  private String city;
  .. several other attributes
}

JSF-Page:

<h:inputText id="username" value="#{userDataFrontendModel.name}"/>
<h:inputText id="city" value="#{userDataFrontendModel.city}"/>

Controller

@RequestScoped
@Named
public class UserDataController {

  @Inject
  private UserDataFrontendModel userDataFrontendModel;

  @Inject
  private UserData userData;

  public String updateUserData() {
      userData.setName(userDataFrontendModel.getName());
      userData.setCity(userDataFrontendModel.getCity());
      return null;
  }

@PostConstruct
private void initUserDataFrontendModel() {
  if(isUpdate) {
     userDataFrontendModel.setName(userData.getName());
     userDataFrontendModel.setCity(userData.getCity());
  }
}

Is this overengineered?! I don't want to have all the user's properties directly in the controller. Should UserDataFrontendBean be a CDI-bean? Is there a simpler way to do what I want? I can't directly use my UserData object, can I?

Upvotes: 0

Views: 169

Answers (1)

Luiggi Mendoza
Luiggi Mendoza

Reputation: 85779

It would be better to have the UserDataController declared as @Named @SessionScoped and just have the UserData field there. Since UserDataController will be stored in session scope, all its fields will be in session scope as well. Using this approach, you don't need the UserDataFrontendModel class at all.

@Named
@SessionScoped
public class UserDataController {
    @Inject
    private UserData userData;
    @PostConstruct
    private void initUserDataFrontendModel() {
        userData = new UserData();
    }
    public void updateUserData() {
         //logic to update the data in database or something
    }
}

Then just bind the data from UserData directly to your elements in view:

<h:form>
    <h:inputText value="#{userDataController.userData.name}" />
    <h:inputText value="#{userDataController.userData.city}" />
    <h:commandButton value="Update User Data"
        action="#{userDataController.updateUserData}" />
</h:form>

Upvotes: 1

Related Questions