e-Spirit / FSDevTools

Project to support developer experience (DX) with FirstSpirit template development by offering a connection between a VCS like Git and FirstSpirit.
Apache License 2.0
28 stars 20 forks source link

Some Issues when setting up FS-CLI #56

Closed ykorzikowski closed 9 months ago

ykorzikowski commented 10 months ago

Hi there,

after setting up the fs-cli on redhat envrionment, I found the following issues:

  1. Javap is not present in JRE -> We are using the dev-tools to automate Import/Export of Projects and installation of FSM. MAybe there is another way to figure out if the additional VM_ARGS are neccessary?
  2. Regarding the presence of file fs-isolated-server-*.jar:

The CLI fails, if its not present, but its not printing a proper error message, if there is only 1 file in the lib dir.

Check

[root@XXXX devtools]# ls fs-cli/lib/
 fsdevtools-cli-4.5.0.jar
[root@XXXX devtools]# sudo -u fs5 ./fs-import-content-export.sh
+ export JAVA_HOME=/usr/java/latest
+ JAVA_HOME=/usr/java/latest
+ sh /opt/firstspirit5/devtools/fs-cli/bin/fs-cli.sh XXXXX
+ JAVACMD=/usr/java/latest/bin/java
++ pwd
+ FS_CLI_DIR=/opt/firstspirit5/devtools/fs-cli
+ VM_ARGS='--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED'
+ /usr/java/latest/bin/java --add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED -Xmx512m -Dlog4j.configurationFile=/opt/firstspirit5/devtools/fs-cli/conf/log4j2.xml -cp '/opt/firstspirit5/devtools/fs-cli/lib/*' com.espirit.moddev.cli.Main XXXX
Exception in thread "main" java.lang.NoClassDefFoundError: de/espirit/firstspirit/access/project/ProjectScriptContext
    at com.espirit.moddev.cli.Main.main(Main.java:33)
Caused by: java.lang.ClassNotFoundException: de.espirit.firstspirit.access.project.ProjectScriptContext
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)

vs.

[root@XXXX devtools]# ls fs-cli/lib/
fs-isolated-server-5.2.230909.jar.bkp  fsdevtools-cli-4.5.0.jar
[root@XXXX devtools]# sudo -u fs5 ./fs-import-content-export.sh
+ export JAVA_HOME=/usr/java/latest
+ JAVA_HOME=/usr/java/latest
+ sh /opt/firstspirit5/devtools/fs-cli/bin/fs-cli.sh XXXX
+ JAVACMD=/usr/java/latest/bin/java
++ pwd
+ FS_CLI_DIR=/opt/firstspirit5/devtools/fs-cli
+ VM_ARGS='--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED'
+ /usr/java/latest/bin/java --add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED -Xmx512m -Dlog4j.configurationFile=/opt/firstspirit5/devtools/fs-cli/conf/log4j2.xml -cp '/opt/firstspirit5/devtools/fs-cli/lib/*' com.espirit.moddev.cli.Main XXXX
ERROR Couldn't find FirstSpirit classes - have you placed your FirstSpirit api jar (fs-isolated-runtime) into the fs-cli lib folder?

Because of bullet 1, we changed the wrapper so far:

#!/bin/sh

# WARNING: This file is managed by Ansible.
# DO NOT EDIT THIS FILE MANUALLY.
# Any changes made directly to this file may be overwritten by Ansible.

set -eux

JAVACMD="/usr/java/latest/bin/java";

# Tries to use readlink or realpath. If not installed, falls back to no conversion.
my_realpath() {
    readlink -f "$1" 2>/dev/null || realpath "$1" 2>/dev/null || echo "$1"
}

FS_CLI_DIR="$( pwd )/fs-cli"

VM_ARGS="--add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED"

$JAVACMD $VM_ARGS -Xmx512m -Dlog4j.configurationFile="${FS_CLI_DIR}/conf/log4j2.xml" -cp "${FS_CLI_DIR}/lib/*" com.espirit.moddev.cli.Main "$@";
RETVAL=$?;
exit ${RETVAL};

Quick-Fix:

Add an additional check in the fs-cli.sh:

if [ ! -f "${FS_CLI_DIR}/lib/fs-isolated-server-*.jar" ]; then
    echo "ERROR: fs-isolated-server-*.jar not found in lib directory."
    exit 1
fi
ykorzikowski commented 10 months ago

ChatGPTs opinion:

The different behavior you're observing when there's only one file in the directory versus when there's more than one file (even a non-JAR file) is likely due to how Java's class loader handles wildcard classpaths.

Here's a deeper look into what might be happening:

Classpath Wildcard Expansion:

When using a wildcard in the classpath like -cp "${FS_CLI_DIR}/lib/*", Java expands this to include all JAR files in the specified directory. Importantly, it does not include directories or non-JAR files. However, Java's wildcard expansion behavior can sometimes be influenced by the presence of other files or directories in the specified path, though this is more typically about how it orders the JAR files, not about including non-JAR files. Application or Java Virtual Machine Behavior:

The script is straightforward and doesn't include logic for checking the contents of the lib directory or for generating specific error messages based on those contents. Therefore, the different error messages you're seeing are likely generated by the Java application (com.espirit.moddev.cli.Main) or by the JVM based on the classpath it constructs. It's possible that the Java application itself is programmed to check for the presence of specific classes or JAR files and to generate error messages based on what it finds or doesn't find. Possible Explanation for Behavior:

When there is only one JAR file, and it doesn't contain the required classes, the Java application may fail with a ClassNotFoundException because it can't find what it needs. When there is more than one file (even a non-JAR file), the Java application might be executing a different code path, possibly due to how the JAR files are ordered or processed, leading to a more informative error message. Investigating Further:

To better understand why the error messages are different, you might need to look into the source code or documentation of com.espirit.moddev.cli.Main, if available. Alternatively, enabling more detailed logging for the Java application, if possible, might provide more insights into what's happening when it runs. In conclusion, the script itself isn't the source of the behavior you're observing. The behavior is more likely due to how the Java application and the JVM are handling the classpath and the loading of classes from the JAR files in the lib directory.

kafmann-e-spirit commented 10 months ago

Hey @ykorzikowski , first of all, thanks for your feedback. We will take a look into the error handling for the described case.

Note: It is not neccessary to place the fs-isolated-server.jar into the lib-folder, you only need the fs-isolated-runtime.jar.

The check that you have implemented is not suitable for all usecases because we don't want to rely on filenames. However, the initial check at startup might need a little fix for some cases (like yours).