websphere-libertyopen-libertyliberty-maven-plugin

Open Liberty - Context Root Not Found error, ClassCastException, CWWKZ0013E


Overview

I am using liberty-maven-plugin "dev mode" to deploy a simple app, running mvn liberty:dev.

I tried to customize my application config via server.xml in two ways:

  1. Set a custom context root, /ctx.
  2. Configure the classloader to add access to third party APIs, as described in this answer. (A similar configuration would be needed when configuring application access to a shared library as described here).

Problems

It seems like my application config is simply being ignored.

  1. I get a Context Root Not Found error when I hit the webpage at the context root I specified in server.xml: `http://localhost:9080/ctx".

  2. My app instead seems to be starting on another context root, /demo, based on the artifact ID:

[INFO] [AUDIT   ] CWWKT0016I: Web application available (default_host): http://localhost:9080/demo/
  1. I get these two error/warning messages in the terminal running Maven
[INFO] [ERROR   ] CWWKZ0013E: It is not possible to start two applications called demo.
...
[INFO] [WARNING ] CWWKZ0014W: The application demo could not be started as it could not be found at location demo.war.
  1. I get a ClassCastException related to using the EclipseLink DescriptorCustomizer API
[INFO] [ERROR   ] CWWJP9992E: java.lang.ClassCastException: io.openliberty.guides.event.dao.EventHistory incompatible with org.eclipse.persistence.config.DescriptorCustomizer
[INFO] [ERROR   ] CWWJP0015E: An error occurred in the org.eclipse.persistence.jpa.PersistenceProvider persistence provider when it attempted to create the container entity manager factory for the jpa-unit persistence unit. The following error occurred: Exception [EclipseLink-28019] (Eclipse Persistence Services - 3.0.3.v202208190922): org.eclipse.persistence.exceptions.EntityManagerSetupException

Configuration

pom.xml

<project>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

<!-- ... -->

  <plugin>
    <groupId>io.openliberty.tools</groupId>
    <artifactId>liberty-maven-plugin</artifactId>
    <version>3.9</version>
    <configuration>
        <copyDependencies>
         <!-- ... -->
        </copyDependencies>
    </configuration>
  <!-- ... -->

server.xml

<server description="Sample Liberty server">

  <featureManager>
    <feature>restfulWS-3.0</feature>
    <feature>jsonb-2.0</feature>
    <feature>jsonp-2.0</feature>
    <feature>cdi-3.0</feature>
    <feature>persistence-3.0</feature>
  </featureManager>
<!--    ...  -->

  <application location="demo.war" type="war" context-root="/ctx">
      <classloader apiTypeVisibility="+third-party" />    
  </application>

  <!-- Derby Library Configuration -->
  <library id="derbyJDBCLib">
    <fileset dir="${shared.resource.dir}/" includes="derby*.jar" />
  </library>

Solution

  • Background explanation

    The core issue comes from the fact that the Liberty Maven (and Gradle) plugin's deploy goal (task), will (by default) generate application config when the application is not already configured in server config (server.xml, etc.).

    This is "a feature, not a bug", however, there's a problem when the user attempts to provide configuration for a given app, while the plugin calculates that this config corresponds to a totally different app.

    If the configuration doesn't "match" the plugin's expectation (based on the location attribute detailed below), the liberty-maven-plugin will go on to generate its own application config as a "config dropin", despite the user's config in server.xml.

    At best, the user config won't take effect, and there might be conflicts such that it won't work at all, like in this example.

    Detailed explanation: Application 'location' attribute, and configDropins file

    The "match" is based on the application location attribute.

    We see the problem if we look at the config generated by the plugin, a "config dropin" generated into a file like: ./target/liberty/wlp/usr/servers/defaultServer/configDropins/defaults/install_apps_configuration_1491924271.xml.

    <server>
        <webApplication id="demo" location="demo-0.0.1-SNAPSHOT.war" name="demo"/>
    </server>
    

    Since the location attribute here includes the version, it does not match the location attribute configured in the original server.xml (which does not include the version):

      <application location="demo.war" type="war" context-root="/ctx">
          ...
    

    Solution

    Align 'location' with the liberty-maven-plugin-calculated value.

    Either:

    1. Set <finalName> to remove the version:
        <build>
            <finalName>${project.artifactId}</finalName>
    

    OR

    1. Use the liberty-maven-plugin's <stripVersion> configuration parameter:
     <plugin>
        <groupId>io.openliberty.tools</groupId>
        <artifactId>liberty-maven-plugin</artifactId>
        <version>3.9</version>
        <configuration>
            <stripVersion>true</stripVersion>