Maven вопросы для начинающих - хотя и несколько сложная настройка проекта - PullRequest
1 голос
/ 18 января 2011

Так что я бы классифицировал себя как старшего разработчика с небольшим опытом работы с Java.Я работаю над небольшим любимым проектом, который в основном представляет собой настольное приложение с sdk для плагинов и набор плагинов, которые приложение загружает, пока они реализуют интерфейсы, определенные в sdk.Это выглядит примерно так:

Структура проекта

main-app
|---pom.xml (depends on <sdk>)
|---src
    |---[com.etc…]
|---target
    |---main-app.jar (does this include sdk.jar?)


sdk
|---pom.xml
|---src
    |---[com.etc…]
        |---IPlugin (public interface IPlugin)
|---target
    |---sdk.jar

(sdk - defines the interface that plugins need to implement)


plugins
|---plugin1
    |---pom.xml (depends on <sdk>)
    |---src
        |---[com.etc…]
    |---target
        |---plugin1.jar

plugin1 is a plugin that implements IPlugin interface and has the following classpath
<com.foo.plugin1>

deploy
|---app.folder
    |---main-app.jar
    |---sdk.jar
    |---plugins.folder
        |---plugin1.jar


При запуске приложения main.app анализирует папку plugins.folder и открывает каждый файл jar - ищет элемент вманифест, который определяет путь к классу плагина, который реализует интерфейс IPlugin.

Существует несколько концепций maven / jar, с которыми у меня возникают проблемы ...

  • Моя папка развертыванияна данный момент фантазия.Не существует.У меня нет знаний, чтобы сделать это существующим.В настоящее время у меня есть отдельный файл JAR в каждом подпроекте (или модуль, как они называются в IntelliJ)
  • Должен ли main-app.jar включать в него классы sdk?
  • Если нет, то как мне развернуть файл main-app.jar, чтобы он знал о sdk.jar и куда мне поместить sdk.jar?
  • Есть ли способ добавить настраиваемое поле в манифест jar plugin1?файл, где я могу указать его путь к классу для основного приложения, чтобы связать его с интерфейсом IPlugin?

Пока что мои файлы pom.xml очень просты.Они в основном определяют groupID, artifactID и тип упаковки (JAR), а также их зависимости.вот и все.

В настоящее время основное приложение (без плагинов) успешно собирается и запускается в IntelliJ - но это никак не помогает мне с пакетом развертывания.

Редактировать:

Просто чтобы прояснить ... main-app и sdk создаются и развертываются во время разработки.plugin1 добавляется третьей стороной в папку plugins.folКак сторонние разработчики указывают свой путь к классу в файле манифеста plugin.jar, используя maven?

Ответы [ 3 ]

1 голос
/ 18 января 2011

Если main_app не является веб-приложением и зависит от других jar-файлов, и если вам нужно distribute, одним из способов будет создание сборки (например, файла .zip или .tar.gz).который включает main_app.jars и зависимые файлы jar. Плагин Maven Assembly может помочь вам в этом.

Вы можете выполнить настройку манифеста, используя Плагин Maven Jar

0 голосов
/ 20 января 2011

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

Во-первых, я бы разбил ваш код на несколько модулей и выложил его какследующим образом:

pom.xml
/src
    /app
        /app-name
            pom.xml
            /src ...
        /app-name-sdk
            pom.xml
            /src ...
        /deployment
            pom.xml
            /src
                /assembly
                    image.xml
                /main
                    /app-folder
                        /bin
                            startup-script.sh
                            startup-script.bat
                        /etc
                            config.conf
                            ...
    /plugins
        /plugin-A
            pom.xml
            /src ...
        /plugin-B
            pom.xml
            /src ...

На этом этапе вы логически разделили все компоненты по частям, оставив на виду, где все находится, упакованы в логические группы.(Теперь это не похоже на тошноту папки, когда я проверяю это снова, так как теперь я могу держать каталоги / doc и / bin на верхнем уровне и знать, что подкаталоги в / src описывают, что находится в каждом связанном подмодуле.)

