This discussion is archived
1 2 Previous Next 15 Replies Latest reply: Dec 8, 2010 11:04 PM by 712739 RSS

Cannot evolve PersistentProxy?

795271 Newbie
Currently Being Moderated
Hi All,
I made changes to my PersistentProxy class, so I need a class converter to provide backwards compatibility.

But I got the following exception when running my class converter:

Exception in thread "main" java.lang.ClassCastException: com.sleepycat.persist.raw.RawObject cannot be cast to com.sleepycat.persist.model.PersistentProxy
at com.sleepycat.persist.impl.ProxiedFormat.newInstance(ProxiedFormat.java:91)
at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:174)
at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:273)
at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:187)
at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
at com.sleepycat.persist.impl.ProxiedFormat.newInstance(ProxiedFormat.java:93)
at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:174)
at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
at com.sleepycat.persist.impl.PersistEntityBinding.readEntity(PersistEntityBinding.java:101)
at com.sleepycat.persist.impl.PersistEntityBinding.entryToObjectInternal(PersistEntityBinding.java:71)
at com.sleepycat.persist.impl.PersistEntityBinding.entryToObject(PersistEntityBinding.java:58)
at com.sleepycat.persist.PrimaryIndex.get(PrimaryIndex.java:591)


So does that mean BDB cannot support evolution of PersistentProxy?

