Комментарии 16
Ещё много изменений произошло в Actuator.

Знаю один из проектов, который ещё не переехал на СБ2 именно из-за Актуатора.


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


public class CustomAttributeSource extends AnnotationTransactionAttributeSource {
  @Override
  protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
    return new DefaultTransactionAttribute() {
      @Override
      public boolean rollbackOn(Throwable ex) {
        return super.rollbackOn(ex) || ex instanceof CustomCheckedException;
      }
    };
  }
}

На чистом Спринге работало, после переезда на СБ1 транзакции откатываться перестали.

Про Gradle не понял. Ни разу не приходило в голову применить boot плагин для всех подпроектов без разбора… А если там вообще нет java кода?

Зависит от проекта. В нашем случае он состоит только из Java-подпроектов, лишь один из которых не является Spring Boot приложением. А всё, что не на Java, мы держим в других репозиториях.

ещё не переехал на СБ2 именно из-за Актуатора

А что конкретно не дает переехать? Интересно узнавать о новых граблях от коллег по цеху.


Насчёт транзакций сам с таким не сталкивался, но уже не в первый раз слышу о подобных проблемах. Я бы в первую очередь выяснил, заходит ли выполнение в метод rollbackOn, чтобы разбить область поиска на два взаимоисключающих участка:


  • Если не заходит, то стоит покопать в сторону того, как регистрируется CustomAttributeSource: точно ли его видят регистрирующие бины (в том числе самописные), и точно ли эти бины сами активны (намекаю на соответствующие классы *AutoConfiguration).
  • Если же выполнение заходит сюда, то надо убедиться, не обёрнуто ли целевое исключение в какое-либо другое (каковых в Spring'е целая иерархия). В случае обёртки (да и не только в нем) следует проверять на instanceof не само исключение, а его корень, например, через Throwables#getRootCause() из Guava.

Точно не скажу, разговор был формата курилки. Спросил про миграцию на СБ2, вылезло несколько проблем, а поскольку задача была не очень важной, то занимались ей в перерывах между основной работой.


Вот что запомнилось точно — проблемы со Спринг Датой. Начиная с версии 2 изменились названия ключевых методов в JpaRepository:


interface JpaRepository<T, ID> {
  //было
  <T> T findOne(ID id);
  <T> List<T> findAll(Iterable<ID> ids);

  //стало
  <T> Optional<T> findById(ID id);
  <T> List<T> findAllById(Iterable<ID> ids);
}

В проекте несколько десятков репозиториев и тысячи обращений к указанным методам. Миграция "в лоб" (использование новых методов) зацепила бы каждый второй файл. Поэтому воспользовались возможностью подгонки репозиториев под свои нужды:


//основа для всех репозиториев
@NoRepositoryBean
public interface BaseJpaRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
  // определяем метод findOne, аналогичный тёзке, существовавшему в версиях 1.*
  @Deprecated
  T findOne(ID id);

  // тоже для findAll
  @Deprecated
  List<T> findAll(Iterable<ID> ids);
}

public class BaseJpaRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseJpaRepository<T, ID> {

  private JpaEntityInformation<T, ?> entityInfo;
  private EntityManager entityManager;

  public BaseJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInfo, EntityManager entityManager) {
    super(entityInfo, entityManager);
    this.entityInfo = entityInfo;
    this.entityManager = entityManager;
  }

  //обеспечиваем совместимость поведения
  @Override
  public T findOne(ID id) {
    return findById(id).orElse(null);
  }

  @Override
  public List<T> findAll(Iterable<ID> ids) {
    return findAllById(ids);
  }
}

//какой-нибудь репозиторий
interface SomeRepository extends BaseJpaRepository<SomeEntiy, Lond> {
}

И о чудо! Все ошибки компиляции исчезают, код работает как и прежде, а изменено всего 2 класса, а не 200. Теперь можно неспешно заменять устаревшее АПИ на новое, благо "Идея" заботливо подсветит все вызовы помеченные @Deprecated.

Спасибо, что поделились!
У меня был схожий опыт с JPA, только нужно было отвязать прикладной код от походов в БД статическими методами Play 1.x, чтобы покрыть код unit-тестами без PowerMockito. Впрочем, тогда машстаб вышел более широким — таки пришлось задеть пару сотен классов. К счастью, правки оказались простыми.
Не за что, мне очень понравились ваш доклад и эта статья, по его следам думаю написать статью про Спринг Бут и некоторые его особенности.
Держите в курсе — с удовольствием почитаю и поделюсь с коллегами.
Можно было просто
  default T findOne(ID id) {
    return findById(id).orElse(null);
  }

в BaseJpaRepository добавить.
Можно и так, правда, в этом случае часть методов, объявленных в интерфейсе и тело будет иметь только в интерфейсе, другая же часть будет реализована в классе. ИМХО, лучше уже всё делать единообразно.

Спасибо! Очень понравился стиль изложения!


Честно, устал от косноязычных переводов про спринг бут на Хабре… Эта статья прям как глоток свежего воздуха!

Мне все больше и больше кажется что Spring это котел с ЧОРНОЙ МАГИЕЙ и контролировать ее становится все трудней.

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

25 марта 2012

Местоположение

Россия

Сайт

jugru.org

Численность

51–100 человек

Дата регистрации

22 августа 2013

Блог на Хабре