8 Replies Latest reply: Dec 3, 2010 4:55 AM by 789192 RSS

    EnvironmentFailureException on opening EntityStore

    789192
      Adding a new secondary key field to an entity class made it impossible to open EntityStore:

      com.sleepycat.je.EnvironmentFailureException: (JE 4.1.6) UNEXPECTED_STATE: Unexpected internal state, may have side effects.
           at com.sleepycat.je.EnvironmentFailureException.unexpectedState(EnvironmentFailureException.java:347)
           at com.sleepycat.compat.DbCompat.unexpectedState(DbCompat.java:507)
           at com.sleepycat.persist.impl.EnhancedAccessor.newInstance(EnhancedAccessor.java:104)
           at com.sleepycat.persist.impl.ComplexFormat.checkNewSecKeyInitializer(ComplexFormat.java:475)
           at com.sleepycat.persist.impl.ComplexFormat.initialize(ComplexFormat.java:451)
           at com.sleepycat.persist.impl.Format.initializeIfNeeded(Format.java:542)
           at com.sleepycat.persist.impl.ComplexFormat.initialize(ComplexFormat.java:334)
           at com.sleepycat.persist.impl.Format.initializeIfNeeded(Format.java:542)
           at com.sleepycat.persist.impl.ComplexFormat.initialize(ComplexFormat.java:334)
           at com.sleepycat.persist.impl.Format.initializeIfNeeded(Format.java:542)
           at com.sleepycat.persist.impl.PersistCatalog.init(PersistCatalog.java:454)
           at com.sleepycat.persist.impl.PersistCatalog.<init>(PersistCatalog.java:221)
           at com.sleepycat.persist.impl.Store.<init>(Store.java:186)
           at com.sleepycat.persist.EntityStore.<init>(EntityStore.java:185)

      Entity store opens fine if there are no changes to format at all or there is no @SecondaryKey annotation for the new field. Here is my entity class:

      @Entity
      public abstract class AbstractMessageEntity implements MessageEntity {

      @PrimaryKey
      private Long id;

      }

      and after adding new secondary key:

      @Entity( version = 3 )
      public abstract class AbstractMessageEntity implements MessageEntity {

      @PrimaryKey
      private Long id;

      @SecondaryKey( relate = Relationship.MANY_TO_ONE )
      private Long executionTime;

      }

      AbstractMessageEntity has 3 persistent subclasses, but they were not changed except increasing their version from 0 to 3.

      I would greatly appreciate any workaround for this problem!
        • 1. Re: EnvironmentFailureException on opening EntityStore
          Greybird-Oracle
          Hi,

          Eric Wang will take a look at this tonight (he is in China) and post a reply.

          --mark                                                                                                                                                                                           
          • 2. Re: EnvironmentFailureException on opening EntityStore
            712739
            Hi,

            According to your given class information, I assume that you have an abstract class, AbstractMessageEntity, and three subclasses, called MessageEntity1, MessageEntity2, and MessageEntity3. All you want to store are those three subclasses, right?

            Before addressing to your problem, I wanna point out that, the annotation of AbstractMessageEntity, which is @Entity should be changed to @Persistent. Because in DPL, you cannot define an entity subclass for another entity class. This is just a reminder, which is not related to your current errors.

            Now come back to your error. Actually, I cannot reproduce your error. Below is the code I made and tried to use it to reproduce your error:
            import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
            
            import java.io.File;
            
            import com.sleepycat.je.Environment;
            import com.sleepycat.je.EnvironmentConfig;
            import com.sleepycat.persist.EntityStore;
            import com.sleepycat.persist.PrimaryIndex;
            import com.sleepycat.persist.StoreConfig;
            import com.sleepycat.persist.model.AnnotationModel;
            import com.sleepycat.persist.model.Entity;
            import com.sleepycat.persist.model.EntityModel;
            import com.sleepycat.persist.model.Persistent;
            import com.sleepycat.persist.model.PrimaryKey;
            import com.sleepycat.persist.model.SecondaryKey;
            
            public class AddNewSecKeyTest {
                
                private Environment env;
                private EntityStore store;
                private PrimaryIndex<Long, MessageEntity> primary;
                
                public static void main(String args[]) {
                    AddNewSecKeyTest epc = new AddNewSecKeyTest();
                    epc.open();
                    epc.writeData();
                    epc.close();
                }
                
                private void writeData() {
                    primary.put(null, new MessageEntity(1));
                }
                
                private void getData() {
                    AbstractMessageEntity data = primary.get(1L);
                }
                
                private void close() {
                    store.close();
                    store = null;
            
                    env.close();
                    env = null;
                }
            
                private void open() {
            
                    EnvironmentConfig envConfig = new EnvironmentConfig();
                    envConfig.setAllowCreate(true);
                    File envHome = new File("./");
                    env = new Environment(envHome, envConfig);
                    EntityModel model = new AnnotationModel();
                    StoreConfig config = new StoreConfig();
                    config.setAllowCreate(envConfig.getAllowCreate());
                    config.setTransactional(envConfig.getTransactional());
                    config.setModel(model);
                    store = new EntityStore(env, "test", config);
                    primary = store.getPrimaryIndex(Long.class, MessageEntity.class);
                }
                
                @Persistent(version = 3)
                static public abstract class AbstractMessageEntity {
                    AbstractMessageEntity(Long i) {
                        this.id = i;
                    }
                    
                    private AbstractMessageEntity(){}
                    
                    @PrimaryKey
                    private Long id;
                    
                    @SecondaryKey( relate = MANY_TO_ONE )
                    private Long executionTime;
                }
                
                @Entity(version = 3)
                static public class MessageEntity extends AbstractMessageEntity{
                    private int f1;
                    
                    private MessageEntity(){}
                    
                    MessageEntity(int i) {
                        super(Long.valueOf(i));
                        this.f1 = i;
                    }
                }
            }
            However, the above code can run successfully on my sandbox (with JE 4.1.6). I don't know how much difference between my code and your code (I mean the class hierarchy). So please post your class hierarchy according to my code, also the code about how you serialize your class.

            Thanks.

            Eric Wang
            BDB JE Team
            • 3. Re: EnvironmentFailureException on opening EntityStore
              789192
              Hello,
              According to your given class information, I assume that you have an abstract class, AbstractMessageEntity, and three subclasses, called MessageEntity1, MessageEntity2, and MessageEntity3. All you want to store are those three subclasses, right?
              Yes, thats right.
              Before addressing to your problem, I wanna point out that, the annotation of AbstractMessageEntity, which is @Entity should be changed to @Persistent. Because in DPL, you cannot define an entity subclass for another entity class. This is just a reminder, which is not related to your current errors.
              The abstract class is @Entity and subclasses are annotated with @Persistent, not @Entity. And normally it works just fine.

              Test you have created does not really reproduces my problem, it occurs not on creation of new environemnt, but on update of existing environment's persistent model. And if it might be of any importance, classes are being registered manually, through AnnotationModel.registerClass() method. So steps to reproduce the error might be like these:

              1. create environment
              2. create AnnotationModel and register all classes
              3. create EntityModel with this AnnotationModel
              4. ...
              5. close environment
              6. change classes (add secondary key to base abstract class)
              7. open environment
              8. create AnnotationModel and register all classes
              9. create EntityModel with this AnnotationModel <-- exception occurs
              • 4. Re: EnvironmentFailureException on opening EntityStore
                789192
                Just reproduced the problem with quite easy steps. Here is the main class:
                import com.sleepycat.je.Environment;
                import com.sleepycat.je.EnvironmentConfig;
                import com.sleepycat.persist.EntityStore;
                import com.sleepycat.persist.StoreConfig;
                import com.sleepycat.persist.model.*;
                
                import java.io.File;
                
                public class BdbModelTest {
                
                    private Environment env;
                
                    private EntityStore store;
                
                    public static void main(String[] args) {
                        new BdbModelTest().run();
                    }
                
                    private void run() {
                        open();
                        close();
                    }
                
                    private void close() {
                        store.close();
                        store = null;
                
                        env.close();
                        env = null;
                    }
                
                    private void open() {
                
                        EnvironmentConfig envConfig = new EnvironmentConfig();
                        envConfig.setAllowCreate( true );
                
                        File envHome = new File( "./" );
                        envHome.mkdirs();
                        
                        env = new Environment( envHome, envConfig );
                
                        EntityModel model = new AnnotationModel();
                        model.registerClass( MessageEntity.class );
                
                        StoreConfig config = new StoreConfig();
                        config.setAllowCreate( envConfig.getAllowCreate() );
                        config.setTransactional( envConfig.getTransactional() );
                        config.setModel( model );
                
                        store = new EntityStore( env, "test", config );
                    }
                
                }
                First time run it with the following entity classes:
                @Entity
                public abstract class MessageEntity {
                
                    @PrimaryKey
                    private Long id;
                
                }
                Add secondary key to the entity class:
                @Entity( version = 3 )
                public abstract class MessageEntity {
                
                    @PrimaryKey
                    private Long id;
                
                    @SecondaryKey( relate = Relationship.MANY_TO_ONE )
                    private Long executionTime;
                
                }
                Run the main test again and get the following exception:

                Exception in thread "main" com.sleepycat.je.EnvironmentFailureException: (JE 4.1.6) java.lang.InstantiationException UNEXPECTED_EXCEPTION: Unexpected internal Exception, may have side effects.
                     at com.sleepycat.je.EnvironmentFailureException.unexpectedException(EnvironmentFailureException.java:286)
                     at com.sleepycat.compat.DbCompat.unexpectedException(DbCompat.java:494)
                     at com.sleepycat.persist.impl.ReflectionAccessor.newInstance(ReflectionAccessor.java:157)
                     at com.sleepycat.persist.impl.ComplexFormat.checkNewSecKeyInitializer(ComplexFormat.java:475)
                     at com.sleepycat.persist.impl.ComplexFormat.initialize(ComplexFormat.java:451)
                     at com.sleepycat.persist.impl.Format.initializeIfNeeded(Format.java:542)
                     at com.sleepycat.persist.impl.PersistCatalog.init(PersistCatalog.java:454)
                     at com.sleepycat.persist.impl.PersistCatalog.<init>(PersistCatalog.java:221)
                     at com.sleepycat.persist.impl.Store.<init>(Store.java:186)
                     at com.sleepycat.persist.EntityStore.<init>(EntityStore.java:185)
                     at BdbModelTest.open(BdbModelTest.java:52)
                     at BdbModelTest.run(BdbModelTest.java:22)
                     at BdbModelTest.main(BdbModelTest.java:18)
                • 5. Re: EnvironmentFailureException on opening EntityStore
                  Greybird-Oracle
                  Thank you for sending a test. Eric will take a look at this tonight.
                  --mark                                                                                                                                                                                   
                  • 6. Re: EnvironmentFailureException on opening EntityStore
                    712739
                    Hi,

                    Thank you for your feedback. I now understand your problem, and I can reproduce the error.

                    I will do further investigation, and give you further feedback or workaround as soon as possible.

                    Eric Wang
                    BDB JE Team
                    • 7. Re: EnvironmentFailureException on opening EntityStore
                      Greybird-Oracle
                      helg,

                      Eric came up with a fix for this, and it will be in a future JE release.

                      In the mean time, it looks like a workaround is to remove 'abstract' from your entity class. I realize this isn't desirable, but is this sufficient to keep you from being blocked by this?

                      --mark                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                      • 8. Re: EnvironmentFailureException on opening EntityStore
                        789192
                        Yes it is, making the entity class non-abstract worked for me. Thanks for the solution!