We wrote a plugin that serializes data (DTOs) to Bandana. Now we work on a new version which needs to migrate this data. So we implemented a PluginUpgradeTask and there we do this:
final OurDto dto = (OurDto) bandanaManager.getValue(ourContext, ourKey);
But this leads to an Exception:
java.lang.ClassCastException: net.confluence.plugin.ourPlugin.dto.OurDto cannot be cast to net.confluence.plugin.ourPlugin.dto.OurDto
I know this has something to do with the classloader and I know that it is not the first time we ran into this, but it seems I don't see the wood for the trees ... :/
I tried this, but I have no idea why the result is "false":
Object object = bandanaManager.getValue(ourContext, ourKey); OurDto.class.isAssignableFrom(object); > Result: false
The DTO itself looks like this:
public class OurDto implements Comparable<OurDto>, Serializable { private static final long serialVersionUID = -2503943733171462701L; private Date date; private String formattedDate; private String userName; private String userFullName; private String key; private Integer version; private Boolean published = false; public OurDto() { } public OurDto(final Date date, final ConfluenceUser user, final String key, final Integer version) { this.date = date; this.userName = user.getName(); this.userFullName = user.getFullName(); this.key = key; this.version = version; } ... getter/setter/compareTo ... }
The only way to get our Bandana data migrated is actually to disable the plugin manually, install the new version and enable it manually. This is not acceptable but how can we prevent this?
Thank you very much in advance for you help!
Kind regards
Manuel
Community moderators have prevented the ability to post new answers.
For some reason the DTO was loaded with a different ClassLoader and that's why the cast fails.
Object object = bandanaManager.getValue(ourContext, ourKey); log.debug(object.getClass().getClassLoader()) // ClassLoader A log.debug(new OurDto.getClass().getClassLoader()) // ClassLoader B
We fixed this problem by using Reflection to access the values from the old Dto and copy them to a new Instance.
// Create new OurDto and fill it with values from old OurDto private OurDto createNewFromOld(final Object oldObject) { final Class oldClass = oldObject.getClass(); final OurDto newDto = new OurDto(); // get and set values newDto.setDate((Date) getFieldValue(oldObject, oldClass, "date")); newDto.setUserName((String) getFieldValue(oldObject, oldClass, "userName")); // ... and so on return newDto; } // Fetch field value from old OurDto private Object getFieldValue(final Object oldObject, final Class oldClass, final String fieldName) { final Field date = oldClass.getDeclaredField(fieldName); date.setAccessible(true); return date.get(oldObject); }
Hope this helps.
We had a similar issue. In our case we had two distinct plugin versions to isolate the cause of our problem. It turned our that the update from Java 7 to Java 8 caused the class incompatibility. The DTO had absolutely no code changes between both version.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Manuel Kummerländer Have you tried to let your custom Bandana context implement BandanaSerializerFactory to handle the serialization process by yourself? Your data-transfer-object has some changed attributes in its latest version? Have you updated the serialVersionUID according to the contract of Serializable?
If the first solution does not work you could try to use reflection to access the properties of the object loaded from Bandana or you could try to directly access Bandana's (XStream) XML storage format.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Our Object has not changed in a way Serializable contract would be injured. We did not try to implement BandanaSerializerFactory or try to serialize ourselfs, but as I see it, this is not the problem.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Have you tried to purge the Bandana cache? Just to be sure?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
We did this, but does not help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.