Search code examples
jsfprimefacesjsf-2managed-bean

Automatically set value of a managed bean variable with JSF


I would like to pass an value to a managed bean under the hood. So I have this managed bean:

@ManagedBean(name = "mbWorkOrderController")
@SessionScoped
public class WorkOrderController {

    // more attributes...

    private WorkOrder workOrderCurrent;

    // more code here...

    public WorkOrder getWorkOrderCurrent() {
        return workOrderCurrent;
    }

    public void setWorkOrderCurrent(WorkOrder workOrderCurrent) {
        this.workOrderCurrent = workOrderCurrent;
    }
}

It holds a parameter workOrderCurrent of the custom type WorkOrder. The class WorkOrder has an attribute applicant of type String.

At the moment I am using a placeholder inside my inputtext to show the user, what he needs to type inside an inputText.

<p:inputText id="applicant"
    value="#{mbWorkOrderController.workOrderCurrent.applicant}"
    required="true" maxlength="6"
    placeholder="#{mbUserController.userLoggedIn.username}" />

What I want to do, is to automatically pass the value of mbUserController.userLoggedIn.username to mbWorkOrderController.workOrderCurrent.applicant and remove the inputText for applicant completely from my form.

I tried to use c:set:

<c:set value="#{mbUserController.userLoggedIn.username}" target="#{mbWorkOrderController}" property="workOrderCurrent.applicant" />

But unfortunatelly I get a javax.servlet.ServletException with the message:

The class 'WorkOrderController' does not have the property 'workOrderCurrent.applicant'.

Does anybody have an advice?


Solution

  • The class 'WorkOrderController' does not have the property 'workOrderCurrent.applicant'.

    Your <c:set> syntax is incorrect.

    <c:set value="#{mbUserController.userLoggedIn.username}"
           target="#{mbWorkOrderController}" 
           property="workOrderCurrent.applicant" />
    

    You seem to be thinking that the part..

    value="#{mbWorkOrderController.workOrderCurrent.applicant}"
    

    ..works under the covers as below:

    WorkOrderCurrent workOrderCurrent = mbWorkOrderController.getWorkOrderCurrent();
    workOrderCurrent.setApplicant(applicant);
    mbWorkOrderController.setWorkOrderCurrent(workOrderCurrent);
    

    This isn't true. It works under the covers as below:

    mbWorkOrderController.getWorkOrderCurrent().setApplicant(applicant);
    

    The correct <c:set> syntax is therefore as below:

    <c:set value="#{mbUserController.userLoggedIn.username}"
           target="#{mbWorkOrderController.workOrderCurrent}" 
           property="applicant" />
    

    That said, all of this isn't the correct solution to the concrete problem you actually tried to solve. You should perform model prepopulating in the model itself. This can be achieved by using @ManagedProperty to reference another bean property and by using @PostConstruct to perform initialization based on it.

    @ManagedBean(name = "mbWorkOrderController")
    @SessionScoped
    public class WorkOrderController {
    
        @ManagedProperty("#{mbUserController.userLoggedIn}")
        private User userLoggedIn;
    
        @PostConstruct
        public void init() {
            workOrderCurrent.setApplicant(userLoggedIn.getUsername());
        }
    
        // ...
    }