Автор: Sebastian Daschner
Оригинал: https://blog.sebastian-daschner.com/entries/stop_saying_heavyweight (09 апреля 2016)
Перевод: Семён Солдатенко

При разработке корпоративных Java приложений приходится выбирать – использовать Java EE или какой-нибудь другой «легковесный» фреймворк. Но что делает корпоративный фреймворк легковесным?

Мы как разработчики в основном должны заботиться о процессе разработки. Наше время драгоценно (и дорого) и чем меньше времени мы потратим на накладные расходы, тем лучше.

Время сборки


Это время в основном складывается из времени на компиляцию, развертывание и тестирование приложения – локально или в специальном окружении. Чтобы время на полный круг было как можно короче, компиляция не должна тянуться больше чем несколько секунд. Да, секунд.

Использование Java EE имеет большое преимущество в том, что разработчик может положится на стандарт, который позволяет разрабатывать опираясь на API – в основном просто интерфейсы и аннотации – при том, что действительная реализация фреймворка не включается в приложение. Собственно зависимость Java EE «поставляется» сервером приложений, что означает, что она требуется только для компиляции, а не включается в пакет установки. У этого есть побочный эффект который состоит в том, что war-файл в основном остается пустым – он содержит только class файлы вашего приложения. А всё остальное должно быть предоставлено Java EE реализацией.

Пока вы будете оставаться тощим и минималистичным, что означает использовать только API Java EE (7), а не сторонние зависимости – если только в этом не возникнет действительная необходимость для ваших бизнес кейсов – вы можете добиться времени компиляции в пределах нескольких секунд. Основные причины медленной сборки либо в медленных (интеграционных) тестах, либо в больших пакетах установки, соответственно требующих много чего копировать.

Размер пакета установки


Типичный простой Java EE war файл имеет размер около нескольких сотен килобайт по сравнению с 50 и более мегабайтами если вы поставляете реализацию даже маленького (ну вы знаете, «легковесного») фреймворка с ним.

Если вы учтёте сервер приложений плюс ваше приложение тогда результат для случая Java EE окажется больше. Но: В целом процесс разработки будет быстрее, так как каждый раз при сборке создаются килобайты. Сервер приложений обычно уже установлен на вашей машине для разработки – или в любом другом окружении – и движущиеся части остаются небольшими. В результате получаем более короткое время сборки и развертывания как на машине разработчика так и на сервере Непрерывной Интеграции. А также: Когда вы размещаете ваши пакеты установки в централизованный репозиторий (Nexus или Maven central, и т. п.) вы также экономите и время, и трафик.

Время развертывания


Все современные Java EE 7 серверы приложений (такие как Wildfly, TomEE, Glassfish / Payara, WLP) демонстрируют очень короткое время на развертывание приложения. В рамках их модульной системы (такой как OSGi) они могут загружать только необходимые компоненты и запускать приложение в течении нескольких секунд.

Сравнивая с другим фреймворком (таким как Spring) работающим на Tomcat самое короткое время развертывания которое я когда либо замерял было как минимум 15 секунд – для простого «Hello World» приложения – при измерении на такой же машине.

Толстые JAR-ы / Интеграция с контейнером


В новом мире микросервисов принято поставлять приложения в виде самостоятельных jar содержащих как разработанное приложение так и реализацию фреймворка. В Java EE этого можно добиться используя технологии подобные Wildfly Swarm или TomEE Embedded.

Однако: Как я говорил выше, я не рекомендую делать ваши пакеты установки такими большими. Самая большая проблема с таким подходом – время сборки, так как вам каждый раз приходится много чего копировать из А в Б. А также: При развертывании с использованием контейнеров, таких как Docker, становится неважным поставляется ли ваше приложение вместе с сервером или сервер является частью контейнера.

В случае если контейнер уже включает установленный сервер приложений вы можете сэкономить много времени сборки (контейнера). В этом случае ваш базовый образ не меняется и вы только добавляете ваше (всего несколько-сот-килобайт-ное) приложение – что достигается почти без затрат времени.

Потребление памяти


Со времен старой J2EE существует миф о том, что «тяжеловесные» серверы приложений потребляют много памяти сразу как только стартуют. Adam Bien опубликовал интересное видео показывающее действительные накладные расходы памяти современных Java EE серверов приложений.

Заключение


С моей точки зрения одно из самых «легковесных» решений для корпоративных приложений следующее:
  • Java EE 7 и Java 8 с использованием только API которое предоставляется сервером
  • Небольшой war файл содержащий только бизнес-логику плюс минимальные конфигурации (такие как JAX-RS ресурсы или JPA)
  • Быстрые модульные тесты без тестовых фреймворков с внедренным контейнером (только простой JUnit)
  • Развертывание на основе контейнеров из базовых образов содержащих все необходимые компоненты, за исключением приложения
  • Процесс сборки опирающийся на Непрерывную Поставку который развертывает приложение в контейнеры, на каждый коммит
  • Автоматическое системное тестирование развернутого в контейнер приложения (чтобы подтвердить высокое качество приложения без необходимости интеграционного тестирования; при этом разработчики всё также будут получать быстрый отклик)

От переводчика:

  • Корпоративное приложение — Enterprise Application
  • Фреймворк — Framework
  • Пакет установки — Deployment artifact
  • Бизнес кейс — Business use case

Семён Солдатенко, CC-BY-NC-SA 4.0
перевод работы Stop saying “heavyweight”, Sebastian Daschner, CC BY-NC-SA 4.0
Поделиться с друзьями
-->

