Статьи

Как поддерживать Java 6, 8, 9 в одном API

В jOOQ 3.7 мы наконец-то добавили формальную поддержку функций Java 8. Это открыло двери для многих приятных улучшений, таких как:

Создание потоков результатов

01
02
03
04
05
06
07
08
09
10
try (Stream<Record2<String, String>> stream =
     DSL.using(configuration)
        .select(FIRST_NAME, LAST_NAME)
        .from(PERSON)
        .stream()) {
 
    List<String> people =
    stream.map(p -> p.value1() + " " + p.value2())
          .collect(Collectors.toList());
}

Вызов операторов асинхронно (jOOQ 3.8+)

1
2
3
4
5
6
7
CompletionStage<Record> result =
DSL.using(configuration)
   .select(...)
   .from(COMPLEX_TABLE)
   .fetchAsync();
 
result.thenComposing(r -> ...);

Но очевидно, что мы не хотели разочаровывать наших платящих клиентов, которые застряли на Java 6 из-за того, что они использовали старый сервер приложений и т. Д.

Как поддерживать несколько версий Java в одном API

Вот почему мы продолжаем публиковать версию jOOQ на Java 6 для наших коммерческих клиентов. Как мы это сделали? Очень легко. Наша коммерческая кодовая база (которая является нашей основной кодовой базой) содержит тонны «флагов», как в следующем примере:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public interface Query
extends
    QueryPart,
    Attachable
    /* [java-8] */, AutoCloseable /* [/java-8] */
{
 
    int execute() throws DataAccessException;
 
    /* [java-8] */
    CompletionStage<Integer> executeAsync();
    CompletionStage<Integer> executeAsync(Executor executor);
    /* [/java-8] */
 
}

(Конечно, AutoCloseable был доступен уже в Java 7, но у нас нет версии для Java 7).

Когда мы собираем jOOQ, мы собираем его несколько раз после использования препроцессора для удаления логики из исходных файлов:

  • Коммерческая версия Java 8 создается сначала как есть
  • Коммерческая версия Java 6 создается вторым путем удаления всего кода между маркерами [java-8] и [/java-8]
  • Коммерческая бесплатная пробная версия создается путем добавления некоторого кода в коммерческую версию
  • Версия с открытым исходным кодом создается третьим путем удаления всего кода между маркерами [pro] и [/pro]

Преимущества этого подхода

Есть несколько преимуществ этого подхода по сравнению с другими:

  • У нас есть только один источник правды, оригинальный коммерческий исходный код.
  • Номера строк одинаковы во всех разных версиях
  • API-интерфейсы в определенной степени совместимы
  • Никакое волшебство не вовлечено через загрузку класса или отражение

Недостатки:

  • Фиксация в репозитории немного медленнее, так как у нас есть несколько репозиториев.
  • Публикация релизов занимает больше времени, так как нужно создавать разные версии и тестировать интеграцию несколько раз
  • Иногда мы просто забываем добавить маркер и приходится перестраивать заново, когда происходит сбой ночной сборки Java-6
  • Мы все еще не можем использовать лямбда-выражения в обычном коде, который содержится в версии Java 6 (большая часть кода)

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

Мы с нетерпением ждем поддержки функций JDK 9, таких как модульность и новый Flow API, без каких-либо компромиссов для существующих пользователей.

А что насчет тебя?

Как вы подходите к кросс-совместимости версий JDK?

Ссылка: Как поддерживать Java 6, 8, 9 в одном API от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ .