javaopen-liberty

Using local libraries in a maven project with Open Liberty Dev mode


I have a maven project that builds a war that is deployed to Open Liberty. I am using the Liberty maven plugin:

<plugin>
    <groupId>io.openliberty.tools</groupId>
    <artifactId>liberty-maven-plugin</artifactId>
    <version>3.9</version>
    <!-- Specify configuration, executions for liberty-maven-plugin -->
</plugin>

I am leveraging Dev mode and its working nicely. However, I want to use local jar file libraries with Dev mode.

I was expecting that I might be able to place the jars files in a particular location in the project, and they would be automatically be picked up by Liberty dev mode - in a similar way to how the server.xml is automatically picked up from src/main/liberty/config. My server.xml is set up to look for the libraries here: ${shared.config.dir}/lib/global, so I tried putting the jars in src/main/liberty/shared/config/lib/global but that doesn't work.

One alternative I can see is to use the copyDependencies configuration for the liberty plugin.

Is there some recommended way to achieve what I want to do? Ideally I want the simplest solution that will work for liberty dev mode, and also for a vanilla maven build (mvn package).

Similar question here leverages the copyDependencies configuration, but specifically I am looking for the best solution for local jars (yes, I could use system scoped maven coordinates or install the jar locally) How to copy external dependency to Open Liberty during maven build

Thanks


Solution

  • Good question, generalizing the question a bit, there's maybe four approaches you could use:

    1. Install the JAR into your local Maven repository with the install-file goal.

    E.g. starting from just the JAR you could do this to generate a POM and specify the GAV coordinates:

    mvn install:install-file -Dfile=my-artifact.jar -DgroupId=my.group -DartifactId=my-artifact -Dversion=1.0.0 -Dpackaging=jar

    You can then reference this as a normal dependency with coordinates:

    <dependency>
      <groupId>my.group</groupId>
      <artifactId>my-artifact</artifactId>
      <version>1.0.0</version>
     </dependency>
    

    Note: This question has a couple answers with different variations of this, including using a whole separate repo or using your default local repo.

    One thing you want to avoid in this approach is using group:artifact:version coordinates that actually exist or are likely to exist one day (you could perhaps workaround this using a SNAPSHOT or custom-named version like <version>1.0.0-mine</version>).

    2. Use resources plugin

        <build>
            <resources>
                <!-- Explicitly configure the default too -->
                <resource>
                    <directory>${project.basedir}/src/main/resources</directory>
                </resource>
                <!-- Custom library -->
                <resource>
                    <directory>${project.basedir}/mylib</directory>
                    <targetPath>${project.build.directory}/liberty/wlp/usr/shared/lib/global</targetPath>
                    <!-- Default, but just emphasizing the point -->
                    <filtering>false</filtering>
                </resource>
            </resources>
    

    Since dev mode invokes the resources:resources goal in its "lifecycle", this can be configured without any plugin config (using the "/project/build/resources" (in XPath terms) elements), and using the <targetPath> you can copy to any location.

    3. Add to the config directory (src/main/liberty/config)

    Along with the main server XML config file at src/main/liberty/config/server.xml, you can put other files and directories in there as well, and all will be copied over by dev mode.

    So you could create, e.g. src/main/liberty/config/mylib/my.jar and it would get copied to target/liberty/wlp/usr/servers/defaultServer/mylib/my.jar. From the server.xml you would then reference this location as "mylib/my.jar" relative to the server config directory.

    (This wouldn't be a good fit for the original use case asking to copy to ".../shared/lib/global" but it might fit for others looking at this question).

    4. Add a system scoped dependency

    This was mentioned in the original question. I don't like this solution as much. I'll mention it for completeness, but leave it up to you to search out the details. This might be interesting reading.