Комментарии (65)


  1. taulatin_one
    12.05.2016 01:23

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


  1. amaksr
    12.05.2016 04:34

    Думаю, что то время сборки и развертывания не являются сколько-нибудь критичными в Enterprise-среде: нет никакой разницы если сборка просходит за минуту или за несколько секунд, так как на думание над кодом разработчику надо потратить часы или дни. Так же не важно время развертывания, так как на согласования, тестирования, подписи и подготовку сопутствующей бюрократии (следование методологии ITIL, которую очень любят в больших компаниях) обычно тоже уходят дни.


    1. lpre
      12.05.2016 10:41
      +2

      Я думаю, смысл статьи не в том, чтобу указать на что-то важное/критичное, а показать бессмысленность термина «тяжеловесный» в применении к крайним версиям Java EE. Я согласен с автором в том, что, начиная с версии 6, Java EE более не является тяжеловесным.


    1. lair
      12.05.2016 10:54
      +3

      нет никакой разницы если сборка просходит за минуту или за несколько секунд, так как на думание над кодом разработчику надо потратить часы или дни.

      Есть разница, есть. Чем быстрее сборка, тем быстрее можно получить фидбек от написанного кода; и когда привыкаешь к TDD, короткие итерации кажутся более продуктивными (для меня, по крайней мере).


      Так же не важно время развертывания

      Аналогично, чем быстрее ваше развертывание, тем быстрее вы можете прогнать тесты против развернутого приложения.


      (это, заметим, никак не влияет на тезисы в самой статье, это конкретные наблюдения за влиянием скорости сборки/развертывания на процесс разработки)


      1. SamSol
        12.05.2016 14:52

        В самом конце автор оригинальной статьи упоминает «автоматическое системное тестирование развернутого в контейнер приложения». Как мне показалось, он его предлагает вместо интеграционного тестирования с локальным подъемом внедренного сервера приложений.


  1. j_wayne
    12.05.2016 07:42

    Я бы не сказал, что мегабайты Spring у меня как-то сильно замедляют именно сборку и деплой. Кешируются в .m2 и используются оттуда.


  1. kefirfromperm
    12.05.2016 08:24

    Весьма сомнительно, что именно копирование фрэймворков замедляет сборку. Gradle замедляет, кто бы что ни говорил, JS-фигня всякая замедляет, интеграционные тесты, но я от них не откажусь. И в случае с интеграционными тестами мы всё-равно подтянем все библиотеки сервера приложений. А если использовать SSD…


    1. guai
      13.05.2016 13:36
      -2

      Gradle, говорите, замедляет сборку?
      А я чота думал, что gradle ее осуществляет :)


      1. kefirfromperm
        13.05.2016 13:46
        -1

        Есть и другие системы сборки. А не говорю, что Gradle хуже или лучше, но совершенно точно что он самый медленный из всех.


        1. guai
          13.05.2016 15:09
          +1

          Совершенно неточно, я бы сказал. Имел с грэдлом ускорение при сборке тяжелого проекта в разы, относительно мэйвена.


          1. kefirfromperm
            13.05.2016 15:24
            +1

            Это ведь как готовить. У меня скорее противоположный опыт.


  1. asm0dey
    12.05.2016 09:52

    Я так скажу — со спрингом я добавляю только то что мне нужно, а сервер приложений поднимает кучу всего ещё. А ещё сервера приложений неудобно конфигурируются.


  1. fogone
    12.05.2016 11:52
    +6

    Время сборки.

    Пока вы будете оставаться тощим и минималистичным, что означает использовать только API Java EE (7), а не сторонние зависимости

    Во-первых, не использовать сторонние зависимости — это фактически утопия. Во-вторых, вы видели этот API? Из за бесконечных компромиссов в разработке этого стандарта удобство его использования по сравнению с тем же спрингом настолько назкое, что этот подход изначально упирается в необходимость использования крайне неудобного инструментария (может быть автор еще jsp для своих web-проектов использует?), что все доводы о мегобайтах и секундах, приведенные ниже, мгновенно блекнут на этом фоне.

    Да, время сборки у девелопера для запуска приложения действительно важно. Но будем честными, для локального запуска не нужно собирать артефакт — идея только подкомпилирует измененные классы и запускает ссылаясь на jar-ники из локального мавеновского репозитория.

    Размер пакета установки.
    В результате получаем более короткое время сборки и развертывания как на машине разработчика так и на сервере Непрерывной Интеграции.

    Не вижу причин для более быстрого развертывания у разработчика, про это выше писал. Из за размера действительно развертывание может занять больше времени, но насколько больше? Где замеры? Сравнения?

    А также: Когда вы размещаете ваши пакеты установки в централизованный репозиторий (Nexus или Maven central, и т. п.) вы также экономите и время, и трафик.

    Время — нет, вас что, кто-то заставляем сидеть и смотреть как в репозиторий что-то деплоится? Трафик — вообще смешно в наше время.

    Размер пакета установки
    В целом процесс разработки будет быстрее, так как каждый раз при сборке создаются килобайты.

    Выше уже написал, что для локальной сборки разницы никакой нет.
    Сервер приложений обычно уже установлен на вашей машине для разработки – или в любом другом окружении – и движущиеся части остаются небольшими.

    Но количество этих частей существенно возрастает. Наличие отдельно стоящего и требующего конфигурации сервера приложений — вот это и есть настоящий ад для разработчика.

    Толстые JAR-ы
    Самая большая проблема с таким подходом – время сборки, так как вам каждый раз приходится много чего копировать из А в Б.

    Похоже, автор вообще не в курсе, что не обязательно каждый раз что-то куда-то копировать. А один раз при деплое — не думаю, что это реальная проблема.

    Заключение
    Возможно, кому-то этот поход и подойдет, но лично я не вижу в нем реальных плюсов. Те немногие плюсы, которые нивелируются при появлении у приложения большего числа зависимостей, с лихвой компенсируются крайним неудобством самих инструментов из стандарта javaee. Так же не буду здесь расписывать, сколько сил было потрачено на борьбу с контейнером и с каким облегчением все вздохнули после перехода на спринг+embedded-tomcat.


    1. lpre
      12.05.2016 12:42

      с каким облегчением все вздохнули после перехода на спринг+embedded-tomcat.

      У нас тоже все в Java team вздохнули с облегчением после перехода на embedded TomEE :-)


  1. fogone
    12.05.2016 13:30
    +5

    Да, на счет «тяжеловесный». Наверное тяжеловесным я бы современный javaee не назвал. К нему больше подходит: монолитный, неповоротливый, неуклюжий — эти слова часто ассоциируются с тяжеловесностью, хотя и не являются его синонимами.


    1. lpre
      13.05.2016 00:42

      К нему больше подходит: монолитный, неповоротливый
      Это давно уже не так.

      Например, при желании вы можете использовать EJB, CDI, JPA, JAX-RS, JAX-WS, JMS, JAXB и т.д. как по отдельности, так и в практически любом сочетании, или в сочетании с любыми другими библиотеками/технологиями. Я уж не говорю о Servlets, JSP, JNDI, RMI, JAAS, JavaMail и др., о которых многие даже не подозревают, что это тоже части JEE.

      Так о какой монолитности может идти речь? Если некоторые реализации коммерческих серверов и страдают этим, то не потому что это JEE spec такой. Вы можете использовать почти все подсистемы JEE 6+ отдельно.


      1. fogone
        13.05.2016 09:16
        +1

        Монолитность jee заключается вовсе не в невозможности использовать отдельно технологии. А в самих технологиях. Например, jee не подразумевает, что может быть несколько разных контекстов запуска, для него приложение это всегда готовая пачка бинов, я уж не говорю, что поменять какое-то поведение контейнера невозможно, потому что jee не предусматривает никаких точек расширения — кушайте, что дают. Вот это я называю монолитом, а совсем не то, что вы подумали.


        1. lpre
          13.05.2016 10:15

          Возможно, я недостаточно хорошо знаю Java вообще и Spring в частности, но что вы имеете в виду?

          jee не подразумевает, что может быть несколько разных контекстов запуска, для него приложение это всегда готовая пачка бинов
          А что в этом «монолитного»? Любое приложение Java — всегда готовая пачка (jar, конфигов, EJB — чего угодно). Если нужно приложение с другим набором бинов — разверните его. Можно даже в тот же контейнер — вот вам и несколько параллельных контекстов.

          поменять какое-то поведение контейнера невозможно, потому что jee не предусматривает никаких точек расширения — кушайте, что дают.
          А разве у контейнера должно быть какое-то поведение? Скажем, какое поведение должно быть у Tomcat (минимальный контейнер; ну или TomEE, чтобы быть ближе к JEE)? И разве это не задача приложения, развернутого в контейнере, реализовывать нужное вам поведение? А контейнер просто предоставляет нужные вам API, многие из которых как раз и являются «точками расширения».


          1. fogone
            13.05.2016 10:41

            Любое приложение Java — всегда готовая пачка (jar, конфигов, EJB — чего угодно). Если нужно приложение с другим набором бинов — разверните его. Можно даже в тот же контейнер — вот вам и несколько параллельных контекстов.

            Я имею ввиду, что в jee все бины, что контейнер нашел, те и поднимает. Спринг же позволяет создавать контексты — т.е. разные наборы бинов. Это удобно как для тестирования, так и для возможностей переиспользования таких наборов. Позволяет решать об имплементации бина во время запуска и множество других необходимых вещей. Не делать же каждый новое приложение, для каждого параметра моего конфига, который меняет реализацию какого-то бина?
            А разве у контейнера должно быть какое-то поведение?

            Это вопрос философский, в идеале, конечно контейнер он как дух божий — ни на что не влияет, только реализует стандарт, однако реальность как всегда рушит все мечты — выходит, что реализация стандарта это тоже какой-то код со своей логикой, но стандарт монолитен, он видимо рассчитывает, что создатели стандарта предусмотрели любые необходимости его пользователей и не дают никакого механизма, чтобы каким-то образом поменять это поведение, кроме как выкинув реализацию целиком. Что я в итоге и сделал. Конечно, стандарт тоже развивается, но несравнимо медленней.


            1. lpre
              13.05.2016 11:27

              Спринг же позволяет создавать контексты — т.е. разные наборы бинов.
              CDI может тоже самое (например, через альтернативы).

              Спринг… Позволяет решать об имплементации бина во время запуска
              По-моему, CDI с этим тоже неплохо справляется, предоставляя продюсеры, альтернативы, селекторы, интерцепоры с декораторами и т.д.

              стандарт монолитен
              Философия — это понятно :-) Однако мне не понятен вопрос, что значит «монолитный стандарт JEE» и «немонолитный Spring» практически? Скажем, на примере JAX-RS или CDI и их аналогах из Spring. Учитывая, что есть opensource реализации всех компонентов JEE.


              1. fogone
                13.05.2016 13:14

                CDI может тоже самое (например, через альтернативы).

                Как через альтернативы создать набор бинов, который будет в зависимости от параметра подключать разные реализации, например, веб-контейнеров, а потом подключать такой пак в разные приложения (микросервисы, я даже не говорю о том, что в спринге это уже реализовано)? Или в зависимости от параметров запуска создавать дочерний контекст с сервисами для миграций, а потом удалять его? Или просто иметь несколько стартовых контекстов, которые переиспользуют общий набор специфичных контекстов вроде подключения к бд? В jee я не могу набрать нужную мне функциональность, подключив и настроив разные контексты — я об этом.

                Скажем, на примере JAX-RS или CDI и их аналогах из Spring.

                Ну, про cdi я выше пример привел, с jax-rs чуть лучше, но тем не менее, он подключается как большой комок, который можно затюнить разными провайдерами, в спринге же есть функциональные бины, реализации которых можно заменить. В этом сила подхода спринга — он весь как детский конструктор, который позволяет собирать из себя разные штуки просто стыкуя и настраивая готовые (или самописные) контексты, jee же это такой монолит, который позволяет тюнить себя в рамках заложенных стандартом.

                Еще раз хочу заметить, что вполне вероятно, что кому-то подход jee годится, но лично я отказался от негу в угоду удобству, простоте, богатству возможностей и постоянному развитию.


                1. lpre
                  13.05.2016 13:49
                  +1

                  Альтернативы как раз инициализуруются в зависимости от внешнего параметра (точнее — xml). Если вам xml не подходит, то нетрудно сделать продюсер, который будет принимать какие угодно параметры и возвращать нужную вам в данном приложении реализацию бина. Для пущей универсальности сам продюсер может искать имеющиеся в системе бины (т.е. развернутые) через итерабельный интерфейс javax.enterprise.inject.Instance<T> (как с квалификаторами, так и без них). Таким образом вы можете выбирать реализацию не только при стартапе, но и динамически в рантайме.

                  Насчет кубиков: вот пример разных наборов TomEE http://tomee.apache.org/comparison.html
                  Состав «кубиков» можно менять, удаляя/добавляя что нужно (с учетом зависимостей, конечно).

                  Возможно, это всё и не те гибкость и легковесность, которые есть в Spring, но тем не менее согласиться с мнением автора статьи (Прекратите повторять «тяжеловесный» в отношении современного JavaEE) можно.


                  1. Throwable
                    13.05.2016 15:22

                    > Альтернативы как раз инициализуруются в зависимости от внешнего параметра (точнее — xml).
                    Это хорошо. Только вот имена всех дескрипторов намертво зашиты стандартом и грузятся из classpath. Как Вы будете их менять от теста к тесту — непонятно.

                    > продюсер, который будет принимать какие угодно параметры и возвращать нужную вам в данном приложении реализацию бина
                    Т.е. при всем «богатстве» и «полезности» JEE API для элементарных и необходимых вещей уже приходится писать велосипеды.


                    1. lpre
                      13.05.2016 15:59

                      Как Вы будете их менять от теста к тесту — непонятно.
                      Да хотя бы ре-деплойментом и рестартом. Вы же сами сказали, что TomEE запускается очень быстро, так что особых проблем с этим нет.

                      Т.е. для элементарных и необходимых вещей уже приходится писать велосипеды.

                      Почему приходится? Этот юзкейс был назван fogone выше.

                      Насколько я знаю, у нас это решается именно что элементарно — надлежащим деплойментом. Например, если нужно, чтобы в определенном микросервисе была инициилизирована нужная реализация бина, то продеплойте (== просто скопируйте) именно эту реализацию в этот самый микросервис. JEE контейнер сам всё найдет, загрузит и инициилизирует, причем без всяких конфигов и параметров запуска. Проще уже просто некуда.

                      А «велосипеды» — это уже те самые «точки расширения», о якобы отсутствии которых говорил опять же fogone. Если нужно, то они используются (а разве в Spring нет таких самописных велосипедов — «точек расширения»? Вот fogone говорит, что есть), но чаще без них.


                      1. Throwable
                        13.05.2016 17:42
                        +2

                        В Spring-е и подобных фреймворках есть ApplicationContext, который определяет сборку компонентов вашего приложения. В JEE он на самом деле тоже присутствует. Но если в спринге контекст имеет явное представление ввиде xml-файла или java-configuration, то в JEE он неявный, и определяется исключительно тем, что лежит в classpath текущего деплоймента.

                        Поэтому если мне нужно оттестировать пару бинов из проекта, я не хочу деплоить все приложение со всеми UI, вебсервисами и т.д. В спринге я просто делаю новый контекст, который в котором указываю только то, что требуется, и говорю при запуске использовать этот контекст. Как уже сказал fogone выше, в JEE не предусмотрена такая возможность. Поэтому приходится исхитряться, чтобы динамически запаковывать лишь необходимые ресурсы. Один из способов — использовать Arquillian. Но это адъ и израиль.

                        > Да хотя бы ре-деплойментом и рестартом. Вы же сами сказали, что TomEE запускается очень быстро, так что особых проблем с этим нет
                        TomEE не решает проблему с фильтрацией. Он задеплоит сразу все, что найдет в проекте. Нельзя сказать, что хочу только эту пару бинов. Фильтеринг ресурсов classpath — это как раз тот велосипед, который пришлось дописывать для TomEE.

                        > а разве в Spring нет таких самописных велосипедов — «точек расширения»
                        Если ваша задача требует специальных решений, то, конечно, приходится решать. Но спринг хорош тем, что для широкого круга повседневных задач у него уже есть простое решение. Например, в документации есть целый раздел «Testing». Ни одна спецификация JEE, ни один сервер апликаций даже вскользь не касаются этой важной и неотъемлимой темы! Естественно, те, кто пишут спецификации, ничего сложнее хелловорлда (и этой статьи) никогда не писали.


                        1. lpre
                          13.05.2016 21:30

                          Поэтому если мне нужно оттестировать пару бинов из проекта, я не хочу деплоить все приложение со всеми UI, вебсервисами и т.д. В спринге я просто делаю новый контекст, который в котором указываю только то, что требуется, и говорю при запуске использовать этот контекст. Как уже сказал fogone выше, в JEE не предусмотрена такая возможность.
                          В стандарте не предусмотрена, потому что это решается внешними средствами.

                          Если ваша пара бинов может работать в ограниченном окружении, то зачем деплоить все UI, вебсервисы, и т.д. в JEE контейнер? Продеплойте только эту пару бинов (+ то, от чего они зависят).

                          Или еще проще: настройте свою IDE так, чтобы она имела различные профайлы запуска проекта с разными classpath. Для полного теста укажите всё что есть, для теста пары бинов укажите только их самих и их зависимости.

                          Т.е. вся разница между JEE и Spring только в способе нестройки контекстов.

                          А если ваши бины — это просто managed beans, а не EJB и не зависят от них, то вы вообще можете их тестировать без JEE контейнера, так как CDI работает и с JavaSE. Настраивайте ApplicationContext как вам удобно, и запускайте хоть из main().

                          TomEE не решает проблему с фильтрацией. Он задеплоит сразу все, что найдет в проекте. Нельзя сказать, что хочу только эту пару бинов.
                          Для продакшена это не важно, для разработки настройте вашу IDE — и проблема решена.

                          Ни одна спецификация JEE, ни один сервер апликаций даже вскользь не касаются этой важной и неотъемлимой темы!
                          В JEE спецификации этого и не может быть. Потому что вся спецификация основана на интерфейсах.

                          А вот в докумтации к конкретным реализациям такая информация есть. У того же TomEE, например (хотя там документация и не очень обширна).

                          Кроме того, отдельные компоненты JEE могут тестируются как обычные Java SE приложения — тот же CDI, например. Поэтому к ним применым весь стандартный набор тестирования.


                          1. fogone
                            14.05.2016 00:21

                            Продеплойте только эту пару бинов

                            Когда вы пишете «продеплойте», вы что-то конкретное имеете ввиду? Мне остальные бины каким-то хитрым образом нужно выпилить из класспаса?
                            Или еще проще: настройте свою IDE так, чтобы она имела различные профайлы запуска проекта с разными classpath.

                            Это серьезное предложение или вы шутите? Может быть вы знаете хорошие способы это сделать? Настолько же простые как написать аннотацию на классе?

                            Для продакшена это не важно, для разработки настройте вашу IDE — и проблема решена.

                            А если для продакшена надо? Что если контексты у меня выбираются в рантайме? (к слову, в spring boot-е именно так и происходит, но если даже не брать его в рассчет, выше я приводил пример, когда есть несколько стартовых контекстов, которые подключают общие контексты — этот пример взят из вполне реального приложения)

                            Не кажется ли вам, что переваливие ответственности за создание контекстов на ide сродни перекладыванию с больной головы на здоровую? По меньшей мере, вы согласитесь, что определения контекста в jee сделано не очень удобно? И такой его подход можно было бы назвать если не монолитным, то неповоротливым и неуклюжим?


                            1. lpre
                              14.05.2016 01:39

                              Когда вы пишете «продеплойте», вы что-то конкретное имеете ввиду? Мне остальные бины каким-то хитрым образом нужно выпилить из класспаса?
                              Почему же хитрым? Ствандартным. Просто не деплойте то, что вам не нужно, в локальную копию контейнера, и они автоматически исчезнут из classpath.

                              Но проще настроить IDE стандартными средствами (см. ниже). Тогда локальный деплоймент вообще не нужен.

                              Может быть вы знаете хорошие способы это сделать? Настолько же простые как написать аннотацию на классе?
                              В Eclipse есть диалоги «Run Configurations» и «Debug Configurations». Там вы можете просто сконфигурировать запуск приложения, точно настроив его classpath. В этом действительно нет ничего сложного.

                              Предполагаю, другие IDE имеют схожие средства.

                              А если для продакшена надо? Что если контексты у меня выбираются в рантайме?
                              Да пожалуйста! Используйте продюсер или javax.enterprise.inject.Instance<T> для выбора бинов в рантайме. Можно спорить об удобстве этих средств, но то, что такая возможность есть, по-моему, неоспоримо.

                              Не кажется ли вам, что переваливие ответственности за создание контекстов на ide сродни перекладыванию с больной головы на здоровую?
                              Нет, не кажется. Это используется для тестов во время разработки. Именно для этого IDE и созданы, так что в данном случае IDE используется по прямому назначению. Наоборот, не использовать имеющиеся возможности среды разработки (IDE) для разработки кажется мне странным.

                              По меньшей мере, вы согласитесь, что определения контекста в jee сделано не очень удобно? И такой его подход можно было бы назвать если не монолитным, то неповоротливым и неуклюжим?
                              Опять же: нет, не соглашусь. Автоматическая инициализация контекста и связывание любых бинов (как простых managed так и EJB) в JEE представляется мне очень удобным и полезным свойством.

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

                              В девелопменте вы можете либо делать то же самое, либо сделать несколько профайлов для запуска одного приложения с разными classpsth. Опять же просто, удобно и гибко.

                              А то, что всё это бесшовно работает через границы разных компонентов JEE независимо от того, как вы скомпоновали свой контейнер (см. разные варианты TomEE для примера) — ещё один большой плюс.

                              Так что на мой взгляд нет никаких основание говорить о монолитности и неповоротливости JEE 6+.


                              1. fogone
                                14.05.2016 10:00

                                Но проще настроить IDE стандартными средствами

                                Вероятно, это действительно проще, чем делать что-то, чего вы не можете объяснить.
                                В Eclipse есть диалоги «Run Configurations» и «Debug Configurations».

                                Заметьте, я не спрашивал, где в ide это сделать, а я спросил, как это сделать хорошо и просто — на этот вопрос вы тоже ответа не дали.
                                … для выбора бинов в рантайме...

                                Но я говорю не о выборе бинов в рантайме, а о выборе конфигураций, готовом наборе связанных бинов, которые реализуют какую-то функциональность. Так же крайне удобным является возможность этот контекст немного подправить для своих нужд без необходимости менять базовую реализацию. С возможностью выбрать конкретную реализацию я не спорю, но наша беседе сейчас в русле контекстов.
                                Это используется для тестов во время разработки.

                                То есть, вы искренне считаете, что главное, чтобы инструмент (в нашем случае javaee) в продакшене работал, а насколько его удобно использовать разработчикам — это значения не имеет?
                                Автоматическая инициализация контекста и связывание любых бинов...

                                Я никогда не говорил, что такой подход не имеет право на жизнь — у спринга, наприимер, тоже есть режим создания контекста сканом класспаса — я думаю только, что иметь исключительно такую возможность — это накладывает чрезмерно много ограничений на разработчика и создает ему много лишних проблем.


                                1. lpre
                                  14.05.2016 11:48
                                  -1

                                  чем делать что-то, чего вы не можете объяснить
                                  Я вам объяснил, но вы похоже не желаете понимаете. Объясню еще раз подробнее: у вас есть локальная копия контейнера (e.g. TomEE), в которую вы можете деплоить свои проекты локальным же скриптом (Ant, Gradle или что-то еще — на ваш выбор) прямо из IDE. Скрипт поддерживает несколько профайлов для развертывания разных наборов ресурсов (бинов, конфигов, и т.д.) из ваших проектов. При этом скрипт делает синхронизацию. Т.е. он автоматически удаляет ресурсы не входящие в текущий выбранный профайл и добавляет ранее отсутствующие ресурсы (например, удаленные в прошлый раз). Удаленные бины при запуске контейнера не входят в его classpath. Скрипт довольно простой и его написание не составляет большого труда. Разумеется, это также может быть не один скрипт, а набор скриптов с разделяемыми функциями.

                                  Заметьте, я не спрашивал, где в ide это сделать, а я спросил, как это сделать хорошо и просто — на этот вопрос вы тоже ответа не дали.
                                  Именно это я вам ответил, но вы опять не хотите понимать. Опять объясню подробнее: в Eclipse есть указанные диалоги для настройки окружения для запуска проектов. При этом вы можете создать сколько угодно профайлов запуска с разными параметрами для одного и того же проекта. Например, вы можете по-разному настроить classpath, добавляя или исключая ресурсы из текущего проекта, параллельных проектов, или внешние ресурсы. Затем вы просто запускаете проект с нужным вам профайлом, выбирая его из меню или тулбара. Ресурсы (бины), не включенные в classpath выбранного профайла, не будут доступны в запущенном приложении.

                                  Чтобы было понятнее: именно это и есть хороший и простой способ настройки в IDE различных профайлов запуска проекта с разными classpath.

                                  Но я говорю не о выборе бинов в рантайме, а о выборе конфигураций, готовом наборе связанных бинов, которые реализуют какую-то функциональность.
                                  Это одно и то же. Поясню: например, у вас есть несколько алтернативных бинов, каждый их которых содержит injection points (которые, в свою очередь, могут содержать inhection points etc.) Т.е. каждый из бинов может представлять собой не просто один обособленный альтернативный бин, а готовый набор автоматически связанных бинов, которые реализуют какую-то функциональность (т.е. именно то, о чем вы говорите). Если у вас есть возможность выбрать один из этих «головных» альтернативных бинов в рантайме (а с тем, что JEE предоставляет такую возможность вы уже согласились), то это озночает, что на самом деле вы выбрали готовый набор связянных бинов с нужной вам функциональностью.

                                  То есть, вы искренне считаете, что главное, чтобы инструмент (в нашем случае javaee) в продакшене работал, а насколько его удобно использовать разработчикам — это значения не имеет?
                                  С чего вы так решили? Наоборот, я считаю, что нужно использовать удобные инструменты предоставляемые IDE. Например, создание разных профайлов запуска. Вы же считаете, что это перекладывание с больной головы на здоровую. Так?

                                  Но то, что инструмент (Java EE) прекрасно работает в продакшене, тоже очень немаловажно ;-)

                                  иметь исключительно такую возможность — это накладывает чрезмерно много ограничений на разработчика и создает ему много лишних проблем
                                  Во-первых, JavaEE предоставляет также и возможность выбора в рантайме (см. выше).

                                  Во-вторых, я считаю, что дефолтный способ JavaEE очень удобен для большинства юзкейсов. Таким образом вы можете управлять внедрением на большом количестве серверов и сервисов всего-лишь надлежащим деплойментом в каждый из них.


                                  1. fogone
                                    14.05.2016 13:04
                                    +2

                                    Т.е. он автоматически удаляет ресурсы не входящие в текущий выбранный профайл...

                                    Хорошо. Значит, у нас где-то должно быть описание того, что входит, а что нет в эти профили, логично? Скажем, следуя логике jee, мы просто пометим бины аннотациями компайл-тайма (или напишем в xml) какой бин в какие профили входит. Теперь мы пишем велосипед в виде плагина для системы сборки, которая смотрит и вкидывает (или включает, правила могут быть не простыми) бины по какому-то переданному ему параметру. Таким образом мы получили то, что нам надо. В итоге мы написали велосипед, который для сложных случаев будет не такой уж простой, а запуск из ide теперь усложнился из за дополнительных зависимостей в процессе сборки. Теперь смотрим на Спринг — он всё это делает из коробки, при этом не требует никаких дополнительных телодвижений в момент сборки. Разве не это называется «сложностью» и «простотой»?

                                    вы можете по-разному настроить classpath

                                    Правильно ли я понимаю, что вы предлагаете вручную указывать список классов прямо в конфигурации запуска? И при этом не считаете, что это усложняет жизнь разработчику, а является «правильным» способом применением ide?


                                    1. lpre
                                      14.05.2016 13:51

                                      1. Совсем недавно вы говорили что с JEE этого вообще нельзя сделать, так как он «грузит все что найдет и протестировать только пару бинов нельзя». Теперь же вы сменили тему, и говорите уже о том что «мы получили то, что нам надо», но это сложно и неудобно. Насчет имеющихся возможностей вопросов больше нет?

                                      Спор перешел из фазы обсуждение принципиальной (не)возможности в фазу (не)удобства. Это уже другая, очень субъективная тема, обсуждать которую я не собирался.

                                      К тому же я уже говорил: проще насторить IDE (см. ниже).

                                      2. В Eclipse самый низкий уровень это список директорий с ресурсами (как из проектов, так и внешние), но можно целые (суб)проекты, или готовые пакеты, и т.д. Или все в любой комбинации. Почитайте доки на свою IDE.

                                      Если IDE предоставляет какую-либо возможность «из коробки», и документация содержит подробное описание как её использовать, то использование этой возможности является «правильным» способом использования IDE. Если вы не согласны, то предложите для начала свое определение «правильного способа использование IDE».

                                      Насчет усложнения жизни: это делается 1 (один) раз для каждого профайла, при этом создание самого профайла занимает от 20 секунд до нескольких минут, и он может сохраняться в репозитории для доступности всем участникам проекта. Весь процесс хорошо документирован в мануалах IDE. Я не считаю это каким-либо усложнением жизни разработчика.

                                      Кстати, а подготовка «нового контекста, в котором указывается только то, что требуется, и используется при запуске» (как предлагал Throwable и что является альтернативой создания профайлов запуска в IDE) разве совсем не требует никакой ручной работы со стороны программиста и не усложняет ему жизнь в той же самой степени, что и подготовка профайлов в IDE? Если же программст в Spring тоже «вынужден» всё это готовить, то к чему ваш пассаж об усложнении жизни программиста JavaEE?

                                      Но опять же, это уже другая тема (не)удобства, которую можно безрезультатно «обсуждать» до бесконечности. Насчет принциальных возможностей вопросов больше нет?


                                      1. fogone
                                        14.05.2016 21:46

                                        Совсем недавно вы говорил и что с JEE этого вообще нельзя сделать

                                        Пожалуй, в нашей отрасли сказать «нельзя» почти никогда нельзя, ведь если продукт, например, опенсорс его можно взять и допилить как тебе надо — и окажется, что уже то, что было нельзя, теперь можно. Вопрос всегда в цене. Так и здесь — когда я говорил «нельзя», я имел ввиду какие-то разумные трудозатраты. То, что вы предлагае те как решение — лично для меня неприемлемо. И для своей команды я бы такое никогда не выбрал и не одобрил, да и не согласился бы работать в команде, где бы такое пытались внедрить. Уверен, что вам оно подходит, раз вы так его защищаете — как и любой инструмент.

                                        Спор перешел из фазы обсуждение принципиальной (не)возможности в фазу (не)удобства.

                                        Обсуждение изначально было о «монолитный, неповоротливый, неуклюжий». Это всё слова оценочного толка, это не точное значение, а скорее некоторое ощущение — и как любое ощущение субъективно, многие ощущают работу с javaee подобным образом. А наш разговор, по моему ощущению, выглядит примерно так:
                                        — Этот камень слишком неповоротливый
                                        — Этот камень не неповоротливый, я такие уже двигал динамитом
                                        — Мне бы только дверку подпереть

                                        … разве совсем не требует никакой ручной работы...

                                        Конечно требует, но тут дело в том, что один раз сделав конфигурацию контекста её можно просто реюзить, в то время как любойпрофиль по вашему рецепту мало того, что потребует перечисления всех бинов и всех зависимых классов вручную (видимо), но еще и копипастить эти списки даже если профили отличаются на один бин. Дело в том, что класлоадер хоть и решает в какой-то мере эту задачу, но делался для загрузки класов. Специальные средства в виде конфигураций контекста намного мощнее и удобнее просто потому, что они специально делались для того, чтобы настраивать контекст приложения. Для ide всё же обычный случай — это когда классы проекта загружаются все — избирательная загрузка классов проекта это скорее экзотика. Еще несколько проблем с настройкой профалов в ide 1) их нужно поддерживать в консистентном состоянии, т.е. добавляя какой-то класс, нужно понять, в какие профили его добавить даже если это не бин 2) обычно настройки ide не хранятся вместе с проектом в репозитории, а если храняться, то всё нужно для разных ide их хранить.


                                        1. lpre
                                          15.05.2016 09:39

                                          Дело в том, что класлоадер хоть и решает в какой-то мере эту задачу, но делался для загрузки класов.
                                          … а управление загрузкой классов через classpath полностью (а вовсе не «в какой-то мере») решает поставленную задачу в среде с автоматическим конфигурированием бинов.

                                          Специальные средства в виде конфигураций контекста намного мощнее и удобнее просто потому, что они специально делались для того, чтобы настраивать контекст приложения.

                                          Профайлы IDE тоже специально созданы для того, чтобы настраивать окружение приложения при его запуске. Копипастить ничего не нужно: просто открыть существующий, подправить и сохранить под другим именем. Использование таких профайлов — не экзотика. В противном случае вы вряд ли нашли бы их в IDE.

                                          Кстати, в Eclipse это не только не экзотика, но вообще стандартный способ запуска/отладки приложения: когда вы запускаете приложение в первый раз, IDE автомтически создает профайл с параметрами по умолчанию. Вы можете его подправить (как с клонированием так и без) по потребностям.


                                          1. fogone
                                            15.05.2016 10:01
                                            +1

                                            Копипастить ничего не нужно: просто открыть существующий, подправить и сохранить под другим именем.

                                            Это и называется копипастить, ведь после этого телодвижения у вас создается копия, которую тоже нужно править, если у вас добавился хоть один класс.
                                            IDE автомтически создает профайл с параметрами по умолчанию

                                            С этим сложно спорить, только я писал о том, что экзотика — это прописывать отдельные классы проекта в класспас, а не профили запуска создавать.


                                            1. lpre
                                              15.05.2016 14:26
                                              -2

                                              Ну, это всё уже терминология/вкусы/привычки/сложившиеся практики. С этим действительно спорить.


                                    1. lpre
                                      14.05.2016 14:03

                                      В итоге мы написали велосипед

                                      Кстати, описанный вами процесс (с аннотациями, плагинами, и т.д.) принципиально возможен, но действительно излишне сложен. Я же имел в виду решение без всяких аннотаций и плагинов. В простейшем случае вы просто используете разные списки ресурсов, которые будут включены в build и деплоймент. Скрипт возьмет только их и зависимости.


                                      1. fogone
                                        14.05.2016 21:53

                                        Ирония. В проекте где мне довелось работать с javaee мы решили вопрос тестирования приложения через спринг. А потом перевели и основной код.


                          1. Throwable
                            16.05.2016 11:14
                            +3

                            В стандарте не предусмотрена, потому что это решается внешними средствами.

                            В стардарте много чего не предусмотрено, что необходимо для повседневной разработки. Негласное делегирование этого "внешним средствам" делает этот стандарт неюзабельным и бесполезным.


                            В JEE спецификации этого и не может быть. Потому что вся спецификация основана на интерфейсах.

                            В спецификации это обязано_быть — средства тестирования приложения. Просто когда стандарт разрабатывался, автоматическая сборка и unit-тестирование еще не вошло в мейнстрим, а в моде было визуальное программирование. Поэтому решили, что все о чем нам лень думать, будут делать умные тулзы. С тех времен идеология программирования сильно поменялась, тулзы умными не стали, а стандарт остался.


                            У того же TomEE, например (хотя там документация и не очень обширна).

                            Ну вот Вы все TomEE ставите в пример, потому что он изначально задумывался для тестирования. Даже девиз одного из создателей: "Don't blame EJB if your sever is not testable." То есть они изначально осозновали проблему, и делали специальное решение. То же самое и с JBoss: они продвигают свой Arquillian, который программно пакует, деплоит и тестирует приложение. Ну взгляните чтоли для разнообразия на Weblogic или на Websphere. Там дела обстоят просто ужасно. Они предлагают всем писать скрипты Ant для сборки и деплоя. А тестировать вообще ручками.


                            Для продакшена это не важно, для разработки настройте вашу IDE — и проблема решена.

                            Для автопрогона тестов на сервере continuous integration тоже запускать и настраивать IDE? Или посадить специального человека, который вручную бы прокликивал все тесты после каждого коммита? Или продублировать отдельно еще раз все тесты в каком-нибудь скрипте?


                            Это изначально плохая идея, т.к. вы добавляете в проект еще одну зависимость — IDE. Они со временем меняются, не гарантируя 100% обратной совместимости. Возможна ситуация, когда через пару лет Вы не сможете собрать проект (или запустить тесты), т.к. новая IDE не совместима, а старая просто не запускается на новой ОС.


                            Тесты — это не нечто мое личное и временно существующее, пока я отлаживаю код. Это такая же неотъемлимая часть проекта, как сам код и документация. И они также должны быть закоммичены в кодовую базу, и каждый в проекте должен иметь возможность запустить каждый тест. В TDD вообще вся логика описывается в тестах, а не в коде. Поэтому если у меня в проекте 700 тестов, я что, должен создават и поддерживать 700 конфигураций запуска к конкретной IDE? Или перед каждым тестом писать в комментариях: "для запуска этого теста сделайте такие-то пассы руками"? А смысл этих 700 тестов не в том, чтобы что-то однажды отладить, а в том, чтобы убедиться, что очередное изменение не затронуло уже имеющуюся логику. И запускаться все оно должно автоматически при каждой сборке.


                            1. lpre
                              16.05.2016 12:14

                              Негласное делегирование этого «внешним средствам» делает этот стандарт неюзабельным и бесполезным.
                              Можно и по доугому сказать: оставляет право выбора за авторами реализаций. (ведь стандарт JEE — это не реализация). Одни делают это лучше, другие — хуже. См. ваши же примеры с TomEE и др.

                              В спецификации это обязано_быть — средства тестирования приложения.
                              Нет, не обязано. См. выше.

                              Ну вот Вы все TomEE ставите в пример, потому что он изначально задумывался для тестирования. Даже девиз одного из создателей: «Don't blame EJB if your sever is not testable.» То есть они изначально осозновали проблему, и делали специальное решение.
                              Да. Именно об этом я и говорю (см. выше).

                              Для автопрогона тестов на сервере continuous integration тоже запускать и настраивать IDE?… Это изначально плохая идея, т.к. вы добавляете в проект еще одну зависимость — IDE.
                              Вариант с IDE приводился в качестве примера для тестов во время разработки, когда вам нужно быстро протеситровать «вот эту пару бинов». Это хорошо работает.

                              Для тестов на сервере мы используем набор конфигураций с альтернативами. Тоже работает хорошо. Во всяком случае, наши потребности это покрывает полностью.

                              Тесты — это не нечто мое личное и временно существующее, пока я отлаживаю код. Это такая же неотъемлимая часть проекта, как сам код и документация. И они также должны быть закоммичены в кодовую базу, и каждый в проекте должен иметь возможность запустить каждый тест. Поэтому если у меня в проекте 700 тестов, я что, должен создават и поддерживать 700 конфигураций запуска к конкретной IDE?
                              Мы в курсе этого ;-)
                              Как уже сказано, мы выполняем свои тесты на сервере при помощи альтернативных конфигураций бинов. Подозреваю, что скофигурировать нужные варианты конфигураций в JEE не сложнее, чем скофигурировать нужные варианты контекстов в Spring. Учтите, что нет нужды конфигурировать альтернативы для всех бинов; достаточно сделать это для «головных», что намного (на порядок) сокращает объем альтернативных конфигураций.


  1. realcnbs
    12.05.2016 17:05
    +1

    Это всё прекрасно пока не сталкиваешься с настройкой того же wildfly, и попытками выпилить всю ненужную муть из него. После пары недель мучений я просто взял и переписал всё на спринг + jetty, не пожалел ни разу. Под «тяжёловесностью» всё таки, мне кажется, подразумевают именно необходимость возиться с ненужными «enterprise» фичами, а не мегабайты.
    К тому же, когда имплементация всех зависимостей включена в сборку разработчик очень легко может посмотреть внутрь, как оно там всё работает прямо из IDE, что лично мне пригодилось не раз. В случае с javaee же, надо рыскать в нете в поисках исходников конкретной библиотеки конкретной версии, которая входит в поставку конкретного сервера, а поди сначала узнай те версии. Вопщем гемор ещё тот.


  1. xakep2011
    12.05.2016 18:20

    интересно, как часто перевод можно определить уже по заголовку


    1. SamSol
      12.05.2016 18:25

      У меня отображается пометка «перевод» в заголовке. А в RSS пометка [Перевод] в начале Subject.


  1. Throwable
    12.05.2016 19:33
    +3

    Меня уже изрядно подзадолбали различные евангелисты JEE. Автор — очередной демагог, рьяно защищающий собственную святую веру.

    > компиляцию, развертывание и тестирование приложения – локально или в специальном окружении

    Давайте расставим точки над i. Вот те грабли, о которых так искусно умолчал автор:

    — Начинается все с установки и конфигурирования сервера апликаций на каждой тачке разработчика. Повляется серьезная лишняя зависимость в проекте.

    — Для развертки приложения требуется настройка окружения контейнера и ресурсов: JMS, JDBC, etc… Опять появляются сторонние зависимости. Простые конфиги Spring-а оборачиваются в мануали на 10 страниц со скниншотами для ручного конфигурирования сервера и настройки ресурсов. Особо продвинутые пишут скрипты, но они постоянно отваливаются.

    — Далее необходимо запустить сторонний контейнер. Желательно в дебагмоде. Если тулинг (+плагины) не позволяет, начинаются танцы с бубном (запуск через порт).

    — Для запуска каждого теста необходимо подготовить специальную сборку, заряженную моками и зависимостями. В JEE все заточено на classpath, поэтому менять на лету контексты как в Spring не получится. Приходиться создавать кучу дескрипторов и извращаться с Maven-ом, либо юзать Arquillian.

    — Сама сборка пакета (со всеми зависимостями). Медленная и рудиментарная операция. Либо мавен с профайлами, либо Arquillian, который использует этот мавен. Автор лукавит, что приложение будет в 100К. Если это не банальный хелловорлд, оно будет тащить с собой десятки мегабайт зависимостей.

    — Развертывание. Опять рудиментарная и тяжелая операция. Плюс танцы с бубном в попытке автоматизировать оное (Arquillian, etc...)

    — Теперь сами тесты. Пускайте как хотите: через remote beans, webservices, etc… JUnit тут вам не помощник. Немного спасает Arquillian. Отдельно спасибо проекту OpenEJB, который может пускать embedded сервер, программно конфигурировать ресурсы и пускать тесты.

    — Запуск и развертка приложения не такая быстрая, как пишет автор. Кроме того, клиент все усугубляет коммерческими решениями как Websphere и Weblogic. Разрабатывать под них тяжко. Использовать более легкий сервер для разработки накладно дополнительными проблемами совместимости: стандарт стандартом, а интерпретация оного у каждого своя. Плюс вендорлок везде, где только возможно.

    Любой шаг с JEE связан с нереальным и совершенно ненужным геморроем, ибо JEE следует изначально неверному дизайну и модели разработки. Все вышесказанное можно избежать натуральным образом, попросту отказавшись от JEE.

    > Если вы учтёте сервер приложений плюс ваше приложение тогда результат для случая Java EE окажется больше
    Типичный демагогичный высер когда уже не хватает аргументов. Если Вы скопируете заранее все библиотеки и зависимости в удаленную папку, то будете деплоить только jar с логикой вашего приложения. Кроме того, при неободимости можно добиться бОльшей модульности и делать дифференциальный деплой.

    Так что если можете, не используйте никогда JEE. Если ваша программа не пускается при помощи public static void main(String[] args) и требует каких-то внешних зависимостей и танцев в бубном, то это не программа, а кусок гиковского дерьма.


    1. lpre
      13.05.2016 00:15

      Я тут уже упоминал TomEE. С ним вы можете использовать JEE Web Profile с простотой обычного Tomcat.


      1. Throwable
        13.05.2016 12:14

        На самом деле проект называется OpenEJB, а TomEE — это их сервер — openEJB, заряженный томкэтом. Фактически — это единственный embeddable, configurable & testable JEE container. Благодаря ему можно хоть как-то мало-мальски разрабатывать на JEE.
        Плюсы:
        — Запускается embedded (причем очень быстро)
        — Автоматически подцепляет и деплоит приложение и ресурсы из classpath проекта. Не надо ничего собирать, паковать и развертывать.
        — Возможность программного конфигурирования ресурсов и дескрипторов (тот еще гемор, когда для тестового бенча одни дескрипторы, а для продакшна другие)
        — Доступен из maven repository — не надо ничего устанавливать, прописываешь dependencies — и готово.
        — Заточен под тестирование, интегрирован с JUnit, возможность «виртуальной» сборки приложения с ApplicationComposer.
        — На сайте есть куча примеров использования.

        Минусы:
        — Отсутствует полная документация. Полезные вещи приходится гуглить или искать в коде. Например, очень удобный для тестирования ApplicationComposer выискивается где-то в блогах.
        — Стабильная ветка поддерживает профайл JEE6. Семерка до сих пор в SNAPSHOT.
        — Местами бажной. Приходится допиливать руками или обходить.
        — Отсутствует хороший фильтр ресурсов, что очень необходимо для тестов. Classpath filter фильтрует только sources, но не сами классы и ресурсы. Для простых тестов спасает ApplicationComposer.
        — У версии из Maven repository вебпрофайл сломан. Для веба приходилось пускать отдельно embedded Jetty и общаться с бэкэндом через remote EJB/JMS. Но так таже лучше.

        Вобщем, последние два проекта я писал на OpenEJB и деплоил в продакшн на Weblogic. Сначала пришлось много разрюхивать, чего нет в документации и много всего допиливать. Но в результате experience намного позитивней, чем Wildfly + Arquillian.


  1. asm0dey
    14.05.2016 10:02
    +2

    В JavaEE нет:


    1. JPA репозиториев
    2. JDBC Темплейтов
    3. Нормальной, удобной в использовании системы Security (Я сейчас не про JAAS, а, скорее, про всё остальное)
    4. Удобного формата хранения настроек
    5. AutoConfiguration
    6. Удобной системы для построения сервисов (не считая RMI, который неудобно дебажить).

    В большинстве серверов приложений есть привязка к каким-то конкретным очередям, привязаться к другому брокеру — целая большая история. И, навеняка, ещё куча всего чего я не смог вспомнить за 30 секунд.


    1. lpre
      14.05.2016 18:38

      Ну и что, что нет? Если вам нужны эти компоненты в JEE проекте, возьмите сторонние библиотеки (из того же Spring) и используйте их. Ведь смысл существования JEE вовсе не в создании мегафрейморка, который будет включать в себя ВСЁ что только может пожелать программист, даже если это уже где-то есть. К тому же JEE — это даже не фреймворк, а спецификация интерфейсов.

      Кстати, в том же Spring тоже много чего нет. Иначе Spring-программисты не включали бы в свои проекты компоненты из JavaEE spec (например, Servlets, JPA, JDBC, JNDI, RMI, JavaMail, JMS, JAX-RS, JMS и др.). Однако обычно никто не использует это как аргумент, чтобы показать недостатки или слабость Spring.

      Переиспользование удачных компонентов — это норма. Так же как и здоровая конкуренция между разными фреймворками.

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

      А многие компоненты, реализующие части JEE spec, можно вообще standalone использовать, без всякой привязки к чему-либо. Те же брокеры.


      1. asm0dey
        14.05.2016 18:49

        Spring, в отличе от JEE даёт свободный выбор. Можно использовать JAX-RS, можно Spring MVC. Можно использовать референсный Eclipselink, можно нереференсный Hibernate, можно вообще не входящие в состав QueryDSL и DataNucleus. Кто тянет JNDI в Spring Boot Приложение мне вообще непонятно — зачем? Опять-таки можно JMS, а можно AMQP — и спринговый аналог MDB будет работать как с тем, так и с другим. А ещё можно редис. И тоже будет работать. JavaMail такой ад в чистом виде, что все стараются уйти от него подальше — на Spring mail, например. JDBC — не часть EE стандарта, это часть SE. И сервлеты к спрингу тоже гвоздями не прибиты, можно использовать netty И основанный на нём ratpack, например. А можно мне посмотреть на некриво реализованный, сертифицированный на JavaEE 7 Full Profile сервер приложений, поддерживающий Java 8, пожалуйста? А если он при этом ещё и бесплатным будет — то совсем круто.


        1. lpre
          14.05.2016 20:47

          Никто и не говорит, что в Spring что-то прибито гвоздями. Но если вы приводите список того, чего нет в JEE, то не следует забывать, что и в Spring-приложения тянутся сторонние библиотеки, причем иногда из JEE.

          JavaEE — это стандарт, потому свобода выбора ограничена, как и в любом другом стандарте. Многие считают это скорее плюсом, чем минусом. Однако он даёт свободу выбора реализации этой стандартной спецификации, чего нет в Spring. У нас предпочитают Web Profile (расширенный по потребностями) в бесплатной реализации TomEE, сертифицированной по JEE 6 (версия 7 пока не стабильна, но тоже будет сертифицирована). С Java 8 работает прекрасно.

          Но это ограничение свободы не техническое, а скорее волевое/административное. Так что если вы не желаете ограничивать себя строгим стандартом, то свобода выбора намого шире. Вплоть до того, что можно испльзовать только отдельные компоненты JEE, как в SE приложениях, так и в том же Spring. Или комбинацию стандартных и нестардатных компонентов, например Hibernate вместо JPA, или AMQP вместо JMS.

          JDBC появился именно как часть Java EE. То, что сейчас он входит в состав как EE так и SE этого факта не отменяет. Так что можно уточнить: SE вообще и Spring в частности используют API разработанный для EE.


          1. asm0dey
            14.05.2016 21:59

            Ну вот мне на прошлой работе в какой-то момент понадобился Full Profile. И EE7 конечно. И единственной сертифицированной реализацией был wildfly. И настраивать его — это кусок чистого ада. Оно почти не документировано же. Glassfish Тоже так умеет. Но он такой тормозной, что разрабатывать под него — тоже кусок ада.
            Неважно, какой API когда и для чего был разаботан. Сейчас это не часть EE спецификации. Как только вы в EE начинаете использовать AMQP — вы теряете транзакционность. А со спрингом (внезапно) не теряете. Это потому что EE монолитен и не умеет работать ни с чем за рамками стандарта. А с другой стороны как только вам нужны одновременно EJB, сервлеты, CDI и MDB — вся эта штука становится реально тяжёлой и неповоротливой. Потому что все мне известные сертифицированные EE 7 Full Profile контейнеры тянут всю спецификацию уже на стадии запуска. Вместе с JSF, JSP, JPA и всем остальным ненужно.


            1. lpre
              15.05.2016 09:48
              -1

              Сейчас это не часть EE спецификации.

              Это до сих пор часть JEE. С сайта Oracle:
              The JDBC 4.0 API is divided into two packages: java.sql and javax.sql. Both packages are included in the Java SE and Java EE platforms

              Я вам ответил не для того, чтобы спорить о сложности приколачивания или выпиливания компонентов, а для этого:

              Но если вы приводите список того, чего нет в JEE, то не следует забывать, что и в Spring-приложения тянутся сторонние библиотеки, причем иногда из JEE.


              1. asm0dey
                15.05.2016 11:04

                Ну так если он овключено в SE — то каким же боком оно часть EE? Тогда вы кж и про java.lang.String не забудьте сказать, что оно часть спецификации EE. Однако (внезапно) так никто не говорит. Потому что EE работает на базе SE.


                А, ну вы просто с тяжесть и монолитностью спорите. А я вас просто попытался привести к мысли что оно-таки монолитное, тяжёлое и при этом плохо расширяется ко всему прочему. Точнее сам-то стандарт вроде как норм, а реализаций-то вроде как и нет, которые позволяют работать с ним не как с тяжёлым и неповоротливым монолитом.


                1. lpre
                  15.05.2016 14:24
                  -2

                  Да, про String никто и не говорит, что это часть EE. А про JDBC Oracle (и Sun в свое время) именно так и говорят (внезапно ;-)): часть JEE.

                  Реализация, используемая у нас, не производит впечатления монолита.


                  1. asm0dey
                    15.05.2016 18:49

                    Ну я же правильно понял, что вы используете старую и порезанную реализацию спецификации? Ну то есть к момента «2 года с выхода новой версии» наконец-то появилась нормальная реализация старой, да и то неполной?


                    А про JDBC как-то глупо ИМХО. Ну то есть если что-то полностью входит в SE — зачем говорить что оно входит в EE? Это самоочевидно.


                    1. lpre
                      16.05.2016 11:56

                      Ну я же правильно понял, что вы используете старую и порезанную реализацию спецификации?

                      Да, мы используем JEE 6.

                      Насчет порезанной — это называется «Web Profile» ;-) И эта «порезаная» реализация сертифицирована на соответствие стандарту.

                      А про JDBC как-то глупо ИМХО. Ну то есть если что-то полностью входит в SE — зачем говорить что оно входит в EE? Это самоочевидно.
                      Однако с тем, что он пришел в JSE из JEE, вы не будете спорить? Это ведь очевидно (читайте ченджхистори JDBC на официальном сайте).

                      Точно так же и с другиме компонентами JEE: они используются не только в JEE, но и в других фрейморках включая Spring.

                      Основная мысль моего ответа вам здесь:

                      Если вы приводите список того, чего нет в JEE, то не следует забывать, что и в Spring-приложения тянутся сторонние библиотеки, причем иногда из JEE.


          1. fogone
            14.05.2016 23:00

            Действительно, смысл стандарта в ограничении свободы, но обычно в пользу упрощения унифицированного обращения. Однако же, что на самом деле унифицирует этот стандарт? Существует несколько серверов приложений со своими реализациями технологий из стандарта, которые видимо по идее создателей стандарта должны быть совместимы — т.е. приложение может переехать с одного сервера на другой (с одной реализации какой-то технологии на другую). Но нет. Оказывается, что стандарт хоть и есть, но настолько неконкретный, что при реализации приходится додумывать массу деталей (что не удивит ни одного опытного разработчика), а в результате — реалзиации не совместимы. Это же мешает стандарту стать базой для изучения — выходит, что работать с разными серверами приложений (читай: реализациями технологий из стандарта) тоже нужно по-разному, ведь они не только имеют собственный способ конфигурации, но и ряд «особенностей» интерпретации стандарта. Выходит, что эти сервера приложений — это несколько продуктов, которые используют схожий api (который был местами сознательно урезан, а местами просто не смогли договориться — как результат некоторый аскетизм результата), но как в автомобиле сесть и поехать — нельзя, потому что у каждого есть своя третья педаль, без которой сервер не едет, но работает она везде по-разному. Со временем, конечно, стандарты становятся лучше — их лучше прорабатывают, решаются неоднозначности в реализациях, но развитие стандартов по причине высокой формализации идут совершенно не современными темпами. Вполне вероятно, что новый стандарт будет лучше соответствовать потребностям, только случится это очень не скоро, фидбек по этому стандарту пойдет еще через какое-то время, а пока всё это работает плохо, мы будем использовать спринг, потому что у них уже есть микросервисы из коробки, а javaee никак не может разобраться с тем как приложение тестировать. Да и действительно, есть ли смысл в таком стандарте? Может лучше было бы выпустить хорошие реализации для этих технологий как это делается с javase? Но нет, оракл даже глассфиш (это было что-то вроде референсной реализации javaee) решил больше не поддерживать — ок.


            1. SamSol
              16.05.2016 13:53
              +1

              Постарайтесь никого не вводить в заблуждения.

              смысл стандарта в ограничении свободы
              В javaee tutorial цель платформы Java EE объясняется так: предоставить разработчикам мощный набор API с одновременным сокращением времени разработки, снижением сложности приложения и улучшением производительности приложения.
              Сравните EJB2 и EJB3 — большое количество ограничений было отменено.

              т.е. приложение может переехать с одного сервера на другой
              во многих частях спецификации указываются ограничения чтобы приложение оставалось «portable application». Все сервера соответствующие спецификации одинаково исполняют «portable application». Такие приложения действительно могут переезжать с одного сервера на другой.

              стандарт хоть и есть, но настолько неконкретный
              Можете привести пример неоднозначности в какой-нибудь части Java EE?

              ведь они не только имеют собственный способ конфигурации, но и ряд «особенностей» интерпретации стандарта.
              каждый сервер имеет свой собственный способ конфигурирования — это не новость, но это за рамками Java EE. И даже спринг имеет свой собственный способ конфигурирования. Специалист по TomEE/Payara/Wildfly/Weblogic сможет настроить сервер. Однако сила Java EE в том, что разработчик может создавать компоненты независимо от конфигурации и модели конкретного сервера.

              но развитие стандартов по причине высокой формализации идут совершенно не современными темпами
              в 2009 Java EE 6, в 2013 Java EE 7, в конце этого 2016 ожидается Java EE 8. Сейчас в Java EE 7 есть всё. Асинхронные запросы, Web Sockets, REST, HTML 5.
              В Java EE 8 (в конце этого года) ожидается HTTP/2, Server-Sent Events. Темпы, на мой взгляд, превосходные!

              javaee никак не может разобраться с тем как приложение тестировать
              Java EE (на сколько мне известно) не имеет своей целью определить как тестировать что-либо. Так что это утверждение не корректное.
              Однако тесто-пригодность java ee приложений на высоте (так же как у спринг приложений).
              Автор оригинальной статьи рекомендует вместо интеграционных «системные тесты» с использованием контейнеров. Вполне пригодная концепция.
              А для модульных тестов (как для java ee так и для spring) отлично подходит mockito с её аннотациями InjectMocks, Mock, Spy.

              Может лучше было бы выпустить хорошие реализации для этих технологий
              имхо оракл поступил даже мудрее! Вместо того чтобы выпускать самому, он сделал так, что теперь для каждого компонента имеются несколько реализаций
              JPA - Hibernate, EclipseLink, OpenJPA
              JTA - Narayana (других не знаю, но они есть)
              JAX-RS - Apache CXF, Jersey, RESTeasy

              Серверы приложений Wildfly, Payara, TomEE, WebLogic, WebSphere — на любой вкус.

              Я с большим уважением отношусь к Spring. Это отличный фреймворк. Однако и спецификация Java EE предлагает как минимум такой же уровень возможностей и удобства.


      1. Throwable
        16.05.2016 11:58
        +3

        Давайте повернем вопрос по-другому. Что такого есть полезного в JavaEE API, что заставит использовать именно его, а не другие решения? Какая киллер-фича?


        • EJB — рудиментарная модель компонента. Единственная полезность — возможность работы через remote. Но он не рекомендован для публикации интерфейсов, а скорей для работы внутри самой системы. Для хорошего ремоутинга есть 100500 альтернативных решений, которые в большей степени подходят для данной работы (начиная с JSE RMI).
        • JPA — скопированный Hibernate. Был еще один "стандарт" JDO, о котором все быстро забыли, т.к. не было нормальной имплементации.
        • Вебстек полностью сломан. Представители других платформ ржут над потугами джавистов, когда при изменении странички приходится редеплоить все приложение, вместо простого нажатия рефреша. Есть куча других более удобных решений, не базирующихся на этом стеке. JSF в публичном продакшне сожрет вам весь проц и всю память, JSP + JSTL уже никто не пользует — есть лучшие альтернативы для темплейтинга.
        • JAX-WS и SOAP входят в состав JSE и не требуют никаких танцев с бубном. Мало кто знает, что реально работающий вебсервис на Java пишется двумя строчками. http://stackoverflow.com/questions/3680600/publishing-a-ws-with-jax-ws-endpoint
        • JNDI — что это за фигня? Глобальный registry ресурсов? Кому оно реально надо, кроме самого сервера приложений? Меппинг ресурсов до сих пор не стандартизован, до JEE6 не было стандарта path для публикации EJB. Всегда vendor-locked. Чтобы это работало на конкретном сервере, всегда требуется добавлять vendor-specific-дескриптор, где прописаны меппинги.
        • JMS. Просто посмотрите доклад Николая Алименкова "Нужен ли нам JMS". Отдельная херь — MDB. Все ресурсы со всеми именами присобачены гвоздями и напрочь лишены возможности что-либо сконфигурировать динамически. В 9 случаях из 10 vendor-lock.
        • JTA. Отдельная любимая тема. XA-транзакции и все, что с ними связано. Мало кто знает, что надежность и атомарность у них условная, и не выше, чем у обычных транзакций. Более того, когда грохается JTA, сервер перестает создавать новые и требуется ручное вмешательство. Сегодня только два ресурса поддерживают JTA: JMS и JDBC. Все эти ваши вебсервисы нарушают транзакционность.
        • CDI: просто урезанная копия Spring IoC и ничего более. Для IoC и DI создано 100500 фреймворков на выбор.


        1. lpre
          16.05.2016 13:20

          Что такого есть полезного в JavaEE API, что заставит использовать именно его, а не другие решения?
          На мой взгляд, это некорректный вопрос по нескольким причинам.

          JavaEE API используется не только в сертифицированных JavaEE контейнерах, но и в JavaSE (включая Spring-apps). Поэтому вопрос следовало бы расширить. К примеру, что заставляет программистов использовать Servlets API?

          С другой стороны, «полезные» API из JavaEE, пользующиеся популярностью, постепенно переходят в JavaSE, ну или хотя бы просто могут использоваться в JavaSE приложениях. Так было с JDBC, JAX-WS, JAX-RS, вероятно будет с CDI. Вы же такие сразу оставляете за скобками: «не требуют никаких танцев с бубном». Но ведь они пришли из Java EE (или даже всё еще являются его частями). Их перенесли (или собираются перенести) в JavaSE только потому, что многие программисты посчтитали их полезными.

          Сама формулировка «что заставит использовать именно его? Какая киллер-фича?» излишне категорична. IMHO, нет ни одного фреймворка с такими характеристиками (ни в JavaEE, ни за его пределами), а оценка полезности фич может быть диаметрально противоположной. Пример из этого же обсуждения: мы находим очень удобным автоматичскую конфигурацию бинов в JavaEE (когда сервер сам находит, грузит и связывает всё, что найдет в classpath). Для нас это очень удобно для тонкой настройки множества сервисов только-лишь через упраявляемый деплоймент. Как выяснилось, для вас (и некоторых других участников) это тоже киллер-фича, но уже против JavaEE. Опять всё с начала, по кругу?

          Ну и наконец, я бы переформулировал вопрос в виде «Какие факторы/фичи влияют на выбор конкретного API/фреймворка для ваших проектов?» Наличие киллер-фич в конкретных API будет, верятно, только одним из факторов.

          P.S. Ваш список дажеко неполный. Списки Java EE API 6 и 7:
          http://www.oracle.com/technetwork/java/javaee/tech/javaee6technologies-1955512.html
          http://www.oracle.com/technetwork/java/javaee/tech/index.html


          1. Throwable
            16.05.2016 14:47
            +1

            К примеру, что заставляет программистов использовать Servlets API?

            Скорей всего, что в один прекрасный момент фреймворки типа Struts и Spring MVC взяли этот стандарт для базы. А также благодаря контейнеру Tomcat, который долгое время был единственной реализацией вебстека на Java. А распространенность томкэта говорит о том, что сервлеты — единственное, что было полезное в JEE, и что вся основная JEE-требуха вобщем-то никому была особо не нужна.


            Так было с JDBC, JAX-WS, JAX-RS, вероятно будет с CDI.

            JDBC изначально был в Java. JAX-RS пока еще не входит в JSE и не планируется. CDI вообще сомневаюсь, что будет когда-то входить.


            Но это все не имеет практически никакого отношения к JEE. Стандартизированием API для Java занимается специальная группа JCP. А спецификация JEE — это всего лишь один из JSR-ов этой группы. В нем определяется какие из стандартизированных API будут входить в состав очередного JEEx и как их там внутри использовать (на самом деле JSR-ов несколько). То же самое со включением того или иного API в JSE. Поэтому абсолютно неверно говорить, что те или иные API в JSE появляются из мира JEE. Вот например спецификация JAX-WS:
            https://jcp.org/en/jsr/detail?id=224
            Вообще нет нигде упоминания JEE. Просто спецификация API. В JCP есть еще огромное количество API, которые не входят ни в JEE ни в JSE. Почти ко всем из них есть reference-реализация ввиде отдельного фреймворка. Также было и с JAX-RS: как только стал популярным Rest, его включили со всеми потрохами в JEE (практически все сервера апликаций используют тот самый Jersey). Так что JEE — это лишь способ использования определенных Java API, причем далеко не лучший.


            P.S. Ваш список дажеко неполный. Списки Java EE API 6 и 7:

            Остальное — никому не нужная требуха. Полтора юзкейса на тысячу. Если уж очень нужен JavaMail — проще полключить стороннюю библиотеку, которая из коробки уже умеет больше, нежели предполагает стандарт.


            P.S. больше 10 лет разрабатываю под JEE по одной простой причине — клиент требует JEE-сертифицированное решение и платит хорошие деньги. У клиента куплен сервер апликаций и поддержка от производителя. По своей воле я бы ни за что не посоветовал решения на базе JEE.


            1. lpre
              16.05.2016 22:54

              распространенность томкэта говорит о том, что сервлеты — единственное, что было полезное в JEE.
              Отчего же вы его в свой список не включили?

              JDBC изначально был в Java.
              Но не весь. Пакет javax.sql появился в JavaSE начиная с версии 1.4 (т.е. с JDBC 3.0), до этого он был только в JavaEE. Просто проверьте java doc для JavaSE: для всех интерфейсов из javax.sql в доках стоит «Since: 1.4»

              JAX-RS пока еще не входит в JSE
              Однако уже сейчас в JSR стоит «target: Java SE». А я сказал: «постепенно переходят в JavaSE, ну или хотя бы просто могут использоваться в JavaSE приложениях». То же самое с CDI.

              JAX-WS: https://jcp.org/en/jsr/detail?id=224 Вообще нет нигде упоминания JEE.
              Правильно. Теперь он входит в состав Java SE, так что с чего бы там Java EE упоминалась? Однако это вторая версия спецификации, первая же (называемая тогда еще JAX-RPC, JSR-101) зависила от API сервлетов и EJB => могла работать только с JEE и потому входила только в её состав, но не в JSE.

              Остальное — никому не нужная требуха.
              Для ответа на ваш вопрос достаточно и того, что входит в web profile — востребованный как целиком, так и по частям.

              По своей воле я бы ни за что не посоветовал решения на базе JEE.
              Ну а мы сами выбрали Java EE 6 Web Profile и не сожалеем. Более того, всем советуем, особенно в приятной, легкой, гибкой и бесплатной реализации TomEE.


        1. grossws
          16.05.2016 14:38
          -1

          Не соглашусь про CDI, там есть полезная фича в буковке C. Очень удобно заинжектить прокси более узкого скоупа (RequestScoped, например) в бин с более широким скоупом (ApplicationScouped). Инжектится прокся, которая будет резолвить бин нужного узкого скоупа при вызове из более широкого.


          В случае спринга требовалось существенно больше танцев с бубном чем просто аннотация.


          1. Throwable
            16.05.2016 15:09

            @ScopedProxy???


            1. grossws
              16.05.2016 15:57

              Такого в документации не нашел. Но увидел, что есть <aop:scoped-proxy/> и @Scope(proxyMode = ...). Видимо, проглядел ранее при чтении документации, прошу прощения.