Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix loose app generation for jar project dependencies in war projects #797

Merged
merged 1 commit into from
Mar 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 27 additions & 14 deletions src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* (C) Copyright IBM Corporation 2014, 2021.
* (C) Copyright IBM Corporation 2014, 2023.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -347,26 +347,39 @@ class DeployTask extends AbstractServerTask {

private void addWarEmbeddedLib(Element parent, LooseWarApplication looseApp, Task task) throws Exception {
ArrayList<File> deps = new ArrayList<File>();
task.classpath.each {deps.add(it)}
task.classpath.each {
deps.add(it)
}
//Removes WEB-INF/lib/main directory since it is not rquired in the xml
if(deps != null && !deps.isEmpty()) {
if (deps != null && !deps.isEmpty()) {
deps.remove(0)
}
File parentProjectDir = new File(task.getProject().getRootProject().rootDir.getAbsolutePath())
for (File dep: deps) {
String dependentProjectName = "project ':"+getProjectPath(parentProjectDir, dep)+"'"
Project siblingProject = project.getRootProject().findProject(dependentProjectName)
boolean isCurrentProject = ((task.getProject().toString()).equals(dependentProjectName))
if (!isCurrentProject && siblingProject != null){
Element archive = looseApp.addArchive(parent, "/WEB-INF/lib/"+ dep.getName());
looseApp.addOutputDirectory(archive, siblingProject, "/");
Task resourceTask = siblingProject.getTasks().findByPath(":"+dependentProjectName+":processResources");
if (resourceTask.getDestinationDir() != null){
String dependencyProjectName = getProjectPath(parentProjectDir, dep)
String projectDependencyString = "project ':" + dependencyProjectName + "'"
Project siblingProject = project.getRootProject().findProject(dependencyProjectName)
boolean isCurrentProject = ((task.getProject().toString()).equals(projectDependencyString))
if (!isCurrentProject && siblingProject != null) {
Element archive = looseApp.addArchive(parent, "/WEB-INF/lib/" + dep.getName());
//Add sibling project class directories to <archive/> as <dir>
siblingProject.sourceSets.main.getOutput().getClassesDirs().each {
looseApp.getConfig().addDir(archive, it, "/");
}
Task resourceTask = siblingProject.getTasks().findByPath(":" + projectDependencyString + ":processResources");
if (resourceTask != null && resourceTask.getDestinationDir() != null) {
looseApp.addOutputDir(archive, resourceTask.getDestinationDir(), "/");
}
File manifestFile = project.sourceSets.main.getOutput().getResourcesDir().getParentFile()
looseApp.addManifestFileWithParent(archive, manifestFile);
} else if(FilenameUtils.getExtension(dep.getAbsolutePath()).equalsIgnoreCase("jar")){
File resourceDir = siblingProject.sourceSets.main.getOutput().getResourcesDir()
File manifestFile = null
if (resourceDir.exists() && resourceDir.listFiles().length > 0) {
File metaInfDir = new File(resourceDir, "META-INF")
if (metaInfDir.exists() && metaInfDir.listFiles().length > 0) {
manifestFile = new File(metaInfDir, "MANIFEST.MF")
}
}
looseApp.addManifestFileWithParent(archive, manifestFile, resourceDir.getParentFile().getCanonicalPath());
} else if (FilenameUtils.getExtension(dep.getAbsolutePath()).equalsIgnoreCase("jar")) {
addLibrary(parent, looseApp, "/WEB-INF/lib/", dep);
} else {
looseApp.addOutputDir(looseApp.getDocumentRoot(), dep , "/WEB-INF/classes/");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package io.openliberty.tools.gradle;

import org.junit.AfterClass
import org.junit.BeforeClass
import org.junit.Test

import java.io.File;
import java.io.FileInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.junit.Assert;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class TestLooseWarWithLooseJar extends AbstractIntegrationTest{
static File resourceDir = new File("build/resources/test/loose-war-with-loose-jar")
static File buildDir = new File(integTestDir, "/loose-war-with-loose-jar")
static String buildFilename = "build.gradle"

@BeforeClass
public static void setup() {
createDir(buildDir)
createTestProject(buildDir, resourceDir, buildFilename)
}

@Test
public void test_loose_config_file_exists() {
try {
runTasks(buildDir, 'deploy')
} catch (Exception e) {
throw new AssertionError ("Fail on task deploy. " + e)
}
assert new File('build/testBuilds/loose-war-with-loose-jar/ejb-war/build/wlp/usr/servers/testServer/apps/ejb-war.war.xml').exists() : 'looseApplication config file was not copied over to the liberty runtime'
}

/*
Expected output to the XML
<?xml version="1.0" encoding="UTF-8"?>
<archive>
<dir sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/loose-war-with-loose-jar/ejb-war/src/main/webapp" targetInArchive="/"/>
<dir sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/loose-war-with-loose-jar/build/classes/java/main" targetInArchive="/WEB-INF/classes/"/>
<archive targetInArchive="/WEB-INF/lib/ejb-ejb.jar">
<dir sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/loose-war-with-loose-jar/ejb-ejb/build/classes/java/main" targetInArchive="/"/>
<file sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/loose-war-with-loose-jar/ejb-ejb/build/resources/tmp/META-INF/MANIFEST.MF" targetInArchive="/META-INF/MANIFEST.MF"/>
</archive>
<file sourceOnDisk="/Users/../.gradle/caches/modules-2/files-2.1/javax/javaee-api/7.0/51399f902cc27a808122edcbebfaa1ad989954ba/javaee-api-7.0.jar" targetInArchive="/WEB-INF/lib/javaee-api-7.0.jar"/>
<file sourceOnDisk="/Users/../.gradle/caches/modules-2/files-2.1/com.sun.mail/javax.mail/1.5.0/ec2410fdf7e0a3022e7c2a2e6241039d1abc1e98/javax.mail-1.5.0.jar" targetInArchive="/WEB-INF/lib/javax.mail-1.5.0.jar"/>
<file sourceOnDisk="/Users/../.m2/repository/javax/activation/activation/1.1/activation-1.1.jar" targetInArchive="/WEB-INF/lib/activation-1.1.jar"/>
<file sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/loose-war-with-loose-jar/ejb-war/build/tmp/META-INF/MANIFEST.MF" targetInArchive="/META-INF/MANIFEST.MF"/>
</archive>
*/
@Test
public void test_loose_config_file_contents_are_correct() {
File on = new File("build/testBuilds/loose-war-with-loose-jar/ejb-war/build/wlp/usr/servers/testServer/apps/ejb-war.war.xml");
FileInputStream input = new FileInputStream(on);

// get input XML Document
DocumentBuilderFactory inputBuilderFactory = DocumentBuilderFactory.newInstance();
inputBuilderFactory.setIgnoringComments(true);
inputBuilderFactory.setCoalescing(true);
inputBuilderFactory.setIgnoringElementContentWhitespace(true);
inputBuilderFactory.setValidating(false);
DocumentBuilder inputBuilder = inputBuilderFactory.newDocumentBuilder();
Document inputDoc=inputBuilder.parse(input);

// parse input XML Document
XPath xPath = XPathFactory.newInstance().newXPath();

//Check for correct number of dir elements in loose war
String expression = "/archive/dir";
NodeList nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <dir/> element ==>", 2, nodes.getLength());

//Check loose jar archive element is present
expression = "/archive/archive";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <archive/> element ==>", 1, nodes.getLength());

//Check loose jar targetLocation is correct
Assert.assertEquals("sibling archive targetInArchive attribute value", "/WEB-INF/lib/ejb-ejb.jar",
nodes.item(0).getAttributes().getNamedItem("targetInArchive").getNodeValue());

//Check loose jar contains correct amount of dir elements
expression = "/archive/archive/dir";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <dir/> element ==>", 1, nodes.getLength());

//Check loose jar classes dir location
String nodeValue = nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "/ejb-ejb/build/classes/java/main",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());

//Check loose jar contains correct amount of file elements
expression = "/archive/archive/file";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <file/> element ==>", 1, nodes.getLength());

//Check loose jar manifest file location
nodeValue = nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "/ejb-ejb/build/resources/tmp/META-INF/MANIFEST.MF",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());

//Check correct number of additional file elements are present
expression = "/archive/file";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <file/> element ==>", 4, nodes.getLength());

Assert.assertEquals("archive targetInArchive attribute value", "/WEB-INF/lib/javaee-api-7.0.jar",
nodes.item(0).getAttributes().getNamedItem("targetInArchive").getNodeValue());

// Check that dependencies are not located in the test build dir since copyLibsDirectory not set. They will be located in the gradle cache somewhere.
nodeValue = nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
assert nodeValue.endsWith("/javaee-api-7.0.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'

Assert.assertEquals("archive targetInArchive attribute value", "/WEB-INF/lib/javax.mail-1.5.0.jar",
nodes.item(1).getAttributes().getNamedItem("targetInArchive").getNodeValue());

// Check that dependencies are not located in the test build dir since copyLibsDirectory not set. They will be located in the gradle cache somewhere.
nodeValue = nodes.item(1).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
assert nodeValue.endsWith("/javax.mail-1.5.0.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'

Assert.assertEquals("archive targetInArchive attribute value", "/WEB-INF/lib/activation-1.1.jar",
nodes.item(2).getAttributes().getNamedItem("targetInArchive").getNodeValue());

// Check that dependencies are not located in the test build dir since copyLibsDirectory not set. They will be located in the gradle cache somewhere.
nodeValue = nodes.item(2).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
assert nodeValue.endsWith("/activation-1.1.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
}
}
19 changes: 19 additions & 0 deletions src/test/resources/loose-war-with-loose-jar/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
allprojects {
group = 'sample'
version = '1.0'
}

subprojects {
apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

repositories {
mavenLocal()
mavenCentral()
}
}
10 changes: 10 additions & 0 deletions src/test/resources/loose-war-with-loose-jar/ejb-ejb/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
description = 'EJB Module'

dependencies {
testImplementation group: 'junit', name: 'junit', version:'4.13.1'
implementation group: 'javax', name: 'javaee-api', version:'7.0'
}

jar {
archiveName = baseName + '.' + extension
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package wasdev.ejb.ejb;

import javax.ejb.Stateless;

@Stateless
public class SampleStatelessBean {

public String hello() {
return "Hello EJB World.";
}
}
41 changes: 41 additions & 0 deletions src/test/resources/loose-war-with-loose-jar/ejb-war/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven {
name = 'Sonatype Nexus Snapshots'
url = 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
dependencies {
classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion"
}
}

apply plugin: 'war'
apply plugin: 'liberty'

jar.enabled = false
description = 'WAR Module'
dependencies {
testImplementation group: 'junit', name: 'junit', version:'4.13.1'
implementation group: 'javax', name: 'javaee-api', version:'7.0'
implementation project(':ejb-ejb')
libertyRuntime group: runtimeGroup, name: kernelArtifactId, version: runtimeVersion
}

war {
archiveName = baseName + '.' + extension
}

liberty {
server {
name = "testServer"
deploy {
apps = [war]
}
verifyAppStartTimeout = 30
looseApplication = true
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package wasdev.ejb.ejb.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.ejb.EJB;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import wasdev.ejb.ejb.SampleStatelessBean;

/**
* A servlet which injects a stateless EJB
*/
@WebServlet({"/", "/ejbServlet"})
public class EJBServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

@EJB
SampleStatelessBean statelessBean;

@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException {
PrintWriter writer = response.getWriter();

// Call hello method on a stateless session bean
String message = statelessBean.hello();

writer.println(message);
}
}
6 changes: 6 additions & 0 deletions src/test/resources/loose-war-with-loose-jar/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rootProject.name = 'ejb-war'
include ':ejb-ejb'
include ':ejb-war'

project(':ejb-ejb').projectDir = "$rootDir/ejb-ejb" as File
project(':ejb-war').projectDir = "$rootDir/ejb-war" as File