2011-03-13 9 views
20

En mi proyecto Maven hay un módulo (núcleo) que tiene algunos recursos para sus clases. Al ejecutar clases dentro del módulo es capaz de obtener sus propios recursos. Todo funciona bien¿Usa los recursos de una dependencia?

Donde se rompe material es cuando otro módulo que depende del núcleo intenta ejecutar esa clase. La carpeta en la que Java está buscando recursos es este módulo, no el módulo principal. Entonces la clase falla

En resumen: ¿Cómo puedo acceder a los recursos de una dependencia?


He experimentado con tratando de hacer esto al declarar en el JAR del Núcleo Manifiesto Class-Path: .. Sin embargo, cuando una lista de los recursos disponibles con JSHookLoader.class.getClassLoader().getResources(""); (JSHookLoader está en Core si significa algo), me sale:

Resource: W:\programming\quackbot-hg\impl\target\classes 
File rebel.xml 

Resource: W:\programming\maven-repo\org\quackbot\core\3.5-SNAPSHOT 
File core-3.5-SNAPSHOT.jar 
File core-3.5-SNAPSHOT.pom 
File maven-metadata-local.xml 
File _maven.repositories 

Por supuesto, esto complica las cosas como esperaba el JAR sí para estar en la ruta de clases, no el directorio del JAR está en

¿Alguna sugerencia?


Volviendo a este proyecto, sigo teniendo este problema. Otras guías han hablado sobre el uso de maven-assembly-plugin y el plugin de recursos remotos, pero eso es muy molesto ya que todos los módulos deben incluir el plugin XML de monstruos.

¿Por qué no simplifico la pregunta a esto: cómo puedo agregar un JAR de dependencias a la lista de recursos?

  1. core.jar tiene algunos recursos en la carpeta/recursos. Ejecutando core.jar puedo ver/recursos en la lista de recursos.
  2. impl.jar depende de core.jar. Al ejecutarlo,/resources no está en la lista de recursos y por lo tanto causa estragos.

Esto debería ser lo suficientemente simple, pero ¿cómo puedo hacerlo? Me he pasado horas tratando de encontrar una forma simple y limpia de hacerlo, pero fue en vano.

Respuesta

21

Después de mucho buscar, finalmente, me topé con una solución.

Mi solución toma el módulo principal y lo descomprime con el Complemento Dependency de Maven, asegurándose de excluir la carpeta META-INF y la carpeta org donde están las clases compiladas. La razón por la que excluyo lo que no quiero en lugar de indicar explícitamente lo que quiero es que se puedan agregar nuevos recursos fácilmente sin tener que actualizar mi POM todo el tiempo.

La razón por la que no utilizo el plugin de ensamblaje o el plugin de recursos remotos es porque usan módulos de recursos dedicados. No creo que deba crear un módulo principal y un módulo de recursos básicos, con el módulo de recursos básicos que solo contiene archivos de configuración de inicio de sesión e hibernación + algunas otras cosas.

Aquí es una copia de lo que estoy usando para ello

<build> 
     <plugins> 
      <!--Extract core's resources--> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-dependency-plugin</artifactId> 
       <version>2.2</version> 
       <executions> 
        <execution> 
         <id>unpack</id> 
         <phase>generate-resources</phase> 
         <goals> 
          <goal>unpack-dependencies</goal> 
         </goals> 
         <configuration> 
          <includeGroupIds>${project.groupId}</includeGroupIds> 
          <includeArtifactIds>core</includeArtifactIds> 
          <excludeTransitive>true</excludeTransitive> 
          <overWrite>true</overWrite> 
          <outputDirectory>${project.build.directory}/core-resources</outputDirectory> 
          <excludes>org/**,META-INF/**,rebel.xml</excludes> 
          <overWriteReleases>true</overWriteReleases> 
          <overWriteSnapshots>true</overWriteSnapshots> 
         </configuration> 
        </execution> 
       </executions> 
      </plugin> 
     </plugins> 
     <!--New resource locations--> 
     <resources> 
      <resource> 
       <filtering>false</filtering> 
       <directory>${project.build.directory}/core-resources</directory> 
      </resource> 
      <resource> 
       <filtering>false</filtering> 
       <directory>${basedir}/src/main/resources</directory> 
      </resource> 
     </resources> 
    </build> 
+0

¡Muchas gracias por publicar su solución! Tengo este problema exacto y he encontrado una respuesta ... pero estaba escrito en términos de maven, y estaba luchando por descifrarlo. – CaffiendFrog

+1

Tenga cuidado con las dependencias circulares al usar esto. Puede tener dificultades para liberar. – Michael

3

Si los recursos se encuentran en /src/main/resourcesy clases en el frasco está accediendo a ellos utilizando getResourceAsStream(), usted debería ser capaz de acceder a estos archivos de clases en otras JAR así (también usando getResourceAsStream()). Esto se debe a que todos los archivos ubicados en /src/main/resources finalmente aterrizan en el mismo directorio lógico (CLASSPATH). En otras palabras: todos los archivos ubicados en /src/main/resources y todas las clases compiladas desde /src/main/java son para decir fusionaron en un solo espacio de nombres.

Si aún no puede acceder a los archivos aunque todas las clases estén usando la API uniforme getResourceAsStream(), es posible que tenga algunos problemas de visibilidad de carga de clases.

+0

Consulte la actualización en mi pregunta, no está funcionando como dijo que lo haría. – TheLQ

0

No creo que sea una buena idea. Supongamos que tiene el módulo A. Depende de 'B'. 'B' depende de C. Básicamente, debe importar A solo sobre la interfaz del módulo B. Quizás, mañana cambie la dependencia de C a D. Si sucediera, necesitarás cambiar A. No es una buena situación, ¿verdad?Así que declare la dependencia A de C de manera implícita.

En resumen: ¿Cómo puedo acceder a los recursos de una dependencia?

En resumen: declare esta dependencia directamente.

+0

Se declara directamente. El módulo del que estoy hablando depende directamente del núcleo. – TheLQ

1

Si su JAR dependiente tiene un OneDependent clase llamada, entonces esto debería funcionar:

OneDependent.class.getResourceAsStream(resourcePath) 
+0

Eso es lo que hice. Solo mostraba el directorio en el que estaba el Core JAR, no el contenido del mismo. – TheLQ

+0

Intentando entender de qué directorio está hablando ... la llamada getResourceAsStream() le proporciona un recurso o nulo si no puede encontrar el recurso. ¿Qué devuelve en tu caso? –

+1

Hice un bucle sobre lo que se devolvió con 'JSHookLoader.class.getClassLoader(). GetResources (" ");' – TheLQ

0

tuve una situación similar en este momento. Tengo un "creador de código de prueba" que toma datos del directorio src/test/resources y transfiere datos a una base de datos H2. Funciona bien desde el módulo A, pero cuando se llama desde el módulo B no lo hace. Construye una ruta con múltiples puntos y comas (debido a que los recursos están en el archivo jar); moduleA luego no encuentra los archivos "locales a sí mismo".

Al final, he añadido

<testResources> 
     <testResource> 
      <directory>src/test/resources</directory> 
     </testResource> 
     <testResource> 
      <directory>../moduleA/src/test/resources</directory> 
     </testResource> 
    </testResources> 

a la sección de construcción de moduleB, y ahora la construcción corre a través de multa y como se esperaba.

Cuestiones relacionadas