Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

ClassCastException on Plugin Upgrade while working with Bandana Data

Manuel Kummerländer October 20, 2015

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 

3 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

3 votes
Answer accepted
Paul Pasler
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
October 21, 2015

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.

Tilman Schweitzer October 5, 2017

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.

3 votes
Micha Kops
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 21, 2015

@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.

 

Paul Pasler
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
October 21, 2015

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.

0 votes
Micha Kops
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 21, 2015

Have you tried to purge the Bandana cache? Just to be sure?

Paul Pasler
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
October 21, 2015

We did this, but does not help.

TAGS
AUG Leaders

Atlassian Community Events