• Angular 2 + Spring хрошо ли все делать на REST контроллерах?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Собственно сам вопрос: ангуляру, как я вижу, совсем не нужны jsp на серверной стороне, ему нужно лишь подтягивать с сервера html для шаблонов, будет ли хорошей практикой в спрингах все делать через рест контроллеры возвращающие статичные html? А уже на них вешать секьюрити?


    Это будет очень плохая практика. Rest-контроллеры должны отдавать только ДАННЫЕ в удобном для клиента формате (JSON, XML, YAML и т.д.), иначе это уже не REST.
    И "вешать секьюрити" на статические ресурсы не имеет смысла. За исключением случаев, когда в этих ресурсах есть защищённые данные, но наличие таких данных в статичных ресурсах в принципе противоречит защищённости.

    Вопрос возник, так как до этого в моей практике все делалось на jsp, и не видел примеров рест контроллеров возвращающих html.


    А их и нет в природе, Rest-контроллер, возвращающий представление, уже по определению не REST.

    На мой взгляд HTML-представления нужно хранить отдельно и отдавать средствами сервлет-контейнера/веб-сервера. В идеале вся статика вообще должна находиться в другом проекте, так как набор REST-сервисов - это серверная сторона, а HTML-приложение - клиентская.
    Ответ написан
    Комментировать
  • 1064 error MySQL при попытке создать базу данных!?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    1064 говорит об использовании зарезервированных слов в качестве элементов БД или ошибке в структуре запросе. А так - SQL-запрос в студию.
    Ответ написан
    Комментировать
  • Лучшая книга для изучения Spring Framework?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Однозначно лучшая книга по Spring - официальная документация. Из книг: Spring in Action и Spring 4 Pro
    Ответ написан
    Комментировать
  • Как лучше организовать отложенные http-запросы?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Данная задача достаточно просто реализуется при помощи Apache Camel. Во всяком случае для меня.

    А вообще да, можно обойтись связкой cron+скрипт.
    Ответ написан
    Комментировать
  • Как использовать Spring HATEOAS (data rest) стороне клиента?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Допустим, у тебя есть ссылка на пользователя:
    http://localhost:8080/user/1

    Тогда ссылка на ассоциацию с филиалом будет:
    http://localhost:8080/user/1/filial

    И две ссылки на филиалы:
    http://localhost:8080/filial/1
    http://localhost:8080/filial/2


    Что бы изменить привязку пользователя к филиалу тебе нужно отправить PUT-запрос на адрес ассоциации пользователя и филиала с указанием ссылки на нужный филиал. Тип данных в запросе должен быть text/uri-list, как это указано здесь.

    Запрос будет примерно таким:
    curl -X PUT -H "Content-type: text/uri-list" http://localhost:8080/user/1/filial -d http://localhost:8080/filial/2
    Ответ написан
  • Как десериализовать объект полученный от Spring Data Rest сервиса?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Дык, в этом и есть смысл REST/HATEOAS - ты не получаешь связанный объект, а только ссылку на него. Т.е. после получения пользователя тебе нужно по ссылке из _links.filial получить филиал.
    Если такой подход не устраивает, то можно реализовать собственное поведение REST-сервиса.
    Ответ написан
  • Принимает ли язык AIML кириллицу?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Должен понимать, т.к. AIML - подмножество XML.
    Ответ написан
  • Как скопировать sheet из одной workbook в другую с помощью apache poi?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Вот здесь уже данная задача решалась. Насчёт альтернатив: они есть, но даже близко по возможностям и качеству к Apache POI нет ничего.
    Ответ написан
    Комментировать
  • Как правильно передать значение из формы INPUT в сервлет?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Причина такого поведения - использование enctype="multipart/form-data".
    Либо убирай enctype, т.к. в нём нет смысла здесь,
    либо на сервлет вешай аннтоацию @MultipartConfig,
    либо получай данные запроса через request.getPart()
    Ответ написан
    4 комментария
  • Spring data rest подводные камни? Применял ли кто в production решениях?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    В целом удобная штука, если не требуется реализация какой-то сложной бизнес-логики, то возможностей Spring Data REST вполне хватает. Плюс из коробки есть фильтрация, пейджинация и даже поддержка HATEOAS. Проблем в взаимодействии с фронтендом на Angular/Vaadin не наблюдал.
    Ответ написан
    3 комментария
  • Почему Tomcat отказывается запускать .war с кастомным репозиторием в зависимостях?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Смотри логи, смотри графы maven-зависимостей (возможно есть конфликт в зависимостях этого проекта и tokenizer), такая возможность есть в IDE.

    Ну и почисти pom.xml от лишних зависимостей. Раз уж ты используешь Spring Boot, то вместо прописывания всех Spring-зависимостей с нужной версией, достаточно прописать в свойства
    <spring.version>4.3.0.RELEASE</spring.version>
    И убери
    <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.0</version>
          <scope>provided</scope>
        </dependency>

    это всё есть у томката

    Зависимость spring-boot-starter-tomcat тоже не нужна.
    Ответ написан
    Комментировать
  • Как отобразить данные из бд на страничку jsp?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Быстрый пример с Spring Framework/Data/Boot

    Создаёшь новый Маven-проект, добавляешь зависимости и указываешь родительский артефакт:
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.5.RELEASE</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>


    Создаёшь класс-сущность, которая будет представлять собой отзыв:
    @Entity
    public class Review implements Serializable {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        @Column(columnDefinition = "TEXT")
        private String reviewText;
        
        @Temporal(javax.persistence.TemporalType.TIMESTAMP)
        private Date createDate;
    
        // get/set-методы и т.д.
    }


    Создаёшь репозиторий для работы с БД:
    @Repository
    public interface ReviewRepository extends CrudRepository<Review, Integer> {
    }


    Создаёшь контроллер с двумя действиями: отображение списка отзывов и добавление нового отзыва:
    @Controller
    public class SiteController {
    
        @Autowired
        private ReviewRepository reviewRepository;
    
        @RequestMapping
        public ModelAndView index() {
            return new ModelAndView("site/index", Collections.singletonMap("reviews", reviewRepository.findAll()));
        }
    
        @RequestMapping(method = RequestMethod.POST)
        public String createReview(@RequestParam String reviewText) {
            reviewRepository.save(new Review(reviewText, new Date()));
    
            return "redirect:/";
        }
    }


    Создаёшь свою JSP-страницу:
    <?xml version="1.0" encoding="UTF-8"?>
    <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" version="2.0">
    
        <jsp:directive.page contentType="text/html" pageEncoding="UTF-8"/>
        <jsp:output doctype-root-element="html" doctype-system="about:legacy-compat" omit-xml-declaration="true"/>
    
        <html>
            <head>
                <title>GuestBoot Example</title>
            </head>
            <body>
                <h1>Post new review</h1>
                <form method="POST">
                    <label>
                        <textarea name="reviewText" placeholder="Your review here"><jsp:text/></textarea>
                    </label>
                    <br/>
                    <button type="submit">Submit</button>
                </form>
                <hr/>
                <h1>Reviews</h1>
                <c:forEach items="${reviews}" var="review">
                    <div>
                        <c:out value="${review.reviewText}"/><br/>
                        <small><c:out value="${review.createDate}"/></small>
                    </div>
                    <br/>
                </c:forEach>
            </body>
        </html>
    </jsp:root>


    Добавляешь конфигурацию для отображения JSP-страниц:
    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            registry.jsp("/WEB-INF/views/", ".jspx");
        }
    
    }


    Создаёшь стартовый класс приложения:
    @SpringBootApplication
    public class GuestBook extends SpringBootServletInitializer {
    
        public static void main(String[] args) {
            SpringApplication.run(GuestBook.class, args)
                    .registerShutdownHook();
        }
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            return builder.sources(GuestBook.class);
        }
    }


    Запускаешь и наслаждаешься результатом.

    Смотришь репозиторий с рабочим кодом и читаешь документацию по Spring Framework и Spring Boot.
    Ответ написан
    Комментировать
  • Как можно фильтровать Entity без запроса в базу и без цикла?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Если нужно отфильтровать список записей, извлечённых из БД. то это можно сделать при помощи лямбд и StreamAPI. Что-то вроде:
    list.stream()
        .filter(entity -> "bar".equals(entity.getFoo()))
        .collect(Collectors.toList());


    А вообще фильтровать нужно в запросе к БД.
    Ответ написан
    Комментировать
  • Как настроить мапинг запросов на ресурсы web-приложения?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Всё правильно, так как адрес example/some.html попадает под оба правила.
    Правило /{version}/** в твоём случае перекрывает все варианты, так что самый простой способ избавиться от проблемы - сделать правило более строгим (например, /api/{version}/**).

    И да, в @RestController возвращать ModelAndView из методов, ИМХО, как-то некрасиво.

    UPD: методом тыка вышел на такой вариант:
    @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/**.html").addResourceLocations("/WEB-INF/");
        }


    Добавляешь это в SpringWebConfig, в результате чего все файлы, заканчивающиеся на .html будут искаться в /WEB-INF/. Из контроллера можешь убрать обработку .html-запросов
    Ответ написан
  • Как сделать веб страницу как в логах?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    То, что ты описал, теоретически реализуется при помощи постоянного соединения. Так же это можно реализовать при помощи веб-сокетов. Вопрос в практическом применении этого всего.
    Ответ написан
    Комментировать
  • Ошибка в jboss.logging?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Всё потому, что у тебя в зависимостях фигурируют и jboss-common и jboss-logging. Оба артефакта содержат класс org.jboss.logging.Logger, но с разными описаниями.

    И советую удалить лишние зависимости.
    Ответ написан
    Комментировать
  • Можно ли использовать one-nio?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Да, можно, лицензия же свободная - APL2.0. Jar - клонируешь и собираешь проект при помощи Maven. Дополнительная информация есть на вики-странице.
    Ответ написан
  • Установка Java 8 b SDK на Win 8.1?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Быстрый вариант - скопируй папку с установленным JDK с другого компьютера на этот.
    Ответ написан
    1 комментарий
  • Как узнать какой класс запущен из командной строки java?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Статические методы не наследуются, так что через рефлексию это не получить.
    Два варианта, пришедшие мне в голову:
    В классах Recv и Send описать свои методы main, которые просто вызывают Robot.main, тогда в Robot.main можно получить информацию о вызываемом классе из стектрейса:
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    stackTrace[stackTrace.length - 1].getClassName();


    Второй вариант - посмотреть системную переменную sun.java.command, которая указывает на класс, который был запущен.
    System.getProperty("sun.java.command");

    Вопрос только в практическом применении этого.
    Ответ написан
    1 комментарий
  • Как портировать java приложения под веб?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    NodeJS - это серверный JavaScript, не более того. Если приложение на 100% работает на мобильном девайсе, т.е. не имеет никакого бекенда, то переписывать с нуля. Если же бекенд есть, то тогда ситуация немного проще - нужно реализовать Rest-сервисы (если их нет) в бекенде и клиентское веб-приложение, которое будет этими сервисами пользоваться.
    Ответ написан
    Комментировать