I'm trying to modify the jni4net sample code MyCSharpDemoCalc, and make the sample as a bridge between a .Net DLL and the Java layer. Here is the C# code:
using System;
using Dynamsoft.DotNet.TWAIN;
namespace MyCSharpDemoCalc
{
public interface ICalc
{
int MySuperSmartFunctionIDontHaveInJava(string question);
bool IsShowUI();
}
public class DemoCalc : ICalc
{
private readonly Random r = new Random();
private DynamicDotNetTwain dynamicDotNetTwain;
public DemoCalc()
{
dynamicDotNetTwain = new Dynamsoft.DotNet.TWAIN.DynamicDotNetTwain();
}
public int MySuperSmartFunctionIDontHaveInJava(string question)
{
if (question == "Answer to the Ultimate Question of Life, the Universe, and Everything")
{
return 42;
}
return r.Next();
}
public bool IsShowUI()
{
return dynamicDotNetTwain.IfShowUI;
}
}
}
In order to build it successfully, I added the following references:
System.Windows.Forms
DynamicDotNetTWAIN
Then typed in the command
proxygen.exe MyCSharpDemoCalc.dll -wd work
to generate MyCSharpDemoCalc.j4n.jarand MyCSharpDemoCalc.j4n.dll.
Now, I can import DynamicDotNetTWAIN.dll, MyCSharpDemoCalc.j4n.dll, jni4net.n.w64.v20-0.8.6.0.dll, jni4net.n-0.8.6.0.dll, jni4net.j-0.8.6.0.jar and MyCSharpDemoCalc.j4n.jar to Java project.
Java code:
import net.sf.jni4net.Bridge;
import java.io.IOException;
import mycsharpdemocalc.DemoCalc;
import mycsharpdemocalc.ICalc;
public class Program {
public static void main(String arsg[]) throws IOException {
Bridge.setClrVersion("v20");
Bridge.init();
Bridge.LoadAndRegisterAssemblyFrom(new java.io.File("DynamicDotNetTWAIN.dll"));
Bridge.LoadAndRegisterAssemblyFrom(new java.io.File("MyCSharpDemoCalc.j4n.dll")); // crashed
ICalc calc = new DemoCalc();
final int result = calc.MySuperSmartFunctionIDontHaveInJava("Answer to the Ultimate Question of Life, the Universe, and Everything");
System.out.printf("Answer to the Ultimate Question is : " + result);
System.out.printf("If show UI : " + calc.IsShowUI());
}
}
When I tried to run the application, it crashed at
Bridge.LoadAndRegisterAssemblyFrom(new
java.io.File("MyCSharpDemoCalc.j4n.dll"));
Exception in thread "main" System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
at System.Reflection.Module._GetTypesInternal(StackCrawlMark& stackMark)
at System.Reflection.Assembly.GetTypes()
at net.sf.jni4net.utils.Registry.RegisterAssembly(Assembly assembly, Boolean bindJVM, ClassLoader classLoader)
at net.sf.jni4net.Bridge.RegisterAssembly(Assembly assembly, ClassLoader classLoader)
at net.sf.jni4net.Bridge.LoadAndRegisterAssemblyFromClassLoader(File assemblyFile, ClassLoader classLoader)
at net.sf.jni4net.Bridge.LoadAndRegisterAssemblyFrom(File assemblyFile)
at net.sf.jni4net.__Bridge.LoadAndRegisterAssemblyFrom3(IntPtr __envp, JniLocalHandle __class, JniLocalHandle assemblyFile)
at net.sf.jni4net.Bridge.LoadAndRegisterAssemblyFrom(Native Method)
at com.main.Program.main(Program.java:68)
How can I fix it? Thanks!
The JNI4NET will attempt to load the image from where the JNI4NET libraries were located at, the only workaround (AFAIK) was to copy the whole libraries to your source directory, and compile your package using the copied libraries, then it will work.
Related
When the rtu.smallview.xhtml action event is triggered it requests info from the java bean, from the database select and hands it back to the xhtml.
The xhtml was not displaying the data from the database, so I added breakpoints in the java bean to figure out what was going wrong, but when the program loaded it never hit the breakpoint in the bean.
The server output is saying this when the program is loaded:
Info: WELD-000119: Not generating any bean definitions from Beans.RTU.RTU_SmallView_Bean because of underlying class loading error: Type pojo.rtu.RTU_unit not found. If this is unexpected, enable DEBUG logging to see the full error.
So I stopped the server, clean and built the project again, and when it runs for the first time it loads the bean, the information is retrieved and displayed. Though if I clean and build the project again, when it runs the second time it displays the same WELD-000119 error.
I copy and pasted just the code to make the RTU section run to a new project and the server doesn't ever throw this error, and it works every time the bean is requested and every time the server is started.
Edit 1:
When I restart NetBeans and Clean and Build the project after it starts it says this:
Note: C:\Users\Administrator\Documents\NetBeansProjects\OIUSA_1\src\java\Beans\RTU\RTU_SmallView_Bean.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
This is the only java class it says this about, so here is the code I used for that class:
package Beans.RTU;
import Database.RTU.RTU_SmallView_Select;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
import pojo.rtu.RTU_unit;
/**
*
* #author Administrator
*/
#Named(value = "rtu_SmallView_Bean")
#RequestScoped
public class RTU_SmallView_Bean {
public RTU_SmallView_Bean() {
try {
RTU_SmallView_Select selectData;
selectData = new RTU_SmallView_Select();
this.smallViewList = selectData.getData();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
List<RTU_unit> smallViewList = new ArrayList();
String unit_type;
int unit_number;
String rig_name;
String location_name;
public List<RTU_unit> getSmallViewList() {
return smallViewList;
}
public void setSmallViewList(List<RTU_unit> smallViewList) {
this.smallViewList = smallViewList;
}
public String getUnit_type() {
return unit_type;
}
public void setUnit_type(String unit_type) {
this.unit_type = unit_type;
}
public int getUnit_number() {
return unit_number;
}
public void setUnit_number(int unit_number) {
this.unit_number = unit_number;
}
public String getRig_name() {
return rig_name;
}
public void setRig_name(String rig_name) {
this.rig_name = rig_name;
}
public String getLocation_name() {
return location_name;
}
public void setLocation_name(String location_name) {
this.location_name = location_name;
}
}
My project structure is as follows:
Sources:
Beans.RTU.RTU_SmallView_Bean.java
Database.RTU.RTU_SmallView_Select.java
pojo.rtu.RTU_unit.java
Webpages:
rtu.rtu_smallview.xhtml
I am thinking it has something to do with the actual server, but I'm not sure where to start looking for this error. If you would like to see the actual code for the beans and what not, let me know and I'll edit the question with all the code. Thanks
Problem has been solved, the file RTU_Unit.java was in a folder called pojo.rtu. I deleted the folder, made it again with a new name pojo.rtus, refactored the file RTU_Unit.java for the new folder and the problem has gone away.
I'm trying to use a custom Configuration for saxon HE 10.3.
The Configuration is not being used. Presumably the config needs to be registered or installed? But how?
Here's my code:
final Configuration config = new net.sf.saxon.Configuration();
/**/ config.setLocalizerFactory(new LocalizerFactory() {
public Numberer getNumberer(final String language, final String country) {
if (language.equals("de")) {
return Numberer_de.getInstance();
} else {
return null;
}
}
});
net.sf.saxon.Transform.main(new String[] {
"-s:source.xml",
"-xsl:stylesheet.xslt",
"-o:result.txt"
});
You really don't want to be running net.sf.saxon.Transform.main from a Java application: use either the s9api or JAXP transformation APIs. The net.sf.saxon.Transform.main interface is designed for use from the command line, and it can therefore only modify the configuration through command line switches. It also has drawbacks like shutting down the Java VM if the transformation fails.
There is a workaround, which is to use the -init option on the command line to trigger user-supplied initialisation code (which has access to the Configuration object), but that's only really digging yourself deeper into your hole. I'd recommend switching to the s9api API.
Documentation: https://saxonica.com/documentation/index.html#!using-xsl/embedding
If you want to change the configuration when running Saxon from the command line, as Michael said, there is the -init option to pass in the name of a class implementing the Initializer interface https://saxonica.com/documentation/index.html#!javadoc/net.sf.saxon.lib/Initializer so you would use roughly e.g.
package com.example;
import net.sf.saxon.option.local.Numberer_de;
import net.sf.saxon.lib.Initializer;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.LocalizerFactory;
import net.sf.saxon.lib.Numberer;
import javax.xml.transform.TransformerException;
public class MyInitializer implements Initializer {
public override void initialize(Configuration config) throws TransformerException {
config.setLocalizerFactory(new LocalizerFactory() {
public Numberer getNumberer(final String language, final String country) {
if (language.equals("de")) {
return Numberer_de.getInstance();
} else {
return null;
}
}
});
}
}
compile that, put it on the classpath and then run e.g. java -cp saxon-he-10.3.jar;com/example/MyInitializer;net/sf/saxon/option/local/Numberer_de net.sf.saxon.Transform -init:com.example.MyInitializer -s:source.xml -xsl:stylesheet.xslt -o:result.txt.
Or you can subclass net.sf.saxon.Transform.
On the other hand, if you don't want to run Saxon from the command line but from the JAXP API then I think one approach is to create the Configuration e.g.
Configuration config = new Configuration();
config.setLocalizerFactory(new LocalizerFactory() {
public Numberer getNumberer(final String language, final String country) {
if (language.equals("de")) {
return Numberer_de.getInstance();
} else {
return null;
}
}
});
TransformerFactory transformerFactory = new TransformerFactoryImpl(config);
Templates templates = transformerFactory.newTemplates(xsltSource);
What was missing, was how to inject the Config. This worked for me:
import net.sf.saxon.Configuration;
import net.sf.saxon.TransformerFactoryImpl;
import net.sf.saxon.lib.Feature;
final TransformerFactoryImpl factory = (TransformerFactoryImpl) TransformerFactory.newInstance();
factory.getProcessor().setConfigurationProperty(Feature.CONFIGURATION, config);
I try to get some data from a dbus service and work with it in Java.
I can get the information in cli with the following command:
dbus-send --print-reply --system --dest=com.victronenergy.solarcharger.ttyUSB0 /Dc/0/Voltage com.victronenergy.BusItem.GetValue
The result is:
method return time=1538903662.321580 sender=:1.14 -> destination=:1.806 serial=335692 reply_serial=2
variant double 13.43
What I tried to get this data in Java, is:
After hours of reading, I created an Interface.
package javadbus;
import java.util.Map;
import org.freedesktop.dbus.DBusInterface;
import org.freedesktop.dbus.DBusSignal;
import org.freedesktop.dbus.Variant;
import org.freedesktop.dbus.exceptions.DBusException;
public interface BusItem extends DBusInterface
{
public static class PropertiesChanged extends DBusSignal
{
public final Map<String,Variant> changes;
public PropertiesChanged(String path, Map<String,Variant> changes) throws DBusException
{
super(path, changes);
this.changes = changes;
}
}
public String GetDescription(String language, int length);
public Variant GetValue();
public String GetText();
public int SetValue(Variant value);
public Variant GetMin();
public Variant GetMax();
public int SetDefault();
public Variant GetDefault();
}
Here I call getConnection() and getRemoteObject() successfully.
package javadbus;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.Variant;
public class VictronEnergyDBusSolarCharger {
private String port;
private DBusConnection conn;
public VictronEnergyDBusSolarCharger(String port) {
this.port = port;
try {
this.conn = DBusConnection.getConnection(DBusConnection.SYSTEM);
} catch (DBusException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String getData(String item) {
BusItem bi;
String data = null;
Variant vData = null;
try {
bi = (BusItem)conn.getRemoteObject("com.victronenergy.solarcharger." + this.port, item, BusItem.class);
vData = bi.GetValue();
//data = bi.GetText();
} catch (DBusException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return data;
}
...
}
It was a big task to resolve all dependecies and get the code compiled. But finaly I did it. So, javac now runs without errors.
But if I try to call the Method GetValue(), I get the following Exception:
[Sender] INFO org.freedesktop.dbus.MessageWriter - <= MethodCall(0,1) { Path=>/org/freedesktop/DBus, Interface=>org.freedesktop.DBus, Member=>Hello, Destination=>org.freedesktop.DBus } { }
[Sender] INFO org.freedesktop.dbus.MessageWriter - <= MethodCall(0,3) { Path=>/Dc/0/Voltage, Interface=>javadbus.BusItem, Member=>GetValue, Destination=>com.victronenergy.solarcharger.ttyUSB0 } { }
Exception in thread "main" org.freedesktop.DBus$Error$UnknownMethod: Method "GetValue" with signature "" on interface "javadbus.BusItem" doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.freedesktop.dbus.Error.getException(Error.java:141)
at org.freedesktop.dbus.Error.throwException(Error.java:171)
at org.freedesktop.dbus.RemoteInvocationHandler.executeRemoteMethod(RemoteInvocationHandler.java:158)
at org.freedesktop.dbus.RemoteInvocationHandler.invoke(RemoteInvocationHandler.java:222)
at com.sun.proxy.$Proxy1.GetValue(Unknown Source)
at javadbus.VictronEnergyDBusSolarCharger.getData(VictronEnergyDBusSolarCharger.java:28)
at javadbus.VictronEnergyDBusSolarCharger.getDcV(VictronEnergyDBusSolarCharger.java:38)
at javadbus.MainClass.main(MainClass.java:7)
Is it necessary to make a implementation of this Method GetValue? But why e.g. how should I do this? I only want to get this Information and not provide it like a Server.
Why was it a big task to get all dependencies?
dbus-java library and dependencies are all available at maven central, so a proper maven project should just work out-of-the-box.
Back to topic:
You don't have to implement GetValue(), but you need a suitable java interface for BusItem.
As far as I can see in the documentation of victronenergy (https://www.victronenergy.com/live/open_source:ccgx:d-bus) , your interface is not correct.
You provide SetDefault()/GetDefault() methods, which are only available on com.victronenergy.settings Objects, but you want to retrieve a com.victronenergy.BusItem (no part of the com.victronenergy.settings package).
This is one error. The second error is: you use the wrong package name for your BusItem class.
In your case DBus will try to resolve an object with the path javadbus.BusItem which is not provided by the connected BusAddress com.victronenergy.solarcharger.ttyUSB0.
The BusItem class has to be in package com.victronenergy or you have to use the annotation #DBusInterfaceName("com.victronenergy.BusItem").
The annotation will tell the DBus library to ignore the java package/class name and use the one provided in the annotation.
The Inteface BusItem had been created by CreateInterface-Script from https://dbus.freedesktop.org/doc/dbus-java/dbus-java/dbus-javase10.html and the XML from Introspect()
But you solved my real problem. I used the annotation #DBusInterfaceName("com.victronenergy.BusItem") now. No Exception anymore an i get data from my solarcharger. Thank you so much!
I'm building a video game and I've built a launcher for my video game as well. The launcher downloads .jar files and stores them in the %appdata% folder for each person who buys the game and downloads the launcher and then runs it.
I need to be able to write a few lines of code to tell the launcher to get the .jar file from the user's computer and run a file from there. The .jar is already compiled and everything is okay and whatnot, but I'm not quite sure how to get the .class file to work with.
Something like this might help:
import System.getPropery("user.home") + "/AppData/Roaming/GameNameHere/bin/game.jar" + ".runGame.class"
And then I could possible do something like this:
if (credentials == true) {
runGame game = new runGame();
game.start();
}
How would I do something like this? Thanks in advance.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So, I looked the ClassLoader.java class and messed around with it for a bit, but nothing really worked well. What am I doing wrong?
private String location = System.getProperty("user.home") + "\\Desktop\\myJar.jar";
URL url = new URL(location);
public Load() throws Exception {
ClassLoader loader = URLClassLoader.newInstance(new URL[]{url}, getClass().getClassLoader());
Class<?> clazz = Class.forName("gumptastic.MyClass", true, loader);
Method method = clazz.getMethod("output");
method.invoke(this);
}
public static void main(String[] args) {
try {
new Load();
} catch (Exception exc) {
exc.printStackTrace();
}
}
Not sure if you're familiar with this but
I think you should look at class loaders.
http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html
I guess you would need to write a simple one for your particular needs.
Alternatively, it would be even easier if you just use URLClassLoader.
Below is a simple example. This program has no idea of the Gson class
at compile time. But it can successfully load it, create an instance of it,
and use it at runtime. It was tested on Windows 7.
You can download Google Gson from here.
http://code.google.com/p/google-gson/downloads/list
Then place the gson-2.2.4.jar file anywhere you like
on your computer, then point this program to it by
setting arr[0] in the proper way.
Then observe the magic that is taking place :)
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
public class Test007 {
public static void main(String[] args) throws Exception {
URL[] arr = new URL[1];
arr[0] = new URL("file:///dir1/dir2/dir3/gson-2.2.4.jar");
URLClassLoader loader = new URLClassLoader(arr);
Class cls = loader.loadClass("com.google.gson.Gson");
System.out.println(cls);
Constructor constructor = cls.getConstructor(new Class[0]);
Object obj = constructor.newInstance(new Object[0]);
System.out.println(obj);
if (obj!=null){
System.out.println("OK, so now we have an instance of:");
System.out.println(obj.getClass().getName());
}
}
}
This question already has answers here:
Java, Classpath, Classloading => Multiple Versions of the same jar/project
(5 answers)
Closed 8 years ago.
I have three Jar files.All jar files contain Same class TestServicesImpl And Same Method displayWeLcomeMessage() But having different messages(output) of displayWeLcomeMessage().
Example :
public void displayWeLcomeMessage() {
System.out.println("wecome msg of JAR version first");
}
public void displayWeLcomeMessage() {
System.out.println("wecome msg of JAR version two");
}
public void displayWeLcomeMessage() {
System.out.println("wecome msg of JAR version third");
}
I have One main application and it contains jars included. My main application calls displayWeLcomeMessage() method.
first JAR is added in classpath and second JAR is loaded with custom classloader and invoke method displayWeLcomeMessage().
File file = new File("C:/Users/amitk/Desktop/Test_1.0.2.jar");
#SuppressWarnings("deprecation")
URL url = file.toURL();
URL[] urls = new URL[]{url};
URLClassLoader loader = new URLClassLoader(urls);
Class classS = loader.loadClass("com.amit.servicesImpl.TestServicesImpl");
Object object = classS.newInstance();
Method getmsg = classS.getMethod("displayWeLcomeMessage");
getmsg.invoke(object);
but it displays the same message as in method of JAR first.
In my third JAR, i have changed the package name.
that is
com.amit.servicesImpl.TestServicesImpl is changed to com.amit.servicesImpl2.TestServicesImpl
and this time it works properly that is message of method of JAR 3 is displayed here.
so let me know the main issue behind this.and solution for this.
Maybe you have your JAR in your initial class loader.
URLClassLoader will check existing class in parent class loader before checking in its own space.
1) You can extend and modify this behavior:
package com.mytool;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
import java.util.HashMap;
import java.util.Map;
public class MyURLClassLoader extends URLClassLoader {
private final Map<String, Class<?>> ourClasses = new HashMap<>();
public MyURLClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public MyURLClassLoader(URL[] urls) {
super(urls);
}
public MyURLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
super(urls, parent, factory);
}
#Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = ourClasses.get(name);
if (c == null) {
// search in our paths
try {
c = findClass(name);
ourClasses.put(name, c);
} catch (ClassNotFoundException e) {
// ignore
}
}
if (c == null) {
c = findLoadedClass(name);
}
if (c != null) {
if (resolve) {
resolveClass(c);
}
return c;
}
// default search
return super.loadClass(name, resolve);
}
}
}
2) Or you can try to move our JAR and not load it at JVM start.
Note:
Instead of using a full reflexivity, I'll use an interface
loaded only by the initial classloader. Your object could implements it, and you'll be able to cast to this interface. If you do this with MyURLClassLoader, please don't add this interface in our dynamic loaded JAR!
Classloader will pick that class which was found first. If you are having 10 packages having same class then only that class will be picked which was introduced first.