
Часть 1 из 2. Здесь — холивар и архитектура. Во второй части — сухие цифры: токены, деньги и классы багов на бенчмарке.
Открой свой Spring-проект, которому больше двух лет. Найди пакет common, core или framework — а он там есть, я почти уверен. Загляни внутрь.
Ты увидишь BaseEntity с id, createdDate и version. Увидишь AbstractCrudController<T, ID>, от которого наследуются все твои контроллеры. Увидишь самодельный слой прав — что-нибудь вроде @CheckPermission поверх PermissionEvaluator. Увидишь свой SoftDeleteRepository и аудит-слушатель на JPA-события.
Поздравляю: ты написал фреймворк. Свой, внутренний, недокументированный (себя-то не обманывай), поддерживаемый одним человеком (который уже собеседуется в другую компанию). И построил ты его ровно для того, чтобы не брать «тяжёлый и навязчивый» opinionated-фреймворк — ты сделал это «ради контроля».
Давай честно поговорим про этот контроль.
Мы вообще не о том спорим
Первое, что убивает этот спор ещё на старте, — ложная дихотомия «Джеймикс против Spring». Её не существует.
Джеймикс и есть Spring Boot. Под капотом — обычный ApplicationContext, обычные бины, обычные JPA-сущности, обычный Spring Security. Джеймикс — это Spring плюс слой конвенций плюс инструменты. Спуститься на голый Spring (как ты любишь) можно из любой точки.
Значит, реальный выбор звучит не так, как тебе кажется. Он звучит так:
Взять готовый, поддерживаемый и документированный слой конвенций — или собрать свой.
Третьего варианта — «чистый Spring вообще без конвенций» — в природе не существует. Любое приложение сложнее туториала обрастает конвенциями, и вопрос только один: чьими? Готовыми, которые кто-то уже отладил и документирует за тебя, или твоими, которые ты иногда вспоминаешь по пятницам и объясняешь новичкам голосом.

