Hi Stephan,

On 16.07.2010 14:51, Stephan Bergmann wrote:
> On 07/16/10 13:48, rony wrote:
>> On 16.07.2010 08:48, Stephan Bergmann wrote:
>>> On 07/15/10 22:10, Rony G. Flatscher wrote:
>>>> today I stumbled over the following interesting (read: time-consuming)
>>>> problem: while caching Java objects representing individual UNO_ENUM
>>>> values, all of a sudden om.sun.star.lang.DisposedException started
>>>> to be
>>>> thrown. Here is one such received exception message:
>>>>
>>>>       ... getCause(): [com.sun.star.lang.DisposedException:
>>>>       java_remote_bridge
>>>>      
>>>> com.sun.star.lib.uno.bridges.java_remote.java_remote_bri...@105b99f
>>>>       is disposed]
>>>
>>> That DisposedException had more than likely a different reason.  Java
>>> objects representing UNO enumeration type values are completely
>>> "local" -- none of their methods initiate any URP communication.
>> This is the use case using the Java bridge, where invocations of UNO
>> APIs via Java are carried out using Java reflection (this allows me to
>> basically address UNO typelessly from the perspective of Rexx users):
>>
>>      * get all the enum values of "com.sun.star.style.ParagraphAdjust"
>>        and cache them for later use, e.g. the value for "RIGHT" is
>>        assigned to a local variable named "right",
>>      * then, later,  an XParagraphCursor is queried for its XPropertySet
>>        and then this is used to setPropertyValue("ParaAdjust", right).
>>
>>        It is in this invocation where unexpectedly the above
>> exception is
>>        thrown.
>>
>> Now, querying for the enum value "RIGHT" before using it in the
>> setPropertyValue() works reliably.
>
> Can you present the exact failing code here?  What type is the
> variable named "right," and how exactly does the (reflective, IIUC)
> call to setPropertyValue look like?
Yes, but you need to fasten your seat-belt!
;-)

Reason being the following architecture:

    * ooRexx (C++) interacting with Java via an external function call
      package for ooRexx (C++) that communicates with Java via JNI (C++),
    * Java support classes which partly use the Apache Software
      Foundation's Bean Script Framework 2.x,
    * an ooRexx package named UNO.CLS that is tailored to ease
      interaction with UNO, taking advantage of ooRexx mechanisms (e.g.
      instead of the programmer issuing explicitly a
      Runtime.queryInterface(...) this is done in UNO.CLS, if the
      programmer merely sent the name of an interface as a message to
      the UNO Rexx object, etc.).

Realizing the complexity of the architecture (which has evolved for the
past four years with the specific OOo/UNO support package) I am always
wary, when analyzing or reporting errors.

In the concrete case the following code snippet had failed:

    ... cut ...
       /* make all of the UNO_ENUM values easily available to Rexx: */
    paraEnum=.uno_enum~new("com.sun.star.style.ParagraphAdjust")
       /* for debugging: show all values */
    say "UNO_ENUM 'ParagraphAdjust':" pp(paraEnum~makeString)

       /* get properties of XParagraphCursor */
    xParagraphCursorProps=xTextCursor~XParagraphCursor~XPropertySet
       /* for debugging: show the definition, including all available 
properties */
    say "'xParagraphCursorProps':" ppd(xParagraphCursorProps~uno.getDefinition)

       /* right adjust paragraph */
    xTextCursor~gotoEnd(.false)
    xText~insertControlCharacter(xTextCursor, ctlConstants~paragraph_Break, 
.false)
    xText~insertString(xTextCursor, "This paragraph will be right-adjusted. 
"~copies(6), .true)
    *xParagraphCursorProps~setPropertyValue("ParaAdjust", paraEnum~right)*
    ^^^ failure with the reported exception ^^^                             
      

In the typeless (actually late binding) ooRexx (http://www.ooRexx.org)
there is an explicit message operator (the tilde, ~) which means that
the object left of the tilde will get the message sent to, that is given
right of the tilde. If a message carries arguments, then these arguments
can be enclosed in round parentheses.

The statement "paraEnum=.uno_enum~new(...)" uses the ooRexx class
UNO_ENUM defined in UNO.CLS to wrap an UNO_ENUM. The result is that one
then merely needs to send the enum value's name as a message and will
get the enum (Java) object returned. This is done in the last statement
above, setting the "ParaAdjust" property.

The ooRexx class UNO_ENUM would cache all enum (Java object) values and
return them. In the process of analyzing the problem I also explicitly
queried the enum (Java object) value right before the last statement
above and it returned the same Java object, that has been cached.
Except, in the latter case the exception was not thrown and the code worked.

As a result I changed the implementation of the UNO_ENUM ooRexx class to
not return a cached enum (Java object) value, but query that value at
that point in time and return it. And the problem went away ...

[I know, you might be inclined to think that the caching in UNO_ENUM
does not work, but I can assure you that I double-checked on that. In a
nutshell: as long as an ooRexx Java proxy is not garbage collected, the
peer Java object which is saved on the Java side in a cache, does not
get freed and cannot for that reason be garbage collected on the Java
side. The same technique is employed over and over in all kind of 
applications that interact with Java, so is proven for almost ten years
now.]

---

In the above last statement the general reflective Java code is used: on
the Java side the class object of  *"*xParagraphCursorProps**" is
retrieved and the methods it implements are queried. In this case
"setPropertyValue(java.lang.String, java.lang.Object)". This method is
then invoked supplying the string "ParaAdjust" and the Java object
representing the enum value. This is where this
exception"com.sun.star.lang.DisposedException" (unexplainably for me )
gets thrown.

The very same reflective code works for *every OOo/UNO program*
flawlessly and reliably, even for the most complex and demanding ones !

> The DisposedException indicates either a problem in the bridge (say,
> it is asked to marshal an object of unexpected type, and thus shuts
> down) or in the remote soffice.bin process (it likely crashed).
soffice.bin did not crash, so maybe it is the first reason, that an
unexpected type is presented ? But if the supplied Java object was not
of the correct type, then an IllegalArgument exception would have to be
thrown (which was not the case here, but would be the case with many
service implementations when one presents value with an illegal type for
an argumetn, something I take reliably advantage of as well in another
context).

---rony

Reply via email to