Skip to content

Commit

Permalink
Fix loose app generation for jar project dependencies in war projects
Browse files Browse the repository at this point in the history
  • Loading branch information
mattbsox committed Mar 1, 2023
1 parent c174b4b commit ae4ab29
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 14 deletions.
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,26 @@
/*******************************************************************************
* (c) Copyright IBM Corporation 2017.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
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,49 @@
/*******************************************************************************
* (c) Copyright IBM Corporation 2017.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
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);
}
}
Empty file.
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

0 comments on commit ae4ab29

Please sign in to comment.