Ответы пользователя по тегу Spring
  • Что значит метод Payload из javax.validation.Payload?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    Это по сути тоже сужает действие, но позволяет применить к кастомным Constraint'ам
    https://docs.jboss.org/hibernate/validator/4.1/ref...
    6031262181841223775751.png
    https://beanvalidation.org/1.1/spec/
    Payloads are typically used by validation clients to associate some metadata information with a given constraint declaration. Payloads are typically non-portable. Describing payloads as interface extensions as opposed to a string-based approach allows an easier and more type-safe approach.
    Ответ написан
    Комментировать
  • Как работать с localeStorage в Spring приложении?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    localStorage это хранилище на клиентской стороне и соответственно к backend не имеет никакого отношения.
    Вы лишь можете при помощи js отправлять данные сохраненные в ls или получать данные из бек-энд и сохранять в ls при помощи js
    Ответ написан
    Комментировать
  • Есть ли необходимость связывать сущности в БД, если я их связываю через spring data jpa в коде?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    название транспорта, фамилии рабочих, инстанции, фамилия агента, фамилия заказчика.

    Скорее всего это должно быть не одной таблицей, а несколькими, так как это разные сущности.
    Т.е. Журнал может содержать в себе сущность пользователя (сущности - агент, заказчик). А далее уже используя связи OneToOne OneToMany ManyToOne ManyToMany нужно связать эти сущности между собой.

    Стоит ли заморачиваться, и связывать через ключи таблицы в sql или можно это связать в самом коде через аннотации?

    Аннотации сделают это за вас. В данном случае вы пишете по принципу code first и соответственно, вся логика создания ddl должна быть в коде.

    Какие могут быть последствия такой связи?

    Ну например, некорректное выставление каскадных типов.

    Какие есть нюансы?

    Будет сложно пересказать нюансы с учетом общности вопроса. Прочитайте документацию к Spring Data JPA и станет яснее.
    Ответ написан
    Комментировать
  • Как правильно вставлять картинки в html представления и настраивать Thymeleaf?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день!
    Картинки проекта нужно добавлять в директорию resources/static Можно создать директорию images и соответственно, путь будет /resources/static/images
    А уже все последующие загружаемые файлы через фронт можно хранить либо на распределеных файловых системах, либо где-нибудь на хостинге.
    Ответ написан
  • Как работает Spring Security JWT?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    Вот, пример Spring Security JWT
    https://github.com/hantsy/spring-webmvc-jwt-sample
    Вот, тут схематическое изображение того, как JWT AUTH работает
    https://www.javainuse.com/spring/boot-jwt
    Надеюсь, что смог помочь вам
    Ответ написан
    Комментировать
  • Платформа для обучения сотрудиков, как лучше реализовать?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день!
    Никто не даст совета по поводу архитектуры сайта не зная полного технического задания.
    Для фронт-энда, если вы планируете использовать фреймворк попроще, то можете выбрать VueJS
    Готовые бесплатные шаблоны есть. Можете тут выбрат шаблоны не только для Vue, но и для других фреймворков - https://www.creative-tim.com/templates/vuejs-free
    Но разумеется, что если вам нужен более юзабельный шаблон, то стоит обратиться к дизайнеру, верстальщику, а затем уже перенести его в выбранный вами фреймворк.
    Бывают разные электронные платформы подготовки специалистов. Например, тот же udemy.com поддерживает стриминг видео и генерирует сертификаты. В общем, в первую очередь определитесь с функционалом, а затем уже точняйте детали архитектуры.
    Ответ написан
    2 комментария
  • Как сделать DTO с валидацией данных в Java Spring?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    Если честно, то меня сама строка настораживает
    @NotNull(message = "123")
        @NotEmpty(message = "456")
        private String proxy;

    NotEmpty и так проверяет строку на NULL и на пустоту и соответственно, аннотация @NotNull не нужна.
    Попробуйте удалить эту аннотацию и проверьте заново.
    Ответ написан
  • Почему Hibernate разрешает удалять сущность, на которую ссылается FK?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    Наверное, помимо ограничений на уровне БД можно использовать проверку средствами Java. Т.е. создать метод, который проверяет наличие курсов у юзера и выбрасывает соответствующее исключение. Соответственно, исключение будет выброшено до вызова метода delete() и будет выброшено то исключение, которе вам нужно.
    Я конечно не отвечу вам наверняка, но думаю этот ответ будет для вас полезен
    https://stackoverflow.com/questions/14875793/jpa-h...

    JPA does offer possibility to cascade operations (merge, persist, refresh, remove) to associated entities. Logic is in JPA and does not utilize database cascades.
    There is no JPA standard compliant way to do cascades with database cascades.

    Т.е. скорее всего вы каскады не указали при создании сущности ManyToMany. Проверьте ваш код

    Дополнено:
    There is no clean cut means to do this in JPA. The following will get you what you want... You can use CascadeType.DELETE, however this annotation only applies to the objects in the EntityManager, not the database. You want to be sure that ON DELETE CASCADE is added to the database constraint. To verify, you can configure JPA to generate a ddl file. Take a look at the ddl file, you'll notice that ON DELETE CASCADE is not part of the constraint. Add ON DELETE CASCADE to actual SQL in the ddl file, then update your database schema from the ddl. This will fix your problem .
    Ответ написан
  • Как к entity присоединить список других entity и потом работать с ними и со списком?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    Во-первых, на основании ваших слов:
    Есть сертификат(Certificate), у него может быть много тегов (Tag).
    Предполагается что в таблице тегов может быть куча дубликатов по имени, т.е. 3 сертификата могут иметь один и тот же тег "Java" ну или как-то так.

    Могу предположить, что связь OneToMany & ManyToOne не очень подходит.
    Вот, смотрите: один сертификат может иметь несколько тегов, но при этом один тег может относится к разным сертификатам. Тут явно связь ManyToMany.
    https://vladmihalcea.com/the-best-way-to-use-the-m...
    https://www.baeldung.com/jpa-many-to-many
    Соответственно, получится, что со стороны Certificate вы сможете получить список его тегов, а со тороны тега, можете получить список сертификатов, к которым он принадлежит.
    А то у вас получается, что и со стороны тега и сертификата OneToMany связь, но при этом с обеих сторон используется List
    При использовании ManyToMany будет создана новая таблица вида certificate_id | tag_id, где вы сможете хранить данные. И соответственно,
    Как к entity присоединить список других entity и потом работать с ними и со списком?

    Этот вопрос устранится само собой
    Ответ написан
    7 комментариев
  • Как создать разные классы под разные роли в Spring Security?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Я бы не создавал классы для каждой из роли, а реализовал бы следующим образом:
    1) Создать класс User. Пометить @MappedSuperclass. Вынести туда общие поля: username, password и др.
    2) Далее создать нужные классы и расширить класс User. Например, Customer, Author и др. И все поля специфичные для каждого из классов указать в них.
    3) Далее можно например, создать паттерн Builder, который при создание сущности по дефолту будет назначать соответствующие классу роли.

    P.S. Не забудьте также имплементировать интерфейс UserDetails нужный для Spring Security.
    Ответ написан
    2 комментария
  • Как работать с изображениями в веб-приложениях на Java?

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

    Как хранить изображение? Насколько я знаю, их можно запихивать прямо в PostgreSQL, но я склоняюсь в сторону того, что изображения надо сохранять в ресурсы, а в бд хранить только ссылки.

    Не самая лучшая идея хранить картинки в виде binary в БД. Лучше, как вы отметили в БД хранить ссылку на объект, а ресурс в файловой системе. Можно хранить файлы в распределенных файловых системах (AWS, Google), но вряд ли вы располагаете таким бюджетом.

    Вот, простая реализация хранения картинок в FS.

    Entity
    @Entity
    @Data
    @NoArgsConstructor
    @Table(name = "attachments")
    public class Attachment {
    
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE)
      private Long attachId;
    
      private String attachTitle;
    
      @Column(nullable = false, updatable = false)
      private LocalDate uploadDate;
    
      private String extension;
    
      private String downloadLink;
    
    }


    Repository
    @Repository
    public interface AttachmentRepository extends JpaRepository<Attachment, Long> {}


    Service
    public interface AttachmentService {
    
      /**
       * Загрузить новый файл
       *
       * @param file
       * @param user
       * @throws IOException
       */
      Attachment addAttachment(MultipartFile file, User user) throws IOException;
    
    
      /**
       * Найти Вложение по его ID
       *
       * @param attachId
       * @return
       */
      Attachment findAttachById(Long attachId);	
    
      /**
       * Скачать файл
       *
       * @param uploadYear
       * @param fileName
       * @return
       * @throws MalformedURLException
       */
      Resource loadFileAsResource(String uploadYear, String fileName) throws MalformedURLException;
    
    }


    ServiceImpl
    @Service
    @RequiredArgsConstructor
    public class AttachmentServiceImpl implements AttachmentService {
    
      private final AttachmentRepository attachmentRepository;
      private final AppProperties appProperties;
      private final FileTools fileTools;
    
      /**
       * Загрузить новый файл
       *
       * @param file
       * @param user
       * @throws IOException
       */
      @Override
      public Attachment addAttachment(MultipartFile file, User user) throws IOException {
        // Создаем директорию если ее не существует
        File uploadDir = new File(appProperties.getUploadPath());
        // Если директория uploads не существует, то создаем ее
        if (!uploadDir.exists()) {
          uploadDir.mkdirs();
        }
        String curDate = LocalDateTime.now().toString();
        // Создаем уникальное название для файла и загружаем файл
        String fileName =
            "attach_" + curDate + "_" + file.getOriginalFilename().toLowerCase().replaceAll(" ", "-");
        file.transferTo(new File(uploadDir + "/" + fileName));
        Attachment attachment = Attachment.builder()
            .attachTitle(fileName)
            .uploadDate(LocalDate.now())
            .extension(fileTools.getFileExtension(file.getOriginalFilename()))
            .downloadLink("/attachments/get/" + Year.now() + "/" + fileName)
            .build();
        attachmentRepository.save(attachment);
        return attachment;
      }
    
    
      /**
       * Найти Вложение по его ID
       *
       * @param attachId
       * @return
       */
      @Override
      public Attachment findAttachById(Long attachId) {
        return attachmentRepository
            .findById(attachId)
            .orElseThrow(() -> new AttachmentNotFoundException("Attachment not found!"));
      }
    
    
      /**
       * Скачать файл
       *
       * @param fileName
       * @return
       * @throws MalformedURLException
       */
      @Override
      public Resource loadFileAsResource( String fileName)
          throws MalformedURLException {
        Path fileStorageLocation =
            Paths.get(appProperties.getUploadPath()).toAbsolutePath().normalize();
        Path filePath = fileStorageLocation.resolve(fileName).normalize();
        return new UrlResource(filePath.toUri());
      }
    
    }


    Conroller
    @Controller
    @RequiredArgsConstructor
    @RequestMapping("/attachments")
    public class AttachmentController {
    
      private final AttachmentService attachmentService;
      private final UserService userService;
    
      /**
       * Загрузить новое вложение
       *
       * @param file
       * @return
       * @throws IOException
       */
      @PostMapping(value = "/add", produces = "application/json")
      @ResponseBody
      public ResponseEntity<Map<String, String>> uploadAttachment(
          @RequestPart(value = "file") MultipartFile file)
          throws IOException {
        Attachment attachment = attachmentService.addAttachment(file);
        Map<String, String> attachmentStatus = new HashMap<>();
        attachmentStatus.put("status", "ok");
        attachmentStatus.put("attachId", attachment.getAttachId().toString());
        return ResponseEntity.ok(attachmentStatus);
      }
    
      /**
       * Получить ссылку на скачивание загруженного файла
       *
       * @param filename
       * @param request
       * @return
       * @throws IOException
       */
      @GetMapping("/get/{filename:.+}")
      public ResponseEntity<Resource> serveFile(
           @PathVariable String filename, HttpServletRequest request)
          throws IOException {
        Resource resource = attachmentService.loadFileAsResource(filename);
        String contentType;
        contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
        if (contentType == null) {
          contentType = "application/octet-stream";
        }
        return ResponseEntity.ok()
            .contentType(MediaType.parseMediaType(contentType))
            .header(
                HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + resource.getFilename() + "\"")
            .body(resource);
      }
    }
    Ответ написан
    4 комментария
  • По какому принципу Spring DataJPA обновляет записи в связанных таблицах?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую, коллега!
    Позволь, внести небольшую лепту в ваш код и отметить следующее:
    CrudCourseRepository

    Наверное, указывать Crud в названии не нужно, так как в репозиторий в будущем могут быть добавлены другие методы и соответственно, с точки зрения clean code название не будет корректным.

    Как JpaRepository производит обновление связей в таблице student_courses?

    Как говорится, лучше один раз увидеть, чем сто раз услышать. Так что лучше включить в properties
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.format_sql=true


    Предположу, что вы увидите примерно следующее:
    Запрос на SELECT (выборку) из двух таблиц вместе с JOIN, а далее запрос на вставку новой записи (INSERT)

    Насколько я понимаю, если я попытаюсь обновить сущность Student, передав в CrudStudentRepository#save() студента с пустым списком курсов, то в таблице student_courses будут удалены все записи, в которых фигурирует обновляемый студент, но по моему опыту этого не происходит. Как мне тогда удалять/обновлять эти записи?

    Тут пожалуй, вам стоит обратить внимание на CascadeType.

    Например, если в связи OneToMany вы постараетесь сохранить список со стороны самой сущности, то элементы списка будут сохранены, но id у них будет null, так как сама сущность еще не сохранена и ей не присвоен идентификатор. Чтобы избежать этого можно как вариант, указать CascadeType.All или PERSIST & MERGE

    В случае с ManyToMany, думаю, что будет корректным указать тип каскада. Например, CascadeType.PERSIST CascadeType.MERGE

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

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую, коллега!
    Да, Spring посложнее, чем Django. Но раз тебе удобно писать именно на нем, то конечно же стоит писать backend на нем.
    И да, если уж делать проект по-хорошему, то тебе нужен Spring Security. Тебе нужно создать роль ADMIN.
    Так как проект простой, то можешь использовать In-Memory Auth.
    Так как ты пишешь REST, то скорее всего тебе нужно будет реализовать jwt auth.
    Чтобы по умолчанию при старте приложения создать пользователя, можешь имплементировать интерфейс CommandLineRunner и в методе run() создать юзеров и сохранить в БД.

    P.S. БД необязательно.
    Ответ написан
    Комментировать
  • Java Spring MVC не видит представления, почему (Inteliji Idea)?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую, коллега!
    Я посмотрел ваш репозиторий и могу предположить следующие причины того, почему вам не удается использовать thymeleaf.
    1) У вас 2 модуля и оба модуля являются war. Соответственно, можно предположить, что вы запускаете первый модуль (firstapp), вместо второго (MVCFirstApp). А шаблонизатор thymeleaf у вас подключен во втором модуле.
    Таким образом вам нужно запустить второй модуль через Tomcat. А также рекомендую прочитать про модули maven, чтобы понять как они устроены и как работают. Например, в родительском pom.xml нужно указать packaging - pom, для модулей, которые являются библиотекой - jar, ну и для основного модуля, который содержит файлы запуска приложения - указать war или jar в зависимости от того, что вам нужно.

    2) Вторая причина того, почему вы не можете открыть страницу может заключаться в контроллере. Возможно, что вы пытаетесь открыть шаблон через базовый URL (/), а метод, для которого назначен шаблон - /hello-world
    Сниппет вашего кода?:
    @Controller
    @RequestMapping("/")
    public class HelloController {
    
        @GetMapping("/hello-world")
        public String sayHello() {
            return "hello_world";
        }
    }


    Таким образом, исходя из текущего проекта, вам достаточно запустить второй модуль через томкат и открыть урл /hello-world, чтобы открыть нужный шаблон
    Ответ написан
  • Как настроить WebSecurityConfig правильно?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую!
    1)
    Хочу сделать чтоб вход на страницы админа /adminPageProduct /adminPageUser

    наверное, лучше сделать общий префикс для админ панели, что-то типа /admin/** и на этом уровне ограничивать доступ, чем перечислять каждую ссылку в настройках конфигурации. А урл делать следующей структуры:/admin/products /admin/users. Вам же в любом случае нужно закрыть доступ ко всей админке

    Мне кажется, что проблема у вас может быть тут:
    .antMatchers("/admin*")
    Других явных проблем не вижу, если все остальное настроено корректно
    Ответ написан
    Комментировать
  • Как вынести конфиг из Spring приложения(внешний настраевыемый)?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Ответ легко находится поисковиком.
    Вот, полезная статья - https://www.baeldung.com/spring-properties-file-ou...

    Пути по которым Спринг по умолчанию ищет файлы конфигурации:
    A /config subdirectory of the current directory
        The current directory
        A classpath /config package
        The classpath root


    Вот, похожий вопрос на SO
    https://stackoverflow.com/questions/26744060/exclu...
    Ответ написан
    Комментировать
  • Почему-то BindingResult не ловит ошибку, как исправить?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    В первую очередь небольшая рекомендация - вместо того, чтобы из view напрямую получить объект User и сохранить его, создайте UserDto класс и далее получив данные из вью замаппите его в User().
    По поводу возможных ошибок валидации загляните по этой ссылке - https://stackoverflow.com/questions/42423553/sprin...
    Ответ написан
    Комментировать
  • Spring + JPA как заставить работать запросы?

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

    - Уточните какие именно библиотеки у вас подключены в pom.xml? В частности интересует библиотека spring data jpa
    - Уточните есть ли у вас в классе City геттеры, сеттеры и конструктор без аргументов? Если нет, то добавьте их.
    Если у вас подключен lombok, то можно прописать@Data @NoArgsConstructor
    - Далее подключитесь к вашей БД и просмотрите записи в БД. Возможно, что они не сохраняются в UTF-8, потому и не находится город по названию. Вместо данных в таблице увидите крякозябры. Если эта проблема наблюдается, то пропишите
    jdbc:mysql://localhost:3306/ticket_system?useUnicode=yes&characterEncoding=UTF-8

    - Также обратите внимание на то создается ли у вас таблица cities.
    Еще есть подозрение, что вы используете слово name, которое зарезервировано в mysql и из-за этого могут наблюдаться проблемы. Попробуйте экранировать его
    @Column(name = "`name`", length = 50,nullable = false)

    https://dev.mysql.com/doc/refman/8.0/en/keywords.html
    https://stackoverflow.com/questions/2224503/how-to...
    Ответ написан
  • Как получить данные со стороннего ресурса?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    Так как вы работаете со Spring, то посмотрите в сторону RestTemplate
    https://www.baeldung.com/rest-template
    Ответ написан
    Комментировать
  • Почему не создается бин jpaRepository?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Здравствуйте!
    Удалось ли вам решить проблему?
    Если нет, то поделюсь некоторыми мыслями, а вы уже продебажьте ваш код.
    Первый раз деплою. через идею все нормально отрабатывает, но при попытке задеплоить на vps выдает ошибку

    Если у вас локально отрабатывает корректно, а на VPS нет, то проверьте конфигурацию сервера. В вашем проекте на гитхаб application.yaml пустой и соответственно, непонятно что именно у вас прописано в конфигах для production. Если у вас есть профили, то проверьте установлен ли hibernate.ddl-auto: validate и если установлен, то импортировали ли вы ddl & dml на сервер. Или у вас он на production должен создать ddl сам?
    Как минимум, это первый момент на что стоит обратить внимание.

    Далее стоит уточнить деплоите ли вы приложение на внешний томкат или используете embedded?
    Далее попробуйте добавить такой класс в ваш проект:

    public class ServletInitializer extends SpringBootServletInitializer {
    
      @Override
      protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(App.class);
      }
    }


    Далее обратите внимание на то, как именно вы собираете build и что в него добавляете. Например, war exploded или war или jar. Есть ли все необходимые классы в нем и т.д.

    Если сборка происходит через Gradle, то используйте bootWar. В общем, нужно проводить дебаг и смотреть что не так
    Ответ написан