• Следует ли использовать геттеры и сеттеры внутри самого класса?

    azerphoenix
    @azerphoenix Куратор тега Java
    Вот, парочка полезных ссылок по теме:
    https://stackoverflow.com/questions/10566222/using...
    https://stackoverflow.com/questions/8466790/java-c...

    Как по мне правильнее использовать геттеры и сеттеры вместо доступа к самому полю. С другой стороны, как отметил коллега, все на усмотрение разработчика.
  • Можно ли заинжектить строку в значение аннотации?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Так вроде можно же. Я нечто похожее проделывал на основе этой статьи:
    https://www.baeldung.com/spring-custom-validation-...

    Я использовал чуть в другом контексте, но также инжектил переменные внутрь аннотации.
    Вот, пример того, что я делал:
    1) создать 2 бина:
    @Bean
        public MessageSource messageSource() {
            ReloadableResourceBundleMessageSource messageSource
                = new ReloadableResourceBundleMessageSource();
    
            messageSource.setBasename("classpath:messages");
            messageSource.setDefaultEncoding("UTF-8");
            return messageSource;
        }
    
        @Bean
        public LocalValidatorFactoryBean getValidator() {
            LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
            bean.setValidationMessageSource(messageSource());
            return bean;
        }


    2) создать файл. Например, message.properties
    Добавить необходимый текст.
    email.notempty=Order name required

    3) Пример использования:
    @NotEmpty(message = "{email.notempty}")
      private String orderName;
  • Почему Spring boot secure login выдает ошибку 404?

    azerphoenix
    @azerphoenix Куратор тега Spring
    djdnkey,
    Есть еще вариант того, что ваши бины располагаются на высшем уровне, чем само приложение и вы не указали источники сканирования. Потому ваш файл конфигурации попросту не воспринимается спрингом.
    Об этом судит вот эта строка:
    package config;
    Т.е. файлы конфигурации у вас лежат в отдельном пакете config.
    Обратите внимание на то, что в туториале файл конфигурации лежит внутри пакета:
    src/main/java/com/example/securingweb/WebSecurityConfig.java

    там же лежит файл самого приложения:
    /src/main/java/com/example/securingweb/SecuringWebApplication.java

    потому в данном примере приложение заработает.

    Чтобы заставить ваш проект работать нужно либо уровень вложенности пакетов организовать корректно, либо использовать аннотацию @ComponentScan
    Полезная информация по теме: https://www.baeldung.com/spring-componentscan-vs-e...

    Если после этого тоже не получится, то можете выложить проект на гитхаб, чтобы я мог точно сказать в чем прчиина. Но скорее всего проблема именно в этом
  • Как проверить имя параметра GET запроса в Sping?

    azerphoenix
    @azerphoenix Куратор тега Java
    Jake Taylor, так вам и не нужно обрабатывать все параметры get запроса. Вообще, в урле могут быть куча параметров. Например, параметры для работы яндекс вебмастера, гугл вебмастера (всякие utm метки и т.д.). Вам нужно лишь получить и обработать лишь свои параметры.
  • Как запустить сервлет?

    azerphoenix
    @azerphoenix Куратор тега Java
    dromanoff1501, рад помочь.
    Вот, кстати причина - https://stackoverflow.com/questions/66806582/tomca...

    И кстати, для удобства разработки советую присмотреться к sdkman
  • Как запустить сервлет?

    azerphoenix
    @azerphoenix Куратор тега Java
    dromanoff1501,
    Установите Томкат 9 версии или ниже. Точно не помню, но какая-то особенность в этом была.
  • Как запустить сервлет?

    azerphoenix
    @azerphoenix Куратор тега Java
    dromanoff1501, как я и сказал проблема именно в этом.
    Только что скачал ваш проект и запустил его у себя с учетом context path.

    Скрин прикладываю:
    hgv7RaX.png

    А вот, где нужно настроить context path в приложении Intellij IDEA:
    MQMll64.png
  • Почему SpringBoot не видит HTML страницу?

    azerphoenix
    @azerphoenix Куратор тега Java
    Что касается ответа на ваш вопрос, то страница видна. Другое дело, что страница могла у вас закешироваться в браузере?
    QHIsUjA.png
  • Почему SpringBoot не видит HTML страницу?

    azerphoenix
    @azerphoenix Куратор тега Java
    Не выставляйте в ваших публичных проектах подобную информацию:
    // App Id - 08f1861f20c248c09ee0a7f6daa9be5f
        // Latest - https://openexchangerates.org/api/latest.json?app_id=08f1861f20c248c09ee0a7f6daa9be5f&symbols=Rub
        // Yesterday -https://openexchangerates.org/api/historical/<DATE>.json?app_id=08f1861f20c248c09ee0a7f6daa9be5f&symbols=rub

    так как она может быть использована злоумышленниками. А представляете, что будет если это окажется платное API?)
  • Как правильно подготовить свои проект для загрузки на GITHUB?

    azerphoenix
    @azerphoenix Куратор тега Java
    Дополню ответ своего коллеги, не забудьте добавить файл .gitignore, где укажите все файлы и директории, которые должны быть проигнорированы. Файлы IDE, внешние лиьы подгружаемые maven & gradle и др. не должны попасть в репозиторий.
    Вот, плагин для Intellij IDEA - https://github.com/JetBrains/idea-gitignore
  • Как исправить ошибку 401 при авторизации в приложении?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Maxim Isaev,
    Я провел код ревью вашего проекта.
    Напишу, все то, что заметил:
    1) Итак, первое что попадается на глаза:
    вы добавили - BCryptPasswordEncoder, но при этом скрипт миграции БД (flyway) добавляет пользователя в БД без хешированного пароля
    HHrtNsd.png
    Отсюда первая причина подобной ошибки. Пароль введенный пользователем (который должен быть захеширован для сравнения со строкой в БД) не совпадает с хешем хранимым в БД, так как в БД нет этого самого хеша. Отсюда - ошибка на клиенте, так как пользователь отправил неправильный пароль.
    2) Настоятельно рекомендую при работе использовать паттерн DTO, так как получать с клиента User и сразу же сохранять не очень хорошо. Создайте UserCreationRequest добавьте туда только нужные поля, добавьте валидацию (spring validation), создайте конвертер (маппер, который замаппит dto -> entity и наоборот) и сохраните пользователя. Можно использовать готовые либы - modelMapper, MapStruct или же интерфейс Converter<S,T>
    3) Важный момент при создании пользователя в сервисном слое вы нигде не конвертируете введенный пользователем пароль в хеш при помощи passwordEncoder. (Что приводит к проблеме обозначенной в пункте 1)
    4) Также у вас были проблемы с самими таблицами. Я закомментировал строчку, чтобы было понятно, где ошибка. Раз упомянул про таблицы, также не забываем про резервированные слова в БД и их экранирование. https://www.drupal.org/docs/develop/coding-standar...
    5) Я добавил демо скрипт Init, который инициализирует демо данные для наглядности (вместо flyway).
    7) В ваших контроллерах слишком много логики. Их можно сократить, отрефакторить и т.д.
    Вот, например:
    if (socks.getQuantity() <= 0
                    || socks.getColor().equals("")
                    || socks.getCottonPart() < 0) {
                return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
            }

    В контроллере вы выполняете бизнес логику на проверку корректности запроса. На самом деле достаточно использовать валидатор и в случае ошибки выбросить кастомное исключение, которое можно потом словить при помощи ControllerAdvice и на клиент отдать код с http ошибкой - bad request.
    Или вот, еще:
    if (!isDataBaseConnected()) {
                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
            }

    В каждом запросе вы проверяете подключена ли БД и выбрасываете исключение. Достаточно исключение SQLException отловить в controllerAdvice и выдать нужную ошибку.
    Или вот еще:
    if(socks.getOperation().equals("moreThan")) {
                        socksList.removeIf(s -> s.getCottonPart() <= socks.getCottonPart() || !s.equals(socks));
                    } else if(socks.getOperation().equals("lessThan")) {
                        socksList.removeIf(s -> s.getCottonPart() >= socks.getCottonPart() || !s.equals(socks));
                    } else {
                        socksList.removeIf(s -> !s.equals(socks));
                    }

    Думаю, что этот код тоже можно упростить. И вообще странно как-то хранить операцию в самой сущности, еще и в виде строки. Раз уж решили хранить, то храните enumerated, чтобы было удобно писать код и исключить возможные ошибки. А то если хранить в виде строки можно легко ошибиться - morethan, moreThan, moreTan и т.д. А вообще, подумайте над тем, как лучше реализовать приложение.
    Я временно закомментировал и добавил простой метод в контроллер, чтобы проверить авторизацию. Также обновил SecurityConfig
    8) Далее ошибка 401 у вас возникает при условии, что вы добавили BCryptPasswordEncoder, но при этом в методе void configure(AuthenticationManagerBuilder auth) используете NoOpPasswordEncoder.getInstance(). Если вы используете NoOpPasswordEncoder, то пароли в flyway подойдут, так как не захешированы. Но я в файле увидел бин BCryptPasswordEncoder и таки добавил хеширование.
    9) Также вам необходимо имплементировать это User implements UserDetails и это Role implements GrantedAuthority и это UserService implements UserDetailsService
    Результат:
    ozpg0nK.png
    Как видим, авторизация заработала.
    Ссылка на проект - https://github.com/hasanli-orkhan/ShopWarehouse
    Разумеется, что в проекте нужно навести красоту и вернуть методы контроллера на место, а проблему с 401 я устранил и показал как.

    Не забудьте клонировать проект себе, чтобы я мог удалить его из своего репозитория
  • Как исправить ошибку 401 при авторизации в приложении?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Maxim Isaev,
    У меня предположение, что косяк в SecurityConfiguration

    Вполне возможно. Сейчас гляну.
  • Не подключается к апи?

    azerphoenix
    @azerphoenix Куратор тега Java
    Так вы же сами пишете, что столкнулись с CORS, нет?
    https://qna.habr.com/q/1058786
  • Как исправить ошибку 401 при авторизации в приложении?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Maxim Isaev, судя по заголовку данные для авторизации отправяются. Надо бы проект подебажить. Если это учебный проект, то можете залить на гит и предоставить доступ.
  • Как правильно закончить решение задачи про валюты (Java)?

    azerphoenix
    @azerphoenix Куратор тега Java
    Добрый день.
    Для оперирования валютами лучше использовать BigDecimal вместо Integer, потому как если вам необходимо ввести сумму 16 рублей 20 копеек, то 16.20 вы просто не введете. В крайнем случае в учебных целях используйте Double.

    Что касается вашего вопроса, то предоставьте условие задачи, иначе не совсем понятно чего вы хотите добиться в конечном результате
  • Почему не работает код java a^b?

    azerphoenix
    @azerphoenix Куратор тега Java
    enabl3, не за что. Кстати, вы можете вынести дублирующийся код в отдельный метод.
  • Можете дать пример для использование паттерна декоратор?

    azerphoenix
    @azerphoenix Куратор тега Java
    У них есть еще неплохой pdf по паттернам. И небольшой cheat sheet тоже в формате pdf. Очень удобно.
  • Почему не работает код java a^b?

    azerphoenix
    @azerphoenix Куратор тега Java
    Добрый день.
    Могу предположить, что у вас есть проблемы в ветке if. Рекомендую сделать дебаг и найти проблему самому. Проверьте насколько корректно срабатывает логика. Хочу обратить внимание, что если пользователь ввел текст, то в выбрасывается исключение InputMismatchException.
    (!get_input.hasNextInt() || ((get_input.nextInt()) <= 0))

    Также у вас есть проблема в следующей ветке:
    while (!get_input.hasNextInt()) {

    А так, вот, один из вариантов решения данной задачи:
    public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.print("Введите число (а): ");
            int a = 0;
            boolean isATrue = true;
            while (isATrue)  {
                a = scanner.nextInt();
                if (a <= 0) {
                    System.out.print("Введите число больше 0: ");
                } else {
                    isATrue = false;
                }
            }
            System.out.print("Введите число (b): ");
            int b = 0;
            boolean isBTrue = true;
            while (isBTrue) {
                b = scanner.nextInt();
                if (b <= 0) {
                    System.out.print("Введите число больше 0: ");
                } else {
                    isBTrue = false;
                }
            }
            System.out.println("'A' в степени 'B' = " + pow(a, b));
        }
    
        public static int pow(int a, int b) {
            return  (int) Math.pow(a, b);
        }

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

    Сделал код ревью. Вот, небольшие советы:
    1) Название классов должны быть с большой буквы. Прочитайте про naming convention.
    2) В названиях переменных слова отделяются при помощи camelCase. Соответственно, get_input -> getInput

    В общем, дебаг наше все)