Skip to content

Commit

Permalink
Merge pull request #1810 from awisniew90/fix-sb-multi
Browse files Browse the repository at this point in the history
Fix multi-module jar skip for spring-boot projects
  • Loading branch information
cherylking authored Apr 19, 2024
2 parents 5d92183 + 746110c commit 9b96fb6
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<artifactId>springboot-project</artifactId>
<version>1.0.0.Final</version>
<packaging>jar</packaging>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- Support for JDK 9 and above-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- Test support for classifier configuration parameter -->
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>

<plugin>
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>SUB_VERSION</version>

<!-- Specify configuration, executions for liberty-maven-plugin -->
<configuration>
<serverName>test</serverName>
<serverXmlFile>src/test/resources/server.xml</serverXmlFile>
<runtimeArtifact>
<groupId>${runtimeGroupId}</groupId>
<artifactId>${runtimeArtifactId}</artifactId>
<version>${runtimeVersion}</version>
<type>zip</type>
</runtimeArtifact>
<appsDirectory>apps</appsDirectory>
<deployPackages>spring-boot-project</deployPackages>
</configuration>

<executions>
<execution>
<id>stop-server-before-clean</id>
<phase>pre-clean</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
<execution>
<id>create-server</id>
<phase>prepare-package</phase>
<goals>
<goal>install-server</goal>
<goal>create</goal>
<goal>install-feature</goal>
</goals>
</execution>
<execution>
<id>install-apps</id>
<phase>package</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>

<execution>
<id>test-start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>test-start</goal>
</goals>
</execution>
<execution>
<id>test-stop-server</id>
<phase>post-integration-test</phase>
<goals>
<goal>test-stop</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<runOrder>alphabetical</runOrder>
</configuration>
<executions>
<execution>
<id>default-integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>default-verify</id>
<phase>verify</phase>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* (C) Copyright IBM Corporation 2018.
*
* 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 application;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class SpringBootApp {
public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}

