CommandLink is an action component to process forms and invoke listeners remotely.
<div class="card">
    <h:form>
        <p:growl id="growl" life="2000"/>
        <h5 class="mt-0">Basic</h5>
        <p:commandLink id="ajax" update="growl" action="#{buttonView.buttonAction}" class="mr-4"
                       value="Ajax Post"/>
        <p:commandLink id="nonAjax" action="#{buttonView.buttonAction}" class="mr-4" ajax="false"
                       value="Regular Post"/>
        <p:commandLink id="disabled" action="#{buttonView.buttonAction}" disabled="true"
                       value="Disabled"/>
        <h5>Disable on Ajax</h5>
        <p:commandLink id="disableOnAjax" action="#{buttonBasicView.sleep()}" value="Sleep"/>
    </h:form>
</div>
package org.primefaces.showcase.view.button;
import org.primefaces.model.menu.DefaultMenuItem;
import org.primefaces.model.menu.DefaultMenuModel;
import org.primefaces.model.menu.DefaultSubMenu;
import org.primefaces.model.menu.MenuModel;
import java.util.concurrent.TimeUnit;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.RequestScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Named;
@Named
@RequestScoped
public class ButtonView {
    private MenuModel model;
    @PostConstruct
    public void init() {
        model = new DefaultMenuModel();
        //First submenu
        DefaultMenuItem item = DefaultMenuItem.builder()
                .value("External")
                .url("http://www.primefaces.org")
                .icon("pi pi-home")
                .build();
        DefaultSubMenu firstSubmenu = DefaultSubMenu.builder()
                .label("Dynamic Submenu")
                .addElement(item)
                .build();
        model.getElements().add(firstSubmenu);
        //Second submenu
        item = DefaultMenuItem.builder()
                .id("mniSave")
                .value("Save")
                .icon("pi pi-save")
                .function((i) -> save())
                .update("messages")
                .build();
        DefaultSubMenu secondSubmenu = DefaultSubMenu.builder()
                .label("Dynamic Actions")
                .addElement(item)
                .build();
        item = DefaultMenuItem.builder()
                .value("Delete")
                .icon("pi pi-times")
                .command("#{buttonView.delete}")
                .ajax(false)
                .build();
        secondSubmenu.getElements().add(item);
        model.getElements().add(secondSubmenu);
    }
    public MenuModel getModel() {
        return model;
    }
    public String save() {
        addMessage("Data saved");
        return null;
    }
    public void update() {
        addMessage("Data updated");
    }
    public void delete() {
        addMessage("Data deleted");
    }
    public String sleepAndSave() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
        return save();
    }
    public void sleepAndUpdate() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
        update();
    }
    public void sleepAndDelete() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
        delete();
    }
    public void buttonAction() {
        addMessage("Welcome to PrimeFaces!!");
    }
    public void addMessage(String summary) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, summary, null);
        FacesContext.getCurrentInstance().addMessage(null, message);
    }
}
package org.primefaces.showcase.view.button;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
@Named("buttonBasicView")
@ViewScoped
public class BasicView implements Serializable {
    public void sleep() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
    }
}