Skip to content

Loose EAR Manifest Class-Path Issue Fix#1073

Open
sajeerzeji wants to merge 11 commits into
OpenLiberty:mainfrom
sajeerzeji:GH766-Multi_module_issue_with_loose_app
Open

Loose EAR Manifest Class-Path Issue Fix#1073
sajeerzeji wants to merge 11 commits into
OpenLiberty:mainfrom
sajeerzeji:GH766-Multi_module_issue_with_loose_app

Conversation

@sajeerzeji
Copy link
Copy Markdown
Contributor

@sajeerzeji sajeerzeji commented Mar 24, 2026

Fixes #766

Issue

The application failed to start in loose EAR mode with,

StateChangeException: Error while loading class com.ibm.websphere.svt.gs.gsdb.session.MfgCategorySessionBean
ResourceLoadingException: Error while loading JPA entity classes (MfgCategory, Category, etc.)

In packaged EAR mode, JAR files are physically present in the EAR, and Liberty's classloader uses the manifest Class-Path entries to locate dependency JARs within the EAR.

In loose EAR mode (looseApplication = true), there are no physical JAR files. Instead, the plugin generates an XML descriptor (GarageSaleLibertyEAR.ear.xml) that maps source directories. Liberty's classloader needs to know which class directories belong to each module.

The Problem

  • EJB modules depend on other modules (e.g., JPA modules) via compileOnly or implementation dependencies
  • The plugin only added the EJB module's own classes to the loose XML
  • Dependency class directories were not included, causing ClassNotFoundException at runtime

Previous Approach (Reverted)
The previous fix attempted to use manifest Class-Path entries to determine dependencies, requiring users to manually declare Class-Path in their build.gradle files. This approach was reverted after cross-checking with Maven plugin implementation.

Current Approach
Added addDependencyClassDirectories() method that,

  1. Scans both compileClasspath and runtimeClasspath for project dependencies
  2. Automatically adds each dependency's class and resource directories to the module in loose XML
  3. Works without requiring manifest Class-Path configuration

How it works

  • Plugin automatically detects project dependencies from Gradle configurations
  • For each EJB/JAR module, it finds all project dependencies
  • Adds dependency class directories as <dir> elements in the loose XML
  • Liberty's classloader can now find all required classes at runtime

Usage Requirements
No special configuration needed. The plugin automatically handles dependencies declared in build.gradle.

Backward Compatibility

  • Packaged EAR mode (looseApplication = false) continues to work unchanged
  • Existing projects work without modification

Testing
Added a new test TestMultiModuleLooseEarEjbDependency that verifies

  • Loose application XML is generated correctly
  • EJB modules include dependency class directories
  • Module's own classes are still included

Before
image

After
image

…ifest, Adds that dependency's class and resource directories to the module archive element in the loose XML
Copy link
Copy Markdown
Contributor

@venmanyarun venmanyarun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed, add tests

Comment thread src/main/groovy/io/openliberty/tools/gradle/utils/LooseEarApplication.groovy Outdated
Comment thread src/main/groovy/io/openliberty/tools/gradle/utils/LooseEarApplication.groovy Outdated
Comment thread src/main/groovy/io/openliberty/tools/gradle/utils/LooseEarApplication.groovy Outdated
@sajeerzeji
Copy link
Copy Markdown
Contributor Author

sajeerzeji commented Mar 27, 2026

Hi @cherylking
After reviewing the changes in this PR against the Maven plugin implementation, I identified a gap in the approach. I've reverted the previous changes and implemented a new fix as below,

Previous approach was to use manifest Class Path entries to determine dependencies, requiring users to manually declare Class-Path in their build.gradle files. This approach was reverted after cross-checking with Maven plugin implementation.

Added addDependencyClassDirectories() method that,

  1. Scans both compileClasspath and runtimeClasspath for project dependencies
  2. Automatically adds each dependency's class and resource directories to the module in loose XML
  3. Works without requiring manifest Class-Path configuration

Now the plugin automatically detects project dependencies from Gradle configurations, for each EJB/JAR module, it finds all project dependencies, adds dependency class directories as <dir> elements in the loose XML.

Comment thread src/main/groovy/io/openliberty/tools/gradle/utils/LooseEarApplication.groovy Outdated
@venmanyarun
Copy link
Copy Markdown
Contributor

@sajeerzeji
can you add screen recording ?

@sajeerzeji sajeerzeji requested a review from cherylking April 10, 2026 13:58
@sajeerzeji
Copy link
Copy Markdown
Contributor Author

@sajeerzeji can you add screen recording ?

Screen.Recording.2026-04-13.at.4.29.14.PM.mov

@cherylking
Copy link
Copy Markdown
Member

Looks like most of the builds are failing. So I am not going to look at the changes further until they are passing.

@sajeerzeji
Copy link
Copy Markdown
Contributor Author

Looks like most of the builds are failing. So I am not going to look at the changes further until they are passing.

Test are passed once re-ran, the issues where network connection timeout in InstallLiberty_runtimeUrl tests.

Comment thread src/main/groovy/io/openliberty/tools/gradle/utils/LooseEarApplication.groovy Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multi module Gradle application failed to deploy into liberty server

3 participants