Back to LanguageTool Homepage - Privacy - Imprint

Detect ready status of JLanguageTool


(Mauro) #1

Hi,
I do initialize JLanguageTool with the following code:
==============================================
private JLanguageTool lt;
private String[] disabledRules = new String[0];
private String[] enabledRules = new String[0];

public JLanguageToolEngine() {
	this(Language.ITALIAN, Language.ITALIAN);
}
@SuppressWarnings("deprecation")
public JLanguageToolEngine(Language language, Language motherTongue) {
	language.getSentenceTokenizer().setSingleLineBreaksMarksParagraph(true);
	motherTongue.getSentenceTokenizer().setSingleLineBreaksMarksParagraph(true);
    try {
		lt = new JLanguageTool(language , motherTongue );
	    lt.activateDefaultPatternRules();
	    lt.activateDefaultFalseFriendRules();
	} catch (IOException e) {
		e.printStackTrace();
	} catch (ParserConfigurationException e) {
		e.printStackTrace();
	} catch (SAXException e) {
		e.printStackTrace();
	}
    Tools.selectRules(lt, disabledRules, enabledRules);
    lt.setListUnknownWords(true);
}
public void dispose() {
	JLanguageTool.removeTemporaryFiles();	  
}

==============================================
Problem is: if I call
==============================================
final List ruleMatches = lt.check(contents);
==============================================
"too early" (i.e.: almost immediately after construction) I get an Exception:
==============================================
Exception in thread "org.eclipse.jface.text.reconciler.MonoReconciler" java.nio.InvalidMarkException
at java.nio.Buffer.reset(Unknown Source)
at morfologik.speller.Speller.charsToBytes(Speller.java:178)
at morfologik.speller.Speller.CharSequenceToBytes(Speller.java:192)
at morfologik.speller.Speller.isInDictionary(Speller.java:203)
at org.languagetool.rules.spelling.morfologik.MorfologikSpellerRule.getRuleMatch(MorfologikSpellerRule.java:125)
at org.languagetool.rules.spelling.morfologik.MorfologikSpellerRule.match(MorfologikSpellerRule.java:98)
at org.languagetool.JLanguageTool.checkAnalyzedSentence(JLanguageTool.java:639)
at org.languagetool.JLanguageTool.check(JLanguageTool.java:564)
at org.languagetool.JLanguageTool.check(JLanguageTool.java:514)
at it.condarelli.texteditor.spelling.JLanguageToolEngine.check(JLanguageToolEngine.java:61)
at it.condarelli.texteditor.spelling.JLanguageToolReconcileStrategy.checkSpelling(JLanguageToolReconcileStrategy.java:17)
at it.condarelli.texteditor.spelling.SpellingReconcileStrategy.reconcile(SpellingReconcileStrategy.java:147)
at it.condarelli.texteditor.spelling.SpellingReconcileStrategy.initialReconcile(SpellingReconcileStrategy.java:130)
at org.eclipse.jface.text.reconciler.MonoReconciler.initialProcess(MonoReconciler.java:105)
at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:173)
==============================================
inserting a delay in the form (50ms seem to be about the minimum on my machine):
==============================================
Thread.sleep(50);
==============================================
Everything works fine.
What am I missing?
Is there some way to check when JLanguageTool is ready to accept check() commands?

Regards
Mauro


(Daniel Naber) #2

Am Mi 29.08.2012, 04:36:53 schrieben Sie:

I do initialize JLanguageTool with the following code:

Are you calling the check method from another thread? Are you sure you're
calling it only when the constructor of JLanguageToolEngine is finished?

LanguageTool should be ready as soon as new JLanguageTool(language ,
motherTongue); is done. You shouldn't call the check method while you
change the configuration with another thread.

Regards
Daniel

--
http://www.danielnaber.de


(Mauro) #3

Are you sure you're calling it only when the constructor of JLanguageToolEngine is finished?

Sorry I fail to understand Your question.
Before constructor return I don't even have a handle for the instance, how can I call a (non static) method?

You are right: I am calling check() from another thread (I should rather say: "Eclipse ReconcileStrategy calls it from another thread), but this happens after I return from my constructor.

My constructor currently calls the following methods in sequence:

lt = new JLanguageTool(language , motherTongue );
lt.activateDefaultPatternRules();
lt.activateDefaultFalseFriendRules();
Tools.selectRules(lt, disabledRules, enabledRules);
lt.setListUnknownWords(true);

Both disabledRules and enabledRules are (currently!) "new String[0]".

Soon after this sequence the checking thread is started leading to the Exception shown before.
If I insert a 50ms delay between the operations the error disappears.

My guess is either the constructor or one of the reconfiguration methods starts a separate thread to execute potentially long operations (e.g.: loading hunspell dictionaries), but I could be wrong.

Please advise me.

Regards
Mauro


(Daniel Naber) #4

You're right, my question probably didn't make that much sense, as your "lt" is private.

Does the problem also occur if you call the check method directly after "lt.setListUnknownWords(true); ", i.e. not from another thread? Can you reproduce this if you remove all the methods one by one, until only "lt = new JLanguageTool(language , motherTongue ); " is left? Does it only happen with Italian?


(Mauro) #5

Thanks.
I'll do some testing and I will be back at you ASAP.

Regards
Mauro


(Mauro) #6

Ok, SOLVED! :smile:

It turns out JLanguageTool.check() is not thread-safe.
I had my wrapper class as a singleton, so multiple documents could be scanned at the same time using the same instance.

This was the case at startup when all open documents are scanned (later they are scanned only when changed).

Wrapping it in a synchronized block

lt = new JLanguageTool(language , motherTongue );

...
synchronized (lt) {
ruleMatches = lt.check(contents);
}

solves the issue without resorting to delays.

Delay worked just because it shuffled the timings enough calls never clashed.

Thanks for Your time.

Regards
Mauro