Ответы пользователя по тегу Spring
  • Почему возникла ошибка Whitelabel?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Исходя из вашего прошлого вопроса прочитайте про - https://www.baeldung.com/spring-controller-vs-rest...

    @org.springframework.stereotype.Controller
    public class Controller {
        @GetMapping
        public String hello() {
            return "Hello";
        }
    }

    Подозреваю, что у вас нет шаблона с названием Hello, потому и ошибка. Вам нужно либо вернуть существующий шаблон, либо если это REST, то пометить RestController. Либо если уж решили использовать Controller, то добавьте к методу @ResponseBody
    Ответ написан
  • Почему вместо шаблона возвращается текст?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день!
    Неправильно:
    @RestController
    public class RegistrationController {


    Должно быть:
    @Controller
    public class RegistrationController {


    Прочитайте про:
    https://www.baeldung.com/spring-controller-vs-rest...

    Далее другая ошибка:
    у вас POST запрос убегает на registration
    А в контроллере:
    @PostMapping("/registrtion")
    Ответ написан
  • Можно ли сделать динамическое добавление WebAPI?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Не знаю поможет ли вам это, но нужный вам функционал есть в составе Spring Cloud.
    Вам нужно следующее:
    - Spring Configuration Server, который стартует первым и подгружает конфигурации для других микросервисов.
    - (Разумеется, что вам также понадобятся Eureka Server & Spring Gateway API)
    - Далее вам необходимо добавить Spring Cloud Bus, который динамически обновляет конфиги.
    Потом происходит примерно следующее:
    Вы заливаете ваши новые конфиги либо в гит репозиторий, либо локально. При наличии новой конфигурации они доставляются через AMQР к соответствующему микросервису.
    KHtD0FG.png
    Ответ написан
    Комментировать
  • CRUD spring+hibernate: передача json и обработка на сервере?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    По-первых, для реализации вашей задачи вам необходимо обратить внимание на паттерно DTO (data to object).
    Также, если у вас приложение на Spring, то можете подключить мапперы для удобства маппинга (конвертации) dto -> entity (и наоборот). Можете использовать такие либы, как modelMapper, MapStruct.
    Если не хотите использовать либу, то имплементируйте интерфейс Converter<S,T>

    Оптимальность, чтобы не надо было передавать лишних полей, если они не заносятся в таблицу или автогенерируются

    Вы можете на клиентской стороне средствами js проверить поля объекта на null и в случае оного просто не передавать это поле. Ну или же можно передать это поле и проверить на null & empty уже на серверной стороне.

    В JSON в поле one-to-many (например при создании юзера у него будут животные) чтобы передавался только массив idшников животных, а не полностью вся информация о них (частично пересекается с первым пунктом - оптимальность)

    Чтобы передать id животного/ных из фронта необходимо, чтобы они были в БД. Если животные добавляются раньше пользователя, то достаточно при получении dto для user (в утильном классе Converter) найти животных по переданным id и назанчить этих животных юзеру через setPets()или метод addPet()
    Ответ написан
    Комментировать
  • Почему Spring boot secure login выдает ошибку 404?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день.
    Могу предположить следующие причины:
    1) либо у вас нет шаблона login.html в /resources/templates/
    2) либо запрос не доходит до /login, так как:
    .antMatchers("/").permitAll()
     .anyRequest().authenticated()

    Вы разрешили доступ без аутентификации только к главной странице. А форма авторизации лежит по пути /login
    Ответ написан
  • Spring mvc tomcat 404 в чем ошибка?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Могу предположить, что вы некорректно настроили томкат. В настройках вашего IDE необходимо указать context path.
    А затем обращаться к вашему приложению примерно так:
    localhost:8080/myPath/hello-world
    Ответ написан
    Комментировать
  • Как исправить ошибку 401 при авторизации в приложении?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый вечер.
    Ошибки 4хх - являются ошибками на клиенте.
    Было бы неплохо увидеть содержимое post запроса, который убегает на сервер и конечно же то, что приходит на сервер.
    Причины могут быт разные:
    1) содержимое формы (названия инпутов - имя пользователя и пароль), а также ожидаемые названия инпутов отличаются. Например, на сервере ожидается username & password, а вы отправляете login & pass. Обратите внимание на атрибут name инпутов и при необходимости добавьте сответствующие названия в конфиг. .formLogin()
    https://www.baeldung.com/spring-security-login
    2) может быть запрос до спринга даже не доходит по каким-то причинам.
    В общем, не буду гадать и вы не гадайте. Проведите дебаг проекта и все станет на свои места
    Ответ написан
  • Spring security собственный шаблон для 403?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день.

    Можно использовать этот сниппет. Тут можно отловить код http ошибки (statusCode), а затем если значение этой переменной равно 403, то отобразить нужный шаблон.
    @Controller
    @RequiredArgsConstructor
    public class HttpErrorController implements ErrorController {
    
      @RequestMapping("/error")
      public ModelAndView handleError(HttpServletRequest request) {
        Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        if (status != null) {
          int statusCode = Integer.valueOf(status.toString());
          // тут при помощи switch case находим код 403 и отдаем нужный шаблон.
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("/frontend/templates/http-errors");
        return modelAndView;
      }
    
      @SuppressWarnings("deprecation")
      @Override
      public String getErrorPath() {
        return null;
      }
    }
    Ответ написан
    Комментировать
  • Как средствами JavaScript отправить форму, содержащую текстовые поля и файл, в формате JSON?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Я так понял, что у всего содержимого формы Content-type должен быть multipart/form-data, верно?

    Да, все верно.

    Также не забывайте отправлять csrf токен, если в настройках безопасности он у вас включен. Некоторые шаблонизаторы (например, thymeleaf) делают это автоматически, но при отправке содержимого формы средствами js надо csrf тоже отправлять. Для этого в head добавляется мета-тег, в который вставляется csrf токен.
    Затем средствами js необходимо получить значение этого тега (токен) и отправить с формой.
    Подробности тут:
    https://www.baeldung.com/spring-security-csrf
    Раздел 3.4 Using Json - https://www.baeldung.com/spring-security-csrf#4-us...

    e.preventDefault();
    Скорее всего эта строка должна быть выше всех. Как бы вы сперва останавливаете form submission, а затем уже делаете все остальное. Иначе у вас форма будет отправлена, а затем выполнится остальной код.

    А вот, ответ на ваш вопрос:
    https://stackoverflow.com/questions/49845355/sprin...
    И в первом ответе и во втором описывается вариант отправки формы средствами js с файлом и с другими данными.
    Ответ написан
  • Почему Role и Privileges выдаются в UserDetailsService в одной коллекции, как равноценные понятия в данном примере?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Собственно говоря, в той же статье откуда вы взяли код (baeldung) ниже написана причина смешивания ролей и привилегий.
    The interesting thing to follow here is how the Privileges (and Roles) are mapped to GrantedAuthority entities.This mapping makes the entire security configuration highly flexible and powerful – you can mix and match roles and privileges as granular as necessary, and at the end, they'll be correctly mapped to authorities and returned back to the framework.


    Вот, еще полезная информация (прочитайте первый ответ) - https://stackoverflow.com/questions/6357579/spring...

    В Spring есть понятие Authority. Это могут быть как роли, так и привилегии (privilege, permission). Так как конечная цель заключается в том, чтобы проверить права пользователя и так как привилегия и роль по факту являются теми самыми "правами", но лишь на разных уровнях абстракции (роль содержит сет привилегий), то в примере кода, который вы указали все смешано в одну кучу.
    Отличие проявляется на другом уровне, когда есть метод для проверки роли hasRole(), к слову, к значению этого метода автоматически добавляется префикс ROLE_, а также метод hasAuthority(), когда проверяются все права (роли и привилегии) и в этом случае для проверки роли нужно указывать префикс ROLE_ самому или уже указать название привилегии (например, READ_PRIVILEGE).
    Ответ написан
    Комментировать
  • Можно ли домен, логин и т.п прописать в properties?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    Пожалуй, я лишь дополню ответ своего коллеги BorLaze некоторыми ссылками на полезные материалы.
    1 - насчет вынесения properties файла за пределы приложения:
    https://docs.spring.io/spring-boot/docs/2.1.8.RELE...
    В частности обратите внимание на:

    SpringApplication loads properties from application.properties files in the following locations and adds them to the Spring Environment:

    A /config subdirectory of the current directory
    The current directory
    A classpath /config package
    The classpath root

    The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).


    Вот, еще по этой же теме:
    https://www.baeldung.com/spring-properties-file-ou...
    Это Spring Boot + Docker: https://stackoverflow.com/questions/46057625/exter...
    Вот, еще информация о том, как можно исключить внешний конфиг файл
    https://stackoverflow.com/questions/26140784/sprin...
    https://stackoverflow.com/questions/26744060/exclu...

    Насчет хранения паролей в properties, вы можете воспользоваться - Jasypt
    Ссылка на первоисточник: https://stackoverflow.com/questions/37404703/sprin...

    Еще можно при старте приложения передать значения этих данных при помощи аргументов.
    Т.е. хранить в properties что-то типа ftp.host=example.com А при старте приложения использовать что-то типа такого:
    mvn spring-boot:run -Dspring-boot.run.arguments=--ftp.host=mysite.com

    https://www.baeldung.com/spring-boot-command-line-...

    В микросервисах подобная задача решается несколько иначе - поднятием отдельного конфиг сервера, который подтягивает конфигурацию извне при старте приложения. Но думаю, что это вам пока не нужно
    Ответ написан
    Комментировать
  • Как получить по ftp самый свежий файл?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день
    получить файл (без сортировки, а просто по указанию путь -> названию файла)

    А чем сортировка вам не подходит?
    Вот, ответ на ваш вопрос с использованием Comparator
    https://stackoverflow.com/questions/3824983/get-la...
    https://stackoverflow.com/questions/30883025/how-t...

    P.S. Как вариант можно попробовать получить список файлов и дату последнего изменения каждого из них. Затем для каждого LocalDateTime применив методы isAfter() isBefore() найти последнюю запись.
    Ответ написан
    Комментировать
  • Как ограничить права на редактирование записей?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день!
    Вам нужно добавить такие сущности, как Role & Privilege.
    Роли - ADMIN, USER и т.д.
    Привилегии - READ_PRIVILEGE, WRITE_PRIVILEGE и т.д.
    Ссылка - https://www.baeldung.com/role-and-privilege-for-sp...
    А затем уже логика работы следующая:
    Если пользователь является админом, то скорее всего у него должны быть все необходимые привилегии. Если это пользователь и если запись была создана им же и если например, у него есть EDIT_PRIVILEGE, то он может отредактировать запись. Если например, у вас есть роль - модератора, то привилегия EDIT_PRIVILEGE у него будет даже, если он не является владельцем записи и т.д. Дальнейшая логика строится на основе ваших нужд
    Ответ написан
  • Как в Spring правильно создавать и инжектить сервисы?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    1. Это нормально?

    Да, нормально. Вообще, наличие сервисного слоя для реализации бизнес-логики необходимо. В сервисном слое вы можете валидировать dto, конвертировать dto <-> model, а также описывать любую бизнес-логику.
    2. Почему инжектится "исходный" интерфейс?

    Коллега подсказал вам правильно. Инжектится реализация данного интерфейса. Если у интерфейса есть несколько реализаций, то необходимо будет уточнить какая реализация должна быть заинжекчена

    Зачем создаётся EmailServiceImpl, если он не используется? Он ведь не используется?

    Конечно же используется. Во время работы происходит примерно следующее:
    private EmailService emailService = new EmailServiceImpl();


    Тут какая-то хитрая магия Spring? Он видит, что есть ИмяИнтерфейсаImpl и учитывает это в процессе? Как это работает?

    Как я и сказал выше, если у интерфейса несколько реализаций, то необходимо уточнить название бина, который должен заинжекчен. Ну а если у интерфейса одна реализация, то конечно же она и будет автоматически взята.

    Как правильно в Spring создавать интерфейсы и правильно их инжектить?

    Собственно говоря, создайте нужный интерфейс. Затем имплементируйте данный интерфейс. В классах (контроллерах или еще где-то) используйте сам интерфейс для создания слабых связей.
    А сприн сам "решит" какую реализацию подключать, ну или же укажите название бина, который нужно заинжектить.
    Ответ написан
    5 комментариев
  • Как правильнее обработать кастомное исключение в Spring MVC?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый вечер.
    1) Прежде всего - вместо скриншотов добавляйте сниппеты кода. Если например, придется вносить правки в ваш код, то что прикажете делать? Не перепечатывать же его со скрина.
    2) Проверку на дубликаты и др. логику лучше перекинуть на сервисный слой.
    Например, некий CategoryService, где обрабатывается бизнес логика, а затем в сервисном слое вызываются методы CategoryDao
    3)
    Насколько ок завязываться на логике выброшеного исключения?

    Выбрасывайте свое кастомное исключение в сервисном слое. Например, DuplicateRecordExistsException, RecordExistsException или что-то типа такого.
    Далее ловите данное исключение на уровне контроллера или controllerAdvice. А затем уже на основе выбрасываемого исключения отдавайте на клиент сообщение с http статусом. Например,
    наличие дубликата это ошибка на клиенте. Соответсвенно, код ошибки 4xx (например, 400). Сообщение ошибки - Запись существует.
    Прочитайте вот это - https://spring.io/blog/2013/11/01/exception-handli...
    Обратите внимание на
    @ExceptionHandler
    а также вот, эту главу - Global Exception Handling Using @ControllerAdvice Classes
    Ответ написан
    Комментировать
  • Spring boot - как происходит запуск?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Есть приложение, читающее файлы из файловой системы и загружающее в БД часть содержимого.

    Ну в данном случае для импорта БД нужно использовать sql скрипты и какую-нибудь либу. Например, flyway.

    Есть сервисные классы, в них ряд методов, но возвращаемые типы в методах повторяются.

    Если это необходимо, то можно использовать дженерики.

    Хотелось бы сделать без спринг шелла, без команд в мейне.

    По идее flyway (или например, liquibase) лучше подходят для этих целей.
    Ответ написан
    Комментировать
  • Правильно ли я называю тесты?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Вопрос не глупый. Ведь, от правильного нейминга зависит то, насколько хорошо ваш код будет читаемым.
    Вот, информация о конвенции нейминга тестов.
    https://dzone.com/articles/7-popular-unit-test-naming
    Ответ написан
    Комментировать
  • Какую аннотацию лучше всего использовать для ролей ( для Hibernate ) в Spring?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Я обычно делаю это иным образом.
    1) создаю enum UserRole, UserPrivilege
    2) создаю entity Role. При необходимости можно еще добавить сет из Privilege для каждой роли
    3) Далее каждый entity содержит роль или сет ролей.
    4) сущность User связываю с сущностью UserRole

    Вот, исходники:
    Сущность User
    @Entity
    @Data
    @Table(name = "users")
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode(callSuper = false)
    public class User {
    
      //...
    
      @JsonBackReference
      @ToString.Exclude
      @ManyToMany(fetch = FetchType.EAGER)
      @JoinTable(
          name = "users_roles",
          joinColumns = @JoinColumn(name = "user_id"),
          inverseJoinColumns = @JoinColumn(name = "role_id"))
      private Set<Role> roles;
    
    }


    Сущность Role
    @Entity
    @Data
    @EqualsAndHashCode(callSuper = false)
    @Table(name = "roles")
    public class Role implements GrantedAuthority {
    
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE)
      private Long roleId;
    
      @JsonBackReference
      @ToString.Exclude
      @ManyToMany(mappedBy = "roles")
      private Collection<User> users;
    
      @JsonBackReference
      @ToString.Exclude
      @ManyToMany
      @JoinTable(
          name = "roles_privileges",
          joinColumns = @JoinColumn(name = "role_id"),
          inverseJoinColumns = @JoinColumn(name = "privilege_id"))
      private Collection<Privilege> privileges;
    
      @Enumerated(EnumType.STRING)
      private UserRole name;
    
      public Role() {
        super();
      }
    
      public Role(UserRole name) {
        super();
        this.name = name;
      }
    
      @Override
      public String getAuthority() {
        return name.name();
      }
    }


    enum UserRole
    public enum UserRole {
      USER,
      ADMIN
    }


    сущность Privilege
    @Entity
    @Data
    @EqualsAndHashCode(callSuper = false)
    @Table(name = "privileges")
    public class Privilege {
    
      
    
      @Enumerated(EnumType.STRING)
      private UserPrivilege name;
    
      @JsonBackReference
      @ToString.Exclude
      @ManyToMany(mappedBy = "privileges")
      private Collection<Role> roles;
    
    
    }


    enum UserPrivilege
    public enum UserPrivilege {
      ADMIN_PRIVILEGE,
      READ_PRIVILEGE,
      WRITING_COMMENTS_PRIVILEGE
    }
    Ответ написан
    6 комментариев
  • Почему Spring Security отказывается пускать, несмотря на permitall()?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Я бы попробовал сделать следующее:
    1) изменить урл и попробовать заново. Например, /admin/**
    2) также попробуйте подебажить проект. Например, что возвращает:
    Role.ADMIN.getAuthority() и что ожидается на вход
    Ответ написан
    Комментировать
  • Как изучать Spring? Где нормальная документация?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Подскажите как лучше изучать spring, какой современный стек?

    Пожалуй, все фреймворки изучаются на основе книг, документаций, а также туториалов. Спринг не является исключением.

    Туториалы: John Thompson - (Spring Guru)
    https://www.udemy.com/courses/search/?q=john+thomp...
    Есть чуть попроще Dan Vega - Learn Spring Boot
    https://www.udemy.com/course/spring-boot-intro/
    Также Наиль Алишев - Spring Framework
    https://www.youtube.com/watch?v=5ePo08sqcpk

    Что касается книг, то можно начать с Spring Boot in Action (Spring Boot в действии)

    Что касается документаций:
    https://docs.spring.io/spring-boot/docs/current/re...
    https://www.baeldung.com/

    Ну и у baeldang есть неплохие курсы по Spring
    https://www.baeldung.com/learn-spring-course
    Ответ написан
    Комментировать