Учитывая <p:selectOneMenu> следующим образом.
<f:metadata>
    <f:viewParam name="id" value="#{testManagedBean.id}" converter="javax.faces.Long"/>
</f:metadata>
<p:selectOneMenu value="#{localeBean.language}" onchange="changeLanguage();">
    <f:selectItem itemValue="en" itemLabel="English" />
    <f:selectItem itemValue="hi" itemLabel="Hindi" />
</p:selectOneMenu>
<p:remoteCommand action="#{testManagedBean.submitAction}"
                 name="changeLanguage"
                 process="@this"
                 update="@none"/>
Соответствующий управляемый bean:
@ManagedBean
@RequestScoped
public final class TestManagedBean {
    private Long id; //Getter and setter.
    public TestManagedBean() {}
    public String submitAction() {
        return FacesContext.getCurrentInstance().getViewRoot().getViewId() + "?faces-redirect=true&includeViewParams=true";
    }
}
Параметр, обозначенный символом <f:viewParam>, является необязательным. Например, страница доступна с использованием URL-адреса следующим образом.
 https://localhost:8181/Project-war/private_resources/Test.jsf
Так как id является необязательным параметром, к URL-адресу прикрепляется пустой параметр (при изменении языка от <p:selectOneMenu>), если он не указан следующим образом.
 https://localhost:8181/Project-war/private_resources/Test.jsf?id=
Этого не должно быть. Пустой параметр не должен быть добавлен, если он не указан, и URL-адрес должен выглядеть как первый.
Есть ли способ предотвратить добавление пустого параметра в URL-адрес, когда он не передан?
  Это связано только с преобразователем, указанным в <f:viewParam> - javax.faces.Long.
Если этот конвертер удален, параметры не добавляются к URL-адресу, если не указаны параметры.
Хотя определение конвертера, как показано здесь, совершенно не нужно, у меня есть преобразователи, как показано ниже, для преобразования id, переданного через URL-адрес в качестве параметра строки запроса в объект JPA.
@ManagedBean
@RequestScoped
public final class ZoneConverter implements Converter {
    @EJB
    private final SharableBeanLocal sharableService = null;
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        try {
            long parsedValue = Long.parseLong(value);
            if (parsedValue <= 0) {
                throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Message Summary", "Message"));
            }
            ZoneTable entity = sharableService.findZoneById(parsedValue);
            if (entity == null) {
                throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_WARN, "Message Summary", "Message"));
            }
            return entity;
        } catch (NumberFormatException e) {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Message Summary", "Message"), e);
        }
    }
    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return value instanceof ZoneTable ? ((ZoneTable) value).getZoneId().toString() : "";
    }
}
Этот преобразователь теперь должен быть явно указан с помощью <f:viewParam> следующим образом.
<f:viewParam name="id" 
             value="#{testManagedBean.id}"
             converter="#{zoneConverter}"
             rendered="#{not empty param.id}"/>
И связанный с ним управляемый bean должен быть изменен следующим образом.
@ManagedBean
@RequestScoped
public final class TestManagedBean {
    private ZoneTable id;  //Getter and setter.
    public TestManagedBean() {}
    public String submitAction() {
        return FacesContext.getCurrentInstance().getViewRoot().getViewId() + "?faces-redirect=true&includeViewParams=true";
    }
}
