Java
Build automation
Comments 62
+6
После того, как maven перестанет качать всякую дрянь из интернета

Ад, конечно.
UFO landed and left these words here
+2

Это куда более характерно для ant'а, в котором это очень сильно зависит от того как именно написали build.xml. mvn -o и использование внутреннего nexus'а — наше усё.

0
Вообще-то Ant по умолчанию вообще ничего на тащит из интернета и не требует его. Если Ant-скрипт что-то и тянет оттуда, то это программист своими очумелыми ручками сделал такой custom-таск (ну, или вставил сторонний таск «для улучшения»).

Тянуть что-либо со стороны — это как раз maven (ну и gradle).

Автору: статья расчитана на новичков, не умеющих делать сборку. Почему вы не началим с простейшего срособа собрать «hello world» без сторонних систем сборок? Или это уже не требуется от желающих найти работу?
0
Вообще-то Ant по умолчанию вообще ничего на тащит из интернета и не требует его. Если Ant-скрипт что-то и тянет оттуда, то это программист своими очумелыми ручками сделал такой custom-таск (ну, или вставил сторонний таск «для улучшения»).

Я в курсе. Обычно народ пишет таск для выкачивания зависимостей для сборки и далеко не всегда использует нормальные средства (типа ivy, который, собственно, используется gradle и sbt), которые нормально работают с кэшами и имеют offline режим.

0

Ну да, тут совершенно согласен. Я вообще сначала думал запустить программу через простой вызов бинарника java. Но потом решил, что раз уж в статье акцент на maven, то надо делать им.

+1

Я не помню такого этапа жизненного цикла у maven. Может быть вы имели в виду package?

0
да package, прошу прощение мое общение с maven окончилось 3 года назад но точно помню что compile на выходу jar и war не давал
а чтобы отработал mvn package необходимо указать entity point
а еще лучше mvn deploy
-2

Для того, чтобы объяснить что такое mvn package, нужно объяснить что такое jar и war и, возможно, рассказать про этапы жизненного цикла. По моему, для первого знакомства это слишком много.
Я считаю, что про jar нужно рассказывать в статье про то, как подключить библиотеки, а про стадии жизненного цикла в статье про то, как запустить юнит-тесты.

0
возможно

но тогда зачем рассказывать человеку о maven если можно использовать javac?
и почему именно maven когда я несколько лет сталкивался с java везде повально перезжали на gradle и maven был только там где это исторически сложилось.

Статья ваша вам, видней, по поводу mvn build да был не прав не так написал, имел ввиду именно package.
0

Видимо надо было подробнее остановиться на вопросе о том, зачем нужен maven, когда есть javac.


maven, помимо того, что о чём написано в статье может делать ещё очень многое. Он может скачать используемые в проекте библиотеки, может разложить куда надо ресурсы может запустить юнит тесты. Кроме того, как верно заметил grossws, он позволяет описать проект и этим описанием может воспользоваться любая современная IDE.


Gradle хорош, но он не стандарт индустрии. Без знания maven пока что обойтись не получится.

0
да именно об этом я и хотел сказать что maven здесь не до конца раскрыт, для чего может применяться и как его применять и в чем он именно может помочь, просто мне не удалось это понятно изложить.

про gradle возможно(сколько людей столько и мнений)
и знаю что maven central repository стандарт де факто, который кстате в gradle используется.
0
Gradle хорош, но он не стандарт индустрии. Без знания maven пока что обойтись не получится.

Не соглашусь с первой частью, но соглашусь со второй.


Насколько я видел по android-проектам, gradle там является стандартом de facto для сборки.


В мире же java se, когда используют gradle, sbt, lein или ant для библиотек — всё равно генерируют pom (хотя при использовании ant'а это бывает несколько реже), описывающий проект, но не сборку: всякие вещи типа project/distributionManagement, project/scm, project/mailingLists и т. п. Например, см. фрагмент из sbt'шных скриптов akka.

+1

Вы не смотрели эпик баттл между gradle, maven и svt? Там Барух Садогурский (один из адептов gradle и groovy) говорит, что gradle хорошо, но для кровавого энтерпрайза не готов потому, что слишком гибок.


Хотя про андроид я конечно немного забыл :)

