JRuby: Java NullPointerException if imagefile not found --- solution

Asked by Paul Grizzaffi

*** solution

have sikuli-script.jar in the class-path, before JRuby interpreter starts to run the script!

--- running JRuby from commandline:
set environment variable JRUBY_PARENT_CLASSPATH to a list of needed jars separated by colon, that contains at least path-to-sikuli-script.jar

--- NetBeans:
in the project properties -> Java add path-to-sikuli-script.jar

--------------------------------------------

Hi again,
I'm calling Java interfact of Sikuli rc2 from JRuby; I'm having great success with it. I do have one issue/question, though.

When calling the Region::exist method, if I pass it a string for a non-existent filename, the method generates a Java NullPointerException. I seem to be unable to catch this exception in JRuby and execution continues after the exception is raised.

I wasn't able to determine which version of the source code matches the rc2 release so can you please tell me, is this exception caught by Sikuli and then displayed to stderr or stdout? If so, is this something that will be addressed in the rc3 release?

Thanks!
Paul

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

The internal workflow with a string as first parameter to any find operation currently is:
--1- check, wether it is an existing image file
--2- if yes: normal visual find operation
--3- if not a valid image file, try to find the given text (switch to text search via tesseract)

And this seems to be the problem here (only the significant messages):

[info] Mac OS X utilities loaded.
[info] Sikuli vision engine loaded.
[debug] File not found: some text, assume it's text.
[info] Text Recognizer inited.
java.lang.NullPointerException
 at java.io.Reader.<init>(Reader.java:61)
 at java.io.InputStreamReader.<init>(InputStreamReader.java:55)
 at org.sikuli.script.ResourceExtractor.writeFileList(ResourceExtractor.java:28)
 at org.sikuli.script.ResourceExtractor.extract(ResourceExtractor.java:22)
 at org.sikuli.script.TextRecognizer.init(TextRecognizer.java:41)
....... some more tracebacks
Unable to load unicharset file tessdatatessdata/eng.unicharset

So it seems, that the text recognizer init makes the problem in a JRuby environment (finding text does not work at all).
This is some kind of bug. I will have a look at it and come back.

*** If you try the same in the Sikuli IDE (which uses Jython), you get the defined behavior:
--- exists("not-exisiting.png")
will simply return None (as it should)

--- find("not-exisiting.png")
will produce a FindFailed exception, which can be catched

Revision history for this message
RaiMan (raimund-hocke) said :
#2

I tried it on the Java level directly (Java app using Sikuli Java API):

It works as expected.

So this is specific to the JRuby environment.

Revision history for this message
Paul Grizzaffi (paul-grizzaffi) said :
#3

Ah, I see. I had not tried it in Java directly (sorry). Thanks again for your very rapid response!

Also interesting is that I was not getting the "Unable to load unicharset file tessdatatessdata/eng.unicharset". I was reworking my example to post it here and now I get that message as well as the stacktrace.

Could you please post or send me your Java example? Perhaps I'm not initializing something correctly and that's therefore causing my JRuby problem.

Also, FWIW, my example is below.

Thanks again!
Paul

require "java"
require "#{ENV["SIKULI_HOME"]}/sikuli-script.jar"

import org.sikuli.script.Region

r = org.sikuli.script.Region.new(0,0, 1000, 1000)

begin
  r.doFind("does_not_exist.png")
rescue java.lang.NullPointerException => e
  puts "exception caught"
end

Revision history for this message
RaiMan (raimund-hocke) said :
#4

--- nothing special with the Java example

import org.sikuli.script.*;
public class test {
 public static void main(String[] args) throws FindFailed{
  Screen s = new Screen();
  s.click("images/img.png", 0); # this image does not exist
  s.getLastMatch().highlight(2);
 }
}

--- the JRuby approach

I have a separate JRuby module to define some constants and global variables and to add/alias/overwrite some features of JRuby and Sikuli.

e.g.

Sikuli = Java::org.sikuli.script
so I can say later on Sikuli::Region.new

I use symbols to name may images and have added to_img to Object::Symbol to return a valid filename for just :img1.to_img (gets "prefix_img1.png")

some more things in Region (wait for multiple images, type for my german keyboard and using symbols for the keys, ...) and App class.

And I stick to the official public top level API (so I use find and not doFind).

So I think, nothing else can be done, to avoid this error.

I will check it now a little bit deeper (though I am also busy with OS X Lion ;-)

Revision history for this message
Paul Grizzaffi (paul-grizzaffi) said :
#5

Thanks for the info. I've been playing with it in both Java and JRuby. It's kind of weird.

If I make my own class in Java and call it from JRuby (not using Sikuli at all), I get a NullPointerException that I can catch. I don't seem to be able to catch the one from the Region::exists method for some reason.

I'll just work around it for now. Thanks again for all of your time. I'll be sure to post again if I find out anything new.

Paul

Revision history for this message
RaiMan (raimund-hocke) said :
#6

I just found a simple workaround:

instead of saying
find("some-image.png")

say
find(Pattern.new("some-image.png"))

this will not switch to text search, in case image not found, since a Pattern always is image only.

I will put this in my :some-image.to_img hack.

I love Ruby and JRuby :-)

Revision history for this message
RaiMan (raimund-hocke) said :
#7

I found the source of the problem: It is so simple - LOL

*** have sikuli-script.jar in the class-path, before JRuby interpreter starts to run the script!

I do not know, how you run your JRuby scripts (I am using Netbeans 6.9 on my Mac Lion), but if sikuli-script.jar is in java classpath BEFORE JRuby interpreter starts up, the problem does not occur.

Trying to add sikuli-script.jar to the class-path (setSystemProperty("java.class.path", "...")) after the script has started does have any effect.

Running JRuby directly from commandline: I have not found until now, how to specify classpath in this case.

Revision history for this message
Best RaiMan (raimund-hocke) said :
#8

added my findings to the top of the question

Revision history for this message
RaiMan (raimund-hocke) said :
#9

works

Revision history for this message
Paul Grizzaffi (paul-grizzaffi) said :
#10

Fantastic! Thanks for all the help and effort. This works great.

I'm a bit ashamed that I didn't try the Pattern thing myself, but I didn't know anything about JRUBY_PARENT_CLASSPATH. Thanks for the heads up on that as well.

Please keep up the good work!

Paul

Revision history for this message
Paul Grizzaffi (paul-grizzaffi) said :
#11

Thanks RaiMan, that solved my question.