Calling java program dependent on external library - java

I am trying to call a java program in php to use it with web interface.
Java program is dependent on an external lib: commons-cli-1.2.jar
So basically I need to export it before calling the java program; but if I export it first as:
shell_exec('export CLASSPATH=$CLASSPATH:~/lib/commons-cli-1.2.jar');
then call the java program as:
shell_exec('java ComputePagerank -i $para_i -d $para_d -e $para_e -o $para_o');
I think it creates different shells for each call; then the export does not have any effect on java program. Or am I wrong?
Otherwise, it should output a file in the server. But simply it does not. So, what is wrong? Any idea?
edit: However can it be because some parameters such as para_i stands for an input file name, so that i have to specify full path for that? Because I just assume if the input file is in the same working directory, there won't be any problem, will it?
edit-2: it outputs properly when i use command line;)

you're right, each shell_exec creates a separate shell.
env CLASSPATH=whatever java -switches

I would use
shell_exec('java -cp $CLASSPATH:/home/yourname/dir/lib/commons-cli-1.2.jar ComputePagerank -i $para_i -d $para_d -e $para_e -o $para_o > message');
and (this is important) replace the tilde(~) with the actual path to your directory (/home/yourname say). The ~ is expanded by the shell and is dependent on which shell you''re using.

Try Creating a simple shell script with the commands that you want to execute. You may pass arguments to a shell script so that is not a problem either.
for example
echo "Running Script..."
java -cp $CLASSPATH:~/lib/commons-cli-1.2.jar ComputePagerank -i $1 -d $2 -e $3 -o $4 > message
etc.
Then try calling it from the command line first with some parameters. Did it output? Then try calling it from the php script. Did it output? If it did not then you may need to check permissions. I had a simiolar experience some time ago with a Java program that simply did not have permission to write a file.

You should be able to call it like this.
shell_exec('java -cp $CLASSPATH:~/lib/commons-cli-1.2.jar ComputePagerank -i $para_i -d $para_d -e $para_e -o $para_o > message');
Another option is to issue the 2 commands seperately, but to the same shell, like this:
shell_exec('export CLASSPATH=$CLASSPATH:~/lib/commons-cli-1.2.jar; java ComputePagerank -i $para_i -d $para_d -e $para_e -o $para_o > message');
edit:
some shells don't let you call export while you're setting up the variable. so this may be safer than the second option above:
shell_exec('CLASSPATH=$CLASSPATH:~/lib/commons-cli-1.2.jar; export CLASSPATH; java ComputePagerank -i $para_i -d $para_d -e $para_e -o $para_o > message');
another edit:
If none of the above work then you're going to have to do some more trouble shooting. Does your java program work from the command prompt?
java -cp $CLASSPATH:/home/user/lib/commons-cli-1.2.jar ComputePagerank -i param1 -d param2 -e param3 -o param4 > message

Related

can't make a shell script to make a jar file

I try to make a simple shell script to make a jar file. The jar command combined with -C does not work with wildcards. Therefor I use a wildcard to find the files I want. Write them to a file, and loop over them.
It looks something like this:
the_classes=''
cd "$bin_folder"
tmp_dir=$(mktemp -d -t java_sucks)
find "imui/core/" -type f -name "IMUI_Widget_Agent*.class" >"$tmp_dir/classes.txt"
while IFS="" read -r p || [ -n "$p" ]
do
the_classes="${the_classes} -C '$bin_folder' '$p'"
done < "$tmp_dir/classes.txt"
Using the above I complete the command:
cmd='jar cfm build/IMUI_Widget_Agent.jar'
cmd="${cmd} \"$bin_folder/imui/core/IMUI_Widget_Agent_MANIFEST.MF\" $the_classes"
printf "\n\n\ncmd\n\n\n"
echo $cmd
Now if I copy and paste this command to execute it works!
But I want to avoid the manual labour of doing the copy and paste by hand every time.
Now I have:
eval "$("$cmd")"
But I get an error File name too long. No matter what I try, every fix I do creates a new problem. I have been working 6 hours now to make this script.
What would be a good step forward?
Since you cd "$bin_folder" you don't actually need -C "$bin_folder":
#!/bin/bash
shopt -s globstar
cd "$bin_folder"
jar cfm build/IMUI_Widget_Agent.jar \
imui/core/IMUI_Widget_Agent_MANIFEST.MF \
imui/core/**/IMUI_Widget_Agent*.class
However, if you still want to add them as part of a larger script, you can easily and robustly build your command in an array:
#!/bin/bash
shopt -s globstar
cmd=(jar cfm build/IMUI_Widget_Agent.jar imui/core/IMUI_Widget_Agent_MANIFEST.MF)
cd "$bin_folder"
for file in imui/core/**/IMUI_Widget_Agent*.class
do
cmd+=(-C "$bin_folder" "$file")
done
echo "About to execute: "
printf "%q " "${cmd[#]}"
echo
"${cmd[#]}"
Alternatively, you can simply do eval "$cmd" with your code, which is equivalent to echo and copy-pasting. However, be aware that this is fragile and error prone because it requires careful escaping of the filenames which you're not currently doing.

