ObjectDB ObjectDB

Unexpected internal exception during set field of an Embeddable to null

#1

Hello,

we get an Unexpected internal exception and have no idea what goes wrong.

We can reproduce (mostly) the error in a very big use case. In the big use case and we create and persist millions of SignalValueImpl objects (Embeddables). Partly as in the stack trace an Embeddable contain another Embeddable.

It seems like that we can't reproduce the problem in smaller use cases with less objects.

Stack trace:

com.objectdb.o.InternalException: Unexpected internal exception
    at com.objectdb.o.JPE.h(JPE.java:168) ~[na:na]
    at com.objectdb.o.ERR.f(ERR.java:66) ~[na:na]
    at com.objectdb.o.OBC.onObjectDBError(OBC.java:1556) ~[na:na]
    at com.objectdb.o.ENT.al(ENT.java:1676) ~[na:na]
    at com.objectdb.o.ENT.beforeModifyEmbedded(ENT.java:1217) ~[na:na]
    at com.objectdb.o.EMT.beforeModifyMember(EMT.java:175) ~[na:na]
    at com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.__odbSet_originalValue(SignalValueImpl.java:1) ~[na:na]
    at com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.clearOriginalValue(SignalValueImpl.java:52) ~[na:na]
    at com.btc.ep.architecture.bl.internal.dmos.values.IntegerSignalValueImpl.setValue(IntegerSignalValueImpl.java:39) ~[na:na]
    at com.btc.ep.architecture.bl.internal.dmos.values.FixedPointSignalValueImpl.setValue(FixedPointSignalValueImpl.java:92) ~[na:na]
    at com.btc.ep.architecture.bl.internal.dmos.values.FixedPointSignalValueImpl.setSignalValueAsDouble(FixedPointSignalValueImpl.java:188) ~[na:na]
    at com.btc.ep.vector.db.bl.internal.services.DBVectorServiceImpl.setValue(DBVectorServiceImpl.java:178) ~[na:na]
    (...A few lines hidden...) 
    at com.btc.ep.atg4req.ui.wizard.Atg4ReqExecutionJob$1.run(Atg4ReqExecutionJob.java:52) [com.btc.ep.atg4req.ui_12.0.0.201606221703.jar:na]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_51]
Caused by: java.lang.ArrayIndexOutOfBoundsException: 3
    at com.objectdb.o.MMM.J(MMM.java:630) ~[na:na]
    at com.objectdb.o.ENT.beforeModifyEmbedded(ENT.java:1213) ~[na:na]
    ... 25 common frames omitted

 

Stripped implementation of SignalValueImpl

import javax.persistence.Basic;
import javax.persistence.Embeddable;

import com.btc.ep.architecture.bl.dmos.values.SignalValue;

/**
*/

@Embeddable
public class SignalValueImpl implements SignalValue {

    @Basic
    private boolean defined;

    @Basic
    String originalValue;

    /**
     * Constructs a new instance whose value is currently undefined.
     */
    public SignalValueImpl() {
        defined = false;
    }

    /**
     * Clear the content of the originalString.
     *
     * <p>The OriginalValue must be cleared if the value has been changed.
     * That can be done by this method.</p>
     */
    protected void clearOriginalValue() {
        originalValue = null;
    }
}

Can you read the problem from the stack trace?

edit
delete
#2

The ArrayIndexOutOfBoundsException is thrown on an attempt to access a 4th field ([3]) in the array of persistent fields of the SignalValueImpl embedded class, which unexpectedly happens to be smaller.

During enhancement of the SignalValueImpl class field originalValue was the 4th field. Assuming that there may have been a schema change since that enhancement rebuilding the project and enhancing all classes again may solve the issue. If it doesn't please upload the embedded class file after enhancement for further review.

ObjectDB Support
edit
delete
#3

Hello,

many thanks, that (enhancing all classes again) solves the problem.

edit
delete
#4

Hello,

the described error occurs again. (with ObjectDB 2.6.8.b05)

The error is now caused by another call. But it is again the embedded class SignalValueImpl.

