Resource files generated by Maven plugin not readable from OSGi bundle

45 views Asked by At

In my maven OSGi project, I use the maven-bundle-plugin to create my bundle jar.

The git-commit-id-maven-plugin generates to target/git.properties by default, and they recommend to generate to /target/classes/git.properties to ensure that the file gets added to the /classes directory inside the jar:

<plugin>
    <groupId>pl.project13.maven</groupId>
    <artifactId>git-commit-id-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>revision</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <dotGitDirectory>${project.basedir}/../.git</dotGitDirectory>
        <generateGitPropertiesFile>true</generateGitPropertiesFile>
        <generateGitPropertiesFilename>
            ${project.build.outputDirectory}/classes/git.properties
        </generateGitPropertiesFilename>
        <includeOnlyProperties>
            <includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
            <includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
        </includeOnlyProperties>
        <commitIdGenerationMode>full</commitIdGenerationMode>
    </configuration>
</plugin>

That works, the file is present in the resulting jar, but I am unable to read the file from within my OSGi bundle.

1

There are 1 answers

0
dschulten On

The reason why the classloader cannot find the resource file at runtime, although it is contained in the bundle, is that the resource file is not declared in META-INF/MANIFEST.MF.

Normally, the maven-bundle-plugin automatically adds everything inside src/main/resources to the manifest. This is why the plugin ignores target/classes/git.properties - the maven-bundle-plugin ignores that location.

You can add additional resources to the manifest using an <Include-Resource/> instruction in the configuration of the maven-bundle-plugin. Note, however:

By default the bundle plugin converts the project’s Maven resource directories into a single instruction. If you specify your own instruction, this will replace the generated one. To include the generated list of Maven resources in your own instruction just add {maven-resources} to the list and it will be expanded automatically.

-- Felix Bundle Plugin Documentation

In my case I wanted my resource to be detected by the maven-bundle-plugin automatically, so I decided to have the git-commit-id-plugin generate its output to target/generated-resources/git.properties:

<plugin>
    <groupId>pl.project13.maven</groupId>
    <artifactId>git-commit-id-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>revision</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <dotGitDirectory>${project.basedir}/../.git</dotGitDirectory>
        <generateGitPropertiesFile>true</generateGitPropertiesFile>
        <generateGitPropertiesFilename>
            ${project.build.directory}/generated-resources/git.properties
        </generateGitPropertiesFilename>
        <includeOnlyProperties>
            <includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
            <includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
        </includeOnlyProperties>
        <commitIdGenerationMode>full</commitIdGenerationMode>
    </configuration>
</plugin>

Next, I added the target/generated-resources folder to the Maven reactor using the build-helper-maven-plugin:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.4.0</version>
    <executions>
        <execution>
            <id>add-resource</id>
            <phase>generate-test-resources</phase>
            <goals>
                <goal>add-resource</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>${project.build.directory}/generated-resources</directory>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

In any case, what you need to achieve is that the resource is present in META_INF/MANIFEST.MF, like so:

Include-Resource: ...all the rest of your resources...,git.propertie
 s=target/generated-resources/git.properties

Only then code like the following will work:

URL gitPropertiesFile = this.getClass().getClassLoader().getResource("/git.properties");
        String gitInfo;
        if (gitPropertiesFile != null) {
            gitInfo = IOUtils.toString(gitPropertiesFile, StandardCharsets.ISO_8859_1);
        } else {
            gitInfo = "No version information found";
        }

As a sidenote, in case you want to use the excellent git-commit-id-maven-plugin: the example above is for V.4.0.0 of that plugin, which works up to Java 8. There are more recent versions, but those have different Maven coordinates. For details, refer to the plugin's documentation.