I appreciate your help.
  • 1. Re: Cannot evolve PersistentProxy?
    greybird Expert
    Currently Being Moderated
    Hi,

    You should be able to evolve your proxy classes.

    To answer your DPL questions, we're going to need a complete set of your classes that we can compile and reproduce the problem here. A single java file is best, that contains enough of the persistent classes and a main program that demonstrates the problem. Rather than post a large file here, you can send email to mark.hayes at o.com (oracle).

    We asked for this information on your previous DPL question also, here:
    Re: class converter problem

    What happened with that? Did you resolve the issue?

    --mark                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
  • 2. Re: Cannot evolve PersistentProxy?
    795271 Newbie
    Currently Being Moderated
    Hi Mark,
    The thread I posted as "http://forums.oracle.com/forums/message.jspa?messageID=9117605#9117605" can be merged with this one. Thanks for you guys' reply.

    First of all, my class converter is successfully registered, but the convert() method is never called.

    I did more digging into this issue. The problem is located in the code of com.sleepycat.persist.impl.ProxiedFormat, the newInstance() method, as follow:
      @Override
        public Object newInstance(EntityInput input, boolean rawAccess) {
            Reader reader = proxyFormat.getReader();
            if (rawAccess) {
                return reader.newInstance(null, true);
            } else {
    
    // My debug information shows: 
    // the reader here is of "com.sleepycat.persist.impl.ConverterReader"
    // reader.newInstance(null, false) is trying to get the old version (e.g. version 0) of my proxy in RawObject type.
    // Now the problem comes when casting the RawObject type into PersistentProxy type.
                PersistentProxy proxy =
                    (PersistentProxy) reader.newInstance(null, false);  
    
    
    // This line will call the convert() method in my converter, but it cannot be reached since exception is thrown
    // in the line before.
                proxy = (PersistentProxy) reader.readObject(proxy, input, false);
                return proxy.convertProxy();
            }
        }
    I think it could be a bug in BDB, please advise. Thanks.

    Edited by: 792268 on 2010-11-11 下午3:33
  • 3. Re: Cannot evolve PersistentProxy?
    greybird Expert
    Currently Being Moderated
    Hi,

    Thank you for tracking this down and reporting it. I think you're right, and this is a JE bug. We (actually Eric Wang, who replied to your earlier message) has reproduced the problem and is working on a fix. We'll give you a status update early next week.

    If you'd like to make a JE code change to get around the problem so you can make forward progress, you could try adding the three lines bracketed by comments below to the src/com/sleepycat/persist/impl/ProxiedFormat.java file. Please consider this a temporary workaround, for now, as we are still working on the problem.
        public Object newInstance(EntityInput input, boolean rawAccess)
            throws RefreshException {
    
            Reader reader = proxyFormat.getReader();
            if (rawAccess) {
                return reader.newInstance(null, true);
            } else {
                /* BEGIN NEW CODE */
                if (ConverterReader.class.isInstance(reader)) {
                    return reader.readObject(reader.newInstance(null, false), input, false);
                }
                /* END NEW CODE */
                PersistentProxy proxy =
                    (PersistentProxy) reader.newInstance(null, false);
                proxy = (PersistentProxy) reader.readObject(proxy, input, false);
                return proxy.convertProxy();
            }
        }
    Thanks,
    --mark                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
  • 4. Re: Cannot evolve PersistentProxy?
    795271 Newbie
    Currently Being Moderated
    Hi Mark,
    I appreciate your quick response.

    I hope this fix can also be applicable to (or included in) je 4.1.6, since we are going to move to this new version shortly.

    Thanks,
    James Li
  • 5. Re: Cannot evolve PersistentProxy?
    greybird Expert
    Currently Being Moderated
    James,

    Is the situation that you are upgrading your application's persistent classes and moving to a new version of JE at the same time, and you need a fix for this bug in order to do so?

    Please send me email -- mark.hayes at o.com (oracle.com) -- so that we can coordinate.

    Thanks,
    --mark                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
  • 6. Re: Cannot evolve PersistentProxy?
    795271 Newbie
    Currently Being Moderated
    Hi,
    My class converter got called with your three-line fix. Thanks.
    But I also got a NullPointerException from BDB code, as follow.

    java.lang.NullPointerException
    at com.sleepycat.persist.impl.ComplexFormat.newInstance(ComplexFormat.java:513)
    at com.sleepycat.persist.impl.ComplexFormat.convertRawObject(ComplexFormat.java:657)
    at com.sleepycat.persist.impl.ProxiedFormat.convertRawObject(ProxiedFormat.java:129)
    at com.sleepycat.persist.impl.PersistCatalog.convertRawObject(PersistCatalog.java:1202)
    at com.sleepycat.persist.impl.ConverterReader.readObject(ConverterReader.java:61)
    at com.sleepycat.persist.impl.ProxiedFormat.newInstance(ProxiedFormat.java:93)
    at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:174)
    at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:273)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:187)
    at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.ProxiedFormat.newInstance(ProxiedFormat.java:98)
    at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:174)
    at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.PersistEntityBinding.readEntity(PersistEntityBinding.java:101)
    at com.sleepycat.persist.impl.PersistEntityBinding.entryToObjectInternal(PersistEntityBinding.java:71)
    at com.sleepycat.persist.impl.PersistEntityBinding.entryToObject(PersistEntityBinding.java:58)
    at com.sleepycat.persist.PrimaryIndex.get(PrimaryIndex.java:591)
    ...

    In ComplexFormat.convertRawObject():
          /* Create the persistent object and convert all RawObject fields. */
            EntityInput in = new RawComplexInput
                (catalog, rawAccess, converted, fields, objects);
    
            // rawAccess is false, which results in NPE is thrown in the newInstance() method.
            Object o = newInstance(in, rawAccess);
    -james
  • 7. Re: Cannot evolve PersistentProxy?
    795271 Newbie
    Currently Being Moderated
    Hi Mark and Eric,
    My class converter is now working with your fix, thanks a lot.

    Now I just have one more question: How to get the RawType of an enum?
    I am using the following code to do it.
    newKeyType = model.getRawType(myEnum.class.getName());
    Since BDB does not allow me to add annotation @Persistent to an enum type, so the 'newKeyType' returned
    from the above line is always null.

    The reason I want to do that is I want to enumerize the keys in the map of my PersistentProxy.

    I appreciate your help.
  • 8. Re: Cannot evolve PersistentProxy?
    greybird Expert
    Currently Being Moderated
    Hi,

    I'm glad to hear that Eric's fix is working for you.

    An enum instance is represented with a RawObject using this constructor:
    http://download.oracle.com/docs/cd/E17277_02/html/java/com/sleepycat/persist/raw/RawObject.html#RawObject(com.sleepycat.persist.raw.RawType, java.lang.String)
    And an enum type is represented with a RawType.

    They can only be evolved by adding new constants, as described in the com.sleepycat.persist.evolve package description:
    Enum values may be added compatibly, but may not be deleted or renamed. As long as new values are declared after existing values, the default sort order for enum key fields will match the declaration order, i.e, the default sort order will match the enum ordinal order. If a new value is inserted (declared before an existing value), it will be sorted after all existing values but before newly added values. However, these ordering rules are only guaranteed for enums containing up to 631 values and only if existing values are not reordered. If more than 631 values are declared or the declarations of existing values are reordered, then the default sort order will be arbitrary and will not match the declaration (ordinal) order.
    Because you cannot delete or rename enum values, you can enumerate your enum values directly (using the enum class itself) safely, regardless of the version of your persistent class.

    --mark

    Edited by: greybird on Dec 8, 2010 9:38 AM Corrected to say that enums actually are represented with RawObject and RawType. Sorry for the confusion caused earlier.
  • 9. Re: Cannot evolve PersistentProxy?
    795271 Newbie
    Currently Being Moderated
    Hi Mark,
    Thank you for your quick reply.

    My old version proxy has a map with String keys, now I want to evolve it to a new map with enum keys.
    Could you please take a look at the following converter code?
    public Object convert(Object fromValue) {
      // get the old String keys and turn to enum keys
      ...
    
      ArrayList<Object> newKeys = new ArrayList<Object>();
      newKeys.add(enumKey);
    
      // Here I use the old RawType, because enum do not have RawType.
      RawObject newRawKeys = new RawObject(oldRawKeys.getType(), newKeys.toArray());
      ...
      
      Map<String, Object> newMapProxyValues = new HashMap<String, Object>();  
      newMapProxyValues.put("keys", newRawKeys);
      newMapProxyValues.put("values", newRawValues);            
      RawObject newMapProxy = new RawObject(oldMapProxy.getType(), newMapProxyValues, null);
      ...
    }
    But I got the following exception: (HttpHeaderConstants.HeaderName is my enum)

    java.lang.IllegalArgumentException: Raw value class: HttpHeaderConstants$HeaderName must be RawObject a simple type
    at com.sleepycat.persist.impl.RawAbstractInput.checkAndConvert(RawAbstractInput.java:104)
    at com.sleepycat.persist.impl.RawArrayInput.readNext(RawArrayInput.java:43)
    at com.sleepycat.persist.impl.RawAbstractInput.readObject(RawAbstractInput.java:38)
    at com.sleepycat.persist.impl.ObjectArrayFormat.readObject(ObjectArrayFormat.java:122)
    at com.sleepycat.persist.impl.ObjectArrayFormat.convertRawObject(ObjectArrayFormat.java:150)
    at com.sleepycat.persist.impl.PersistCatalog.convertRawObject(PersistCatalog.java:1202)
    at com.sleepycat.persist.impl.RawAbstractInput.checkAndConvert(RawAbstractInput.java:99)
    at com.sleepycat.persist.impl.RawComplexInput.readNext(RawComplexInput.java:42)
    at com.sleepycat.persist.impl.RawAbstractInput.readObject(RawAbstractInput.java:38)
    at com.sleepycat.persist.impl.MapProxy.bdbReadNonKeyFields(MapProxy.java)
    at com.sleepycat.persist.impl.MapProxy$HashMapProxy.bdbReadNonKeyFields(MapProxy.java)
    at com.sleepycat.persist.impl.EnhancedAccessor.readNonKeyFields(EnhancedAccessor.java:163)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.ComplexFormat.convertRawObject(ComplexFormat.java:662)
    at com.sleepycat.persist.impl.ProxiedFormat.convertRawObject(ProxiedFormat.java:129)
    at com.sleepycat.persist.impl.PersistCatalog.convertRawObject(PersistCatalog.java:1202)
    at com.sleepycat.persist.impl.RawAbstractInput.checkAndConvert(RawAbstractInput.java:99)
    at com.sleepycat.persist.impl.RawComplexInput.readNext(RawComplexInput.java:42)
    at com.sleepycat.persist.impl.RawAbstractInput.readObject(RawAbstractInput.java:38)
    at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:273)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.ComplexFormat.convertRawObject(ComplexFormat.java:662)
    at com.sleepycat.persist.impl.ProxiedFormat.convertRawObject(ProxiedFormat.java:129)
    at com.sleepycat.persist.impl.PersistCatalog.convertRawObject(PersistCatalog.java:1202)
    at com.sleepycat.persist.impl.ConverterReader.readObject(ConverterReader.java:61)
    at com.sleepycat.persist.impl.ProxiedFormat.newInstance(ProxiedFormat.java:93)
    at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:174)
    at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:273)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:187)
    at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.ProxiedFormat.newInstance(ProxiedFormat.java:98)
    at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:174)
    at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:406)
    at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:285)
    at com.sleepycat.persist.impl.ComplexFormat.readObject(ComplexFormat.java:520)
    at com.sleepycat.persist.impl.PersistEntityBinding.readEntity(PersistEntityBinding.java:101)
    at com.sleepycat.persist.impl.PersistEntityBinding.entryToObjectInternal(PersistEntityBinding.java:71)
    at com.sleepycat.persist.impl.PersistEntityBinding.entryToObject(PersistEntityBinding.java:58)
    at com.sleepycat.persist.PrimaryIndex.get(PrimaryIndex.java:591)

    I trace into the method checkAndConvert(Object o, Format declaredFormat). Here o is a enum-type key and declaredFormat is
    <ComplexType id="1" class="java.lang.Object" version="0" currentVersionId="1" kind="persistent">
    </ComplexType>, when the above exception was thrown.

    Thank you for your help.
  • 10. Re: Cannot evolve PersistentProxy?
    712739 Newbie
    Currently Being Moderated
    Hi,

    I understand your problem, and I can reproduce the error. However, I need more time to do investigation.

    I will give you any feedback or workaround as soon as possible.

    Eric
    BDB JE Team
  • 11. Re: Cannot evolve PersistentProxy?
    greybird Expert
    Currently Being Moderated
    I apologize! I said the wrong thing earlier when I said:
    Enums do not have a RawType, they are treated more like a String or a primitive
    .
    And I'm afraid I caused unnecessary work for you and Eric. Sorry about that!

    An enum instance is represented with a RawObject using this constructor:
    http://download.oracle.com/docs/cd/E17277_02/html/java/com/sleepycat/persist/raw/RawObject.html#RawObject(com.sleepycat.persist.raw.RawType, java.lang.String)
    And an enum type is represented with a RawType.

    So in a conversion that creates an enum, you must create a RawObject. And you must get the RawType for the enum as you would for any other class.

    I've corrected my earlier post as well.

    --mark                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
  • 12. Re: Cannot evolve PersistentProxy?
    795271 Newbie
    Currently Being Moderated
    Thank you for your clarify.

    Yes, I probably need to use this constructor to create a RawObject for an enum, but I still not sure how to get the param 'type', because
    BDB does not allow me to add @Persistent to enums, which results in a null returned from EntityModel.getRawType()...
    public RawObject(RawType type, String enumConstant)
  • 13. Re: Cannot evolve PersistentProxy?
    795271 Newbie
    Currently Being Moderated
    Thank you, Eric.
  • 14. Re: Cannot evolve PersistentProxy?
    greybird Expert
    Currently Being Moderated
    To be clear: You are calling EntityModel.getRawType from your converter, after the EntityStore is open, and you are getting null? If so, try calling EntityModel.registerClass on the enum class before opening the store.

    --mark                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
1 2 Previous Next

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points