Професионална програма
Loading...
+ Нов въпрос
lapd87 avatar lapd87 102 Точки

[Homework] Java Spring Auto Mapping - 01. Problem - Game Store

Привет,

моля някой ако може да погледне кода ми и да каже защо не ми работят валидаторите (говорим мейл и парола). Предполагам грешката е една и съща, но гледах видеото от упражненията на Иван, гледах и примерите от слидо не успявам да намеря разлика.

https://www.dropbox.com/s/j3kbushhp9p9xd4/_01GameStore.zip?dl=0

 

Весело прекарване на празника на всички :)

Тагове:
1
Module: Java DB
k.sevov avatar k.sevov 1073 Точки

Edit: Какво тествах и аз не знам... Бях написал глупости, присъединявам се и аз към въпроса, тъй като си нямам идея защо се получава така. 

0
07/04/2018 11:02:24
lapd87 avatar lapd87 102 Точки

:) тъкмо видях какво написа и викам ще оправям ама ...

още нещо добавям предполагам отговора ще е същия,  но това също не се изпълнява като проверка

@Size(min = 0, message = "Size must be positive")

https://github.com/AtanasYordanov/JavaDB-Frameworks---Hibernate-Spring-Data/blob/master/10.Spring%20Data%20Auto%20Mapping/src/main/java/app/services/impl/UserServiceImpl.java

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

0
07/04/2018 13:49:55
k.sevov avatar k.sevov 1073 Точки

Да, точно до това достигнах и аз сега. Бях пропуснал, че validator.validate() не хвърля exception, а връща колекция от грешки, където вече да се провери дали има някакви. Значи все пак се оказва, че работи ако го направим така "ръчно" с autowire на Validator и само да се сложат анотациите не е достатъчно.

1
MartinBG avatar MartinBG 2792 Точки

Не съм се заглеждал много в кода ти, но на пръв поглед ти липсват параметрите, по които да правиш валидацииите.

 

Тук съм качил работещи анотации към една от по-старите задачи, които може да ползваш за вдъхновение :)

1
lapd87 avatar lapd87 102 Точки

Ами огледах но честно казано не схванах какво точно се случва...

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

 

И има ли вариант при провал на проверката да ми хвърля грешката само, а не една камара съобщение?

0
07/04/2018 20:51:22
MartinBG avatar MartinBG 2792 Точки

Проверката се прави автоматично при записване в базата на полето, анотирано директно или чрез гетъра:

    @Column(nullable = false)
    @Password(minLength = 6,
            maxLength = 50,
            containsDigit = true,
            containsLowerCase = true,
            containsUpperCase = true,
            containsSpecialSymbols = true)
    public String getPassword() {
        return this.password;
    }

Ако някое от горните условия не бъде изпълнено, записа в базата ще хвърли ексепшън с грешката, която е сетната в анотацията (това е и смисъла от това да имаме различни съобщения за различните проверки).

Например, при опит за записване в базата на юзър, с парола без специален символ, ще получим тази грешка:

Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [user.models.entities.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='Password should contain one of: !@#$%^&*()_+<>?', propertyPath=password, rootBeanClass=class user.models.entities.User, messageTemplate='Password should contain one of: !@#$%^&*()_+<>?'}
]

Дали ще я вхащаме и как ще я обработваме, или ще оставим приложението да крашне, зависи от конкретните ни цели.

(Добрата практика изисква такива грешки да бъдат хващани и обработвани там, където са предизвикани - напр. на мястото, от където са подадени невалидните данни, защото най-често там има най-много информация за причините за възникването им и съответно може да се вземе правилно решение за обработването им: най-често съобщение към потребителя и/или логване на събитието).

 

1
08/04/2018 05:39:54
lapd87 avatar lapd87 102 Точки

Съжелявам ама пак нищо не разбрах от обясненията :)

пуснах си видеото от предния курс и на 1:48:00 откриха топлата вода. Имплементирах си го и след добавяне на депенданси проработи перфектно :)

<!-- https://mvnrepository.com/artifact/org.glassfish.web/el-impl -->
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>el-impl</artifactId>
    <version>2.2</version>
</dependency>

в имплементацията на регистрирането след като наглася user правя валидацията и всичко е ок

user.setRole(role);

ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Set<ConstraintViolation<User>> constraintViolations = validatorFactory.getValidator().validate(user);

