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

springbootapplication node multiple occurrence fix #467

Merged
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* (C) Copyright IBM Corporation 2017, 2024.
* (C) Copyright IBM Corporation 2017, 2025.
*
* 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 @@ -75,7 +75,8 @@ public class ServerConfigDocument {
private Properties defaultProps;
private Map<String, File> libertyDirectoryPropertyToFile = null;

Optional<String> springBootAppNodeLocation=Optional.empty();
Optional<String> springBootAppNodeLocation = Optional.empty();
Optional<String> springBootAppNodeDocumentURI = Optional.empty();

private static final XPathExpression XPATH_SERVER_APPLICATION;
private static final XPathExpression XPATH_SERVER_WEB_APPLICATION;
Expand Down Expand Up @@ -505,15 +506,13 @@ private void parseApplication(Document doc, XPathExpression expression) throws X

NodeList nodeList = (NodeList) expression.evaluate(doc, XPathConstants.NODESET);
if(expression.equals(XPATH_SERVER_SPRINGBOOT_APPLICATION) && nodeList.getLength()>1){
throw new PluginExecutionException("Found multiple springBootApplication elements specified in the server configuration. Only one springBootApplication can be configured per Liberty server.");
throw new PluginExecutionException(String.format("Found multiple springBootApplication elements specified in the server configuration file %s. Only one springBootApplication can be configured per Liberty server.", doc.getDocumentURI()));
}
for (int i = 0; i < nodeList.getLength(); i++) {
String nodeValue = nodeList.item(i).getAttributes().getNamedItem("location").getNodeValue();
// add unique values only
if (!nodeValue.isEmpty()) {
if(expression.equals(XPATH_SERVER_SPRINGBOOT_APPLICATION)){
springBootAppNodeLocation = Optional.of(nodeValue);
}
checkForSpringBootApplicationNode(doc, expression, nodeValue);
String resolved = VariableUtility.resolveVariables(log, nodeValue, null, getProperties(), getDefaultProperties(), getLibertyDirPropertyFiles());
if (resolved == null) {
// location could not be resolved, log message and add location as is
Expand All @@ -529,6 +528,20 @@ private void parseApplication(Document doc, XPathExpression expression) throws X
}
}

private void checkForSpringBootApplicationNode(Document doc, XPathExpression expression, String nodeValue) throws PluginExecutionException {
if(expression.equals(XPATH_SERVER_SPRINGBOOT_APPLICATION)){
// checking whether any springBootAppNodeLocation already configured from other server configuration files
if(springBootAppNodeLocation.isPresent() && springBootAppNodeDocumentURI.isPresent()){
throw new PluginExecutionException(String.format("Found multiple springBootApplication elements specified in the server configuration in files [%s, %s]. Only one springBootApplication can be configured per Liberty server.", springBootAppNodeDocumentURI.get(), doc.getDocumentURI()));
}
else {
log.debug("Setting springBootApplication location as "+ nodeValue);
springBootAppNodeLocation = Optional.of(nodeValue);
springBootAppNodeDocumentURI = Optional.of(doc.getDocumentURI());
}
}
}

private void parseInclude(Document doc) throws XPathExpressionException, IOException, SAXException, PluginExecutionException {
// parse include document in source server xml
NodeList nodeList = (NodeList) XPATH_SERVER_INCLUDE.evaluate(doc, XPathConstants.NODESET);
Expand All @@ -550,9 +563,9 @@ private void parseInclude(Document doc) throws XPathExpressionException, IOExcep
for (Document inclDoc : inclDocs) {
parseApplication(inclDoc, XPATH_SERVER_APPLICATION);
parseApplication(inclDoc, XPATH_SERVER_WEB_APPLICATION);
parseApplication(doc, XPATH_SERVER_SPRINGBOOT_APPLICATION);
parseApplication(inclDoc, XPATH_SERVER_SPRINGBOOT_APPLICATION);
parseApplication(inclDoc, XPATH_SERVER_ENTERPRISE_APPLICATION);
parseNames(doc, XPATH_ALL_SERVER_APPLICATIONS);
parseNames(inclDoc, XPATH_ALL_SERVER_APPLICATIONS);
// handle nested include elements
parseInclude(inclDoc);
}
Expand Down Expand Up @@ -707,7 +720,9 @@ private void parseDocumentsInDirectory(File directory, ArrayList<Document> docs)
*/
public Document parseDocument(File file) throws FileNotFoundException, IOException {
try (FileInputStream is = new FileInputStream(file)) {
return parseDocument(is);
Document document= parseDocument(is);
document.setDocumentURI(file.getCanonicalPath());
return document;
} catch (SAXException ex) {
// If the file was not valid XML, assume it was some other non XML
// file in dropins.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class ServerConfigDocumentOverridesTest {
private final static Path SERVER_CONFIG_DIR = WLP_USER_DIR.resolve("servers/defaultServer");
private final static Path SHARED_CONFIG_DIR = WLP_USER_DIR.resolve("shared");
private final static Path SERVERS_RESOURCES_DIR = RESOURCES_DIR.resolve("servers/");
private final static Path SERVER_CONFIG_INCLUDE_DIR = SERVER_CONFIG_DIR.resolve("includes");

// 1. variable default values in server.xml file
// 6. variable values declared in the server.xml file
Expand Down Expand Up @@ -277,4 +278,28 @@ public void testServerConfigDocumentForLCLS() throws IOException, PluginExecutio
assertEquals("ServerConfigDocument http.port variable is not assigned properly ", "1111", configDocument.getProperties().getProperty("http.port"));
assertEquals("ServerConfigDocument includeLocation default property is not assigned properly ", "includes", configDocument.getDefaultProperties().getProperty("includeLocation"));
}

@Test
public void testProcessServerXmlWithMultipleSpringBootNodesInMultipleConfigFiles() throws IOException{
// we have added <springbootapplication> in valid_server.xml and included_server.xml
File serverConfigDir = SERVER_CONFIG_DIR.toFile();
Map<String, File> libertyDirPropMap = new HashMap<String, File>();
libertyDirPropMap.put(ServerFeatureUtil.SERVER_CONFIG_DIR, serverConfigDir);
libertyDirPropMap.put(ServerFeatureUtil.WLP_INSTALL_DIR, WLP_DIR.toFile());
libertyDirPropMap.put(ServerFeatureUtil.WLP_USER_DIR, WLP_USER_DIR.toFile());
libertyDirPropMap.put(ServerFeatureUtil.SHARED_CONFIG_DIR, SHARED_CONFIG_DIR.toFile());
File serversResourceDir = SERVERS_RESOURCES_DIR.toFile();
File springBootServerXmlDir = new File(serversResourceDir, "springBootApplicationTest");

File includedServerXml = new File(springBootServerXmlDir, "included_server.xml");
File newIncludedServerXml = new File(SERVER_CONFIG_INCLUDE_DIR.toFile(), "included_server.xml");
Files.copy(includedServerXml.toPath(), newIncludedServerXml.toPath(), StandardCopyOption.REPLACE_EXISTING);
File validServerXml = new File(springBootServerXmlDir, "valid_server.xml");
File newValidServerXml = new File(SERVER_CONFIG_INCLUDE_DIR.toFile(), "valid_server.xml");
Files.copy(validServerXml.toPath(), newValidServerXml.toPath(), StandardCopyOption.REPLACE_EXISTING);
assertThrows("Expected multiple springBootApplication elements specified in the server configuration. Only one springBootApplication node is found.",
PluginExecutionException.class, () -> new ServerConfigDocument(new TestLogger(), null, libertyDirPropMap));
Files.delete(newIncludedServerXml.toPath());
Files.delete(newValidServerXml.toPath());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@
<variable name="server.env.defined" value="${this.value}"/>
<variable name="bootstrap.property.defined" value="${that.value}"/>
<variable name="config.dropins.server" value="2"/>

<include location="${includeLocationNonDefault}/included_server.xml"/>
<include location="${includeLocationNonDefault}/valid_server.xml"/>
</server>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
<springBootApplication id="guide-spring-boot"
location="guide-spring-boot-0.2.0.jar"
name="guide-spring-boot" />
</server>
Loading