user3128303 user3128303 - 7 months ago 16
Java Question

Calling methods in jsf

I wanted to make the possibility of booking /remove booking the product page.
Reservations is ok, removing unfortunately not ...

@ManagedBean(name = "wardrobeDetailsBean")
@SessionScoped
//@RequestScoped
public class WardrobeDetailsBean implements Serializable {

@Inject
WardrobeService wardrobeService;
@Inject
AuthBean authBean;

// other fields + setters, getters

@ManagedProperty("#{param.id}")
private Long id;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getUsernameReserving() {
this.selectedWardrobe = wardrobeService.getWardrobeById(id);
String usernameById = selectedWardrobe.getReservingUserId().getUsername();
StringBuilder sb = new StringBuilder();
sb.append(usernameById.substring(0, 2));
sb.append("...");
sb.append(usernameById.substring(usernameById.length() - 2, usernameById.length()));
return sb.toString();
}

@PostConstruct
public void init() {
if (FacesContext.getCurrentInstance().getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
dbImage1 = new DefaultStreamedContent();
} else if (id != null) {
this.selectedWardrobe = wardrobeService.getWardrobeById(id);
}
}
}

public String reserve() {
this.selectedWardrobe = wardrobeService.getWardrobeById(id);
if (authBean.getUser() != null && authBean.getUser().getId() != null) {
selectedWardrobe.setReservingUserId(authBean.getUser());
wardrobeService.reserveProduct(selectedWardrobe);
return null;
} else {
return "/login.xhtml?faces-redirect=true";
}
}

public void unreserve() {
this.selectedWardrobe = wardrobeService.getWardrobeById(id);
selectedWardrobe.setReservingUserId(null);
wardrobeService.reserveProduct(selectedWardrobe);
}
}


productView.xhtml

<h:commandButton id="reserve" styleClass="btn-u btn-u-sea-shop btn-u-lg" rendered="#{wardrobeDetailsBean.selectedWardrobe.reservingUserId eq null}"
value="Reserve" action="#{wardrobeDetailsBean.reserve()}">
<f:ajax execute="@form" render="reservePanel"/>
</h:commandButton>

<h:outputText value="This product has been reserved by #{wardrobeDetailsBean.usernameReserving}" rendered="#{wardrobeDetailsBean.selectedWardrobe.reservingUserId ne null}"/>
<br />
<input type="hidden" name="remoteUser" value="#{request.remoteUser}"/>
// added using guidance from the answers
<h:commandButton id="unreserve" styleClass="btn-u btn-u-red btn-u-lg" rendered="#{request.remoteUser eq wardrobeDetailsBean.selectedWardrobe.reservingUserId.username}"
value="Unreserve" action="#{wardrobeDetailsBean.unreserve()}">
<f:ajax execute="@form" render="reservePanel"/>
</h:commandButton>


When I removed the
rendered="#{request.remoteUser eq wardrobeDetailsBean.selectedWardrobe.reservingUserId.username}"
, it works.

When the reservation is clicked it should only be visible button for removal.
What is wrong, it does not work? The log any errors I have not.

After using guidance from the answers, application works like this.
enter image description here

I click "Reserve". The product has been reserved, the button will be swapped.

enter image description here

I click "Unreserve" and still the method is not called, I lose the information about the product (refresh the page returns information about the product, but the product is still reserved)

enter image description here

Answer

Rendered attribute of button is evaluated in the process of submitting form before request is reached to your bean method,

and as you checked request.remoteUser in rendered method, it will be empty for new request (post request of action), the rendered evaluation will be "false", so your method is not called.

So you must make sure that rendered attribute of your button and its parents remain to true during form submission.

That's the cause when you remove rendered attribute, it works fine.

As a workaround you can add a hidden input to your form:

<input type="hidden" name="remoteUser" value="#{request.remoteUser}"/>
<input type="hidden" name="id" value="#{param.id}"/> 


Update: another solution

another solution is to use one single button, but use a conditional value attribute and a toggle method:

<h:commandButton id="toggle" 
    styleClass="btn-u btn-u-#{(wardrobeDetailsBean.selectedWardrobe.reservingUserId eq null) ? 'sea-shop' : 'red' } btn-u-lg" 
    value="#{(wardrobeDetailsBean.selectedWardrobe.reservingUserId eq null) ? 'Reserve' : 'Unreserve'}" 
    action="#{wardrobeDetailsBean.toggle()}">
        <f:ajax execute="@form" render="reservePanel"/>
</h:commandButton>

And in your bean, use a toggle method:

public String toggle() {
        this.selectedWardrobe = wardrobeService.getWardrobeById(id);
        if(selectedWardrobe.getReservingUserId() == null){
            if (authBean.getUser() != null && authBean.getUser().getId() != null) {
                selectedWardrobe.setReservingUserId(authBean.getUser());
                wardrobeService.reserveProduct(selectedWardrobe);
                return null;
            } else {
                return "/login.xhtml?faces-redirect=true";
            }
        }else{
            this.selectedWardrobe = wardrobeService.getWardrobeById(id);
            selectedWardrobe.setReservingUserId(null);
            wardrobeService.reserveProduct(selectedWardrobe);
        }

    }
Comments