diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index c42116f0..938d04cc 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -15,42 +15,42 @@ */ package io.openliberty.tools.gradle.tasks +import groovy.xml.XmlParser +import io.openliberty.tools.ant.ServerTask +import io.openliberty.tools.common.plugins.util.BinaryScannerUtil +import io.openliberty.tools.common.plugins.util.DevUtil +import io.openliberty.tools.common.plugins.util.InstallFeatureUtil +import io.openliberty.tools.common.plugins.util.JavaCompilerOptions +import io.openliberty.tools.common.plugins.util.PluginExecutionException +import io.openliberty.tools.common.plugins.util.PluginScenarioException +import io.openliberty.tools.common.plugins.util.ProjectModule +import io.openliberty.tools.common.plugins.util.ServerFeatureUtil +import io.openliberty.tools.common.plugins.util.ServerFeatureUtil.FeaturesPlatforms +import io.openliberty.tools.common.plugins.util.ServerStatusUtil +import io.openliberty.tools.gradle.utils.DevTaskHelper +import io.openliberty.tools.gradle.utils.LooseWarApplication import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.internal.file.DefaultFilePropertyFactory +import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.SourceSet -import org.gradle.api.logging.LogLevel +import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.options.Option import org.gradle.testfixtures.ProjectBuilder import org.gradle.tooling.BuildException import org.gradle.tooling.BuildLauncher -import org.gradle.tooling.ProjectConnection import org.gradle.tooling.GradleConnector +import org.gradle.tooling.ProjectConnection +import java.nio.file.Path +import java.util.Map.Entry import java.util.concurrent.ArrayBlockingQueue import java.util.concurrent.ThreadPoolExecutor - -import io.openliberty.tools.ant.ServerTask - -import io.openliberty.tools.common.plugins.util.DevUtil -import io.openliberty.tools.common.plugins.util.InstallFeatureUtil -import io.openliberty.tools.common.plugins.util.PluginExecutionException -import io.openliberty.tools.common.plugins.util.PluginScenarioException -import io.openliberty.tools.common.plugins.util.ServerFeatureUtil -import io.openliberty.tools.common.plugins.util.ServerFeatureUtil.FeaturesPlatforms -import io.openliberty.tools.common.plugins.util.ServerStatusUtil -import io.openliberty.tools.common.plugins.util.ProjectModule -import io.openliberty.tools.common.plugins.util.BinaryScannerUtil - import java.util.concurrent.TimeUnit -import java.util.Map.Entry -import java.nio.file.Path; -import groovy.xml.XmlParser class DevTask extends AbstractFeatureTask { @@ -371,23 +371,22 @@ class DevTask extends AbstractFeatureTask { Map libertyDirPropertyFiles = new HashMap (); private ServerTask serverTask = null; - DevTaskUtil(File buildDir, File installDirectory, File userDirectory, File serverDirectory, File sourceDirectory, File testSourceDirectory, File configDirectory, File projectDirectory, List resourceDirs, boolean changeOnDemandTestsAction, boolean hotTests, boolean skipTests, boolean skipInstallFeature, String artifactId, int serverStartTimeout, int verifyAppStartTimeout, int appUpdateTimeout, double compileWait, boolean libertyDebug, boolean pollingTest, boolean container, File containerfile, File containerBuildContext, String containerRunOpts, int containerBuildTimeout, boolean skipDefaultPorts, boolean keepTempContainerfile, - String mavenCacheLocation, String packagingType, File buildFile, boolean generateFeatures + String mavenCacheLocation, String packagingType, File buildFile, boolean generateFeatures, List webResourceDirs, + List projectModuleList ) throws IOException, PluginExecutionException { super(buildDir, serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, projectDirectory, /* multi module project directory */ projectDirectory, resourceDirs, changeOnDemandTestsAction, hotTests, skipTests, false /* skipUTs */, false /* skipITs */, skipInstallFeature, artifactId, serverStartTimeout, verifyAppStartTimeout, appUpdateTimeout, ((long) (compileWait * 1000L)), libertyDebug, true /* useBuildRecompile */, true /* gradle */, pollingTest, container, containerfile, containerBuildContext, containerRunOpts, containerBuildTimeout, skipDefaultPorts, - null /* compileOptions not needed since useBuildRecompile is true */, keepTempContainerfile, mavenCacheLocation, null /* multi module upstream projects */, - false /* recompileDependencies only supported in ci.maven */, packagingType, buildFile, null /* parent build files */, generateFeatures, null /* compileArtifactPaths */, null /* testArtifactPaths */, new ArrayList() /* webResources */ + null /* compileOptions not needed since useBuildRecompile is true */, keepTempContainerfile, mavenCacheLocation, projectModuleList /* multi module upstream projects */, + false /* recompileDependencies only supported in ci.maven */, packagingType, buildFile, null /* parent build files */, generateFeatures, null /* compileArtifactPaths */, null /* testArtifactPaths */, webResourceDirs /* webResources */ ); - this.libertyDirPropertyFiles = AbstractServerTask.getLibertyDirectoryPropertyFiles(installDirectory, userDirectory, serverDirectory); ServerFeatureUtil servUtil = getServerFeatureUtil(true, libertyDirPropertyFiles); FeaturesPlatforms fp = servUtil.getServerFeatures(serverDirectory, libertyDirPropertyFiles); @@ -1262,7 +1261,11 @@ class DevTask extends AbstractFeatureTask { File buildFile = project.getBuildFile(); + List webResourceDirs = DevTaskHelper.getWebSourceDirectoriesToMonitor(project); // Instantiate util before any child gradle tasks launched so it can help find available port if needed + // Project modules contain all child modules. This project modules will be present only for multi-module + // used to watch sub project src and test source files + List projectModules = getProjectModules() try { this.util = new DevTaskUtil(project.getLayout().getBuildDirectory().getAsFile().get(), serverInstallDir, getUserDir(project, serverInstallDir), serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, project.getRootDir(), @@ -1270,7 +1273,7 @@ class DevTask extends AbstractFeatureTask { verifyAppStartTimeout.intValue(), verifyAppStartTimeout.intValue(), compileWait.doubleValue(), libertyDebug.booleanValue(), pollingTest.booleanValue(), container.booleanValue(), containerfile, containerBuildContext, containerRunOpts, containerBuildTimeout, skipDefaultPorts.booleanValue(), keepTempContainerfile.booleanValue(), localMavenRepoForFeatureUtility, - getPackagingType(), buildFile, generateFeatures.booleanValue() + DevTaskHelper.getPackagingType(project), buildFile, generateFeatures.booleanValue(), webResourceDirs, projectModules ); } catch (IOException | PluginExecutionException e) { throw new GradleException("Error initializing dev mode.", e) @@ -1410,6 +1413,81 @@ class DevTask extends AbstractFeatureTask { } } + private List getProjectModules() { + List upstreamProjects = new ArrayList(); + for (Project dependencyProject : DevTaskHelper.getAllUpstreamProjects(project)) { + // TODO get compiler options for upstream project + // JavaCompilerOptions upstreamCompilerOptions = getMavenCompilerOptions(p); + JavaCompilerOptions upstreamCompilerOptions = new JavaCompilerOptions(); + SourceSet mainSourceSet = dependencyProject.sourceSets.main; + SourceSet testSourceSet = dependencyProject.sourceSets.test; + DefaultFilePropertyFactory.DefaultDirectoryVar outputDirectory = mainSourceSet.java.classesDirectory; + DefaultFilePropertyFactory.DefaultDirectoryVar testOutputDirectory = testSourceSet.java.classesDirectory; + Set compileArtifacts = new HashSet(); + Set testArtifacts = new HashSet(); + File upstreamSourceDir = new File(mainSourceSet.java.sourceDirectories.asPath) + File upstreamOutputDir = outputDirectory.asFile.get(); + File upstreamTestSourceDir = new File(testSourceSet.java.sourceDirectories.asPath); + File upstreamTestOutputDir = testOutputDirectory.asFile.get(); + // resource directories + List upstreamResourceDirs = mainSourceSet.resources.srcDirs.toList(); + /* TODO all gradle items + // properties that are set in the pom file + Properties props = dependencyProject.getProperties(); + + // properties that are set by user via CLI parameters + Properties userProps = session.getUserProperties(); + + Plugin libertyPlugin = getLibertyPluginForProject(p); + // use "dev" goal, although we don't expect the skip tests flags to be bound to any goal + Xpp3Dom config = ExecuteMojoUtil.getPluginGoalConfig(libertyPlugin, "dev", getLog()); + + boolean upstreamSkipTests = DevHelper.getBooleanFlag(config, userProps, props, "skipTests"); + boolean upstreamSkipITs = DevHelper.getBooleanFlag(config, userProps, props, "skipITs"); + boolean upstreamSkipUTs = DevHelper.getBooleanFlag(config, userProps, props, "skipUTs"); + + // only force skipping unit test for ear modules otherwise honour existing skip + // test params + + + // build list of dependent modules + List dependentProjects = graph.getDownstreamProjects(p, true); + List dependentModules = new ArrayList(); + for (MavenProject depProj : dependentProjects) { + dependentModules.add(depProj.getFile()); + } + */ + boolean upstreamSkipTests = false + boolean upstreamSkipITs = false + boolean upstreamSkipUTs = false + + if (DevTaskHelper.getPackagingType(dependencyProject).equals("ear")) { + upstreamSkipUTs = true; + } + // build list of dependent modules + List dependentModules = new ArrayList(); + ProjectModule upstreamProject = new ProjectModule(dependencyProject.getBuildFile(), + dependencyProject.getName(), + DevTaskHelper.getPackagingType(dependencyProject), + compileArtifacts, + testArtifacts, + upstreamSourceDir, + upstreamOutputDir, + upstreamTestSourceDir, + upstreamTestOutputDir, + upstreamResourceDirs, + upstreamSkipTests, + upstreamSkipUTs, + upstreamSkipITs, + upstreamCompilerOptions, + dependentModules); + + upstreamProjects.add(upstreamProject); + } + + return upstreamProjects; + } + private boolean isInstallDirChanged(Project project, File currentInstallDir) { if (project.getLayout().getBuildDirectory().getAsFile().get().exists() && new File(project.getLayout().getBuildDirectory().getAsFile().get(), 'liberty-plugin-config.xml').exists()) { XmlParser pluginXmlParser = new XmlParser() diff --git a/src/main/groovy/io/openliberty/tools/gradle/utils/DevTaskHelper.groovy b/src/main/groovy/io/openliberty/tools/gradle/utils/DevTaskHelper.groovy new file mode 100644 index 00000000..ec71de0d --- /dev/null +++ b/src/main/groovy/io/openliberty/tools/gradle/utils/DevTaskHelper.groovy @@ -0,0 +1,153 @@ +/** + * (C) Copyright IBM Corporation 2024 + * + * 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 io.openliberty.tools.gradle.utils + +import org.apache.commons.io.FilenameUtils +import org.apache.tools.ant.taskdefs.Jar +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.tasks.bundling.War +import org.gradle.plugins.ear.Ear + +import java.nio.file.Path + +public class DevTaskHelper { + + /** + *

Get packaging type of Gradle project + * @param project gradle project + * @return + * @throws Exception + */ + public static String getPackagingType(Project project) throws Exception{ + if (project.plugins.hasPlugin("war") || !project.tasks.withType(War).isEmpty()) { + if (project.plugins.hasPlugin("org.springframework.boot")) { + return "springboot" + } + return "war" + } + else if (project.plugins.hasPlugin("ear") || !project.tasks.withType(Ear).isEmpty()) { + return "ear" + } + else if (project.plugins.hasPlugin("org.springframework.boot") ) { + return "springboot" + } else if (project.plugins.hasPlugin("java") ||!project.tasks.withType(Jar).isEmpty()) { + return "jar" + } + else { + throw new GradleException("Archive path not found. Supported formats are jar, war, ear, and springboot jar.") + } + } + + /** + * get deploy dependencies for gradle project + * @param project project + * @return + */ + public static Map getDeployDependencies(Project project) { + Map completeDeployDeps = new HashMap(); + File[] filesAsDeps = project.configurations.deploy.getFiles().toArray() + Dependency[] deployDeps = project.configurations.deploy.getAllDependencies().toArray() + + if (filesAsDeps.size() == deployDeps.size()) { + for (int i = 0; i < filesAsDeps.size(); i++) { + completeDeployDeps.put(filesAsDeps[i], deployDeps[i]) + } + } + return completeDeployDeps + } + + /** + * get all upstream projects for a gradle project. Iterate through all projects and recursively find all dependent projects + * @param project + * @return + */ + public static Set getAllUpstreamProjects(Project project) { + Set allDependentProjects = new HashSet<>() + + for (Iterator iter = project.getConfigurations().iterator(); iter.hasNext(); ) { + Configuration element = iter.next(); + if (element.canBeResolved) { + Dependency[] deployDeps = element.getAllDependencies().toArray() + for (Dependency dependency1: deployDeps) { + if (dependency1 instanceof ProjectDependency) { + Project dependencyProject = dependency1.getDependencyProject() + allDependentProjects.add(dependencyProject) + allDependentProjects.addAll(getAllUpstreamProjects(dependencyProject)) + } + } + } + } + return allDependentProjects; + } + + /** + * get web app source directories + * @param project + * @return + */ + public static List getWebSourceDirectoriesToMonitor(Project project) { + List retVal = new ArrayList(); + Task warTask = project.getTasks().findByName('war') + if (warTask != null) { + setWarSourceDir(warTask, retVal) + } else if (project.configurations.deploy != null) { + setWarSourceDirForDeployDependencies(project, retVal) + } else { + retVal.add("src/main/webapp") + } + return retVal; + } + /** + * find war deploy dependencies and add source dir + * @param project + * @param retVal + */ + private static void setWarSourceDirForDeployDependencies(Project project, ArrayList retVal) { + Task warTask + HashMap completeDeployDeps = DevTaskHelper.getDeployDependencies(project) + for (Map.Entry entry : completeDeployDeps) { + Dependency dependency = entry.getValue(); + File dependencyFile = entry.getKey(); + + if (dependency instanceof ProjectDependency) { + Project dependencyProject = dependency.getDependencyProject() + String projectType = FilenameUtils.getExtension(dependencyFile.toString()) + switch (projectType) { + case "war": + warTask = dependencyProject.getTasks().findByName('war') + if (warTask != null) { + setWarSourceDir(warTask, retVal) + } + break; + default: + break; + } + } + } + } + + private static void setWarSourceDir(Task warTask, ArrayList retVal) { + War war = (War) warTask.getProject().war + if (war.getWebAppDirectory().getAsFile().get() != null) { + retVal.add(war.getWebAppDirectory().get().asFile.toPath().toAbsolutePath()) + } + } +} diff --git a/src/main/groovy/io/openliberty/tools/gradle/utils/LooseWarApplication.groovy b/src/main/groovy/io/openliberty/tools/gradle/utils/LooseWarApplication.groovy index 35a74c3b..e6168d9d 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/utils/LooseWarApplication.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/utils/LooseWarApplication.groovy @@ -1,4 +1,4 @@ -package io.openliberty.tools.gradle.utils; +package io.openliberty.tools.gradle.utils import io.openliberty.tools.common.plugins.config.LooseApplication import io.openliberty.tools.common.plugins.config.LooseConfigData @@ -31,5 +31,4 @@ public class LooseWarApplication extends LooseApplication { } config.addDir(sourceDir, "/") } - } diff --git a/src/test/groovy/io/openliberty/tools/gradle/TestMultiModuleLooseEarAppDevMode.groovy b/src/test/groovy/io/openliberty/tools/gradle/TestMultiModuleLooseEarAppDevMode.groovy new file mode 100644 index 00000000..1891c79f --- /dev/null +++ b/src/test/groovy/io/openliberty/tools/gradle/TestMultiModuleLooseEarAppDevMode.groovy @@ -0,0 +1,50 @@ +package io.openliberty.tools.gradle + +import org.junit.AfterClass +import org.junit.BeforeClass +import org.junit.Test + +import static org.junit.Assert.assertTrue; + +class TestMultiModuleLooseEarAppDevMode extends BaseDevTest { + static File resourceDir = new File("build/resources/test/multi-module-loose-ear-pages-test") + static File buildDir = new File(integTestDir, "/multi-module-loose-ear-pages-test") + static String buildFilename = "build.gradle" + + @BeforeClass + public static void setup() throws IOException, InterruptedException, FileNotFoundException { + createDir(buildDir); + createTestProject(buildDir, resourceDir, buildFilename); + new File(buildDir, "build").createNewFile(); + runDevMode(buildDir) + } + + @Test + public void modifyJavaFileTest() throws Exception { + + // modify a java file + File srcHelloWorld = new File(buildDir, "/jar/src/main/java/io/openliberty/guides/multimodules/lib/Converter.java"); + File targetHelloWorld = new File(buildDir, "/jar/build/classes/java/main/io/openliberty/guides/multimodules/lib/Converter.class"); + assertTrue(srcHelloWorld.exists()); + assertTrue(targetHelloWorld.exists()); + + long lastModified = targetHelloWorld.lastModified(); + waitLongEnough(); + String str = "// testing"; + BufferedWriter javaWriter = new BufferedWriter(new FileWriter(srcHelloWorld, true)); + javaWriter.append(' '); + javaWriter.append(str); + javaWriter.close(); + + assertTrue(waitForCompilation(targetHelloWorld, lastModified, 6000)); + } + + @AfterClass + public static void cleanUpAfterClass() throws Exception { + String stdout = getContents(logFile, "Dev mode std output"); + System.out.println(stdout); + String stderr = getContents(errFile, "Dev mode std error"); + System.out.println(stderr); + cleanUpAfterClass(true); + } +} diff --git a/src/test/groovy/io/openliberty/tools/gradle/TestMultiModuleLooseEarWithPages.groovy b/src/test/groovy/io/openliberty/tools/gradle/TestMultiModuleLooseEarWithPages.groovy new file mode 100644 index 00000000..f2cea3a5 --- /dev/null +++ b/src/test/groovy/io/openliberty/tools/gradle/TestMultiModuleLooseEarWithPages.groovy @@ -0,0 +1,124 @@ +package io.openliberty.tools.gradle + +import org.junit.AfterClass +import org.junit.Assert +import org.junit.BeforeClass +import org.junit.Test +import org.w3c.dom.Document +import org.w3c.dom.NodeList + +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 io.openliberty.tools.common.plugins.util.OSUtil + +public class TestMultiModuleLooseEarWithPages extends AbstractIntegrationTest{ + static File resourceDir = new File("build/resources/test/multi-module-loose-ear-pages-test") + static File buildDir = new File(integTestDir, "/multi-module-loose-ear-pages-test") + static String buildFilename = "build.gradle" + + @BeforeClass + public static void setup() { + createDir(buildDir) + createTestProject(buildDir, resourceDir, buildFilename) + } + + @AfterClass + public static void tearDown() throws Exception { + runTasks(buildDir, 'libertyStop') + } + + @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/multi-module-loose-ear-pages-test/ear/build/wlp/usr/servers/ejbServer/apps/ejb-ear-1.0-SNAPSHOT.ear.xml').exists() : 'looseApplication config file was not copied over to the liberty runtime' + } + /* + Expected output to the XML + + + + +

+ + + + + + + + + + + + + + */ + @Test + public void test_loose_config_file_contents_are_correct(){ + File on = new File("build/testBuilds/multi-module-loose-ear-pages-test/ear/build/wlp/usr/servers/ejbServer/apps/ejb-ear-1.0-SNAPSHOT.ear.xml"); + FileInputStream input = new FileInputStream(on); + String ejbWar = "/ejb-war-1.0-SNAPSHOT.war" + String warWebappsFolder = "/multi-module-loose-ear-pages-test/war/src/main/webapp" + String ejbJar = "/WEB-INF/lib/ejb-jar-1.0-SNAPSHOT.jar" + + + // get input XML Document + DocumentBuilderFactory inputBuilderFactory = DocumentBuilderFactory.newInstance(); + inputBuilderFactory.setIgnoringComments(true); + inputBuilderFactory.setCoalescing(true); + inputBuilderFactory.setIgnoringElementContentWhitespace(true); + inputBuilderFactory.setValidating(false); + inputBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false) + inputBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false) + DocumentBuilder inputBuilder = inputBuilderFactory.newDocumentBuilder(); + Document inputDoc=inputBuilder.parse(input); + + // parse input XML Document + XPath xPath = XPathFactory.newInstance().newXPath(); + String expression = "/archive/dir"; + NodeList nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET); + Assert.assertEquals("Number of element ==>", 0, nodes.getLength()); + + expression = "/archive/archive"; + nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET); + Assert.assertEquals("Number of element ==>", 2, nodes.getLength()); + String expectedResult1 = nodes.item(0).getAttributes() + .getNamedItem("targetInArchive").getNodeValue(); + String expectedResult2 = nodes.item(1).getAttributes() + .getNamedItem("targetInArchive").getNodeValue(); + Assert.assertTrue("actual targetInArchive paths [" + expectedResult1 + "," + + expectedResult2 + "] is not matching with actual result : " + ejbWar, + expectedResult1.equals(ejbWar) || expectedResult2.equals(ejbWar)) + + if (OSUtil.isWindows()) { + warWebappsFolder = "\\multi-module-loose-ear-pages-test\\war\\src\\main\\webapp" + } + expression = "/archive/archive/dir"; + nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET); + Assert.assertEquals("Number of element ==>", 3, nodes.getLength()); + String sourceOnDisk1 = nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue(); + String sourceOnDisk2 = nodes.item(1).getAttributes().getNamedItem("sourceOnDisk").getNodeValue(); + String sourceOnDisk3 = nodes.item(2).getAttributes().getNamedItem("sourceOnDisk").getNodeValue(); + + Assert.assertTrue("actual sourceOnDisk paths [" + sourceOnDisk1 + ","+ sourceOnDisk2 + "," + + sourceOnDisk3 + "] is not containing with actual result : " + warWebappsFolder, + sourceOnDisk1.contains(warWebappsFolder) || sourceOnDisk2.contains(warWebappsFolder) || sourceOnDisk3.contains(warWebappsFolder)); + + expression = "/archive/archive/archive"; + nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET); + Assert.assertEquals("Number of element ==>", 1, nodes.getLength()); + + Assert.assertEquals(ejbJar, nodes.item(0).getAttributes().getNamedItem("targetInArchive").getNodeValue()) + + expression = "/archive/file"; + nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET); + Assert.assertEquals("Number of element ==>", 2, nodes.getLength()); + } +} diff --git a/src/test/resources/multi-module-loose-ear-pages-test/build.gradle b/src/test/resources/multi-module-loose-ear-pages-test/build.gradle new file mode 100644 index 00000000..e8e6ce22 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/build.gradle @@ -0,0 +1,18 @@ +allprojects { + group = 'io.openliberty.guides' + version = '1.0-SNAPSHOT' +} +subprojects { + apply plugin: 'java' + + sourceCompatibility = 8 + targetCompatibility = 8 + tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' + } + + repositories { + mavenLocal() + mavenCentral() + } +} diff --git a/src/test/resources/multi-module-loose-ear-pages-test/ear/build.gradle b/src/test/resources/multi-module-loose-ear-pages-test/ear/build.gradle new file mode 100644 index 00000000..2fb6b9c3 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/ear/build.gradle @@ -0,0 +1,53 @@ +apply plugin: 'ear' +apply plugin: 'liberty' + +description = 'EAR Module' + +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" + } +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + deploy project(path:':war', configuration:'archives') + deploy project(path:':jar', configuration:'archives') + testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0' + libertyRuntime group: runtimeGroup, name: kernelArtifactId, version: runtimeVersion +} + +ear { + archiveFileName = rootProject.name+"-"+getArchiveBaseName().get() +"-"+rootProject.version+ '.' + getArchiveExtension().get() + deploymentDescriptor { + module ('ejb-jar-1.0-SNAPSHOT.jar', 'java') + webModule ('ejb-war-1.0-SNAPSHOT.war', '/converter') + } +} + +liberty { + server { + name = "ejbServer" + deploy { + apps = [ear] + copyLibsDirectory = file("${project.getLayout().getBuildDirectory().getAsFile().get()}/libs") + } + verifyAppStartTimeout = 30 + looseApplication = true + } +} + +deploy.dependsOn 'ear' +ear.dependsOn ':jar:jar', ':war:war' diff --git a/src/test/resources/multi-module-loose-ear-pages-test/ear/src/main/liberty/config/server.env b/src/test/resources/multi-module-loose-ear-pages-test/ear/src/main/liberty/config/server.env new file mode 100644 index 00000000..542a949e --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/ear/src/main/liberty/config/server.env @@ -0,0 +1 @@ +WLP_LOGGING_CONSOLE_LOGLEVEL=INFO \ No newline at end of file diff --git a/src/test/resources/multi-module-loose-ear-pages-test/ear/src/main/liberty/config/server.xml b/src/test/resources/multi-module-loose-ear-pages-test/ear/src/main/liberty/config/server.xml new file mode 100755 index 00000000..4452444e --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/ear/src/main/liberty/config/server.xml @@ -0,0 +1,21 @@ + + + + pages-3.1 + + + + + + + + + + + + + + diff --git a/src/test/resources/multi-module-loose-ear-pages-test/ear/src/test/java/it/io/openliberty/guides/multimodules/IT.java b/src/test/resources/multi-module-loose-ear-pages-test/ear/src/test/java/it/io/openliberty/guides/multimodules/IT.java new file mode 100644 index 00000000..7e136754 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/ear/src/test/java/it/io/openliberty/guides/multimodules/IT.java @@ -0,0 +1,71 @@ +// tag::copyright[] +/******************************************************************************* + * Copyright (c) 2017, 2024 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +// end::copyright[] +package it.io.openliberty.guides.multimodules; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.junit.jupiter.api.Test; + +public class IT { + String port = System.getProperty("http.port"); + String war = "converter"; + String urlBase = "http://localhost:" + port + "/" + war + "/"; + + @Test + // tag::testIndexPage[] + public void testIndexPage() throws Exception { + String url = this.urlBase; + HttpURLConnection con = testRequestHelper(url, "GET"); + assertEquals(200, con.getResponseCode(), "Incorrect response code from " + url); + assertTrue(testBufferHelper(con).contains("Enter the height in centimeters"), + "Incorrect response from " + url); + } + // end::testIndexPage[] + + @Test + // tag::testHeightsPage[] + public void testHeightsPage() throws Exception { + String url = this.urlBase + "heights.jsp?heightCm=10"; + HttpURLConnection con = testRequestHelper(url, "POST"); + assertTrue(testBufferHelper(con).contains("3 inches"), + "Incorrect response from " + url); + } + // end::testHeightsPage[] + + private HttpURLConnection testRequestHelper(String url, String method) + throws Exception { + URL obj = new URL(url); + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + // optional default is GET + con.setRequestMethod(method); + return con; + } + + private String testBufferHelper(HttpURLConnection con) throws Exception { + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer response = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + return response.toString(); + } + +} diff --git a/src/test/resources/multi-module-loose-ear-pages-test/jar/build.gradle b/src/test/resources/multi-module-loose-ear-pages-test/jar/build.gradle new file mode 100644 index 00000000..5d081ad3 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/jar/build.gradle @@ -0,0 +1,10 @@ + +description = 'EJB Module' + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0' +} + +jar { + archiveFileName = rootProject.name+"-"+getArchiveBaseName().get() +"-"+rootProject.version+ '.' + getArchiveExtension().get() +} diff --git a/src/test/resources/multi-module-loose-ear-pages-test/jar/src/main/java/io/openliberty/guides/multimodules/lib/Converter.java b/src/test/resources/multi-module-loose-ear-pages-test/jar/src/main/java/io/openliberty/guides/multimodules/lib/Converter.java new file mode 100644 index 00000000..7cc2f690 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/jar/src/main/java/io/openliberty/guides/multimodules/lib/Converter.java @@ -0,0 +1,48 @@ +// tag::copyright[] +/******************************************************************************* + * Copyright (c) 2017, 2021 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +// end::copyright[] +package io.openliberty.guides.multimodules.lib; + +public class Converter { + + // tag::getFeetMethod[] + public static int getFeet(int cm) { + int feet = (int) (cm / 30.48); + return feet; + } + // end::getFeetMethod[] + + // tag::getInchesMethod[] + public static int getInches(int cm) { + double feet = cm / 30.48; + int inches = (int) (cm / 2.54) - ((int) feet * 12); + System.out.println(inches); + return inches; + } + // end::getInchesMethod[] + + public static int sum(int a, int b) { + return a + b; + } + + public static int diff(int a, int b) { + return a - b; + } + + public static int product(int a, int b) { + return a * b; + } + + public static int quotient(int a, int b) { + return a / b; + } + +} diff --git a/src/test/resources/multi-module-loose-ear-pages-test/settings.gradle b/src/test/resources/multi-module-loose-ear-pages-test/settings.gradle new file mode 100644 index 00000000..7ba263a0 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/settings.gradle @@ -0,0 +1,8 @@ +rootProject.name = 'ejb' +include ':jar' +include ':war' +include ':ear' + +project(':jar').projectDir = "$rootDir/jar" as File +project(':war').projectDir = "$rootDir/war" as File +project(':ear').projectDir = "$rootDir/ear" as File \ No newline at end of file diff --git a/src/test/resources/multi-module-loose-ear-pages-test/war/build.gradle b/src/test/resources/multi-module-loose-ear-pages-test/war/build.gradle new file mode 100644 index 00000000..35852bd3 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/war/build.gradle @@ -0,0 +1,18 @@ + +apply plugin: 'war' + +description = 'WAR Module' +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0' + compileOnly 'javax.servlet:javax.servlet-api:4.0.1' + compileOnly 'jakarta.platform:jakarta.jakartaee-api:10.0.0' + implementation project(':jar') + compileOnly 'org.eclipse.microprofile:microprofile:6.1' +} + +war { + archiveFileName = rootProject.name+"-"+getArchiveBaseName().get() +"-"+rootProject.version+ '.' + getArchiveExtension().get() +} + +war.dependsOn ':jar:jar' + diff --git a/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/java/io/openliberty/guides/multimodules/web/HeightsBean.java b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/java/io/openliberty/guides/multimodules/web/HeightsBean.java new file mode 100644 index 00000000..2ad11b91 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/java/io/openliberty/guides/multimodules/web/HeightsBean.java @@ -0,0 +1,67 @@ +// tag::copyright[] +/******************************************************************************* + * Copyright (c) 2017, 2019 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +// end::copyright[] +package io.openliberty.guides.multimodules.web; + +public class HeightsBean implements java.io.Serializable { + private String heightCm = null; + private String heightFeet = null; + private String heightInches = null; + private int cm = 0; + private int feet = 1; + private int inches = 0; + + public HeightsBean() { + } + + // Capitalize the first letter of the name i.e. first letter after get + // If first letter is not capitalized, it must match the property name in + // index.jsp + public String getHeightCm() { + return heightCm; + } + + public String getHeightFeet() { + return heightFeet; + } + + public String getHeightInches() { + return heightInches; + } + + public void setHeightCm(String heightcm) { + this.heightCm = heightcm; + } + + // Need an input as placeholder, you can choose not to use the input + // tag::setHeightFeet[] + public void setHeightFeet(String heightfeet) { + this.cm = Integer.valueOf(heightCm); + // tag::getFeet[] + this.feet = io.openliberty.guides.multimodules.lib.Converter.getFeet(cm); + // end::getFeet[] + String result = String.valueOf(feet); + this.heightFeet = result; + } + // end::setHeightFeet[] + + // tag::setHeightInches[] + public void setHeightInches(String heightinches) { + this.cm = Integer.valueOf(heightCm); + // tag::getInches[] + this.inches = io.openliberty.guides.multimodules.lib.Converter.getInches(cm); + // end::getInches[] + String result = String.valueOf(inches); + this.heightInches = result; + } + // end::setHeightInches[] + +} diff --git a/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/WEB-INF/web.xml b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..69ec1a29 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetypes Created Web Application + \ No newline at end of file diff --git a/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/heights.jsp b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/heights.jsp new file mode 100644 index 00000000..16f33ad8 --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/heights.jsp @@ -0,0 +1,41 @@ +<%-- +******************************************************************************* +* Copyright (c) 2017, 2024 IBM Corporation and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License 2.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-2.0/ +* +* SPDX-License-Identifier: EPL-2.0 +******************************************************************************* +--%> + + +Height Converters + + +

Height Converter

+ + + + + + +

+ Height in centimeters: + + cm +

+ +
+ +

+ Height in feet and inches: + + feets + + inches +

+ + + diff --git a/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/index.jsp b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/index.jsp new file mode 100644 index 00000000..594e859a --- /dev/null +++ b/src/test/resources/multi-module-loose-ear-pages-test/war/src/main/webapp/index.jsp @@ -0,0 +1,26 @@ +<%-- +******************************************************************************* +* Copyright (c) 2017, 2024 IBM Corporation and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License 2.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-2.0/ +* +* SPDX-License-Identifier: EPL-2.0 +******************************************************************************* +--%> + + +Height Converter + + +

Height Converters

+

Enter the height in centimeter

+ +
+ cm
+
+ + +