Maven et Eclipse: chargement des propriétés par défaut dans le projet de bibliothèque maven et utilisez-le dans Jar exécutable

je crois que ce problème a déjà été posé sur stackoverflow. Et je tiens à mentionner que j'ai essayé les solutions qui sont venus avec les questions liées à la mienne. Celui qui s'est le plus rapproché de mon problème était: Charger le fichier de propriétés dans le BOCAL?.
<!-Malheureusement, la solution décrite n'a pas fonctionné pour moi. Et en raison de l'âge de la question, je pensais demander à nouveau est le chemin à parcourir.

en route vers la description de mon problème.

Si actuellement, je travaille sur un projet de bibliothèque qui a été mis en place avec maven et crée une extension pour le projet AMQP du printemps en cours.

Le but ici est de fournir un fichier JAR qui peut être inclus dans un autre projet pour soutenir une manière spécifique de communiquer sur un courtier de messages.

À ce stade, j'implémente l'option de configuration pour permettre aux utilisateurs de configurer le client de messagerie à leur convenance. Mais pendant que je testais la fonctionnalité de ce la fonctionnalité j'ai frappé un problème en utilisant la bibliothèque dans un pot exécutable.

en l'exécutant dans L'espace de travail Eclipse, tout semble fonctionner parfaitement. Mais quand j'essaie de l'exécuter depuis mon bureau (comme un JAR exécutable) le fichier de propriétés ne semble pas se trouver n'importe où.

Juste pour donner un aperçu rapide de l'espace de travail/projets d'installation comme décrit ci-dessus: workspace overview

la structure du projet des deux projets reflète le maven default un:

- src/main/java
    - java source files
- src/main/resources
    - resource files
- src/test/java
    - java test files
- src/test/resources
    - test resource files

Où le fichier de la bibliothèque contient une valeur par défaut.fichier de propriétés dans le dossier src/main/resources et le projet chatclient personnalisé.fichier de propriétés.

une fois que le fichier JAR exécutable a été compilé, il a la structure suivante.

- com
- junit
- META-INF
- org
- resources
    - default.resources
    - custom.resources

je crois que les fichiers de ressources ne doit pas être situé là. mais dans le dossier META-INF/maven. Après avoir essayé des trucs comme:

  • Ajouter un META-INF dossier dans mon dossier src/main / resources et y placer les fichiers de propriétés.
  • ajout d'un fichier de manifeste avec Class-Path:..
  • chargement du fichier en code de plusieurs façons.

Mais rien ne semble fonctionner. Je suppose que c'est lié au Maven et un simple changement dans le pom.xml pourrait résoudre. Malheureusement, mes connaissances sur la configuration du projet Maven et les sujets liés à la pom sont très rudimentaires (c'est mon premier projet utilisant maven). Et je n'arrive pas trouver n'importe quelle documentation sur elle, même si je sais qu'elle devrait être là (probablement un problème causé par moi).

avant que j'oublie de le mentionner. Je charge la propriété des fichiers à l'aide de cette façon:

Properties props = new Properties();
prop.load(<custom static class>.class.getResourceAsStream(filename));
return props;

aussi le pom.xml pour ma bibliothèque ressemble à:

-- Artifact stuff --
<packaging>jar</packaging>
<build>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>
-- Dependency stuff --

Et l'un pour le projet qui utilise la bibliothèque ressembler à ça:

-- Artifact stuff --
<build>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>

<dependencies>
  <dependency>
    <groupId>com.maxxton</groupId>
    <artifactId>async-amqp-messaging</artifactId>
    <version>0.2</version>
  </dependency>
</dependencies>
-- Other stuff --

j'espère qu'il y est quelqu'un qui est un peu plus avancé sur ce sujet et pourrait aider à trouver une solution pour cela problème. Et si vous avez besoin d'informations supplémentaires sur les fichiers/structures du projet, merci de me le faire savoir. Je serais heureux de partager avec vous.

mise à Jour (28-04-2015 {1})

pour tester j'ai créé un exemple de projet qui essaie de charger les fichiers de propriétés de la même manière que le scénario décrit ci-dessus. Même en suivant le Maven documentation (en utilisant le dossier META-INF) Je n'ai pas été capable de charger les propriétés.

pour le bien de cette question I téléchargé les tests de l'espace de travail ici.

j'espère que quelqu'un pourrait m'aider à corriger cela, car la manière normale décrite sur le site Maven ne semble pas fonctionner pour moi.

mise à Jour (28-04-2015 {2})