Дисклеймер: я по ту сторону баррикад — работаю с Джеймиксом и пишу про него. Поэтому ниже — ни одной ссылки на его маркетинг: только чужие анти-паттерны, чужой код с GitHub и чужие покаянные посты. Позицию заявил, пруфы независимые — проверяй сам.
Не согласен? Всё ещё пурист? Добро пожаловать под кат.
Блок А. Ты уже это делаешь. У этого даже есть имя
Вернёмся к твоему пакету common, или как ты его назвал. Ты не уникален — и это не наезд, это статистика. Люди выкладывают такое на GitHub десятками репозиториев.
Вот Cepr0/generic-crud — целая библиотека, опубликованная в Maven Central, единственный смысл жизни которой — абстрактный контроллер:
public abstract class AbstractCrudController< T extends IdentifiableEntity<ID>, ID extends Serializable, Q extends CrudRequest, S extends CrudResponse<ID>> { ... }
Четыре дженерик-параметра, полный набор create()/update()/delete()/getOne()/getAll() с правильными HTTP-кодами. Человек не поленился оформить это как «переиспользуемый артефакт» и залить в центральный репозиторий — «чтобы не писать boilerplate в Spring-приложениях». Таргет, кстати, ещё Spring 4.3 / Boot 1.5 — то есть этим переизобретением занимаются не первый год.
Вот leonardombr/Generic-CRUD-Spring-Boot — @MappedSuperclass BaseEntity с id и name, от которого наследуются доменные сущности, плюс дженерик-триплет ControllerGeneric / ServiceGeneric / GenericRepository (нейминг осуждаю). Тот самый твой BaseEntity, только чужими руками.
Это не разгильдяйство отдельных людей. Это закономерность, у которой в каталоге анти-паттернов есть собственное имя — и не одно.
Inner-platform effect. Термин формально назвал Alex Papadimoulis (основатель The Daily WTF) ещё в апреле 2006 года. Определение с Wikipedia — прочитай медленно, оно про тебя:
«Склонность архитекторов делать систему настолько кастомизируемой, что она становится копией — и часто худшей копией — той платформы, на которой построена».
Возникает эффект ровно тогда, «когда самопальная библиотека разрастается, включая функции общего назначения, которые дублируют уже доступное в платформе» — и результат «работает медленнее, а при кривой реализации ещё и менее надёжен».
Greenspun’s tenth rule. Классика, зафиксированная в Wikipedia:
«Любая достаточно сложная программа на C или Fortran содержит ad hoc, неформально специфицированную, забагованную и медленную реализацию половины Common Lisp».
Замени «C или Fortran» на «голый Spring», а «половину Common Lisp» — на «половину Джеймикса», и получишь описание твоего пакета common дословно. Пол Грэм замечал: это случается в крупных проектах так часто, что явлению дали отдельное имя.
Вот в чём соль этого блока: твоя «гибкость» и твой «контроль» — не уникальное инженерное решение. Это позиция в каталоге анти-паттернов, у которой есть автор и дата. Неприятно? Так и должно быть.
Блок Б. Если бы голый Spring закрывал вопрос — не было бы этой индустрии
Хорошо, скажешь ты, это анекдоты про отдельные репозитории. Тогда посмотри на масштаб явления. Вокруг «голого» Spring выросла целая индустрия инструментов, которые добавляют ему ровно то, что opinionated-фреймворк даёт из коробки. Каждый такой проект — это вещдок: значит, из коробки этого не хватало.
Начнём с самого болезненного экспоната. Spring Roo — это когда закрыть boilerplate-разрыв попытался сам Spring. Генератор, который инкрементально доводил приложение до готового CRUD с JPA, Security и Data. Чем кончилось? Репозиторий архивирован в spring-attic — это официальное кладбище Spring — в октябре 2022, read-only, последний релиз ещё в 2019-м. Надгробие. Даже родная команда попробовала решить проблему генерацией и сдалась.
Живые же участники зоопарка чувствуют себя отлично:
-
JHipster — жив и активен (на момент написания — v9.1.0, июль 2026, десятки тысяч коммитов). Генерирует целые Spring Boot-приложения: сущности, CRUD, админ-интерфейсы, аутентификацию (JWT/OAuth2), RBAC, управление пользователями. То есть ровно тот код, который ты пишешь руками. Отдельная ирония: из коробки у JHipster
ROLE_USERиROLE_ADMINдают одинаковый доступ к сущностям — гранулярность прав придётся допиливать. Даже у зрелого генератора «безопасность из коробки» оказывается грубой; что тогда у тебя в@CheckPermission? -
Apache Causeway — top-level проект Apache Software Foundation, который поверх Spring Boot в рантайме генерирует UI, GraphQL и REST прямо из доменной модели — «без единого рукописного контроллера, шаблона или строчки JavaScript». Это уже не скаффолдинг, это metamodel-driven UI. И это ASF, а не маркетинг вендора.
-
Openkoda (MIT, ~1000 звёзд на момент написания) — бизнес-платформа на Spring Boot 3.x: аутентификация, ролевая модель, управление пользователями, мультиарендность, аудит-трейл и админ-дашборд «уже на месте, из коробки».
-
Erupt — поднимает полноценную админку с CRUD и RBAC из одной аннотации над сущностью за 2–5 секунд. Без фронтенда, без контроллеров.
А теперь выйди из мира Java и посмотри по сторонам — контекст добивает. У Django админка встроена в фреймворк: CRUD, аутентификация, права и аудит-лог из коробки, без гемов и плагинов. Скаффолдинг у Rails свой есть (rails g scaffold), а вот готовой админки уровня Django — нет, и поэтому там расплодился целый выводок гемов (ActiveAdmin, RailsAdmin, Administrate). Сам факт, что гемов несколько, тоже своего рода диагноз: встроенного решения нет, каждый лепит своё. А в Spring-мире есть проект jcrud с гениальным самоописанием: «Spring Booted Django admin clone». Человек буквально портирует чужую встроенную админку в Spring, потому что своей нет.
Складываем: надгробие Spring Roo + живой зоопарк генераторов + Spring-разработчик, вручную клонирующий Django admin. Это не мнение адептов opinionated-подхода. Это форма рынка. Рынок инструментов существует только там, где есть незакрытая потребность.
И да — тот самый «готовый слой конвенций» здесь зовут Джеймикс
Раз дочитал — вот честно и коротко, без списка «10 преимуществ». Джеймикс — это opinionated-фреймворк поверх Spring Boot для бизнес-приложений. Помнишь список из начала — твои BaseEntity, AbstractCrudController, самодельный слой прав, soft-delete, аудит? Джеймикс отдаёт ровно это, одним визардом, ещё до первой строки твоего кода:
-
сущность
User, роли, экран логина и готовый CRUD пользователей — а не «один Spring Security юзер с паролем в логе»; -
гранулярные политики доступа (Entity / Attribute / View / Menu) из единой декларации — рулят и бэком, и видимостью в UI разом;
-
soft-delete, оптимистичная блокировка (
@Version), аудит, миграции — дефолты, а не твой пятничный код; -
CRUD-вью генерируются, но правишь их руками — это code-first, а не рантайм-магия и не low-code.
Разница с твоим common не в том, что «оно делает то же». Разница в том, что это задокументировано, поддерживается не тобой и переживёт увольнение Пети.
«Но UI же на Vaadin!» — да, и это честный разговор
Знаю, что ты подумал именно в этом месте. Не «а безопасность?», не «а миграции?» — а «UI на Vaadin, фу, серверный стейт, спасибо, не надо». Это возражение №1 против Джеймикса, и оно заслуживает честного ответа, а не увиливания.
Да, UI Джеймикса построен на Vaadin Flow. Да, это серверный UI: компоненты живут на сервере, состояние экрана — в серверной сессии, браузер работает тонким клиентом. И да, для публичного масс-маркет-сайта с анонимным трафиком на миллионы это плохая идея: сессия на каждого посетителя, тяжелее кэшировать и раздавать через CDN, SEO — отдельная боль. Если кто-то в комментах напишет «на Vaadin нельзя построить нормальный публичный сайт» — он прав. Только это ответ не на тот вопрос.
Притормози и вспомни, о чём вообще статья. Мы не строим публичный лендинг. Мы строим LOB — внутреннее бизнес-приложение: админки, бэк-офис, конвейеры заявок, CRM. Ограниченное число известных, залогиненных пользователей. И вот здесь серверный UI — не компромисс, а фича:
-
Нет отдельного фронтенда. Ты не пишешь React/Vue/Angular, не держишь второй репозиторий, не нанимаешь фронтендера, не воюешь с webpack. UI — на Java, там же, где домен.
-
Нет REST-DTO-прослойки между фронтом и бэком. Не нужно проектировать API-контракт, версионировать его, маппить DTO туда-обратно, ловить рассинхрон фронта и бэка. Один язык, один дебаггер, один стектрейс от нажатия кнопки до строки в базе.
-
Тот самый boilerplate, который ты не написал. Помнишь свой
common? А теперь прибавь к нему рукописный SPA: роутинг, стейт-менеджмент, формы, валидация, дёрганье API. Для внутренней админки ты пишешь ВТОРОЕ приложение на JS — ровно то, чего Vaadin-подход не требует вовсе.
Честная граница ровно одна: нужен публичный высоконагруженный фронт — бери headless и свой фронтенд поверх (Джеймикс умеет отдавать данные как контент-бэкенд, но это отдельный разговор). Нужна внутренняя бизнес-система — серверный UI экономит тебе целый слой, который ты иначе будешь клепать руками. Вопрос тот же, что и с common: не «Vaadin или не Vaadin», а «готовый UI-слой на твоём языке — или ещё один самодельный фронт, который поддерживает всё тот же Петя».
Маленький спойлер второй части: на бенчмарке агент на китайской модели на голом Spring честно написал руками SPA фронт на полтысячи строк JavaScript. Он же на Джеймикс — ноль строк фронта. Эти строки тоже кто-то потом поддерживает, или их просто нет.
Блок В. Ты защищаешь контроль не над той переменной
Это — для тех, кто принимает решения, а не пишет AbstractController. Здесь холивар превращается в разговор про деньги.
Аргумент пуриста в переводе на язык бизнеса звучит так: «мы хотим полный контроль». Отлично. Только давай уточним, над чем контроль.
Контроль, за который бьётся пурист, — это контроль над «сантехникой»: над тем, как именно устроены базовая сущность, CRUD-эндпоинт, проверка прав, миграция и аудит. Но эту «сантехнику» ты прокладываешь одинаково в каждом проекте. Она не отличает твой продукт от продукта конкурента. В ней нет ни грамма твоей бизнес-ценности. Твоя ценность — в доменных правилах: как считается скоринг, как согласуется заявка, какие инварианты у сделки. Вот где контроль критичен. Вот где его нельзя отдавать.
Opinionated-фреймворк забирает у тебя контроль над сантехникой (который тебе не нужен) и оставляет полный контроль над доменом (который тебе нужен). Самопальный фреймворк делает наоборот: ты тратишь ресурс команды на 500-ю реализацию CRUD+security+audit — и гордишься тем, что своими руками проложил трубы, пока конкурент строил продукт.
У этой гордости есть цена, и её платят ЛПР:
-
Bus-factor. Готовый фреймворк документирован и поддерживается сообществом/вендором. Твой
common-пакет держится в голове у одного сеньора. Он уходит — уходит и понимание. -
Онбординг. Нового человека на Джеймиксе учит документация и большое сообщество. Нового человека в твоём внутреннем фреймворке учить некому и негде — только «спроси Петю».
-
TCO. Ты платишь не только за то, чтобы это написать. Ты платишь за то, чтобы это вечно чинить, документировать и объяснять — и делаешь это из своего кармана, а не из чужого.
-
Шаблонность. В хорошем смысле слова: фреймворк живёт конвенциями и стандартами. Раз увидел, что сделано путём А, — в следующий раз ты уже понимаешь, что надо тоже выбрать путь А. Это одновременно заставляет думать шаблонами и применять индустриально стандартные паттерны, а не придумывать костыли.
И это не только моя риторика. Инженеры, прошедшие через самопальные фреймворки, пишут об этом покаянные тексты. Björn Wilmsmann прямо называет внутренние фреймворки следствием NIH-синдрома (Not Invented Here) и предупреждает: они «становятся непрозрачными и переусложнёнными на удивление быстро», «текут абстракциями» и «закрывают лишь узкий набор кейсов, делая краевые случаи почти нерешаемыми». Эрик Дитрих посвятил отдельный текст выживанию в проектах с «ужасным корпоративным фреймворком», а Aaron Stannard разбирает, как благое намерение DRY вырождается в самодельный фреймворк-обузу. (Оговорюсь честно: это мнения практиков, а не эмпирические замеры. Но их подозрительно много, и все — про одно и то же.)
Решение всё ещё за тобой
Спойлер: написанное выше — не аксиома и не догма, а приглашение к дискуссии. Против пунктов — аргументируй.
Если ты десять лет строишь LOB-приложения на «голом» Spring — ты наверняка классный инженер, который принял рациональное решение в мире, где opinionated-фреймворки долго ассоциировались с legacy, вендор-локом и «магией». Ты оптимизировал понятную и уважаемую переменную — независимость от чужих решений.
Проблема не в тебе. Проблема в том, что ты оптимизировал не ту переменную. Контроль над сантехникой — это не то же самое, что контроль над продуктом. А цену за первое платят как за второе.
Открой ещё раз пакет common. Посчитай, сколько человеко-месяцев в нём лежит. А потом честно ответь себе: это ядро твоего продукта — или это ad hoc, informally-specified, bug-ridden реализация половины фреймворка, от которого ты отказался, чтобы «не потерять контроль»?
И это я ещё не начал про агентов

