Ошибка одна — перехват исключений. В подавляющем большинстве случаев его в бизнес-коде вообще не должно быть. Практически всегда обработка исключений — это удел абстракций верхнего уровня, где как правило нет особой необходимости сильно различать тип эксепшна. К сожалению в Java checked exceptions обязуют перехватывать непосредственно в вызывающем методе, хотя практически всегда это не его ответственность. В частности в Java все исключения доступа к ресурсам checked: IOException, SQLException, JMSException, etc… Архитекторы посчитали, что вызывающий метод во что бы то ни стало просто обязан позаботиться о том, что если вдруг что-то пойдет не так. Реально же бизнес-код вообще не должен заботиться об ошибке доступа к ресурсам также как и не должен заботиться об InterruptedException или OutOfMemoryError — это должны компоненты верхнего уровня универсальным способом, например откатить транзакцию.
Большинство джунов не в состоянии не только написать такой, но и понять зачастую. Поэтому посты типа "я ненавижу..." следует читать с солидной долей скепсиса.
Это понятно. С другой точки зрения, джун, который мало-мальски в состоянии распарсить файл и запихнуть его в базу данных, при попытке сделать это на Spring Batch наполняется лютой и праведной ненавистью.
На мой взгляд основная проблема спринга, превращающая его из фреймворка в книгу заклинаний, состоит в повсеместном использовании аннотаций. Аннотации в java были придуманы для определения метаданных в коде. Но строить на их основе некий расширяемый метаязык для определения контекста приложения — это вкорне неверная идея, аннотации для этого не приспособлены. Расставленные в коде аннотации сематнически никем не контролируются, кроме рантайма: @EnableWebMvc я могу вообще поставить на любой объект, не обязательно на @Configuration — никто меня не ограничит.
Есть гораздо более удобные, правильные и открытые способы задания конфигурации контекста без аннотаций, например Guice.
Спринг же пытается всю задачу замести под ковер, оставляя пользователю лишь набор заклинаний и рецептов для описания бизнес логики, которые нужно использовать в определенном порядке, иначе просто не взлетит. Это очень эффектно для демонстраций и презентаций, но в реальных проектах при попытке заглянуть под ковер и что-то там изменить всегда сопряжена с головной болью и геморроем.
огромное количество библиотек и реализаций. Попробуйте навелосипедить свой spring-security c каким-нибудь oauth собственнм сервером и клиентом.
В большинстве случаев это не нужно. Как правило вы используете какую-то одну конкретную технологию и уже готовую библиотеку для нее. Spring же предлагает навороченный абстрактный леер, интеграцию сразу со всеми известными технологиями и толстую книгу рецептов как это все засандалить в ваше приложение. Причем зачастую многие проблемы уже решены на более низком уровне, например тот же Servlet уже содержит простые средства security.
Альтернативу @Transactional с нетривиальнм двухфазным коммитом (например БД + Очередь в единой транзакции).
Двухфазный коммит делает не Spring, а стороннияя библиотека-координатор, например Atomikos, Narayana, etc. Spring @Transactional делает лишь наивный автоматический прокси на коммит/роллбэк, который также легко сделать вручную при помощи java.lang.reflect.Proxy, AspectJ или ByteBuddy. В реальных проектах практически всегда требуется вручную контролировать сбои и взависимости от типа ошибки нужно помимо роллбека повторить транзакцию, реинициализировать ресурс, отрапортовать о сбое, собрать метрики… Вот вам и свой @Transactional. Кроме того есть мнение, что XA вообще не рекомендуется использовать...
но опять же время на изучение и не меньшее время чтобы все это подружить между собой
Убеждался и продолжаю убеждаться, что гораздо быстрее сделать все самому, чем читать тонны документации, втыкать, стековерфловить и пытаться все это подружить между собой. Кроме того, как это зачастую бывает в спринге: шаг влево-шаг вправо от рецепта — и геморрой обеспечен.
Представьте, что у вас ушел 1-2 ключевых разработчика, кто делал ваши велосипеды и потом найдите и пофиксите сложный баг.
Ваши 1-2 разработчика писали когда-нибудь bean postprocessors? Скорей всего они намолотили кучу кривой прикладной магии ввиде специфических @Заклинаний. Разобраться почему не проксируется бин, кто его процессит и в какой последовательности и почему вдруг что-то перестало работать — никто не будет. Девелоперы как правило понавтыкают костылей, чтобы хоть как-то решить требуемую задачу.
Куча проблем за вас решена
И на ровном месте создана другая куча. Если все так просто — почему на SO Spring держится в топе? Как правило всегда есть более простое и элегантное решение каждой конкретной проблемы. Spring же пытается влезть без вазелина везде, где это только возможно, вцелом значительно усложняя архитектуру и упрощая лишь какие-то конкретные простые случаи использования. Кроме того, подобное упрощение имеет негативный эффект: куча кодеров, не понимая принципы работы, начинает копипейстить туториалы и SO, допуская архитектурные ошибки. И, столкнувшись с проблемами или с незнанием того, как что-то конкретное сделать на спринге, начинают грязно костылить.
Сделать достаточно сложный проект на spring-boot для быстрого старта как прототип относительно несложно
Сделать демку типа "хелло-ворлд" с кучей подключенных технологий. В реальном проекте требуется более полный контроль над кодом, где в итоге все плюсы ввиде средств автоматического бутстрапа превращаются в огромные минусы.
Вобщем-то на Java ввиду особенностей языка как раз нельзя написать нормальный DSL. Лямбды немного улучшают ситуацию, но не сильно. В частности, проблемы возникают с описанием иерархической структуры и со ссылками на проперти (которые всегда будут не type-safe). Стандартрый способ — клепать билдеры, но с ними получается очень гормоздко. Поэтому практически всегда для описания структур используют сторонний язык типа XML.
P.S. В Java 8 идентификатор _ объявлен как deprecated, а Java 9 вообще запрещает его использовать.
В пятницу их работники получали уведомление отключить все персональные компьютеры до выяснения обстоятельств, что практически парализовало работу многих служб. Вобщем-то это говорит о низком уровне корпоративной политики безопасности.
Вы хотите сказать в том же IBM отдельно сидят люди, которые участвуют в JCP и отдельно те, кто пишет софт и причем первые не общаются со вторыми? Не проблема ли это IBM
Это проблема не только IBM, а всех крупных компаний, где есть жесткое разделение труда. И да, специалисты, участвующие в JCP, возможно не писали реальный бизнес-код уже лет десять или больше.
Поэтому еще год назад от них были призывы "если вы видите какие-то проблемы у вашей библиотеки/фреймворка при переходе на Jigsaw — напишите нам!".
Это когда еще мало-мальски стабильной девятки не было? Есть очень много решений, базирующихся на classpath. SLF4J использует classpath для поиска бэкенда для логгинга и настроек. Чтобы это сработало в модульной среде, библиотека должна быть изменена концептуально. И все остальные библиотеки, использующие SLF4J, будут ждать, пока мейнтейнеры соизволят выпустить его модульную версию, а также модульную версию всех своих зависимостей. И так с каждыми библиотеками, фреймворками и тулзами для сборки, тестинга и, наконец, продуктами. Период перехода может затянуться лет на 5 или больше, и все это время придется поддерживать две версии. В итоге экосистема сплитанется на две — модульную и classpath-ную.
А теперь главный вопрос: в чем реальный профит модульности?
Очевидно, это разные люди — те, кто пишет спецификации и те, кто разрабатывает софт. Когда появился более-менее стабильный кандидат девятки, компании попробовали портировать свой стек под новую платформу и во многом обломались. Я не уверен, что изначально даже был сделан анализ более-менее распространенных библиотек, фрекмворков и тулзов на предмет насколько их затронет изменение и какие могут быть методы решения. В любом случае, выход девятки — это будет глобальный сплит всей экосистемы.
Наконец-то в браузере появятся нормальные лейауты! FlexBox вместе с GridLayout покрывают практически всю необходимость разметки в приложениях.
А вообще, как-то странно: именно производители "того самого браузера" изначально предложили и пилили спецификацию GridLayout, теперь же хуже всех ее поддерживают.
Дааа! Респект за упоминание Ultimae Records!!! В свое время они выпускали годную серию сборников псайбиента под названием Fahrenheit Project. Рекомендую всем! Просто офигительное звучание и очень интересные наработки! Из Solar Fields очень нравится его первый альбом Reflective Frequencies. Упомянутые Asura больше работает в стиле Slow Trance, а вот их бывший музыкант Aes Dana делает чистый dark ambient. Также вместе с Solar Fields они запилили неплохой проект H.U.V.A. Networks на том же Ultimae но по мне, так он слишком атмосферный — люблю тяжелые драм секции. Вобщем, лейбл Ultimae Records — номер один для любителей псайбиента.
Еще тащился от проекта Vibrasphere — в основном они работают в PsyTrance, но у них есть прям сказочные псайбиентные треки. Жаль, что закрылись.
Да, согласен. В этом случае OSGi действительно помогает как единая платформа для деплоя, если имеется большое число более-менее независимых модулей.
Я сам не большой фанат контейнеров и микросервисов, поскольку в самой Java уже встроены неплохие средства виртуализации. Контейнеры сильно усложняют архитектуру и деплой и должны применяться только там, где это действительно необходимо, а не по зову моды. Также не имеет смысла искусственно дробить приложение на микросервисы, если у него единый функционал и цикл разработки.
А вот интересно, как вы все это пускаете в devmode? По стандартной схеме build-pack-deploy? Или плагин какой используете?
И мне кажется, не совсем аргументирована модульность приложения. Внутренне — да, имеет смысл для кода и тестов. Но с точки зрения деплоя лучше иметь единственный артефакт, нежели груду джарников.
Если необходима модульность, по-моему лучше будет разбить приложение на микросервисы и стартовать каждый в отдельной JVM/контейнере, как это делается сейчас. Единственный сценарий, который приходит на ум — платформа для деплоя различных приложений и микросервисов с разным циклом разработки. Что-то типа ESB или AppServer. Фактически там он в осносном и используется.
Я не совсем согласен с такой точкой зрения. Иметь свой корпоративный репозиторий в команде это, конечно же, хорошо и правильно. Но я всегда следую принципу, что проект должен уметь собираться всегда и везде, без лишних геморроев. Локальный репозиторий проекта — разумное решение, когда тебе нужен всего лишь какой-нибудь пропиетарный драйвер. Это делает сборку проекта автономной и независимой от окружения. Maven Wrapper при этом еще отлично помогает.
Есть одна проблема с локальным репозиторием — для мультимодульного проекта придется корректировать путь к нему в каждом pom.xml, так как project.badedir будет у каждого модуля свой.
У меня сложилось такое впечатление, что сейчас под трендом "микросервисы" пытаются втюхать Spring Boot, Rest и иногда каким-то образом припаять Docker. И если посмотреть в Google Trends, то собственно так оно и есть. То есть чтобы в мозгу разработчика четко отложилось: java-приложения, оказывается, можно разрабатывать без контейнера, но для этого нужен Spring Boot, который нам даст Rest. И это теперь называется микросервисами.
Тем не менее, 10 лет назад в эпоху засилия SOA и JavaEE, когдя я писал что-то вроде:
@WebService
public class AddService {
@WebMethod
public int add(int a, int b) {
return a+b;
}
public static void main(String[] args ){
Endpoint.publish("http://0.0.0.0:1234/AddService", new AddService());
}
}
не было подходящего названия для этого. Люди недоумевали: если это java-приложение, то где интерфейс с кнопочками? Если это веб-приложение, то где сервер приложений, куда оно должно деплоиться? Здесь даже не было более-менее знакомого слова "Spring". И вплоть до того, что клиенты отказывались принимать работу, поскольку не знали каким словом это назвать (мой клиент все-таки придумал название — "тамагочи"))).
Теперь же я любое решение, которое не требует контейнера, я с гордосью называю "микросервис" и вопросов не возникает.
Практическая полезность была бы кстати, если бы JVM умела бы делать быстрый hot-restart: прибиваются все треды, освобождаются все системные ресурсы, но при этом оставлялся бы PermGen с классами, сгенеренной статистикой выполнения и предкомпилированным кодом.
Предлагаю следующий этап эволюции GC и архитектуры приложений: не собирать мусор, пока не заполнится вся память, затем вызвать специальный OutOfMemory-хандлер у тредов, у которых он зарегистрирован, после чего начать полную сборку мусора.
Что это даст? Процессинговые треды, имеющие OutOfMemory хандлер смогут обработать ситуацию: закрыть ресурсы, вернуть ошибку клиенту, сообщить в кластер, что нода отвалилась, и при необходимости рестартнуть после сборки мусора. Чтобы при вызове хандлеров не было повторного OutOfMemory вся аллокация ведется в отдельно зарезервированной области.
Таким образом можно реализовать быстрый перезапуск процессинга без реальной необходимости перезапуска системы.
Ошибка одна — перехват исключений. В подавляющем большинстве случаев его в бизнес-коде вообще не должно быть. Практически всегда обработка исключений — это удел абстракций верхнего уровня, где как правило нет особой необходимости сильно различать тип эксепшна. К сожалению в Java checked exceptions обязуют перехватывать непосредственно в вызывающем методе, хотя практически всегда это не его ответственность. В частности в Java все исключения доступа к ресурсам checked: IOException, SQLException, JMSException, etc… Архитекторы посчитали, что вызывающий метод во что бы то ни стало просто обязан позаботиться о том, что если вдруг что-то пойдет не так. Реально же бизнес-код вообще не должен заботиться об ошибке доступа к ресурсам также как и не должен заботиться об InterruptedException или OutOfMemoryError — это должны компоненты верхнего уровня универсальным способом, например откатить транзакцию.
Что за треш? Paths.get(".", "log", "service.log") позволит вам навсегда забыть о File.separator.
Это понятно. С другой точки зрения, джун, который мало-мальски в состоянии распарсить файл и запихнуть его в базу данных, при попытке сделать это на Spring Batch наполняется лютой и праведной ненавистью.
На мой взгляд основная проблема спринга, превращающая его из фреймворка в книгу заклинаний, состоит в повсеместном использовании аннотаций. Аннотации в java были придуманы для определения метаданных в коде. Но строить на их основе некий расширяемый метаязык для определения контекста приложения — это вкорне неверная идея, аннотации для этого не приспособлены. Расставленные в коде аннотации сематнически никем не контролируются, кроме рантайма: @EnableWebMvc я могу вообще поставить на любой объект, не обязательно на @Configuration — никто меня не ограничит.
Есть гораздо более удобные, правильные и открытые способы задания конфигурации контекста без аннотаций, например Guice.
Спринг же пытается всю задачу замести под ковер, оставляя пользователю лишь набор заклинаний и рецептов для описания бизнес логики, которые нужно использовать в определенном порядке, иначе просто не взлетит. Это очень эффектно для демонстраций и презентаций, но в реальных проектах при попытке заглянуть под ковер и что-то там изменить всегда сопряжена с головной болью и геморроем.
В большинстве случаев это не нужно. Как правило вы используете какую-то одну конкретную технологию и уже готовую библиотеку для нее. Spring же предлагает навороченный абстрактный леер, интеграцию сразу со всеми известными технологиями и толстую книгу рецептов как это все засандалить в ваше приложение. Причем зачастую многие проблемы уже решены на более низком уровне, например тот же Servlet уже содержит простые средства security.
Двухфазный коммит делает не Spring, а стороннияя библиотека-координатор, например Atomikos, Narayana, etc. Spring @Transactional делает лишь наивный автоматический прокси на коммит/роллбэк, который также легко сделать вручную при помощи java.lang.reflect.Proxy, AspectJ или ByteBuddy. В реальных проектах практически всегда требуется вручную контролировать сбои и взависимости от типа ошибки нужно помимо роллбека повторить транзакцию, реинициализировать ресурс, отрапортовать о сбое, собрать метрики… Вот вам и свой @Transactional. Кроме того есть мнение, что XA вообще не рекомендуется использовать...
Убеждался и продолжаю убеждаться, что гораздо быстрее сделать все самому, чем читать тонны документации, втыкать, стековерфловить и пытаться все это подружить между собой. Кроме того, как это зачастую бывает в спринге: шаг влево-шаг вправо от рецепта — и геморрой обеспечен.
Ваши 1-2 разработчика писали когда-нибудь bean postprocessors? Скорей всего они намолотили кучу кривой прикладной магии ввиде специфических @Заклинаний. Разобраться почему не проксируется бин, кто его процессит и в какой последовательности и почему вдруг что-то перестало работать — никто не будет. Девелоперы как правило понавтыкают костылей, чтобы хоть как-то решить требуемую задачу.
И на ровном месте создана другая куча. Если все так просто — почему на SO Spring держится в топе? Как правило всегда есть более простое и элегантное решение каждой конкретной проблемы. Spring же пытается влезть без вазелина везде, где это только возможно, вцелом значительно усложняя архитектуру и упрощая лишь какие-то конкретные простые случаи использования. Кроме того, подобное упрощение имеет негативный эффект: куча кодеров, не понимая принципы работы, начинает копипейстить туториалы и SO, допуская архитектурные ошибки. И, столкнувшись с проблемами или с незнанием того, как что-то конкретное сделать на спринге, начинают грязно костылить.
Сделать демку типа "хелло-ворлд" с кучей подключенных технологий. В реальном проекте требуется более полный контроль над кодом, где в итоге все плюсы ввиде средств автоматического бутстрапа превращаются в огромные минусы.
Вобщем-то на Java ввиду особенностей языка как раз нельзя написать нормальный DSL. Лямбды немного улучшают ситуацию, но не сильно. В частности, проблемы возникают с описанием иерархической структуры и со ссылками на проперти (которые всегда будут не type-safe). Стандартрый способ — клепать билдеры, но с ними получается очень гормоздко. Поэтому практически всегда для описания структур используют сторонний язык типа XML.
P.S. В Java 8 идентификатор _ объявлен как deprecated, а Java 9 вообще запрещает его использовать.
Те, кто юзают в бэкенде Java и Hibernate знают о такой вещи как JPA 2.1 Entity Graphs. Фактически это та же идея, что и GraphQL.
У нас пострадали в основном крупные компании.
http://www.elmundo.es/tecnologia/2017/05/12/59158a8ce5fdea194f8b4616.html
В пятницу их работники получали уведомление отключить все персональные компьютеры до выяснения обстоятельств, что практически парализовало работу многих служб. Вобщем-то это говорит о низком уровне корпоративной политики безопасности.
Это проблема не только IBM, а всех крупных компаний, где есть жесткое разделение труда. И да, специалисты, участвующие в JCP, возможно не писали реальный бизнес-код уже лет десять или больше.
Это когда еще мало-мальски стабильной девятки не было? Есть очень много решений, базирующихся на classpath. SLF4J использует classpath для поиска бэкенда для логгинга и настроек. Чтобы это сработало в модульной среде, библиотека должна быть изменена концептуально. И все остальные библиотеки, использующие SLF4J, будут ждать, пока мейнтейнеры соизволят выпустить его модульную версию, а также модульную версию всех своих зависимостей. И так с каждыми библиотеками, фреймворками и тулзами для сборки, тестинга и, наконец, продуктами. Период перехода может затянуться лет на 5 или больше, и все это время придется поддерживать две версии. В итоге экосистема сплитанется на две — модульную и classpath-ную.
А теперь главный вопрос: в чем реальный профит модульности?
Очевидно, это разные люди — те, кто пишет спецификации и те, кто разрабатывает софт. Когда появился более-менее стабильный кандидат девятки, компании попробовали портировать свой стек под новую платформу и во многом обломались. Я не уверен, что изначально даже был сделан анализ более-менее распространенных библиотек, фрекмворков и тулзов на предмет насколько их затронет изменение и какие могут быть методы решения. В любом случае, выход девятки — это будет глобальный сплит всей экосистемы.
Наконец-то в браузере появятся нормальные лейауты! FlexBox вместе с GridLayout покрывают практически всю необходимость разметки в приложениях.
А вообще, как-то странно: именно производители "того самого браузера" изначально предложили и пилили спецификацию GridLayout, теперь же хуже всех ее поддерживают.
Дааа! Респект за упоминание Ultimae Records!!! В свое время они выпускали годную серию сборников псайбиента под названием Fahrenheit Project. Рекомендую всем! Просто офигительное звучание и очень интересные наработки! Из Solar Fields очень нравится его первый альбом Reflective Frequencies. Упомянутые Asura больше работает в стиле Slow Trance, а вот их бывший музыкант Aes Dana делает чистый dark ambient. Также вместе с Solar Fields они запилили неплохой проект H.U.V.A. Networks на том же Ultimae но по мне, так он слишком атмосферный — люблю тяжелые драм секции. Вобщем, лейбл Ultimae Records — номер один для любителей псайбиента.
Еще тащился от проекта Vibrasphere — в основном они работают в PsyTrance, но у них есть прям сказочные псайбиентные треки. Жаль, что закрылись.
Да, согласен. В этом случае OSGi действительно помогает как единая платформа для деплоя, если имеется большое число более-менее независимых модулей.
Я сам не большой фанат контейнеров и микросервисов, поскольку в самой Java уже встроены неплохие средства виртуализации. Контейнеры сильно усложняют архитектуру и деплой и должны применяться только там, где это действительно необходимо, а не по зову моды. Также не имеет смысла искусственно дробить приложение на микросервисы, если у него единый функционал и цикл разработки.
А вот интересно, как вы все это пускаете в devmode? По стандартной схеме build-pack-deploy? Или плагин какой используете?
И мне кажется, не совсем аргументирована модульность приложения. Внутренне — да, имеет смысл для кода и тестов. Но с точки зрения деплоя лучше иметь единственный артефакт, нежели груду джарников.
Если необходима модульность, по-моему лучше будет разбить приложение на микросервисы и стартовать каждый в отдельной JVM/контейнере, как это делается сейчас. Единственный сценарий, который приходит на ум — платформа для деплоя различных приложений и микросервисов с разным циклом разработки. Что-то типа ESB или AppServer. Фактически там он в осносном и используется.
Я не совсем согласен с такой точкой зрения. Иметь свой корпоративный репозиторий в команде это, конечно же, хорошо и правильно. Но я всегда следую принципу, что проект должен уметь собираться всегда и везде, без лишних геморроев. Локальный репозиторий проекта — разумное решение, когда тебе нужен всего лишь какой-нибудь пропиетарный драйвер. Это делает сборку проекта автономной и независимой от окружения. Maven Wrapper при этом еще отлично помогает.
Есть одна проблема с локальным репозиторием — для мультимодульного проекта придется корректировать путь к нему в каждом pom.xml, так как project.badedir будет у каждого модуля свой.
По поводу IT-рекрутинга в блоге у yegor256 понравилась фраза: "You're Just the Mayonnaise in a Bad Sandwich"
У меня сложилось такое впечатление, что сейчас под трендом "микросервисы" пытаются втюхать Spring Boot, Rest и иногда каким-то образом припаять Docker. И если посмотреть в Google Trends, то собственно так оно и есть. То есть чтобы в мозгу разработчика четко отложилось: java-приложения, оказывается, можно разрабатывать без контейнера, но для этого нужен Spring Boot, который нам даст Rest. И это теперь называется микросервисами.
Тем не менее, 10 лет назад в эпоху засилия SOA и JavaEE, когдя я писал что-то вроде:
не было подходящего названия для этого. Люди недоумевали: если это java-приложение, то где интерфейс с кнопочками? Если это веб-приложение, то где сервер приложений, куда оно должно деплоиться? Здесь даже не было более-менее знакомого слова "Spring". И вплоть до того, что клиенты отказывались принимать работу, поскольку не знали каким словом это назвать (мой клиент все-таки придумал название — "тамагочи"))).
Теперь же я любое решение, которое не требует контейнера, я с гордосью называю "микросервис" и вопросов не возникает.
Практическая полезность была бы кстати, если бы JVM умела бы делать быстрый hot-restart: прибиваются все треды, освобождаются все системные ресурсы, но при этом оставлялся бы PermGen с классами, сгенеренной статистикой выполнения и предкомпилированным кодом.
Предлагаю следующий этап эволюции GC и архитектуры приложений: не собирать мусор, пока не заполнится вся память, затем вызвать специальный OutOfMemory-хандлер у тредов, у которых он зарегистрирован, после чего начать полную сборку мусора.
Что это даст? Процессинговые треды, имеющие OutOfMemory хандлер смогут обработать ситуацию: закрыть ресурсы, вернуть ошибку клиенту, сообщить в кластер, что нода отвалилась, и при необходимости рестартнуть после сборки мусора. Чтобы при вызове хандлеров не было повторного OutOfMemory вся аллокация ведется в отдельно зарезервированной области.
Таким образом можно реализовать быстрый перезапуск процессинга без реальной необходимости перезапуска системы.