Not able to load my custom java classes in JRuby - java

I have created one java project. Folder structure is like
Test
- src
-TestJavaCall.java
I created jar of this prject test.jar.
Code in my ruby file is as follows.
include Java
require '/home/office/test.jar'
java_import Java::TestJavaCall
testJava = TestJavaCall.new
When i am executing this script, i am getting this error.
NameError: cannot link Java class TestJavaCall
get_top_level_proxy_or_package at org/jruby/javasupport/JavaUtilities.java:49
const_missing at file:/home/spaul/.rvm/rubies/jruby-1.7.4/lib/jruby.jar!/jruby/java/java_module.rb:4
Please let me know what is the way to use custom java classes in ruby?
Source code of TestJavaCall.java
public class TestJavaCall {
public void testJavaCall()
{
System.out.println("test java call");
}
}

Related

Using jar from scala project from python via Py4j

I have built a jar from my Scala project.
I have the following structure for what I want to use from this jar
package aaa.bbb.ccc
case class FooResult(...)
trait Foo(...) {
def bar(): FooResult
}
object Foo {
private class FooImpl(...) extends Foo {
...
}
def apply(...): Foo
}
First question: Maybe I have misunderstood something in what Py4J offers,
but do I have to write a java/scala class to start the Py4J gateway if I want to use my own classes? Or is it enough to add it to the gateway's jvm's classpath?
Second question (which I guess doesn't apply depending on the answer to above): How do I add my jar when starting the java gateway in order to make it available? To solve this temporarily, I just started the jvm manually with my jar along with the Py4J jar with this command
java -classpath "path/to/py4j.jar:path/to/my.jar" py4j.GatewayServer 0
and then connected to it manually from the Python code. Then I tried to import my classes via
java_import(gateway.jvm, "aaa.bbb.ccc.*")
which didn't throw any error but I'm not sure it worked because it doesn't throw any error if I input some fake classpath.
Third question (which applies if the answer to the first is that I have to write the entry point to access my classes): How does this work when using scala?
object Main extends App {
val gw = new GatewayServer(// TODO: how to expose my classes here?
}

How to compile and run a java class with a package

I have a class called MyClass in the file MyClass.java file (code mentioned below)
package myclass;
class MyClass {
public int add (int a, int b){
return a+b;
}
public static void main(String args[]) {
MyClass obj = new MyClass();
System.out.println(oobj.add(2, 3));
}
}
I am compiling the class with
javac MyClass.java
But I am trying to run the class using
java MyClass
or
java myclass.MyClass
I am getting the Error
Error: Could not find or load main class MyClass
But, I am able to run this program if I omit out the package name.
where am I going wrong?
Make sure that you are inside the parent directory of the package folder (the folder in which your compiled class file is), and execute the following command:
java myclass.MyClass
Below is an example file structure:
bin
-> myclass
-> MyClass.class
In the example structure above, you would have to execute the command from the "bin" directory.
Also, define the class as public and recompile the java source file.
I ran into this too. It's very frustrating for someone from other languages. The key here is, the java file has to be in the right directory depending on the package declaration.
if the java file Test1.java starts with
package com.xyz.tests;
Then the java file Test1.java needs to be in directory com/xyz/tests
You can compile and run as
javac com/xyz/tests/Test1.java
java com/xyz/tests/Test1
Good luck.
You Need To Compile The Class using :
javac -d ./myclass
I get my example to run by
java <package>.<class>
From parent directory of package

How to keep a jar file external but still use its classes in my Android project?

I need to have a jar file located in a main/assets directory within an Android project. It is important the jar file is located there.
With my main Android project is there a way to reference this jar file in my code and to use its classes?
To be clear I don't want to add the jar to the main project once compiled.
EDIT: I have tried the link below and it seems to load the Class file I've stated. But I'm strugging how to define constructor arguments for the dynamically loaded Class.
android-custom-class-loading-sample
EDIT2
Nearly there. I've confirmed the class is loaded from my classes.jar. I'm stuck instantiating it though.
On the licenseValidatorClazz.getConstructor line I get the error below. I'm guessing I'm missing something from my Interface file?
java.lang.NoSuchMethodException: [interface com.google.android.vending.licensing.Policy, interface com.google.android.vending.licensing.DeviceLimiter, interface com.google.android.vending.licensing.LicenseCheckerCallback, int, class java.lang.String, class java.lang.String]
public Class licenseValidatorClazz = null;
public LicenseValidator validator;
...
// Initialize the class loader with the secondary dex file.
DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
optimizedDexOutputPath.getAbsolutePath(),
null,
mContext.getClassLoader());
try {
// Load the library class from the class loader.
licenseValidatorClazz = cl.loadClass("com.google.android.vending.licensing.LicenseValidator");
validator = (LicenseValidator) licenseValidatorClazz.getConstructor(Policy.class,DeviceLimiter.class,LicenseCheckerCallback.class,int.class,String.class,String.class).newInstance(ddd, new NullDeviceLimiter(),
callback, generateNonce(), mPackageName, mVersionCode);
} catch (Exception exception) {
// Handle exception gracefully here.
exception.printStackTrace();
}
I have an Interface which contains the functions to pass to the loaded class.
public interface LicenseValidator
{
public LicenseCheckerCallback getCallback();
public int getNonce();
public String getPackageName();
public void verify(PublicKey publicKey, int responseCode, String signedData, String signature);
public void handleResponse(int response, ResponseData rawData);
public void handleApplicationError(int code);
public void handleInvalidResponse();
}
TO use an external jar to be associated with your application and use it during runtime, it needs to be in dalvik format since normal jars cannot work under dalvikVM.
Convert your files using the dx tool
using aapt cmd , add those classes.dex to your jar file.
Now this jar which contains files in dalvik format can be loaded into our project.
Here is a post which explains the procedure to accomplish it.
There are steps to accomplish this.
You have to make a copy of your JAR file into the private internal storage of your aplication.
Using the dx tool inside the android folder, you have to generate a classes.dex file associated with the JAR file. The dx tool will be at the location /android-sdks/build-tools/19.0.1 (this file is needed by the Dalvik VM, simply jar can not be read by the dalvik VM))
Using the aapt tool command which is also inside the same location, you have to add the classes.dex to the JAR file.
This JAR file could be loaded dynamically using DexClassLoader.
If you are making a JAR from any one your own library, you have to do this steps (1-4) every time when there is a change in your library source code. So you can automate this steps by creating a shell script(in Mac/Linux/Ubuntu) or batch scripts(in Windows). You can refere this link to understand how to write shell scripts.
Note : One situation for implementing this method is, when it is impossible to add the JAR files directly to the build path of core project and need to be loaded dynamically at run time. In normal cases the JAR files could be added to the build path.
please check this link for the detailed code and implementation.
How to load a jar file at runtime
Android: How to dynamically load classes from a JAR file?
Hope this helps!!
You should try out the Services API - java.util.ServiceLoader
You define a service interface and its implementations in your jar.
package com.my.project;
public interface MyService { ... }
public class MyServiceBarImpl implements MyService { ... }
public class MyServiceFooImpl implements MyService { ... }
Then you define the services contained within the jar file in the META-INF/services/ directory. For instance, in the file 'META-INF/services/com.my.project.MyService', you list the provider classes.
# Known MyService providers.
com.my.project.MyServiceBarImpl # The original implementation for handling "bar"s.
com.my.project.MyServiceFooImpl # A later implementation for "foo"s.
Then, in your main codebase, you can instantiate a MyService instance with the ServiceLoader:
for (MyService service : ServiceLoader.load(MyService.class)) {
//Perform some test to determine which is the right MyServiceImpl
//and then do something with the MyService instance
}
These examples are taken more-or-less straight from the API, although I've changed the package names to make them slightly less annoying to read.

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.