How to tell whether current bash script was invoked from call script

I have a script that ideally will be used in two different ways. One, run stand-alone from command line. Two invoke from a service script located in /etc/init.d.
I would like the script (call it run_app.sh) to work as follows:
#/bin/bash
# this is run_app.sh. It should be able to be run stand-alone or called from another script
if [ invoked by a calling script ] then
java -cp . -jar blah.jar
else
nohup java -cp . -jar blah.jar 2>&1 &
, so its the "invoked by a calling script" that I would need help with. Thank you.
If you plan to launch your script either by issuing ./run_app.sh or the service. You can just use $0:
#!/bin/bash
# this is run_app.sh. It should be able to be run stand-alone or called from another script
this_script_name="run_app.sh"
if [ "$0" == "./${this_script_name}" ] then
java -cp . -jar blah.jar
else
nohup java -cp . -jar blah.jar 2>&1 &
Instead of trying to find out how the script was called, I suggest to use a command line argument.
Script app.sh
#/bin/bash
# this is run_app.sh. It should be able to be run stand-alone or called from another script
if [ "$1" = "--service" ] then
java -cp . -jar blah.jar
else
nohup java -cp . -jar blah.jar 2>&1 &
fi
Manually run the script as app.sh, from the calling script run app.sh --service.
If you need to pass additional command line arguments to your script, you might have to implement some better option parsing.
Note: Checking $0 may work under certain conditions, but may not work in some other cases. Trying to find out details about the parent processes is even more difficult and fragile.
Another note: Your java command line arguments -cp . -jar blah.jar depend on the current directory. To make sure this works in all cases, the script should cd into the correct directory before calling java. e.g. cd $(dirname "$0") if the script is located in the same directory as blah.jar.

Error: Could not find or load main class Swagger Codegen

