Calling Java Methods from Shell Scripts - java

How to execute a Java method from inside shell scripts?

You can only call the main method. Design your main method such that it calls the method you want.
When I say call main method, you don't explicitly invoke it. It's the only entry point to a java program when you invoke it.
If your class looks like:
package com.foo;
public class Test {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
You can use the following command line to invoke the main from within the directory where you can find com/foo/Test.class (If you're in the classes directory in the structure shown far below):
java com.foo.Test
If you want to do so from a different (See the directory structure far below) directory, then you'll have to set classpath.
java -cp /path/to/classes com.foo.Test
Assume the below directory structure for clarity.
-path
-to
-classes
-com
-foo
>Test.class

You can't execute an arbitrary method directly from a shell script, you'll need to have that method exposed externally in some way.
The simplest way of course is to write a main method that directly invokes the code you want to test.
Alternatively, you could make use of a Java application that takes parameters to act as a sort of launcher. In its crudest form you can imagine an app that takes a classname and method name as arguments, then instantiates the class and invokes the method via reflection. In a similar vein, but a bit more elegant, we use an app that invokes operations exposed via JMX in order to fire certain methods on a server when required.
Ultimately though, bash (or equivalent) doesn't understand JVM bytecode. You will need to launch a Java process to run the method, which will involve executing some main method that in turn invokes what you need.

You can use shell script and call your java program like this:
`#!/bin/bash
JAVA_HOME=/usr/lib/jvm/jdk1.6.0_02
CLASSPATH=/home/freddy/myapp/lib/whatever.jar: .
$JAVA_HOME/bin/java -cp $CLASSPATH MyJavaClass
exit 0`

Try bashj (a bash mutant with java support) https://sourceforge.net/projects/bashj/. It is intended to cover your need (and much more):
for instance:
#!/usr/bin/bashj
echo Math.cos(0.5)
echo Math.hypot(3.0,4.0)
echo System.getProperty("java.runtime.version")
You can also put your own methods in a jar loaded by bashj, or include some java source code within the bashj script:
#!/usr/bin/bashj
##java
public static int factorial(int n)
{if (n<=0) return(0);
if (n==1) return(1);
return(n*factorial(n-1));}
##bash
echo j.factorial(10)

Related

How to invoke the Cucumber runner class from a different main method

I'm new to using Command Line Interface. So I just have a question on how to invoke the runner class of the cucumber using CLI technique.
I have a Java program which contains a main method. When testers pass the argument which is test case, it will fetch the feature file. The java program invoke a custom made API which will fetch the correct feature file.
Next I'll have to invoke the Cucumber runner class to execute the test case. I need to pass this particular feature file as the argument. Two questions, Can we invoke the runner class from a different main method. I did some research and I was not able to find a concrete answer.
Two questions,
cucumber.api.cli.Main.main(arguments); So how do i specify the jar location of my runner class.
`FeatureFileCreation.main("xxxxx"); - API that fetches the right feature file
String[] arguments = {"-", ""};
cucumber.api.cli.Main.main(arguments);
How do I specify where my jar is located? How can I pass my feature file?`
Should I create a main method in the runner class, something like this? For the sake of using CLI,Since I need to create a runnable jar. I should have a main method in my runner class.
`
#RunWith(Cucumber.class)
#Cucumber.Options(features="C:/Users/IBM_ADMIN/Desktop/CRAutomation/CR Regression1/src/My.feature",glue={"bell.canada.step.definition"})
public class AutomationRunnerAction {
public void main(){
}
}`
Please note that, Getting the right feature file is 1 java API. I will invoking that API from one main method of one java program. The runner class with step definition and methods are a diff java program.
Unfortunately the accept answer is not correct. If you look at the source of Main.main() you'll notice that it contains: System.exit(exitstatus) which terminates the system.
The proper way to run the commandline programatically would be to use Main.run() like this:
String [] argv = new String[]{ "-g","","./src/main/java/featureDetails/Testing.feature"};
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
byte exitstatus = Main.run(argv, contextClassLoader);
Try this if this works. You do not need any Runner class. Just call the static main method of Main class that corresponds to running cucumber from cli.
public static void main(String[] args) throws Throwable {
//Your code to get feature file full path
Main.main(new String[]{"-g", "classpath to step definition file", "Full path to feature file"});
// My stepdefinition is inside java package at cucumber.sample.test
// My feature file is inside src/test/resources/features/samplethree.feature
}
For additional parameters like tags or plugin use "-t","#Tags". Important the feature file path has to be the last option.
I am running this for Eclipse with Maven setting up classpath and jar dependencies.

Change name of a Class

Is it possible to change the name of a class retrieved using:Foo.class.getName() (or getSimpleName() or getCanonicalName()).
I know that those methods are part of java.lang.Class<T> the question itself is if there is a way to tell java.lang.Class<T> what is the name that I want it to display for my class.
I know that it "opens the door to tricky things" since that name is used by the reflection libraries to do "stuff" and bla bla bla. nevertheless I was wondering wether is posible to call Foo.class.getSimpleName() and get something like MyFoo.
All of this of course without string manipulation which is the last alternative I have.
Find the src.zip in your JDK. Extract java/lang/Class.java into some directory and modify getSimpleName() method. For example like this:
public String getSimpleName() {
return "MyName"; // return MyName for any class
}
Compile it normally with javac (you will get many warnings, ignore them). Remove all additional classes created like Class$1.class, leaving only java/lang/Class.class file. Put it into jar:
$ jar -c java >myclass.jar
Now prepend the bootstrap path with your new jar. For example, let's consider this test class:
public class Test {
public static void main(String[] args) {
System.out.println(Test.class.getSimpleName());
}
}
$ java Test
Test
$ java -Xbootclasspath/p:myclass.jar Test
MyName
I don't even want to explain how dangerous it is. Also according to the Oracle binary code license (supplemental term F) you cannot deploy your application this way.
You may try Powermock which according to their home page allows mocking final classes although it needs to use it's own class loader.
Other mocking frameworks that do not do byte code manipulation with custom class loaders such as Mockito and Easymock cannot work with classes that are final which java.lang.Class is.

main method as final in java

I saw this code in one of the certification exams:
public class SimpleClass
{
int num;
final static void main(final String args[])
{
String s1="new";
String s2="String";
String s3="Creation";
System.out.println(s1+s2+s3);
}
}
I know that final methods are ones which are not possible to override. I also know that if the usual signature of the main method is altered, it will be treated as any other ordinary method by the JVM, and not as main().
However, the options given to me were:
1> Code won't compile
2> Code will throw an exception
3> will print newStringCreation.
It's not possible to run this program on eclipse IDE. Can anyone explain what should be the answer and why?
Ok let me put my question like this - When I execute my program, what will happen? Which of the 3 options above should I choose?
final static void main won't run, since main is not public.
public final static void main will work.
At least that's the behavior on my Eclipse IDE.
The Code will compile without any problems but it will throw a run-time exception saying "main method not public". The main method has to be public because it has to be called by JVM which is outside the scope of the package and hence would need the access specifier-public. If you are unable to run it in eclipse, try the archaic method of saving the file in a notepad with filename.java. Go to cmd and reach the file location..If on desktop, use cd desktop! Use the following commands to run the file-
javac filename.java
java filename
You will see the required run-time exception that I mentioned above.
The main method has to be accessible from the outside. Hence, in your case the application will compile but throw an execution at runtime.
You have the main method but since the modifier is final JVM wont be able to run the main method of the program.You wont see any compilation error.
You can run the program in eclipse when you make the modifier change of final to public

Run javac compiled groovy code using java?

I have a simple groovy file as follows:
class test2 {
public static void main(String[] args) {
println("In groovy!!");
}
}
My gradle task is compiling this into a test2 class file
How do I run this file from prompt ?
java test2 (from the location of the test2.class file)
causes a : Error: Could not find or load main class test2.class
I assuming I need to add asm and groovy to the class path. However:
java -cp "groovy-all-2.3.6.jar;asm-all-3.3.1.jar" test2
also doesn't work (files are in correct locations).
I know this may be a bit late for the OP but nevertheless:
Given that your groovy main exists, the error message:
Error: Could not find or load main class YOUR_MAINCLASS_HERE
from the java command while executing a groovy main (of a compiled groovy file which produced classes) means basically that your groovy jar is not in the classpath.
Longer Answer:
Lets see why that is for a simple hello world example. I have a file called main.groovy with the following content:
class Main {
static void main(String[] args){
println('hello world')
}
}
Put this somewhere in your filesystem. Open a command prompt in the same directory and ensure that groovy and java is accessable though the PATH.
In the command prompt, compile the file with groovyc, so just type in:
groovyc main.groovy
This will produce a file called Main.class (with uppercase M because of the class name).
Ok now we have the appropriate test setup. If you now try to run the file just with java command:
java Main
you will get the error message:
Error: Could not find or load main class Main
This is a bit unexpected, because one can think that we just can invoke the main in our Main.class without linking the groovy library, so we would expect an exception like ClassNotFoundException.
In contrast, try again with groovy in your classpath. I will refer to the directory of your groovy installation as GROOVY_HOME. To run the hello world Main class finally, we can type in:
java -cp ".:/$GROOVY_HOME/lib/*" Main
which produces the expected output on unix-like systems (on windows you need to replace the colon with a semicolon and the variable access would be like %GROOVY_HOME%).
The reason is quite simple: Groovy produces for groovy main methods not the same signature as required by the java specification. Therefore, you can only invoke a groovy main with groovy on the CLASSPATH - what makes totally sense!
You can check this for yourself. Try now the command:
javap Main.class
This will give you a quick analysis of the bytecode and the present interfaces of the class "Main.class". All along you will see something similar to this output:
Compiled from "main.groovy"
public class Main implements groovy.lang.GroovyObject {
public static transient boolean __$stMC;
public Main();
public static void main(java.lang.String...);
protected groovy.lang.MetaClass $getStaticMetaClass();
public groovy.lang.MetaClass getMetaClass();
public void setMetaClass(groovy.lang.MetaClass);
public java.lang.Object invokeMethod(java.lang.String, java.lang.Object);
public java.lang.Object getProperty(java.lang.String);
public void setProperty(java.lang.String, java.lang.Object);
}
Of interest is line 5:
public static void main(java.lang.String...);
This seems quite similar to a normal java main, but with one difference: groovyc used an java.lang.String ellipsis (as stated by the three dots) and not and java.lang.String[].
So this could be the reason. I'm not so sure, because normally java will give you an appropriate error output if it can find the class but not the method signature. For example, try:
java java.lang.Integer
which has clearly not a main method. Java sees that correctly:
Error: Main method not found in class java.lang.Integer, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
I'm also not sure, what groovy does during class loading for understanding this kind of main signature (or lets says this kind of bytecode), but if you compare that with a normal java hello world javap output, you get
public class JMain {
public JMain();
public static void main(java.lang.String[]);
}
which has a different and the normal java main signature.
Maybe someone from the pivotal groovy team can clarify.
I hope this will give you a hint.
The test2.class needs to be on your CLASSPATH. For example, if it is at /Users/you/classes/test2.class then /Users/you/classes/ needs to be on your CLASSPATH.
Since you are building with Gradle, you could also just let Gradle sort all of that out for you using JavaExec. See http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.JavaExec.html for more info. A simple example in your build.gradle might be something like this:
task myTask(type: JavaExec, dependsOn: 'classes') {
main = 'test2'
classpath = sourceSets.main.runtimeClasspath
}
I hope that helps.

command line arguments.

I am beginner and I want to pass a string as a command line argument in netbeans .how can i do this?
thanks
In a standard Java program that can take command line arguments, there will be a class that acts as the entry point of the whole program. That class will have a static method in it like this:
public class FooBar {
// ...
public static void main(String[] arguments) {
// ...
}
// ...
}
The arguments are in the array that is the parameter to that method, which must have that signature and be both public and static. If you're using a hosting engine or framework, the entry point is often taken care of for you; you should consult its documentation to see how to get command line arguments (if that is possible at all, or even reasonable).
Command line arguments are always strings. If you want to interpret them as something else, you've got to convert them manually.
A Tut for it:
http://wiki.netbeans.org/TaT_PassRuntimeArgs
In NetBeans IDE 8.0 you can use a community contributed plugin named NbRunWithArgs. This plugin provides features like
Run project with Arguments (Context menu and Run menu option)
Run File with Arguments context menu for Java files having main method
You can read more details about this plugin on this blog post.

Categories

Resources