Как вернуть статусные сообщения в JSF? - PullRequest
5 голосов
/ 02 апреля 2012

Я сделаю себя довольно объективным:

Пользователь зарегистрирует себя, после этой операции register Я хотел бы показать какое-то сообщение с надписью Поздравляем!Добро пожаловать! , что-то в этом роде или какое-то сообщение, если в моей базе данных есть проблема типа duplicated key.

Я уже знаю, как показать некоторые сообщения с помощью RichFaces, но я хочу, чтобы это было просто, RichFacesНемного запутался с CSS, поэтому я хочу пока этого избежать.

Итак, вот моя страница и мои управляемые bean-компоненты:

    <h:form id="form_user">
        <h:panelGrid columns="3">
            <h:outputLabel for="name" value="Name:" />
            <h:inputText id="name" value="#{personc.personb.person.name}">
                <f:ajax event="blur" listener="#{personValidate.name}" render="m_name" />
            </h:inputText>
            <h:message id="m_name" for="name" />

            <!--other fields...-->

            <h:commandButton value="Register" action="#{personc.register}">
                <f:ajax execute="@form" render="@form" />
            </h:commandButton>

        </h:panelGrid>
    </h:form>

Person Controller (следуя структуре MVC):

@ManagedBean(name="personc")
@SessionScoped
public class PersonController implements Serializable {
    private static final long serialVersionUID = 2000186666864113813L;

    // attributes
    @EJB PersonEAO personEAO;
    private PersonBean personb;

    public PersonController() {
        personb = new PersonBean();
    }

    // methods
    public String register(){
        if (personEAO.register(personb.getUser(), personb.getPerson())){
            status = "welcome!";
            return "success";
        }else{
            status = "an error occurs";
            return "failure";
        }
    }
        // others methods..

И сущность PersonEAO:

@Stateless
@LocalBean
public class PersonEAO {
    @PersistenceContext
    EntityManager em;

    public PersonEAO() {}

    public boolean register(User user, Person person){
        try{
            em.persist(user);

            person.setUser(user);
            em.persist(person);
        }catch(Exception e){
                    // would like to treat better the exceptions here 
                    // should I keep returning boolean here ? or a string would be better ? 
            return false;
        }
        return true;
    }

У меня есть несколько вопросов:

Если я продолжу возвращать boolean из операций с JPA, я бы хотелчтобы лучше передать пользователю сообщение о том, что произошло, например, duplicate key.

Ответы [ 2 ]

2 голосов
/ 02 апреля 2012

Не используйте логические флаги (или перечисления), чтобы указать исключительные результаты.Используйте исключения для этого.Вам нужно только добавить некоторую логику, к какому виду исключения для конкретной реализации JPA относится PersistenceException, а затем повторно выбросить его как ваше конкретное бизнес-исключение, например, пользовательское public class DuplicateKeyException extends PersistenceException.

Например, в вашей бизнес-службереализация

public void register(User user, Person person) throws PersistenceException, DuplicateKeyException {
    try {
        em.persist(user);
        person.setUser(user);
        em.persist(person);
    }
    catch (PersistenceException e) {
        if (Exceptions.is(e, ConstraintViolationException.class)) {
            throw new DuplicateKeyException(e);
        }
        else {
            throw e;
        }
    }
}

с помощью этого метода в служебном классе Exceptions:

public static <T extends Throwable> boolean is(Throwable exception, Class<T> type) {
    for (;exception != null; exception = exception.getCause()) {
        if (type.isInstance(exception)) {
            return true;
        }
    }

    return false;
}

, который вы затем обрабатываете на стороне контроллера:

public String register() {
    try {
        personEAO.register(personb.getUser(), personb.getPerson());
        Messages.addGlobalInfo("user.register.success");
        return "success";
    }
    catch (DuplicateKeyException e) {
        logger.log(e); // If necessary.
        Messages.addGlobalError("user.register.error.duplicate");
        return "failure";
    }
}

The Messages.addGlobalXxx() может добавить глобальный FacesMessage к контексту, как показано ниже:

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
    FacesMessage.SEVERITY_INFO, someBundle.getString(key), null));

OmniFaces имеет подобный класс , который может помочь вам здесь.

Такое глобальное сообщение будет только отображаться в

<h:messages globalOnly="true" />
1 голос
/ 02 апреля 2012

Как насчет создания перечисления с предопределенными значениями и вместо catch(Exception e) сделать несколько более специфических уловок, и в каждом из них установить параметр retrun метода с этим конкретным значением перечисления

пример перечисления

public enum REGISTERCODE{
    SUCCESS , DUPLICATE, GENERAL_ERROR, SESSION_EXPIRED, MORE, MORE2; 
}

также измените подпись на что-то вроде

public REGISTERCODE register(User user, Person person){...return REGISTERCODE.SUCCESS...

. Вы можете создать ключ в вашем языковом файле с префиксом ResgisterCode_ и затем возвращать сообщения вашему пользователю на основе этого, например,

localizationClass.getMessageFromBundle("ResgisterCode_"+REGISTERCODE_variable.name())

, где REGISTERCODE_variable - это возвращаемое значение из метода регистра

, а затем в методе вызывающего объекта в вашем бине personc возвращает подробное сообщение на основе значения перечисления ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...