How to access DLL methods in Java code using JNA?

By running System.loadLibrary("myAPI"), I verified that the DLL file "myAPI.dll" can be successfully loaded into my Eclipse Java project. Now I need to call methods specified inside this DLL file from my Java code. To do this, I added JNA to my Java project. Then I wrote the below-given code snippet that should be able to get instances of classes IProject and ProjectFactory (specified in the DLL file).
I still don't understand how to properly implement this with JNA. I checked different threads, e.g. this one, but the ones I checked don't provide an answer. Any help is highly appreciated. Thanks.
import com.sun.jna.Library;
import com.sun.jna.Native;
public class MyClass {
public interface myAPI extends Library {
//...
}
void LoadProj() {
myAPI api = (myAPI) Native.loadLibrary("myAPI",myAPI.class);
String fileName = "xxx.sp";
IProject project; // this is wrong but shows what I am trying to do
try {
project = ProjectFactory.LoadProject(fileName);
}
catch (Exception ex) {
MessageBox.Show(this, ex.Message, "Load failure");
}
}
}
Not sure what problem you are facing but as a practice your myAPI interface should declare all the methods verbatim with appropriate parameter mapping. I don't see any methods inside your interface.
Please checkout the this link as well as the link mentioned above by #Perception
If there are no Java classes or Java source hidden inside this DLL (which would be ... strange), then it will never work this way. You can't instantiate C# classes or use C# interfaces. MessageBox.Show( isn't Java either, it is Windows Forms code.

Categories

Resources