If you need to build a runnable spring-based JAR using maven, there could be some problems in the spring's configuration parsing. You know, to build a runnable JAR we have to include in the JAR all the dependencies, and Maven can help a lot in this, for example using the maven-assembly-plugin.
Here is a sample configuration of such plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>fully.qualified.name.of.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
The plugin works well, but if you have more than the simple spring-core dependency, than you could have an Exception like:
Exception in thread "main" org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/security]
The problem is that spring uses in each module's JAR two meta files:
- META-INF/spring.handlers
- META-INF/spring.schemas
such files are used in conjuction with configurations' XML Schemas to validate the application configuration even if the application is executed off-line. Because each Spring module brings these files, when the assemply plugin runs, it simply overwrites multiple times such files in the META-INF/ directory of the resulting JAR.
As result, we have that some configurations can't be validated and so the BeanDefinitionParsingException is thrown.
To avoid the problem we can use the maven-shade-plugin that performs some transformations to the resulting JAR's files. Here is an example configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>fully.qualified.name.of.MainClass</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
As you can see we are specifying something more than the MainClass: we are also saying that when spring.handlers and spring.schemas files are found, their contents must be appended to already existing files in the META-INF directory.
Running the maven package goal, we'll now get a working spring-based runnable JAR!
浙公网安备 33010602011771号