На этом этапе pom.xml верхнего уровня должен выглядеть примерно так:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <artifactId>app-name-parent</artifactId>
    <groupId>com.mycompany.my-app</groupId>
    <version>1.3.2-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>[Parent]  My App</name>

    <modules>
        <!-- App -->
        <module>src/app/app-name</module>
        <module>src/app/my-app-sdk</module>

        <!-- Plugins -->
        <module>src/plugins/plugin-A</module>
        <module>src/plugins/plugin-B</module>

        <!-- Packaging -->
        <module>src/app/distribution</module>
    </modules>

    <properties>
        <!-- Useful properties to define here -->
        <scm.revision>USER</scm.revision>
        <compiler.debug>true</compiler.debug>
        <compiler.optimize>false</compiler.optimize>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <!-- If you're not going to version your plugins with the parent,
             then you should pick out the specific version info here 
             for each plugin.  That way, you could just update individual plugins.
             If this is to be packaged up and shipped together, it's probably not necessary.
        -->
        <plugin-A.version>1.1</plugin-A.version>
        <plugin-B.version>1.3</plugin-B.version>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                        <debug>${compiler.debug}</debug>
                        <optimize>${compiler.optimize}</optimize>
                        <fork>true</fork>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.5</version>
                    <configuration>
                        <includes>
                            <include>**/*Test.java</include>
                        </includes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <dependencyManagement>
        <dependencies>

            <!-- Test Dependencies -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.3.1</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <profiles>
        <profile>
            <id>release</id>

            <properties>
                <compiler.debug>false</compiler.debug>
                <compiler.optimize>true</compiler.optimize>
            </properties>
        </profile>

        <profile>
            <id>ci-server</id>

            <activation>
                <property>
                    <name>env.SVN_REVISION</name>
                </property>
            </activation>

            <properties>
                <scm.revision>${env.SVN_REVISION}</scm.revision>
            </properties>
        </profile>
    </profiles>
</project>

Тогда все ваши дочерние модули должны определить ссылку на родительский элемент, вот так:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>app-name-parent</artifactId>
        <groupId>com.mycompany.my-app</groupId>
        <version>1.3.2-SNAPSHOT</version>
        <relativePath>../../..</relativePath>
    </parent>

    <groupId>com.mycompany.my-app</groupId>
    <artifactId>app-name</artifactId>

    <name>[App]    My App</name>
    <description>
        TODO
    </description>

    <dependencies>
         <!-- System dependencies -->
        <dependency>
            <groupId>${project.parent.groupId}</groupId>
            <artifactId>app-name-sdk</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- Test Dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Ради любви ко всему святому и правильному в этом мире, не пытайтесь упаковать все в один из модулей, связанных с выводом jar.Это неправильно, и все те, кто это делают, шунт .

Я шучу.

А если серьезно: разбейте процесс упаковки на отдельный модуль,здесь модуль src/app/deployment для упаковки других артефактов сборки.Тогда он действительно зависит только от других компонентов системы и может выглядеть примерно так:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>app-name-parent</artifactId>
        <groupId>com.mycompany.my-app</groupId>
        <version>1.3.2-SNAPSHOT</version>
        <relativePath>../../..</relativePath>
    </parent>

    <groupId>com.mycompany.my-app</groupId>
    <artifactId>deployment</artifactId>
    <packaging>pom</packaging>

    <name>[App]     Deployment Image</name>
    <description>
        TODO
    </description>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <id>image</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <tarLongFileMode>gnu</tarLongFileMode>
                            <descriptors>
                                <descriptor>src/assembly/image.xml</descriptor>
                            </descriptors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>${project.parent.groupId}</groupId>
            <artifactId>my-app</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <!-- Notice the separate group namespace element 'plugins', for clarity -->
            <groupId>${project.parent.groupId}.plugins</groupId>
            <artifactId>plugin-A</artifactId><!-- Or project.version, depending... -->
            <version>${plugin-A.version}</version>
        </dependency>
        <dependency>
            <groupId>${project.parent.groupId}.plugins</groupId>
            <artifactId>plugin-B</artifactId>
            <version>${plugin-B.version}</version><!-- Or project.version, depending... -->
        </dependency>
    </dependencies>
</project>

Затем вы можете использовать файл дескриптора сборки (здесь, image.xml), чтобы упаковать все в одинсвязное целое, вот так:

<assembly>
    <id>image</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>

    <dependencySets>
        <!--  Everything  -->
        <dependencySet>
            <outputDirectory>/app-folder/jars</outputDirectory>
            <useProjectArtifact>false</useProjectArtifact>
            <fileMode>0644</fileMode>
            <directoryMode>0644</directoryMode>
            <!-- This includes all transitive, <scope>compile</scope> dependencies -->

            <includes>
                <include>${project.parent.groupId}:*</include>
            </includes>
        </dependencySet>
    </dependencySets>

    <!--  Packaged scripts, config files, etc.  -->
    <fileSets>
        <fileSet>
            <outputDirectory>/app-folder/bin</outputDirectory>
            <lineEnding>unix</lineEnding>
            <fileMode>0755</fileMode>
            <directoryMode>0744</directoryMode>
            <filtered>false</filtered>

            <directory>src/main/app-folder/bin</directory>
            <includes>
                <include>**/*</include>
            </includes>

            <!--  Some weird files are added here, for some reason  -->
            <excludes>
                <exclude>*.*.formatted</exclude>
            </excludes>
        </fileSet>
        <fileSet>
            <outputDirectory>/app-folder/etc</outputDirectory>
            <lineEnding>unix</lineEnding>
            <fileMode>0640</fileMode>
            <directoryMode>0744</directoryMode>
            <filtered>true</filtered>

            <directory>src/main/app-folder/etc</directory>
            <includes>
                <include>**/*</include>
            </includes>

            <!--  Some weird files are added here, for some reason  -->
            <excludes>
                <exclude>*.*.formatted</exclude>
            </excludes>
        </fileSet>
    </fileSets>
</assembly>

С упаковкой вы можете стать намного интереснее, но это голые кости, которые доставят вас на 90% пути.

Извините заПродолжительность этого, но я делаю это много , и следование этой практике действительно делает все намного чище и легче понять, особенно если мне придется возвращаться к этому спустя месяцы.

0 голосов
/ 18 января 2011

Возможно, я не понял вашего вопроса.Но похоже, что вы пытаетесь достичь тривиально. Ваше основное приложение зависит от двух других модулей.Так что вам просто нужно добавить тег зависимости в ваш основной проект приложения, ссылающийся на дочерние модули.(Я оставлю область действия пустой).

Допустим, ваш pom для модуля плагинов выглядит следующим образом.

<groupId>om.foo.plugin1</groupId>
<artifactId>plugin1</artifactId>
<version>1.0</version>

Просто добавьте соответствующий тег зависимости в основной модуль.*

Еще одна небольшая вещь: необходимо построить зависимости с помощью mvn clean install, прежде чем вы сможете собрать родительский объект.

...