I left an open issue for here
I´m trying to create a custom codegen, I managed to make it work by putting the files inside of the codegen project but I want it to work like this: https://github.com/swagger-api/swagger-codegen#making-your-own-codegen-modules
I haven't modified the autogenerated project at all but I keep getting:
Error: Could not find or load main class io.swagger.codegen.SwaggerCodegen
This is the command line:
java -cp output/myLibrary/target/myCustomCodegen-swagger-codegen-1.0.0.jar:swagger-codegen-cli-2.1.6.jar io.swagger.codegen.SwaggerCodegen generate -i https://watson-api-explorer.mybluemix.net/listings/conversation-v1-experimental.json -l com.my.company.codegen.Mycustomcodegengenerator -o outputlocation
I got the jar from here https://mvnrepository.com/artifact/io.swagger/swagger-codegen-project/2.1.6
This is what I'm doing:
Run java -jar swagger-codegen-cli-2.1.6.jar meta \ -o output/myLibrary -n myClientCodegen -p com.my.company.codegen to create costume codegen
Run mvn package in output/myLibrary
Run java -cp output/myLibrary/target/myCustomCodegen-swagger-codegen-1.0.0.jar:swagger-codegen-cli-2.1.6.jar io.swagger.codegen.SwaggerCodegen generate -i https://watson-api-explorer.mybluemix.net/listings/conversation-v1-experimental.json -l com.my.company.codegen.Mycustomcodegengenerator -o outputlocation in the folder that contains both swagger-codege-cli-2.1.6.jar and the output folder
It does find the class if I remove the first part, but doesn´t find the new language:
java -cp swagger-codegen-cli-2.1.6.jar io.swagger.codegen.SwaggerCodegen generate -i https://watson-api-explorer.mybluemix.net/listings/conversation-v1-experimental.json -l com.my.company.codegen.Mycustomcodegengenerator -o outputlocation
I have looked at the answers for "Error: Could not find or load main class" problems but haven't manage to fix it.
Here is a link to the jar
For Windows, change the colon (:) to a semicolon (;) - between the jars in the class path. So instead of
java -cp output/myLibrary/target/myCustomCodegen-swagger-codegen-1.0.0.jar:swagger-codegen-cli-2.1.6.jar io.swagger.codegen.SwaggerCodegen generate -i https://watson-api-explorer.mybluemix.net/listings/conversation-v1-experimental.json -l com.my.company.codegen.Mycustomcodegengenerator -o outputlocation
It should be
java -cp output/myLibrary/target/myCustomCodegen-swagger-codegen-1.0.0.jar;swagger-codegen-cli-2.1.6.jar io.swagger.codegen.SwaggerCodegen generate -i https://watson-api-explorer.mybluemix.net/listings/conversation-v1-experimental.json -l com.my.company.codegen.Mycustomcodegengenerator -o outputlocation
Multiple class paths need to be separated by a semicolon. http://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html
The problem is that you don't specify that correct path of swagger-codegen-2.1.6.jar in your call. Thats why it can't find the main-class.
If you are inside the root project swagger-codegen you should specify it like this: modules/swagger-codegen-cli/target/swagger-codegen-cli.jar
~$ cd ~/git/swagger-codegen # go into your root project
~/git/swagger-codegen$ # ... do the steps you described
~/git/swagger-codegen$ java -cp \
output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar \
io.swagger.codegen.SwaggerCodegen \
generate -i https://watson-api-explorer.mybluemix.net/listings/conversation-v1-experimental.json \
-l com.my.company.codegen.Mycustomcodegengenerator \
-o outputlocation
Or as a one-liner:
~/git/swagger-codegen$ java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar io.swagger.codegen.SwaggerCodegen generate -i https://watson-api-explorer.mybluemix.net/listings/conversation-v1-experimental.json -l com.my.company.codegen.Mycustomcodegengenerator -o outputlocation
Update 1
I'm pretty sure when you construct the classpath with -cp you have a mistake with the swagger-codegen-cli-2.1.6.jar. Please test the following.
Copy both (myClientCodegen-swagger-codegen-1.0.0.jar and swagger-codegen-cli-2.1.6.jar) jars into the same folder. Then go into this folder and try the following:
javap -cp myCustomCodegen-swagger-codegen-1.0.0.jar:swagger-codegen-cli-2.1.6.jar io.swagger.codegen.SwaggerCodegen
javap checks whether the main class io.swagger.codegen.SwaggerCodegen is available. On my machine it prints this:
Compiled from "SwaggerCodegen.java"
public class io.swagger.codegen.SwaggerCodegen {
public io.swagger.codegen.SwaggerCodegen();
public static void main(java.lang.String[]);
}
I had this similar problem when running as Spring Boot app in Eclipse 4.19 in macOS 10.14:
"Error: Could not find or load main class
io.swagger.Swagger2SpringBoot"
…even as I was staring at this very class containing the main method. My solution was issuing a "maven update project". This, like in other situations with odd Java symptoms, fixed the issue.

Solaris/UNIX passing "$*" to compiled java

I am having a strange issue with passing "$*" to a java compiled program. The program will not parse the variables when I pass it from the following command line:
/export/home/checkout>/tmp/jsnmp.sh -f noc2 -t 4,4 -x \"resdiag SilentDiag 1\",18
The "/tmp/jsnmp.sh" contains the following:
#!/bin/sh
$JAVA_HOME/bin/java -jar /export/home/checkout/jsnmp.jar $*
Now if I run this:
$JAVA_HOME/bin/java -jar /export/home/checkout/jsnmp.jar \
-f noc2 -t 4,4 -x "resdiag SilentDiag 1",18
Everything works.
Any ideas folks?
You probably want to maintain the quoting within the script, so use "$#".
This has nothing to do with Java or Solaris, this is purely shell stuff.
This is because after $* substitution arguments will get re-parsed and will become separate arguments. E.g. your java executable will see it as
-f noc2 -t 4,4 -x resdiag SilentDiag 1,18
or something like that.
Check out the following test code:
a.sh:
echo $1
echo $2
echo $3
./b.sh $*
b.sh:
echo b
echo $1
echo $2
echo $3
Running it will produce the following output:
$ ./a.sh "1 2" 3
1 2
3
b
1
2
3
See how it was 2 arguments for the first script and 3 params for the second.
Encompassing $* in double quotes won't help, because it will send all arguments as one argument.
The following should work:
#!/bin/sh
$JAVA_HOME/bin/java -jar /export/home/checkout/jsnmp.jar "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"
You will have some max number of arguments though...

use of double quotes when executing a java program in a shell script

