3
votes

I'm working on an component in which smaller components are stacked. The user should be able to change the order of these components using drag and drop. I've made this work by implementing an TransferHandler that accepts a local reference DataFlavor (javaJVMLocalObjectMimeType) of the underlying data models. This works fine.

Now I would like to also run my application a second time and be able to drag on of my components from one application into the other. In this case I want to bundle the necessary data of the drag source into a serializable object to reconstruct the object at the drop application and use a serializable DataFlavor for that. I don't want to use object serialization in both situations.

How do I decide if my drag operation is originated in the same JVM so that I can decide to use the object reference or the serialized version of the data. The official swing DnD documentation mentions that it is possible to mix local and serialization flavors but it doesn't tell how to make best use of this.

Edit

Here's how I create the flavor in my DataModelTransferable

public static DataFlavor localFlavor;

static {
    try {
        localFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" +  ArrayList.class.getName() + "\"");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}
...
@Override
public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] { localFlavor };
}

And in my TransferHandler I do this

@Override
public boolean canImport(TransferSupport support) {
    return support.isDataFlavorSupported(DataModelTransferable.localFlavor);
}

As I said, this works fine locally, but if I drag from one to another instance the drag is accepted which leads to a java.io.IOException: Owner failed to convert data on the drop application and a java.io.NotSerializableException: alignment.model.DataModel on the drag source application. This is ok but the drag shouldn't be accepted on another app in the first place.

I'm using a ArrayList as I also want to be able to drag several objects at once, fyi.

2
When I have tried using javaJVMLocalObjectMimeType now, what I have seen when dropping into the the second instance of the application was the call isDataFlavorSupported called in my canImport returned true, but getTransferable.getTransferData from importData has returned null. - Suma

2 Answers

2
votes

I just found out myself what the problem was. I wrote a wrapper class DataModelListfor my ArrayList of DataModels that doesn't implement Serializable and modified the declaration of my data flavor to this:

localFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" +  DataModelList.class.getName() + "\"");

After that, this flavor is not considered to be equal between the drag source and the drop target if they are not within the same JVM.

I conclude that it's not possible to use local object reference flavors directly with classes that implement Serializable. If someone knows where this is documented I would be glad to hear about it.

0
votes

Your object reference flavor will normally be different for each running JVM. So you first check whether the Transferable supports your 'object reference flavor' before you ask for the 'serialized dataflavor version'.