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?