@RequestMapping("/spring")
public String hello() {
return "HELLO SPRING BOOT!!";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

<!-- Enable features -->
<featureManager>
<feature>springBoot-2.0</feature>
<feature>servlet-4.0</feature>
</featureManager>

<!-- To access this server from a remote client add a host attribute to
the following element, e.g. host="*" -->
<httpEndpoint httpPort="9080" httpsPort="9443"
id="defaultHttpEndpoint" />
</server>
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*******************************************************************************
* (c) Copyright IBM Corporation 2019, 2022.
*
* 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 net.wasdev.wlp.test.dev.it;

import static org.junit.Assert.*;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.util.Scanner;

import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import static io.openliberty.tools.common.plugins.util.BinaryScannerUtil.*;

public class SpringBootRunTest extends BaseDevTest {

@BeforeClass
public static void setUpBeforeClass() throws Exception {
setUpBeforeClass(null, "../resources/springboot-project", false, false, null, null);
}

@AfterClass
public static void cleanUpAfterClass() throws Exception {
BaseDevTest.cleanUpAfterClass(false);
}

/**
* As part of the multi-module validation, the run goal is skipped on projects with a "jar" packaging type.
* There is an exception for Spring Boot projects. This test will validate that the spring boot project is not skipped
*
* @throws Exception
*/
@Test
public void validateRunExecutionNotSkipped() throws Exception {
String mavenPluginCommand = "mvn package io.openliberty.tools:liberty-maven-plugin:"+System.getProperty("mavenPluginVersion")+":run";

StringBuilder command = new StringBuilder(mavenPluginCommand);
ProcessBuilder builder = buildProcess(command.toString());

builder.redirectOutput(logFile);
builder.redirectError(logFile);
process = builder.start();
assertTrue(process.isAlive());

OutputStream stdin = process.getOutputStream();

writer = new BufferedWriter(new OutputStreamWriter(stdin));

// Make sure we are not skipping the project
assertTrue(getLogTail(), verifyLogMessageDoesNotExist("Skipping module springboot-project which is not included in this invocation of the run goal", 30000));

// Check that the server has started
assertTrue(getLogTail(), verifyLogMessageExists("CWWKF0011I", 120000));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private static boolean isSubModule(MavenProject potentialTopModule, MavenProject
* @return
* @throws MojoExecutionException
*/
protected List<MavenProject> getRelevantMultiModuleProjects(ProjectDependencyGraph graph) throws MojoExecutionException {
protected List<MavenProject> getRelevantMultiModuleProjects(ProjectDependencyGraph graph, boolean skipJars) throws MojoExecutionException {
getLog().debug("Resolve relevant multi-module projects");

List<MavenProject> sortedReactorProjects = graph.getSortedProjects();
Expand All @@ -181,10 +181,10 @@ protected List<MavenProject> getRelevantMultiModuleProjects(ProjectDependencyGra
for (MavenProject reactorProject : sortedReactorProjects) {
if (graph.getDownstreamProjects(reactorProject, true).isEmpty()) {
getLog().debug("Found final downstream project: " + reactorProject.getArtifactId());
if (skipConfigured(reactorProject)) {
getLog().debug("Skip configured on project: " + reactorProject.getArtifactId() + " - Ignoring");
} else if (reactorProject.getPackaging().equals("jar")) {
} else if (reactorProject.getPackaging().equals("jar") && skipJars) {
getLog().debug(reactorProject.getArtifactId() + " is a jar project - Ignoring");
} else {
leaves.add(reactorProject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,11 @@ private void doDevMode() throws MojoExecutionException {

// In a multi-module build, dev mode will only be run on one project (the farthest downstream) and compile will
// be run on any relative upstream projects. If this current project in the Maven Reactor is not one of those projects, skip it.
List<MavenProject> relevantProjects = getRelevantMultiModuleProjects(graph);
boolean skipJars = true;
if("spring-boot-project".equals(getDeployPackages())) {
skipJars = false;
}
List<MavenProject> relevantProjects = getRelevantMultiModuleProjects(graph, skipJars);
if (!relevantProjects.contains(project)) {
getLog().info("\nSkipping module " + project.getArtifactId() + " which is not included in this invocation of dev mode.\n");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
* config/dropins directory.
*/
@Mojo(name = "generate-features", threadSafe = true)
public class GenerateFeaturesMojo extends ServerFeatureSupport {
public class GenerateFeaturesMojo extends PluginConfigSupport {

public static final String FEATURES_FILE_MESSAGE = "The Liberty Maven Plugin has generated Liberty features necessary for your application in "
+ GENERATED_FEATURES_FILE_PATH;
Expand Down Expand Up @@ -119,7 +119,11 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx

// In a multi-module build, generate-features will only be run on one project (the farthest downstream).
// If this current project in the Maven Reactor is not that project or any of its upstream projects, skip it.
List<MavenProject> relevantProjects = getRelevantMultiModuleProjects(graph);
boolean skipJars = true;
if("spring-boot-project".equals(getDeployPackages())) {
skipJars = false;
}
List<MavenProject> relevantProjects = getRelevantMultiModuleProjects(graph, skipJars);
if (!relevantProjects.contains(project)) {
getLog().info("\nSkipping module " + project.getArtifactId() + " which is not configured for the generate-features goal.\n");
return;
Expand Down Expand Up @@ -367,22 +371,6 @@ private File getBinaryScannerJarFromRepository() throws PluginExecutionException
}
}

/*
* Return specificFile if it exists; otherwise return the file with the requested fileName from the
* configDirectory, but only if it exists. Null is returned if the file does not exist in either location.
*/
private File findConfigFile(String fileName, File specificFile) {
if (specificFile != null && specificFile.exists()) {
return specificFile;
}

File f = new File(configDirectory, fileName);
if (configDirectory != null && f.exists()) {
return f;
}
return null;
}

private ServerConfigXmlDocument getServerXmlDocFromConfig(File serverXml) {
if (serverXml == null || !serverXml.exists()) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ private void doRunServer() throws MojoExecutionException {

// In a multi-module build, the run server goal will only be run on one project (the farthest downstream) and compile will
// be run on any relative upstream projects. If this current project in the Maven Reactor is not one of those projects, skip it.
List<MavenProject> relevantProjects = getRelevantMultiModuleProjects(graph);
boolean skipJars = true;
if("spring-boot-project".equals(getDeployPackages())) {
skipJars = false;
}
List<MavenProject> relevantProjects = getRelevantMultiModuleProjects(graph, skipJars);
if (!relevantProjects.contains(project)) {
getLog().info("\nSkipping module " + project.getArtifactId() + " which is not included in this invocation of the run goal.\n");
return;
Expand Down

0 comments on commit 9b96fb6

Please sign in to comment.