com.objectdb.o.JPE.h(JPE.java:168)
com.objectdb.o.ERR.f(ERR.java:66)
com.objectdb.o.OBC.onObjectDBError(OBC.java:1556)
com.objectdb.o.ENT.al(ENT.java:1676)
com.objectdb.o.ENT.beforeModifyEmbedded(ENT.java:1217)
com.objectdb.o.EMT.beforeModifyMember(EMT.java:175)
com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.__odbSet_originalValue(SignalValueImpl.java:1)
com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.clearOriginalValue(SignalValueImpl.java:58)
com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.setDefined(SignalValueImpl.java:69)
com.btc.ep.vector.bl.internal.services.MergedVectorServiceImpl.getValue(MergedVectorServiceImpl.java:534)

The class was build and enhanced by our jenkins.

We build and enhance per feature. (a feature contains several bundles, but no bundle is used in different features.)

We have a defined build pipeline that all our features built in the correct order.

Example:  e depends on d;  c depends on b; d depends on a; b depends on a;

Then the Build order is:  1) a    2) b    3) d     4) c     5) e

Please tell us if this way, to enhance the classes feature for feature, can cause any enhancement problem. We will release the first version (with ObjectDB) of our Application at the end of the week.

 

I attach the enhanced class file.

edit
delete
#5

This exception is different. Could you please check for additional stack trace in the log file?

You should be able to enhance each feature separately, as long as the classpath that is available to the Enhancer includes all the required classes for the feature, but it might be safer to enhance everything in one enhancement operation on final build for distribution (but again, it is unclear if the new exception is related to enhancement).

ObjectDB Support
edit
delete
#6

Oh sorry, there is an adittional stack strace:

at com.objectdb.o.JPE.h(JPE.java:168) ~[na:na]
at com.objectdb.o.ERR.f(ERR.java:66) ~[na:na]
at com.objectdb.o.OBC.onObjectDBError(OBC.java:1556) ~[na:na]
at com.objectdb.o.ENT.al(ENT.java:1676) ~[na:na]
at com.objectdb.o.ENT.beforeModifyEmbedded(ENT.java:1217) ~[na:na]
at com.objectdb.o.EMT.beforeModifyMember(EMT.java:175) ~[na:na]
at com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.__odbSet_originalValue(SignalValueImpl.java:1) ~[na:na]
at com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.clearOriginalValue(SignalValueImpl.java:58) ~[na:na]
at com.btc.ep.architecture.bl.internal.dmos.values.SignalValueImpl.setDefined(SignalValueImpl.java:69) ~[na:na]
at com.btc.ep.vector.bl.internal.services.MergedVectorServiceImpl.getValue(MergedVectorServiceImpl.java:534) ~[na:na]
....
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:119) ~[na:na]
Caused by: java.lang.ArrayIndexOutOfBoundsException: 2
at com.objectdb.o.MMM.J(MMM.java:630) ~[na:na]
at com.objectdb.o.ENT.beforeModifyEmbedded(ENT.java:1213) ~[na:na]
... 19 common frames omitted
edit
delete
#7

It seems that the class in #4 above is not synchronized with the stack trace, or in other words, a different version of the class was used when the exception was thrown.

