Annotation scan does not scan external banks in the classpath

Problem: Spring Scanning component annotations does not raise a class annotated in an external jar that is not included in pom.xml. But I need to scan classes with special annotation from external cans. These external banks will be placed in the classpath, but will not be known to my application at compile time.

1) We have a maven module (artifactId = "metric_processor"), which creates a jar file (metric_processor.jar) and has the following classes

package com.metric; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ProcessMetric { String name(); } package com.metric; public interface MetricProcessor { int computeMetric(); } package com.metric; @ProcessMetric(name="LATENCY") @Component public class LatencyMetricProcessor implements MetricProcessor { ..... } 

2) We have another maven module ("artifactId =" metric_processor_external "), which creates a jar (metric_processor_external.jar) and includes the" metric_processor "module as a compile-time region.

 package com.metric; @ProcessMetric(name="TEST_METRIC_EXTERNAL") @Component public class TestMetricProcessor implements MetricProcessor { .... } 

3) We have a third (main) maven module (artifactId = "main_application"), which is a standalone application (uses spring), which includes the metric_processor module in the compilation area. (But does not include "metric_processor_external"). Assembly plugin for the third module

 <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.4</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.main.TriggerMetricProcessor</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> 

Xml application context for this module

  <beans> <context:component-scan base-package="com.metric"> <context:include-filter type="annotation" expression="com.metric.ProcessMetric" /> </context:component-scan> <bean id="triggerMetricProcessor" class="com.main.TriggerMetricProcessor" /> </beans> 

I have the following class which is the starting point of the application

 package com.main; import ... public class TriggerMetricProcessor { public static void main(String[] args) throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml"); TriggerMetricProcessor triggerMetricProcessor = (TriggerMetricProcessor) context.getBean("triggerMetricProcessor"); triggerMetricProcessor.initMetricProcessor(context); } private void initMetricProcessor(ApplicationContext context) { GenericBeanFactoryAccessor beanFactoryAccessor = new GenericBeanFactoryAccessor(context); final Map<String, Object> metricProcessors = beanFactoryAccessor.getBeansWithAnnotation(ProcessMetric.class); for (final Object metricProcessor : metricProcessors.values()) { final Class<? extends MetricProcessor> metricProcessorClass = (Class<? extends MetricProcessor>)metricProcessor.getClass(); final ProcessMetric annotation = metricProcessorClass.getAnnotation(ProcessMetric.class); System.out.println("Found MetricProcessor class: " + metricProcessorClass + ", with name: " + annotation.name()); } } } 

we will compile the third module as

 maven clean install assembly:single 

This creates the jar file "main_application-with-dependencies.jar"

Then we run it like

 java -cp "metric_process_external.jar" -jar main_application-with-dependencies.jar 

Now the application finds only "LatencyMetricProcessor" and does not find "TestMetricProcessor".

Can anybody help?

+6
spring jar annotations console-application
source share
1 answer

When you use the -jar parameter to execute a jar file, the -cp parameter is ignored.

Oracle Java docs for the -jar option:

-jar

Run a program encapsulated in a JAR file. The first argument is the name of the JAR file instead of the name of the launch class. In order for this parameter to work, the manifest of the JAR file must contain a line of the form Main-Class: classname. Here, the class name identifies the class that has the public static void main (String [] args) method, which serves as the starting point for your application. See the Jar Tool man page and the Jar trail Java tutorial for information on working with Jar files and Jar file manifests.

When you use this parameter, the JAR file is the source for all user classes and other user class path parameters are ignored.

Also check out this post: https://stackoverflow.com/a/316677/

Therefore, you need to specify metric_process_external.jar in the manifest file using the Class-Path: header. You should be able to plug in the Maven build plugin.

If this is not practical, you need to run the application without the -jar flag:

 java -cp "metric_process_external.jar:main_application-with-dependencies.jar" com.main.TriggerMetricProcessor 
+8
source share

All Articles