JPype class not found, $1 with no inner class - java

I have these java files:
LDF1File.java
LDFFile.java <-- super class
which generate these class files:
LDF1File.class -- there is no inner class
LDF1File$1.class <-- no idea where this comes from
LDFFile.class
In my python code, I can import LDF1File$1, but not LDF1File. I get:
>>> JClass('aero.blue.bdms.ldf.stream.LDF1File')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/eric/Software/anaconda3/envs/blue3/lib/python3.5/site-packages/JPype1-0.6.1-py3.5-linux-x86_64.egg/jpype/_jclass.py", line 55, in JClass
raise _RUNTIMEEXCEPTION.PYEXC("Class %s not found" % name)
jpype._jexception.RuntimeExceptionPyRaisable: java.lang.RuntimeException: Class aero.blue.bdms.ldf.stream.LDF1File not found
Here's the full code:
from jpype import *
startJVM(getDefaultJVMPath(), "-ea", '-Xms1024m', '-Xmx4096m', '-Djava.class.path=./jars/bdms-chunkjava-lib-1.0.9-SNAPSHOT.jar:./jars/bdms-ldfjava-lib-1.0.9-SNAPSHOT.jar')
LDF1File = JClass('aero.blue.bdms.ldf.stream.LDF1File')
shutdownJVM()
So i'm not sure why there is a class file with a dollar sign in it's name, and I'm not sure why JPype can't locate LDF1File. Just to rule some possible suggestions out, there is no dependency injection, no aspectj stuff, no spring, no guava. This is just plain java.

I had only included in my classpath the jar of the package i was working with and none of the dependencies. Having added all dependency jars to the classpath, it was able to load LDF1File.java

Related

Standard Method TEXT is undefined when compiling jasper report

When I package my stand-alone-java-application, that compiles, renders and prints Jasper-Reports, in a fat jar with all dependencies, I get the error that the function TEXT – a function used in the report and defined in the net.sf.jasperreports-functions-library is not found.
The method TEXT(Integer, String) is undefined for the type [...]
value = IF(LEN(TEXT(((java.lang.Integer)parameter_X.getValue()),"#"))==2,"***",REPT("*",6-LEN(TEXT(((java.lang.Integer)parameter_X.getValue()),"#")))) //$JR_EXPR_ID=58$
Other functions from the same library work. When I run the application with gradle run, the function is found and the report can be printed. The library is on my classpath.
There are several similar questions on this site and Stackoverflow, but neither provided answers, that worked for me. In the following, I will explain what I tried:
In my build.gradle-File I defined dependencies to the following libraries:
implementation('net.sf.jasperreports:jasperreports:6.18.1')
implementation('net.sf.jasperreports:jasperreports-functions:6.18.1')
In my java-Files, I created a DesignFile and statically imported the functions into it. I tried two methods:
Method 1 as given in an answer in this thread: Unresolved symbols when compiling jasper report
/*…*/
designFile = JRXmlLoader.load(sourceFile.getAbsolutePath());
designFile.addImport("static net.sf.jasperreports.functions.standard.TextFunctions.*");
designFile.addImport("static net.sf.jasperreports.functions.standard.MathFunctions.*");
designFile.addImport("static net.sf.jasperreports.functions.standard.DateTimeFunctions.*");
designFile.addImport("static net.sf.jasperreports.functions.standard.LogicalFunctions.*");
JasperReport compiledReport = JasperCompileManager.getInstance(ctx).compile(designFile);
/*…*/
Method 2: importing each function on its own
public static String[] textFunctions(){
return new String[]{"BASE", "CHAR", "CLEAN", "CODE", "CONCATENATE", "DOUBLE_VALUE",
"EXACT", "FIND", /*"FIXED", */"FLOAT_VALUE", "INTEGER_VALUE", "LEFT", "LEN", "LONG_VALUE",
"LOWER", "LTRIM", "MID", "PROPER", "REPLACE", "REPT", "RIGHT", "RTRIM", "SEARCH", "SUBSTITUTE",
"T", /*"TEXT",*/ "TRIM", "UPPER"};
}}
/*…*/
designFile = JRXmlLoader.load(sourceFile.getAbsolutePath());
for (String textFunction : textFunctions()){
designFile.addImport("static net.sf.jasperreports.functions.standard.TextFunctions." + textFunction);
}/* similarly for logical functions, numeric functions and datetime functions*/
}
JasperReport compiledReport = JasperCompileManager.getInstance(ctx).compile(designFile);
/*…*/
As you can see, the function TEXT is commented out. That’s because the program fails at runtime when run with “gradle run”, when I comment it in:
net.sf.jasperreports.engine.JRException: Errors were encountered when compiling report expressions class file:
1. The import net.sf.jasperreports.functions.standard.TextFunctions.TEXT cannot be resolved
import static net.sf.jasperreports.functions.standard.TextFunctions.TEXT;
The same thing is true with most datetime-functions, in fact, only TIME can be imported to the DesignObject without error at runtime
In addition to that, when I type net.sf.jasperreports.functions.standard.TextFunctions. in my IDE, the content-assist shows a list of available functions, yet TEXT is missing.
I suspected, that the function is simply missing in the library, but it is there. In the .gradle/cache/modules-2/files-2.1/… directory, there is the jar with the TextFunctions.java, that contains the function TEXT:
When building the FatJar with dependencies, I have a TextFunctions.class-File in it, that contains the TEXT-Function as well.
In my jar, there are two jasperreports_extension.properties on the root level:
with the smaller one (from the jasperreport-functions-dependency) containing the following lines:
net.sf.jasperreports.extension.registry.factory.functions=net.sf.jasperreports.functions.FunctionsRegistryFactory
net.sf.jasperreports.extension.functions.datetime=net.sf.jasperreports.functions.standard.DateTimeFunctions
net.sf.jasperreports.extension.functions.math=net.sf.jasperreports.functions.standard.MathFunctions, net.sf.jasperreports.functions.standard.LogicalFunctions
net.sf.jasperreports.extension.functions.text=net.sf.jasperreports.functions.standard.TextFunctions
net.sf.jasperreports.extension.functions.report=net.sf.jasperreports.functions.standard.ReportFunctions
Funnily enough, commenting out TEXT, running it locally with gradle run, it works without problems. But packaging it and running it with java -jar it fails to find this function. And statically importing this function leads to gradle run failing as well.
What is happening and how can I fix this? I want to distribute my FatJar on a server and run it, but this problems makes it impossible for me.