eh Bien j'ai réussi à résoudre une partie du problème. Depuis que j'ai ajouté la configuration pour le maven-assembly-plugin (construction de JAR exécutable avec deps), j'ai pu obtenir la structure correcte dans mon fichier JAR. La chose que j'ai ajoutée est:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <finalName>project</finalName>
                <appendAssemblyId>false</appendAssemblyId>
                <archive>
                    <manifest>
                        <mainClass>com.test.project.Application</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

puis en courant clean compiler assembly: single j'ai réussi à obtenir la bonne structure.

JAR root
    - com
    - META-INF
        - MANIFEST.MF
        - default.properties
        - custom.properties

Tout cela résout une partie du problème. Le chargement du fichier se traduit toujours par une NullPointerException.

Dernière Mise À Jour (04-05-2015)

après une longue lutte, j'ai réussi à obtenir tout ce que je voulais. Suivant les conseils donnés par @Deepak et @Joop Eggen, j'ai fait quelques recherches sur la façon de avoir toutes les dépendances dans un dossier lib comme jar au lieu de les déballer dans un jar 'uber'. Après avoir essayé des tas de choses, je suis tombé sur cette réponse. Suivant les instructions, il semble que cette structure soit créée:

- runnable.jar
- lib
    - spring-amqp.jar
    - spring-core.jar
    ...

en suivant les conseils de @Joop Eggen, j'ai réussi à charger la propriété comme je le voulais. Il semble donc que cette question ait trouvé une réponse. Actuellement, je suis toujours en train de comprendre comment attribuer chaque réponse que je ne suis pas en mesure de diviser la prime en deux pièce. Je vais revenir sur ce que.

Note

bien que j'ai accordé à la fois la prime et la réponse à @Joop Eggen ne signifie pas que la réponse de @Deepak n'a pas contribué. Elle a fourni des informations intéressantes sur les meilleures pratiques, mais elle n'était pas aussi complète que la réponse acceptée. Alors s'il vous plaît en trouvant votre réponse ici lui donner une partie du crédit aussi.

11
demandé sur Community 2015-04-24 12:44:47

2 réponses

Il y a deux façons d'obtenir des ressources,

  • avec un ClassLoader contre le chemin de classe entier en utilisant des chemins absolus (sans /...),
  • avec une classe, en utilisant un parent (...) ou absolue (/... chemin d'accès à l'intérieur du pot de cette classe.

ce dernier semble plus directe, et peut être utilisé comme:

getClass().getResource("/...");
ClassInJar.class.getResource("/...");

getClass() n'est possible que dans un objet non statique et est dangereux trop: la classe réelle pourrait sois un enfant, pas dans le bocal de la bibliothèque.


Sur la structure réelle de votre application. Je sais que maven répertoire convention:

src/main/java/...
src/main/resources/...

où /... entre dans le jar/war; le répertoire des paquets.

réassembler les pots n'est pas bon. Il y a toujours l' Class-Path: ... entrée dans META-INF / MANIFEST.MF. Il est préférable de suivre les conventions maven de base.

1
répondu Joop Eggen 2015-04-29 12:12:40

la solution à cela est plus simple, cependant il y a quelques concepts que je voudrais que vous soyez conscient.

  1. ce n'est pas une bonne pratique de créer un grand bocal en utilisant le plugin Maven assembly. Dans vos exemples, vous utilisez de petits pots développés tous les deux par vous, donc il pourrait sembler correct. Mais, comme vos vrais projets prennent de l'ampleur, ce n'est pas l'idéal, vous souhaitez que la séparation des différents modules et pas un grand bocal. La pratique idéale est à l'opposé de ce que vous essayez pour atteindre - vous devez vous efforcer d'avoir des pots plus petits et plus petits. Vous pourriez à l'avenir vouloir la commodité de remplacer ces pots plus petits sans avoir à livrer le paquet entier à nouveau.

  2. vous ne voudriez sûrement pas déballer les pots de 3PP et les emballer comme votre propre pot!

  3. sur la base de ce qui précède, vous pourriez vous demander comment créer des pots exécutables. Eh bien, la réponse est d'avoir les pots dépendants dans le chemin de classe. Lors de l'exécution du "projet" jar, vous devriez avoir la "bibliothèque" jar dans le chemin de classe et il sera en mesure de trouver le fichier de propriétés à l'intérieur comme prévu.

  4. vous placez les fichiers de propriétés dans le répertoire META-INF. Le bon endroit pour eux est le dossier Ressources. Et si vous suivez le point N ° 1, les choses fonctionneront comme prévu.

1
répondu KDK 2015-04-29 12:02:34