I have a shell script that executes a Java program with parameters returned from a different Java program.
java -cp $wekaPath $(java GetFilter $WandFDir) -i $(pwd)/temp/training"$i"_$arffName.arff -o $(pwd)/temp/training_"$i"_$arffName.arff
When echoed, it produces the following string:
java -cp /home/robobenny/Documents/WEKA/weka-3-7-4/weka.jar weka.filters.supervised.attribute.AttributeSelection -E "weka.attributeSelection.InfoGainAttributeEval" -S "weka.attributeSelection.Ranker -T -1.7976931348623157E308 -N 20" -c first -i /home/robobenny/Documents/WEKA/Pipeline/temp/training1_Test.arff -o /home/robobenny/Documents/WEKA/Pipeline/temp/training_1_Test.arff
Which is great, because if I copy the string to the command line, it runs the Java program without incident. The problem arises when I don't echo it and try to execute it from the shell script, and I get the following from the terminal:
<!-- language: lang-none -->
Can't find class called: "weka.attributeSelection.InfoGainAttributeEval"
Filter options:
-S <"Name of search class [search options]">
Sets search method for subset evaluators.
eg. -S "weka.attributeSelection.BestFirst -S 8"
-E <"Name of attribute/subset evaluation class [evaluator options]">
Sets attribute/subset evaluator.
eg. -E "weka.attributeSelection.CfsSubsetEval -L"
Options specific to evaluator weka.attributeSelection.CfsSubsetEval:
-M
Treat missing values as a separate value.
-L
Don't include locally predictive attributes.
Options specific to search weka.attributeSelection.BestFirst:
-P <start set>
Specify a starting set of attributes.
Eg. 1,3,5-7.
-D <0 = backward | 1 = forward | 2 = bi-directional>
Direction of search. (default = 1).
-N <num>
Number of non-improving nodes to
consider before terminating search.
-S <num>
Size of lookup cache for evaluated subsets.
Expressed as a multiple of the number of
attributes in the data set. (default = 1)
General options:
-h
Get help on available options.
(use -b -h for help on batch mode.)
-i <file>
The name of the file containing input instances.
If not supplied then instances will be read from stdin.
-o <file>
The name of the file output instances will be written to.
If not supplied then instances will be written to stdout.
-c <class index>
The number of the attribute to use as the class.
"first" and "last" are also valid entries.
If not supplied then no class is assigned.
When I hard code the output of $(java GetFilter $WandFDir) in the shell script:
java -cp $wekaPath weka.filters.supervised.attribute.AttributeSelection -E "weka.attributeSelection.InfoGainAttributeEval" -S "weka.attributeSelection.Ranker -T -1.7976931348623157E308 -N 20" -c first -i $(pwd)/temp/training"$i"_$arffName.arff -o $(pwd)/temp/training_"$i"_$arffName.arff
It also runs without incident. Interestingly though, when echoed, the double quotes disappear.
java -cp /home/robobenny/Documents/WEKA/weka-3-7-4/weka.jar weka.filters.supervised.attribute.AttributeSelection -E weka.attributeSelection.InfoGainAttributeEval -S weka.attributeSelection.Ranker -T -1.7976931348623157E308 -N 20 -c first -i /home/robobenny/Documents/WEKA/Pipeline/temp/training2_Test.arff -o /home/robobenny/Documents/WEKA/Pipeline/temp/training_2_Test.arff
When I leave the double quotes out of the output of $(java GetFilter $WandFDir) I get the following error:
<!-- language: lang-none -->
Illegal options: -T -1.7976931348623157E308 -N 20
Filter options:
-S <"Name of search class [search options]">
Sets search method for subset evaluators.
eg. -S "weka.attributeSelection.BestFirst -S 8"
-E <"Name of attribute/subset evaluation class [evaluator options]">
Sets attribute/subset evaluator.
eg. -E "weka.attributeSelection.CfsSubsetEval -L"
Options specific to evaluator weka.attributeSelection.InfoGainAttributeEval:
-M
treat missing values as a seperate value.
-B
just binarize numeric attributes instead
of properly discretizing them.
Options specific to search weka.attributeSelection.Ranker:
-P <start set>
Specify a starting set of attributes.
Eg. 1,3,5-7.
Any starting attributes specified are
ignored during the ranking.
-T <threshold>
Specify a theshold by which attributes
may be discarded from the ranking.
-N <num to select>
Specify number of attributes to select
General options:
-h
Get help on available options.
(use -b -h for help on batch mode.)
-i <file>
The name of the file containing input instances.
If not supplied then instances will be read from stdin.
-o <file>
The name of the file output instances will be written to.
If not supplied then instances will be written to stdout.
-c <class index>
The number of the attribute to use as the class.
"first" and "last" are also valid entries.
If not supplied then no class is assigned.
I've looked around, and can't seem to find anything that solves my problem.
It's really a catch at the straw, but did you try something like
var="$(java GetFilter $WandFDir)"
java -cp $wekaPath $var -i $(pwd)/temp/training"$i"_$arffName.arff -o $(pwd)/temp/training_"$i"_$arffName.arff

Categories

Resources