In the posted class (#4 above) there are 2 persistent fields and in the class from the stack trace at least 3.

Please verify that the same class version is used everywhere, and eliminate old class versions from the classpath.

ObjectDB Support
edit
delete
#8

We have further embedded classes derived from SignalValueImpl.

In the described error the SignalValueImpl is an instance of IntegerSignalValueImpl. I attach the class file.


 

edit
delete
#9

The exception is related to field originalValue (according to the stack trace).

According to the class the field index is 1 and that it what is sent to beforeModifyMember:

    public static void __odbSet_originalValue(SignalValueImpl signalvalueimpl, String s)
    {
        if(signalvalueimpl.__odbTracker != null && signalvalueimpl.__odbTracker.beforeModifyMember(1))
        {
            signalvalueimpl.originalValue = s;
            signalvalueimpl.__odbTracker.afterModify();
        } else
        {
            signalvalueimpl.originalValue = s;
        }
    }

but according to the stack trace beforeModifyMember received 2, which caused ArrayIndexOutOfBoundsException, so it seems that the stack trace was generated when using a different version of the enhanced class, in which the field index was 2.

The sub class at #8 doesn't seem to be related.

ObjectDB Support
edit
delete
#10

No, it is the related sub class. After ours of decompiling and debugging I hope that I found a important hint. The stack trace has been reduced to very (by the printer).

The enhanced class call  "signalvalueimpl.__odbTracker.beforeModifyMember(1)"

But __odbTracker is from Type EMT !

And the method EMT.beforeModifyMember(1)  call  "ENT.beforeModifyEmbedded(2)"

 

I enhanced SignalValueImpl, decompiled it and debugged the decompiled SignalValueImpl. And beforeModifyMember is called with "1".

See screenshot for stackTrace.

edit
delete
#11

This is known and normal. beforeModifyEmbedded invokes beforeModifyEmbedded (as you can see in #6 above) with the same field index, when applicable.

Are you sure that you get the same exception. i.e.

    java.lang.ArrayIndexOutOfBoundsException: 2

with the new enhanced class with field index 1?

ObjectDB Support
edit
delete
#12

Yes I'm sure.

Can you prepare a ObjectDB version (objectdb-jee.jar) with a try catch for ArrayIndexOutOfBoundsException in EMT.beforeModifyMember() and throw an ArrayIndexOutOfBoundsException with some additional information in the catch block?

So that we see the current value of the beforeModifyMember parameter, which value are delegated to beforeModifyEmbedded, and the class name of the processed Entity/Embeddable.

edit
delete
#13

Looking further into this problem it seems that it may be related to a specific way of using embedded objects.

Could you please provide more information about the way in which SignalValueImpl and IntegerSignalValueImpl are used in this case. Do you have nested embedded objects? Can you show a complete graph of objects of that specific entity class with all its embedded objects?

If you can provide a test case that demonstrates the exception then fixing it should be quick and easy. If you cannot, we will try to build a test case that reflects the same relationships between your objects as in your application, bur for that we will need more information.

ObjectDB Support
edit
delete
#14

We have tried to create a testCase.
But it is not so easy to debug it. We have a long scenario with which we can reproduce that. But the setting of "original value" for Class IntegerSignalValueImpl works once on a attched Object and the second time (another attached Object) it results in the error.

 

We have an Entity with a list of SignalValueImpl.

We have SignalValue instances which contain another SignalValue.

AND yes in our case the second IntegerSignalValueImpl Object, on which we get the Exception, is a nested object of a PointerSignalInstanceValueImpl. The first Object, on which it works, is direcly in the list of the Entity.

 


@Embeddable
public class PointerSignalInstanceValueImpl extends SignalValueImpl implements PointerSignalInstanceValue {

    @Embedded
    SignalValue pointedToInstanceValue;

    /**
     * Constructor
     */
    public PointerSignalInstanceValueImpl() {
        // never use the original string of the Pointer itself - only from the instanceValue!
        originalValue = null;
    }

    @Override
    public SignalValue getInstanceValue() {
        return pointedToInstanceValue;
    }

    @Override
    public void setInstanceValue(SignalValue pointedToInstanceValue) {
        clearOriginalValue();
        this.pointedToInstanceValue = pointedToInstanceValue;
        setDefined(pointedToInstanceValue != null, null);
    }
}
edit
delete
#15

I can provide a test case that demonstrates the exception.

I always forgot to enhance the Entity Class "MyEntity". After i add the class to the enhance-script the error occurs.

The attached zip contains the example.  The Reproduce class contains the main().

Its not a OneLine-Example, because it was easier to enhance the class files.

 

 

 

edit
delete
#16

You wrote that you forgot to enhance MyEntity and then enhanced it later.

If you do enhance it with all the other classes, does the error still happen?

ObjectDB Support
edit
delete
#17

This test case is very useful and demonstrates an issue in a particular use of nested embedded objects.

We are working on this now and we hope to be able to provide a quick fix.

ObjectDB Support
edit
delete
#18

Please try build 2.6.8_06.

ObjectDB Support
edit
delete
#19

Thank you very much. With build 2.6.8_06 it works.

 

You wrote that you forgot to enhance MyEntity and then enhanced it later.
If you do enhance it with all the other classes, does the error still happen?

First the class 'MyEntity' was a subclass of Reproduce.java and therefore I had forgotten to enhancen it. If the class MyEntity was not enhanced i got no error. Then I added the class to the enhance script and then the error was reproducable.

edit
delete

Reply

To post on this website please sign in.