Всё вышесказанное — про мир, где код пишут люди. Помнишь ещё эти стародавние времена? Но теперь код всё чаще пишут агенты. И вот здесь у opinionated-фреймворка появляется второй, неожиданный козырь.
Конвенции, которые ты воспринимал как клетку для себя, — это рельсы для агента. Строгий фреймворк резко сужает пространство выбора: агент принимает меньше произвольных решений, меньше дрейфует, выдаёт единообразный код. Голый Spring даёт агенту девятнадцать способов настроить security — и, значит, девятнадцать способов ошибиться. Твой недокументированный common-пакет агент не знает вообще: он будет героически угадывать твои конвенции и в среднем угадывать неверно.
Звучит как ещё один холиварный тезис? Согласен. Поэтому во второй части я не буду им размахивать — я положу на стол цифры. Реальный бенчмарк: два плеча, одна модель, одна задача, голый Spring против Джеймикса. Токены, деньги, кэш, количество ручных вмешательств и — самое интересное — классы багов, которые один стек исключает by design, а другой честно наступает на каждый.
Вот там и поговорим про «получается хуже» — уже не риторикой, а числами.
Но вторая часть будет позже, а комментарии открыты прямо сейчас — и я знаю, что ты уже дописываешь аргументированный и конструктивный (ведь да?) ответ. Давай по-честному.
Если у тебя есть боевой Spring-проект старше двух лет без самопального BaseEntity, generic-CRUD и самодельного слоя прав внутри — брось ссылку в комментарии. Не «у нас всё чисто, поверь на слово», а репозиторий. Один такой пример — и я публично признаю, что тезис не универсален.
Со всех остальных — чистосердечное: как называется ваш внутренний фреймворк, кто его последний живой мейнтейнер и сколько лет его уже «вот-вот отрефакторят»?
И чтобы ругать предметно, а не по памяти — вот сам виновник, Джемикс: сайт, документация и исходники на GitHub. Потыкай, прежде чем писать в комментах, что «это лоукодная игрушка».
Да начнётся холивар. 🍿
Продолжение следует.
Источники
Анти-паттерны:
-
Inner-platform effect — Wikipedia; первоисточник — The Daily WTF, Alex Papadimoulis, 2006
-
NIH-синдром / внутренние фреймворки — Björn Wilmsmann, 2016 (мнение практика)
Зоопарк скаффолдеров / генераторов:
Самопальный код (живые примеры):
Покаянные тексты:
Цифры звёзд/версий/коммитов актуальны на момент написания (июль 2026) — перед публикацией освежить.
ссылка на оригинал статьи https://habr.com/ru/articles/1059692/