if (!constraintViolations.isEmpty()) {
    for (ConstraintViolation<User> constraintViolation : constraintViolations) {
        System.out.println(IODelimiter + constraintViolation.getMessage());
    }

    return false;
}

this.userRepository
        .saveAndFlush(user);

return true;
1
lapd87 avatar lapd87 102 Точки

всичко хубаво си има край. Като сложих ограниченията за игрите и се получи следния проблем при нова игра

HV000030: No validator could be found for constraint 'javax.validation.constraints.Size' validating type 'java.lang.Double'. Check configuration for 'size'

като се сменяше на BigDecimal за цената и т.н.

хвърля ексепшъна при

Set<ConstraintViolation<Game>> constraintViolations = validatorFactory.getValidator().validate(game);

За целта оправих така:

@Size(min = 0, message = "Size must be positive")
@Column(nullable = false, scale = 1)

@Range(min = 0, message = "Price must be positive")
@Column(nullable = false, scale = 2)

сега гърми с 

javax.validation.ValidationException: HV000032: Unable to initialize softuni.gamestore.model.validators.TrailerCheckValidator.

не ми е ясно какво се случва....

Идеи?

Ето проекта към момента

https://www.dropbox.com/s/j3kbushhp9p9xd4/_01GameStore.zip?dl=0

 

Edit:

Видях че имам проблем с регекса на трейлъра и го оправих:

return trailer.matches("^\\w{11}$");

освен това оправих логиката при добавяне и редактиране на игра да поема цял линк и само края:

String[] trailerInput = inputArgs[4].split("=",2);

String trailer = trailerInput[0];
if (trailerInput.length > 1) {
    trailer = trailerInput[1];
}

но все още грешката е същата...

Видях че от копи-пейст е останало в трейлъра на заглавието класовете... тъпо ама го оправих и него

сега пак се връщаме на грешките с Double...

малко гугъл и ето това е решението за големина и цена:

@DecimalMin(value = "0.0", inclusive = true, message = "Price must be positive")

 

Весел празник ето линка на оправената задача :) Благодаря отново на всички отзовали се, без вас нямаше да успея :)

https://www.dropbox.com/s/j3kbushhp9p9xd4/_01GameStore.zip?dl=0

2
08/04/2018 14:17:34
MartinBG avatar MartinBG 2792 Точки

Опитваш се да изпълниш условието за прецизност (символи след десетичната зашетая) за цена и размер, предполагам. :)

Тука има няколко подхода, които могат да се разделят най-общо на две групи:

А. Валидация на входните данни

Б. Валидация на ниво ентити + сетване на колоните в таблиците на базата с желаната прецизност

В. Комбинация между горните две

Входните данни може да се проверяват на няколко места: при прочитането, при конструирането на DTO, при подаването за запис към базата. Най-смислено, според мен, в този случай е проверката да бъде в DTO, като всякакви грешки, открити там се връщат към потребителя.

Системата ще работи и при правилно създадено ентити с валидация на всяко поле - това е най-лесно за реализация и като цяло не е лоша идея да го има, дори и да правим валидацията на други нива (един вид застраховка, ако някой опита да persist-не обект, създаден по нестандартен начин).

По-трудно е за поддръжка, но това може да се адресира, ако си направим анотации за проверка на всяко поле и използваме само и единствено тях на всяко от нивата в програмата ни (напр. @Password, @Email, @URL и т.н., които да ползваме както за entity, така и за dto). 

 

Относно задаването на прецизност за числата в базата през Hibernate, аз знам за 2 начина:

1. Използване BigDecimal тип в entiti-то и към него подбна анотация: @Column(precision = 10, scale = 1)

2. Сетване на типа директно чрез анотация, като това работи и за float/double, но не е добра идея, защото е един вид хардкодване и може да не работи на друга база : @Column(columnDefinition = "DOUBLE(10,1)")

2
lapd87 avatar lapd87 102 Точки

Благодаря че го видя

@Digits(integer = 20, fraction = 1, message = "Invalid size format")

добавих това :) мисля че е най-лесно

1
nickhub avatar nickhub 0 Точки

Nice to see this here and thanks for sharing this to us. websites like rabbit  is given here to check.

 

-1
19/09/2019 14:42:50 1