Софтуерно Инженерство
Loading...
+ Нов въпрос
MartinBG avatar MartinBG 1136 Точки

[Exercise - Employee Register] - Решение с валидация

Здравейте, колеги!

 

И в трите домашни от това упражнение, които ми се падна да проверя, забелязах, че не е изпълнена следната част от условието:

If there is an empty field, NOTHING should happen, and NO Employee should be added.

 

Понеже и аз имах известни проблеми с имплементирането ѝ, реших да споделя моето решение.

 

Правим си binding модела с валидациите, както си го знаем:

public class EmployeeRegisterBindingModel {

    @NotNull
    @Size(min = 1, max = 32)
    private String firstName;

    @NotNull
    @Size(min = 1, max = 32)
    private String lastName;

    @NotNull
    @Size(min = 1, max = 32)
    private String position;

    @NotNull
    @Min(0)
    private BigDecimal salary;

    @NotNull
    @Min(0)
    private Integer age;

    // constructor, getters, setters
}

 

При натискане на "Register", данните ще бъдат валидирани, а при невалидни данни заявката ще бъде игнорирана (без да се нулират полетата:), с грешка като тази в лога:

16-Feb-2019 17:02:34.176 WARNING [http-nio-8000-exec-2] org.apache.myfaces.lifecycle.RenderResponseExecutor.execute There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered.
These unhandled FacesMessages are: 
- j_id_h:salary: must be greater than or equal to 0
- j_id_h:age: must be greater than or equal to 0

 

Освен валидациите на модела, може да добавим и валидации на полетата във формата, например required="true":

<p:inputText value="#{...}" id="..." placeholder="..." required="true"/>

 

При натискане "Register" ще бъде направена валидация на полетата, като при грешка заявката ще бъде игнорирана, а в лога ще получим описание на проблема. Напр.:

16-Feb-2019 17:10:22.527 WARNING [http-nio-8000-exec-6] org.apache.myfaces.lifecycle.RenderResponseExecutor.execute There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered.
These unhandled FacesMessages are: 
- j_id_h:firstName: Validation Error: Value is required.
- j_id_h:lastName: Validation Error: Value is required.
- j_id_h:position: Validation Error: Value is required.
- j_id_h:salary: Validation Error: Value is required.
- j_id_h:age: Validation Error: Value is required.

 

Двата типа валидации работят заедно, като първо се прави валидацията на input полетата, а после - на binding модела (само за полета, които са минали първата валидация).

Комбиниран лог:

16-Feb-2019 17:11:56.334 WARNING [http-nio-8000-exec-8] org.apache.myfaces.lifecycle.RenderResponseExecutor.execute There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered.
These unhandled FacesMessages are: 
- j_id_h:firstName: Validation Error: Value is required.
- j_id_h:lastName: Validation Error: Value is required.
- j_id_h:position: Validation Error: Value is required.
- j_id_h:salary: must be greater than or equal to 0
- j_id_h:age: must be greater than or equal to 0

 

 

В конкретната задача имаше и един допълнителен проблем, поне при мен.

При натискане на Delete бутона, се активираше валидацията на binding модела, която съответно не минаваше за празна форма и заради това не сработваше изтриването.

 

Решението (за PrimeFaces) беше да добавя immediate="true" като параметър към commandButton-а, който трие записи:

<p:commandButton value="Remove" immediate="true" action="#{...}"/>

 

Накрая - бонус съвет при използването на "PrimeFaces".  :)

Aко не искате да ви се променя стилизацията на елементите, когато използвате PrimeFaces, добавете следната директива към web.xml:

 

    <context-param>
        <param-name>primefaces.THEME</param-name>
        <param-value>none</param-value>
    </context-param>

 

Поздрави!

Тагове:
4
Java Web
Ivelin_Dimitrov avatar Ivelin_Dimitrov 146 Точки
Best Answer

Добра работа Мартине, за тези валидации не сe говори много на лекциите и вярвам, че тази статия ще е полезна на много хора. 

В допълнение бих добавил само, че в jsf може да си валидираме данните с f:validate, като има различен набор от валидации validateLength, validateLongRange, validateDoubleRange.. Съответно можем да визуализираме message-те с 

<h:message id="m3" for="color" style="color:red; margin: 0 auto;"/>

Пример за такава jsf валидация

<div class="row">
   <div class="col-md-12 d-flex justify-content-center">
     <div class="form-group">
       <h:outputLabel for="age" value="Age"/>
       <p:inputNumber id="age" value="#{createCatManageBean.bindingModel.age}" styleClass="form-control-range"
                  required="true" validatorMessage="Age must be an integer between 1 and 31." label="Age">
            <f:validateLongRange maximum="31" minimum="1" for="age"/>
         </p:inputNumber>
     </div>
   </div>
   <h:message id="m4" for="age" style="color:red; margin: 0 auto;"/>
</div>

 За да не ни изписва съобщения от сорта на "- j_id_h:age:...." се добавя 'label=Age', с 'require="true" си гарантираме, че полето не може да бъде празно, като генерираното съобщение ще бъде "Age: Validation Error: Value is required.". Също така поставяме допълнителна валидация 

<f:validateLongRange maximum="31" minimum="1" for="age"/>

Която ни валидира полето да е в диапазона от 1 до 31 включително. Като допълнително сме указали какъв да е messege-а ако валидацията фелне с атрибута 

validatorMessage="Age must be an integer between 1 and 31."

 и накрая посочваме къде да се визуализира error message-а ако има такъв

<h:message id="m4" for="age" style="color:red; margin: 0 auto;"/>

Това съвсем не е единственият начин, можем да падаваме errorMessages от managed Bean-а към jsf-а като го добавим в FacesContext-a примерно за логин: 

//If login failed, should show errorMessage with "Invalid credentials."
if (userServiceModel == null) {
   FacesContext facesContext = FacesContext.getCurrentInstance();

   //Send an error message on Login Failure
   facesContext.addMessage(null, new FacesMessage("Invalid credentials."));
   return;
}

 съответно в jsf-а го прихващаме и рендерираме отново с h:message 

 <!-- Show authentication failed error message -->
 <h:messages globalOnly="true" style="color: red; margin: 8px; text-align: center" />

 

1
18/02/2019 13:18:31