Calling custom java class from python using JPype

Getting class not found exception while trying to call java class from python using jpype. Below are version and path details:
JPype version:JPype1-py3
Python: 3.6
Java: 1.8.0_171
Java file path: /home/neha/Downloads/fontAttributes/PDFFontExtractor.java
Python file path: /home/neha/Downloads/call_java.py
Below is Python code: call_java.py
import jpype
from jpype import *
cpath="-Djava.class.path=%s" % ("/home/neha/Downloads")
startJVM(getDefaultJVMPath(), "-ea",cpath)
Test = JClass('fontAttributes.PDFFontExtractor')
Test.getFontAttributes()
java.lang.System.out.println(str)
shutdownJVM()
Output:
/usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so
Traceback (most recent call last):
File "call_java.py", line 14, in <module>
Test = JClass('fontAttributes.PDFFontExtractor')
File "/usr/local/lib/python3.6/dist-packages/jpype/_jclass.py", line 55, in JClass
raise _RUNTIMEEXCEPTION.PYEXC("Class %s not found" % name)
jpype._jexception.ExceptionPyRaisable: java.lang.Exception: Class fontAttributes.PDFFontExtractor not found

Gen-Class does not generate a .class file

I'd like to use Clojure code within Java. The Clojure code itself should implement a Java-interface (TestGenClassInterface).
My project.clj is:
(defproject com.stackoverflow.clojure/tests "0.1.0-SNAPSHOT"
:description "Tests of Clojure test-framework."
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"]
[instaparse "1.3.4"]]
:source-paths ["src/main/clojure"]
:java-source-paths ["src/main/java"]
:test-paths ["src/test/clojure"]
:java-test-paths ["src/test/java"]
;:aot :all
)
The Java interface looks like this:
package com.stackoverflow.clojure;
public interface TestGenClassInterface {
public String addToString(String text, String appendText);
}
The Clojure code is:
(ns com.stackoverflow.clojure.testGenClass
(:gen-class
:name com.stackoverflow.clojure.TestGenClass
:implements com.stackoverflow.clojure.TestGenClassInterface
:prefix "java-"))
(def ^:private pre "START: ")
(defn java-addToString [this text post]
(str pre text post))
(java-addToString "TexT" " :END")
I expected, that after running lein compile or "Run as Clojure-Application" in eclipse+CounterClockwise a .class file (named TestGenClass.class) is generated an saved within *compile-path* (here: target/classes/com/stackoverflow/clojure/). Unfortunately it's not.
When adding :aot :all to my project.clj, I get the following stacktrace:
Compiling com.stackoverflow.clojure.testGenClass
Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(com/stackoverflow/clojure/testGenClass.clj:1:1)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6651)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782)
at clojure.lang.Compiler$TryExpr$Parser.parse(Compiler.java:2191)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5217)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3846)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6642)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6632)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3665)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler.compile1(Compiler.java:7221)
at clojure.lang.Compiler.compile1(Compiler.java:7216)
at clojure.lang.Compiler.compile(Compiler.java:7292)
at clojure.lang.RT.compile(RT.java:398)
at clojure.lang.RT.load(RT.java:438)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5066.invoke(core.clj:5641)
at clojure.core$load.doInvoke(core.clj:5640)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5446)
at clojure.core$compile$fn__5071.invoke(core.clj:5652)
at clojure.core$compile.invoke(core.clj:5651)
at user$eval9.invoke(form-init4595004281107083893.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6703)
at clojure.lang.Compiler.eval(Compiler.java:6693)
at clojure.lang.Compiler.load(Compiler.java:7130)
at clojure.lang.Compiler.loadFile(Compiler.java:7086)
at clojure.main$load_script.invoke(main.clj:274)
at clojure.main$init_opt.invoke(main.clj:279)
at clojure.main$initialize.invoke(main.clj:307)
at clojure.main$null_opt.invoke(main.clj:342)
at clojure.main$main.doInvoke(main.clj:420)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
at clojure.lang.RT.seqFrom(RT.java:505)
at clojure.lang.RT.seq(RT.java:486)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$map$fn__4245.invoke(core.clj:2551)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$map$fn__4245.invoke(core.clj:2551)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.boundedLength(RT.java:1654)
at clojure.lang.RestFn.applyTo(RestFn.java:130)
at clojure.core$apply.invoke(core.clj:624)
at clojure.core$mapcat.doInvoke(core.clj:2586)
at clojure.lang.RestFn.invoke(RestFn.java:423)
at clojure.core$generate_class.invoke(genclass.clj:164)
at clojure.core$gen_class.doInvoke(genclass.clj:638)
at clojure.lang.RestFn.invoke(RestFn.java:1557)
at clojure.lang.Var.invoke(Var.java:519)
at clojure.lang.AFn.applyToHelper(AFn.java:270)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.lang.Compiler.macroexpand1(Compiler.java:6552)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6630)
... 46 more
Compilation failed: Subprocess failed
The proximate issue you have is a missing :aot :all in your project.clj file. Without that the ahead-of-time compilation will not be attempted.
Once you put that in, you'll have the following further issues:
you must prefix the names of the functions designated to become Java methods (default prefix is -);
you must include this as an explicit first argument of each such method (this is the recommended convention, but any name is acceptable);
you must correct your :implements clause: it takes a vector as the value, even if it has a single member.
According to http://clojure.org/compilation
... the implementation functions for instance methods will always take an
additional first arg corresponding to the object the method is called
upon, called by convention 'this' here.
Try adding 'this' to each function definition.
(defn java-addToString [this text post]
...
http://clojure.org/compilation mentions the compilation process makes use of
... *compile-path*, which must be in the classpath
The default location is a classes folder.
The second answer to Stack Overflow question Compiling Clojure? mentions that this path is relative to the jvm startup folder. If you did lein repl from the main project folder (the folder where project.clj lives) then creating a classes folder there should make it work.

Using a functional java construct (Predicate) from jython

So, I'm attempting to use the selenium java libraries from jython (yes, I know selenium has a python interface, but for good reasons of corporate teamwork accessing the pure java libraries makes more sense if it can be done well).
I'm just trying to do the example script here: http://seleniumhq.org/docs/03_webdriver.html#introducing-the-selenium-webdriver-api-by-example
Which I've implemented with the following jython code:
from org.openqa.selenium.firefox import FirefoxDriver
from org.openqa.selenium import By
from org.openqa.selenium import WebDriver
from org.openqa.selenium import WebElement
from org.openqa.selenium.support.ui import ExpectedCondition
from org.openqa.selenium.support.ui import WebDriverWait
driver = FirefoxDriver()
driver.get('http://www.google.com')
element = driver.findElement(By.name('q'))
# The array wrapper around the string is the only weird thing I encountered
element.sendKeys(["Cheese!"])
print "Page title is: " + driver.getTitle()
class ExpectedConditionTitle(ExpectedCondition):
def apply(d):
print(type(d))
return d.title.toLowerCase().startsWith(["cheese!"])
def equals(d):
pass
print(type(driver))
WebDriverWait(driver, 10).until(ExpectedConditionTitle().apply())
print driver.getTitle()
driver.quit()
And it's puking on the ExpectedCondition bit. I can't figure out how to make a subclass for the variety desired by until. I've gotten the following errors with variations in my code:
last
Traceback (innermost last):
File "Example.py", line 24, in ?
File "Example.py", line 19, in apply
AttributeError: 'instance' object has no attribute 'title'
and
Traceback (innermost last):
File "Example.py", line 24, in ?
File "Example.py", line 19, in apply
AttributeError: getTitle
and
Traceback (innermost last):
File "Example.py", line 22, in ?
TypeError: until(): 1st arg can't be coerced to com.google.common.base.Function or com.google.common.base.Predicate
The selenium ExpectedCondition interface is basically just a front for the Guava Predicate interface.
I'm not well versed enough in python or java to figure this out. Anyone have any ideas how I might accomplish this?

Jython missing functions in sys module

I have an python script which I need to run in my java application. I tried to execute it from jython but I have strange problem:
from sys import getdlopenflags
I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name getdlopenflags
When I try to check contents of sys:
import sys
dir(sys)
the output is:
['JYTHON_DEV_JAR', 'JYTHON_JAR', 'PYTHON_CACHEDIR', 'PYTHON_CACHEDIR_SKIP', 'PYTHON_CONSOLE_ENCODING', '__delattr__', '__dict__', '__displayhook__', '__excepthook__', '__findattr_ex__', '__name__', '__new__', '__rawdir__', '__setattr__', '__stderr__', '__stdin__', '__stdout__', '_getframe', '_jy_interpreter', '_systemRestart', 'add_classdir', 'add_extdir', 'add_package', 'argv', 'builtin_module_names', 'builtins', 'byteorder', 'classDictInit', 'classLoader', 'cleanup', 'copyright', 'currentWorkingDir', 'defaultencoding', 'determinePlatform', 'displayhook', 'doInitialize', 'exc_clear', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'filesystemencoding', 'getBaseProperties', 'getBuiltin', 'getBuiltins', 'getClassLoader', 'getCurrentWorkingDir', 'getDefaultBuiltins', 'getPath', 'getPathLazy', 'getPlatform', 'getWarnoptions', 'getdefaultencoding', 'getfilesystemencoding', 'getrecursionlimit', 'hexversion', 'initialize', 'isPackageCacheEnabled', 'last_traceback', 'last_type', 'last_value', 'maxint', 'maxunicode', 'meta_path', 'minint', 'modules', 'packageManager', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'recursionlimit', 'registerCloser', 'registry', 'setBuiltins', 'setClassLoader', 'setCurrentWorkingDir', 'setPlatform', 'setWarnoptions', 'setprofile', 'setrecursionlimit', 'settrace', 'shadow', 'stderr', 'stdin', 'stdout', 'subversion', 'toString', 'unregisterCloser', 'version', 'version_info', 'warnoptions']
obviously getdlopenflags is missing. Is it possible to use this function in jython (I have the newest - 2.5.2) According to the documentation on the http://jython.org/docs/library/sys.html the sys.getdlopenflags is present.
Thanks for help
It says "Availability: Unix" in the documentation. The Jython docs seem to have copied that unchanged from the CPython docs. So this function is only available on a Unix installation. Possibly Jython doesn't have it at all - I don't know Java well enough, but since it's supposedly platform-independent, it can't support system-specific functions.

Categories

Resources