+2

И, в качестве project model для IDE, gradle, боюсь, никогда не потянет в силу той же гибкости и динамичности.


Той же idea приходится исполнять build.gradle на каждый чих при его изменениях, и с десятком зависимостей и без модулей/плагинов это уже становится не менее дорогой операцией, чем изменение зависимостей в maven-проекте с парой-тройкой сотен транзитивных зависимостей и десятком профилей сборки.

UFO landed and left these words here
0

Для maven'а существовали (и местами существуют) плагины для генерации проекта под конкретную ide (типа m2e), но использование их, а равно описываемого вами генератора для проекта, имеет один фатальный недостаток: это дополнительное ручное действие, которое надо не забыть сделать после модификации pom.xml/build.gradle.


Рано или поздно оно забывается, а дальше — happy-debug. Ловля проблем с неконсистентными версиями зависимостей — очень неприятное развлечение.

UFO landed and left these words here
+1

maven package по умолчанию (при packaging=jar) соберёт jar без зависимостей и запускаться он не будет. Чтобы он запускался надо сделать одно из двух:


  • собирать uberjar (с помощью assembly/shade/jarjar/onejar) с указанием Main-Class в манифете (можно сделать, например, через plugin/configuration/archive/addManifestEntries/mainClass в рамках maven-jar-plugin/maven-shade-plugin или в assembly дескрипторе)
  • собирать jar+deps (можно использовать к mainClass добавить addClasspath плюс опционально classpathPrefix и сложить зависимости в classpath prefix с помощью maven-dependency-plugin'а.

Оно может работать автоматически, если настроено в parent pom'е, но в корневом parent pom'е (который используется по умолчанию) этого нет. Ниже примеры из моего parent'а, которые я использую для сборки uberjar'ов и standalone jar + libs для случаев типа embedded jetty + weld (реализация CDI), которые не работают в режиме uber jar'а либо требуют дополнительной хитрой настройки для работы.


Любой из вариантов ниже (plugin и ниже по дереву) можно скопировать в project/build/plugins.


uberjar
    <!-- uberjar -->
    <profile>
      <id>uberjar-assembly</id>

      <activation>
        <file>
          <exists>.uberjar-assembly</exists>
        </file>
      </activation>

      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>

            <configuration>
              <finalName>${project.build.finalName}-uber</finalName>

              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>${mainClass}</mainClass>
                </transformer>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                  <resource>reference.conf</resource>
                </transformer>
                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                  <resource>META-INF/spring.handlers</resource>
                </transformer>
                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                  <resource>META-INF/spring.schemas</resource>
                </transformer>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer" />
                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
                  <addHeader>false</addHeader>
                </transformer>
              </transformers>
            </configuration>

            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>shade</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

Наличие в проекте файла .uberjar-assembly подключит этот профиль и он будет генерировать jar с classifier'ом uber, сконфигурированный для запуска через java -jar. Требует наличие в проекте property mainClass.


assembly с лежащими отдельно библиотеками
    <!-- app assembly -->
    <profile>
      <id>app-assembly</id>

      <activation>
        <file>
          <exists>.app-assembly</exists>
        </file>
      </activation>

      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>

            <configuration>
              <archive>
                <manifest>
                  <addClasspath>true</addClasspath>
                  <classpathPrefix>lib/</classpathPrefix>
                  <mainClass>${mainClass}</mainClass>
                </manifest>
              </archive>
            </configuration>
          </plugin>

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>

            <executions>
              <execution>
                <phase>compile</phase>
                <goals>
                  <goal>copy-dependencies</goal>
                </goals>
              </execution>
            </executions>

            <configuration>
              <outputDirectory>${project.build.directory}/lib</outputDirectory>
              <stripVersion>false</stripVersion>
            </configuration>
          </plugin>

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>

            <dependencies>
              <dependency>
                <groupId>org.example</groupId>
                <artifactId>example-assemblies</artifactId>
                <version>1</version>
              </dependency>
            </dependencies>

            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
                <configuration>
                  <descriptorRefs>
                    <descriptorRef>app</descriptorRef>
                  </descriptorRefs>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

В org.example:example-assemblies:1:jar должен быть доступен дескриптор такого вида (положить в src/main/resources/assemblies/app.xml):


<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
  <id>app</id>

  <formats>
    <format>tar.gz</format>
  </formats>

  <includeBaseDirectory>false</includeBaseDirectory>

  <files>
    <file>
      <!-- fix extra space before `source` tag below -->
      < source>target/${project.build.finalName}.jar</source>
      <outputDirectory/>
      <destName>${project.artifactId}.jar</destName>
    </file>
  </files>

  <dependencySets>
    <dependencySet>
      <outputDirectory>lib</outputDirectory>
      <useProjectArtifact>false</useProjectArtifact>
    </dependencySet>
  </dependencySets>
</assembly>

Профиль включается наличием файла `.app-assembly` и генерирует `.tar.gz` с приложением и его зависимостями в директории `lib/`.

В случае packaging=war всё проще, так как war содержит необходимые зависимости в себе и это обеспечивается maven-war-plugin'ом автоматически. Правда, в зависимости от того для servlet container'а оно или для application server'а разный набор зависимостей должен быть со scope=provided.

0

По ссылке статья о том, как собрать код на java, не используя системы сборки. Я делал акцент на maven. Конечно таких руководств тоже много. Возможно пользоваться моим кому-нибудь будет проще, чем каким-то другим.

0
Maven позволяет разруливать нависимости
Цена на самом деле не велика, правильно настроенный pom.xml
0

Про это я хочу написать отдельную статью. Благо тема, если её раскрывать полностью, заслуживает чуть ли не книги.

0
А стоит ли? Мне кажется что maven своего рода инструмент как git, выполняет свою задачу на отлично.
Но на самом деле если сделать как https://git-scm.com/book/ru/v1/, то это будет весьма похвально
0

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

+2

Особенно весело, что хорошая книга уже есть. Это даже без учёта maven by example.


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

0

Я специально остановился на абсолютном минимуме. Тем, кто хочет научиться пользоваться maven этой статьи конечно недостаточно. Она предназначена для тех, кто хочет понять зачем нужен мавен и провести с ним первое знакомство.

+2

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

0

Про то, что в maven есть такая сущность как проект — есть. Про структуру проекта в maven тоже есть. Минимальный помник есть. Что означают обязательные строки в этом помнике — есть. Есть даже про то, что IDE может создать проект в собственном формате на основме pom.xml, но наверное на этом надо было сделать больший акцент.


Что ещё, по вашему мнению, нужно было добавить к минимуму?

+1
Зачем нужен maven, проектная модель и т.д.
Вы показали, как при помощи этого микроскопа забить гвоздь, который можно забить javac ом, но не показали, зачем он, maven, нужен вообще. Мне, как новичку, непонятно, а зачем надо делать вот так, именно так. Зачем структурировать проект именно таким образом и т.д.
-1

Есть объяснение, зачем нужны систем сборки вообще. Оно очень короткое. Я опасаюсь, что если сделать его длиннее, то потеряется фокус статьи.

0
Без претензий, я просто задумался, как, например, я бы объяснил, зачем нужен make и makefile'ы, если мы можем собрать проект из Visual Studio. Я бы взял простой случай из DDK или что-то аналогичное, где используется, скажем, некоторое количество модулей на ассемблере, несколько модулей на языке С, объяснил бы, как это будет строиться, как почистится мусор, как определится, что нужно откомпилировать, и как все соберется. А потом показал бы дооолгий и нудный путь того же самого, но руками.
0
Пользуясь случаем хочу спросить:
Как можно избежать передеплоя всего war-файла, если измеился только один class-файл?
Эклипс как-то ругнулся на Ctrl+S что, мол "… не поддерживаю hot redeploy..." но я не понял что ему нужно…

+2

Если для разработки, то можно использовать dcevm. Если для production'а, то есть штуки типа rebel'а, но не стоит ожидать, что это будет стоить сколь-либо гуманно.

+2
А зачем запускать с помощью мавена? И можно ли как-то сделать из class exe-файл, что бы без консоли и батников запускать?
0

Запускать с помощью мавена не обязательно, но в статье акцент на использование мавена и поэтому я решил привести пример запуска с его помощью.


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

+2
Можно сделать exe c помощью Excelsior JET. AOT компиляция в gnu gcj была, но проект давно мертв… На днях опубликую статью про запуск java проекта сервисом, ссылку выложу тут.
+2
Есть стоковый Java FX packager (но только в oracle jdk вроде с 7 версии, в 8 точно есть), он умеет создавать нативные сборки.
https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/self-contained-packaging.html

Не уверен насчет non-fx аппов — мельком видел, что без UI может глючить. Не знаю так ли это, использовал для Java FX приложения, для сервера особого смысла в принципе и нет.
0
Спасибо! Интересный способ, не знал.
А как с лицензией на распространения oracle jre со своим приложением?
+1
Все нормально, это легальный способ, специально открытый разработчикам.
Подробно не скажу, но есть определенные несложные правила — не менять состав jre, оставить файлы лицензий и т.п.
0
Шутка с бородой «В качестве ОС для компьютера в храме всегда выберут windows. Ведь в windows — иконы и службы, а в linux — демоны и зомби».
+1
«Дорогая, в интернете кто-то неправ»…
хотел написать комментарий с кучей замечаний… но решил всё-таки его в личку отправить…
Впрочем пару моментов здесь опишу:

> Сразу скажу, что Java программиста, который не может собрать свою программу из консольки, на работу не возьмут

— вплоть до мидла возьмут. Умение составлять грамотные билд-файл требуется нечасто и 1-2х человек на проект хватает вполне.

> После того, как maven перестанет качать всякую дрянь из интернета

вы вроде мануал пишете? Для новичков? Ну и зачем засорять неокрепшие умы такой фигнёй? Неужели тяжело было написать что-то вроде после того, как мавен скачает зависимости и инструменты, определённые в проектном файле (а также maven-exec-plugin, к которому вы и обратились командой exec:java)"

А ещё можно было рассказать, что можно разом mvn compile exec:java -Dexec.mainClass=«com.app.HelloWorld»
0

Спасибо за рекомендации. Я думаю, что то, что вы написали в личку нужно было писать в коментарии. Это интересно всем, не только мне.


вы вроде мануал пишете? Для новичков? Ну и зачем засорять неокрепшие умы такой фигнёй?

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

0
Возможно ламерский вопрос, но что означает слово SNAPSHOT в версиях артифактов?
0

Оно означает, что артифакт нестабилен и может измениться без изменения версии. Мавен понимает, что это может произойти и обновляет артифакт при каждой сборке.

0
Ещё из особенностей — обычная версия не имеет права изменяться в мавен-репозитории (а вот снепшот — может, потому и идёт проверка при каждой сборке).
0

Действительно не при каждой, это ценное замечание, я сильно упрощаю. SNAPSHOT версии будут обновляться, если с момента предыдущего получения зависимости из удалённого репозитория и до текущего запуска maven прошло больше суток. Интервал можно настраивать через repository->shapshots->updatePolicy.


Опция -U обновит снепшоты принудительно, независимо от интервалов и всего такого.

0

Плюс можно в repository/snapshots/updatePolicy указать always. При использовании nexus'а на небольшом расстоянии (в смысле rtt) довольно удобно.

0

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

0
Был бы очень интересно читать, если бы в статье было написано о работе с несколькими подпроектами в одном проекте. Ведь maven это могет.
0

Это тема для отдельной статьи, я надеюсь её написать. Но вообще следующую я планирую написать про то, как подключать сторонние библиотеки.

Only those users with full accounts are able to leave comments.  , please.