How to retrieve the serialized object from Hazelcast's Imap? - java

The below code is for putting a kryo serialised object into an Hazelcast's Imap instance followed by retrieving. On retrieving the object it throws an error named:
com.hazelcast.nio.serialization.HazelcastSerializationException: com.esotericsoftware.kryo.KryoException: java.io.EOFException: Unexpected end of ZLIB input stream
My code is given below.
package hazelcast2;
import java.util.Scanner;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.config.Config;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.SerializerConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.core.ISet;
public class zlibtry {
public static Config config;
public static ClientConfig cfg;
public static HazelcastInstance hz;
public static IMap<String,MyDataObject> mapItemCount;
public static void main(String[] args) throws Exception{
// Scanner obj = new Scanner(System.in);
config= new Config();
config.setProperty("hazelcast.elastic.memory.enabled" , "true");
config.setProperty("hazelcast.elastic.memory.total.size", "60G");
config.setProperty("hazelcast.elastic.memory.chunk.size","2");
MapConfig mapConfig = new MapConfig();
mapConfig.setInMemoryFormat( InMemoryFormat.OBJECT );
//config.getNetworkConfig().setPort(5701);
//config.getNetworkConfig().setPublicAddress("127.0.0.1");
config.setProperty("address","127.0.0.1");
SerializerConfig productSerializer = new SerializerConfig()
.setTypeClass(MyDataObject.class).setImplementation(new ProductKryoSerializer(true));
config.getSerializationConfig().addSerializerConfig(productSerializer);
hz=Hazelcast.newHazelcastInstance(config);
mapItemCount=hz.getMap("objectMap");
MyDataObject obj = new MyDataObject();
ISet<Integer> iset = hz.getSet("zlibset2");
iset.add(1);
obj.setMyList(iset);
mapItemCount.put("1", obj);
System.out.println(mapItemCount.get("1").getMyList().toString());
}
}
The below code is for productKyroSerializer:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.nio.serialization.StreamSerializer;
public class ProductKryoSerializer implements StreamSerializer {
private final boolean compress;
private static final ThreadLocal<Kryo> kryoThreadLocal
= new ThreadLocal<Kryo>() {
#Override
protected Kryo initialValue() {
Kryo kryo = new Kryo();
kryo.register(MyDataObject.class);
return kryo;
}
};
public ProductKryoSerializer(boolean compress) {
this.compress = compress;
}
public int getTypeId() {
return 2;
}
public void write(ObjectDataOutput objectDataOutput, MyDataObject product)
throws IOException {
Kryo kryo = kryoThreadLocal.get();
if (compress) {
ByteArrayOutputStream byteArrayOutputStream =
new ByteArrayOutputStream(16384);
DeflaterOutputStream deflaterOutputStream =
new DeflaterOutputStream(byteArrayOutputStream);
Output output = new Output(deflaterOutputStream);
kryo.writeObject(output, product);
output.close();
byte[] bytes = byteArrayOutputStream.toByteArray();
objectDataOutput.write(bytes);
} else {
Output output = new Output((OutputStream) objectDataOutput);
kryo.writeObject(output, product);
output.flush();
}
}
public MyDataObject read(ObjectDataInput objectDataInput)
throws IOException {
InputStream in = (InputStream) objectDataInput;
if (compress) {
in = new InflaterInputStream(in);
}
Input input = new Input(in);
Kryo kryo = kryoThreadLocal.get();
return kryo.readObject(input, MyDataObject.class);
}
public void destroy() {
}
// #Override
// public Object read(ObjectDataInput arg0) throws IOException {
// // TODO Auto-generated method stub
// return null;
// }
public void write(ObjectDataOutput arg0, Object arg1) throws IOException {
// TODO Auto-generated method stub
}
}
And moreover, I think there should be some proper method to retrieve the object after deserialisation.
You can see the "objectMap" hazelcast's IMap instance and I have updated some code in hazelcast.xml:
<map name="objectMap">
<in-memory-format>OBJECT</in-memory-format>
</map>
<map name="cachedMap">
<in-memory-format>CACHED</in-memory-format>
</map>
<map name="binaryMap">
<in-memory-format>BINARY</in-memory-format>
</map>
and the code for myDataObject is
import com.hazelcast.core.IList;
import com.hazelcast.core.ISet;
public class MyDataObject {
ISet<Integer> myList;
public ISet<Integer> getMyList() {
return myList;
}
public void setMyList(ISet<Integer> myList) {
this.myList = myList;
}
}

ISet is not serializable and cannot be serialized directly as a field inside of a class. See the following snippet for a possible solution.
public class MyDataObject
implements KryoSerializable, HazelcastInstanceAware {
private ISet<Integer> myList;
private String myListName;
public ISet<Integer> getMyList() {
return myList;
}
public void setMyList(ISet<Integer> myList) {
this.myList = myList;
this.myListName = myList.getName();
}
public void write (Kryo kryo, Output output) {
output.writeString(myListName);
}
public void read (Kryo kryo, Input input) {
this.myListName = input.readString();
}
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
this.myList = hazelcastInstance.getSet(myListName);
}
}
I guess that should work (at least kind of ;-)) just wrote it in the browser.

Related

Unit testing a function using java library azure-storage-blob mocked

When working with azure BlobStorage I'm quite new to this topic but I managed to get it working in java. So we have some xml files saved there and collect the file list as strings. Now I've tried to create a unit tests to verify it stays working and since the getFiles() function is a very small I expected it to be very simple to test.
#Override
public List<String> getFiles(ExecutionContext context) {
return StreamSupport.stream(blobContainerClient.listBlobs().spliterator(), true)
.map(BlobItem::getName)
.collect(Collectors.toList());
}
I can mock the com.azure.storage.blob.blobContainerClient and its function listBlobs, but when trying to create the PagedIterable from a simple List I cannot make it fit the right data types or it runs into an endless loop.
Since the functionality is so minimal, we would just skip to test this, but ou of curiosity I just want to know if it could be tested or what is wrong with my code:
import com.azure.core.http.rest.*;
import com.azure.core.util.IterableStream;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.models.BlobItem;
import com.microsoft.azure.functions.ExecutionContext;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.core.CoreSubscriber;
import reactor.core.Fuseable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Supplier;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;
class BlobstoreConnectorListFilesTest {
private final BlobContainerClient blobContainerClientMock = mock(BlobContainerClient.class);
private final ExecutionContext context = mock(ExecutionContext.class);
private final String id1 = UUID.randomUUID().toString();
private final String id2 = UUID.randomUUID().toString();
#BeforeEach
void setUp() {
BlobItem item1 = mock(BlobItem.class);
when(item1.getName()).thenReturn(id1 + ".xml");
BlobItem item2 = mock(BlobItem.class);
when(item2.getName()).thenReturn(id2 + ".xml");
List<BlobItem> arrayList = new ArrayList<>();
arrayList.add(item1);
arrayList.add(item2);
Mono<PagedResponse<BlobItem>> monoSource = new Mono<>() {
private final Page<BlobItem> page = new Page<>() {
#Override
public IterableStream<BlobItem> getElements() {
return new IterableStream<>(Flux.fromIterable(arrayList));
}
#Override
public String getContinuationToken() {
return null;
}
};
final PagedResponseBase<String, BlobItem> pagedResponseBase = new PagedResponseBase<>(null, 200, null, page
, null);
final Fuseable.QueueSubscription<BlobItem> fuseableQueueSubscription = new Fuseable.QueueSubscription<>() {
#Override
public void request(long l) {
}
#SneakyThrows
#Override
public void cancel() {
throw new InterruptedException();
}
#Override
public int size() {
return arrayList.size();
}
#Override
public boolean isEmpty() {
return arrayList.isEmpty();
}
#Override
public void clear() {
arrayList.clear();
}
#Override
public BlobItem poll() {
var value = arrayList.stream().findFirst().orElse(null);
if(value!=null){
arrayList.remove(value);
}
return value;
}
#Override
public int requestFusion(int i) {
return 0;
}
};
#Override
public void subscribe(CoreSubscriber<? super PagedResponse<BlobItem>> coreSubscriber) {
coreSubscriber.onNext(pagedResponseBase);
coreSubscriber.onSubscribe(fuseableQueueSubscription);
}
};
Supplier<Mono<PagedResponse<BlobItem>>> blobItemSupplier = () -> monoSource;
PagedFlux<BlobItem> pagedFlux = new PagedFlux<>(blobItemSupplier);
PagedIterable<BlobItem> leaflets = new PagedIterable<>(pagedFlux);
doReturn(leaflets).when(blobContainerClientMock).listBlobs();
}
#Test
void getAllFiles() {
BlobstoreConnector connector = new BlobstoreConnector(blobContainerClientMock);
List<String> actual = connector.getFiles(context);
assertEquals(2, actual.size());
assertTrue(actual.stream().anyMatch(fileName -> fileName.equals(id1 + ".xml")));
assertTrue(actual.stream().anyMatch(fileName -> fileName.equals(id2 + ".xml")));
}
}

Unable to set Pojo Object variable with an external value during JaxB MoXY Unmarshalling

I am trying the above approach that you have mentioned for NodeAdaptar, but I am getting null for my element.
Scenario:
I have to set the value of variable defined in my Java Model(POJO) Class with a value, coming externally(not part of the input XML). This value will be used in some calculation post unmarshal.
input XML: its a huge one. I am able to unmarshall it correctly.
POJO Class:
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name="root")
#XmlAccessorType(XmlAccessType.FIELD)
public class MainModelClass {
#XmlPath("abc/def/Result/text()")
#XmlElement(name="Result")
private String result;
#XmlPath("/abc/def/Score/text()")
#XmlElement(name="Score")
private String score;
///This is where I want to populate the external value ///
#XmlElement
#XmlJavaTypeAdapter(PCNDateAdaptar.class)
private PCNDate pcnDateObject;
public PCNDate getPcnDateObject() {
return pcnDateObject;
}
public void setPcnDateObject(PCNDate pcnDateObject) {
this.pcnDateObject = pcnDateObject;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
// Block for overridden toString() //
}
Adaptar Class:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class PCNDateAdaptar extends XmlAdapter<Integer, PCNDate> {
private PCNDate pcnDateObject;
public void setPcnDateObject(PCNDate pcnDateob) {
this.pcnDateObject = pcnDateob;
}
#Override
public PCNDate unmarshal(Integer v) throws Exception {
if(v == null)
return this.pcnDateObject;
else
return this.pcnDateObject;
}
#Override
public Integer marshal(PCNDate v) throws Exception {
if(v == null)
return null;
else
return null;
}
}
PCNDate.class:
public class PCNDate {
private Integer processControlDate;
public Integer getProcessControlDate() {
return processControlDate;
}
public void setProcessControlDate(Integer pcn) {
this.processControlDate = pcn;
}
}
Unmarshaller Method:
public static <T> T getXMLSnippetObject(String xmlString, Class<T> modelClass, XmlAdapter<?, ?> xmlAdapterObject) throws XMLStreamException, JAXBException {
JAXBContext context = JAXBContext.newInstance(modelClass);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setAdapter(xmlAdapterObject);
InputStream xmlInputStream = IOUtils.toInputStream(xmlString);
XMLInputFactory2 xmlInputFactory = (XMLInputFactory2)XMLInputFactory.newInstance();
xmlInputFactory.setProperty("javax.xml.stream.isCoalescing", true);
xmlInputFactory.setProperty("javax.xml.stream.isNamespaceAware", true);
xmlInputFactory.setProperty("javax.xml.stream.isReplacingEntityReferences", true);
xmlInputFactory.setProperty(XMLInputFactory2.P_AUTO_CLOSE_INPUT, true);
//xmlInputFactory.setProperty(XMLInputFactory2.P_DTD_OVERRIDE, false);
xmlInputFactory.setProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE, false);
xmlInputFactory.setProperty(XMLInputFactory2.P_PRESERVE_LOCATION,false);
xmlInputFactory.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, true);
XMLStreamReader2 xmlStreamReader = (XMLStreamReader2) xmlInputFactory.createXMLStreamReader(xmlInputStream);
T objectInstance = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(xmlStreamReader, modelClass));
return objectInstance;
}
Main Calling Class:
public class XMLparsing {
public static void main(String[] args) throws XMLStreamException, JAXBException, IOException {
String xmlString = // Xml String //
MainModelClass modelObj = null;
Integer pcnDate = 20171010;
// PCNDate & PCNDateAdapter are both no-arg-constructor classes for JAXB purpose
PCNDate pcnObj = new PCNDate();
pcnDateObj.setProcessControlDate(pcnDate);
PCNDateAdaptar pcndateAdaptar = new PCNDateAdaptar();
pcndateAdaptar.setPcnDateObject(pcnObj);
modelObj = XmlUtilsStAX.getXMLSnippetObject(xmlString, MainModelClass.class, pcndateAdaptar);
}
Result:
The whole Xml String is getting correctly parsed. Only MainModelClass's pcnDateObject is null, result & score have values. I want pcnDateObject to have 20171010.
I don't know, what I am missing, please help.

Statically defined KeyDeserializer not found but if defined locally everything perfect

I am baffled by how registering a custom KeyDeserializer works.
Here is my code:
Matchday.java
package com.example;
import java.io.Serializable;
import java.util.Objects;
public class Matchday implements Serializable, Comparable<Matchday> {
private static final long serialVersionUID = -8823049187525703664L;
private final int matchdayNumber;
public Matchday(final int matchdayNumber) {
this.matchdayNumber = matchdayNumber;
}
public int getMatchdayNumber() {
return matchdayNumber;
}
#Override
public int compareTo(Matchday o) {
return Integer.compare(matchdayNumber, o.getMatchdayNumber());
}
#Override
public final int hashCode() {
return Objects.hash(matchdayNumber);
}
#Override
public final boolean equals(final Object obj) {
return obj instanceof Matchday && Integer.valueOf(matchdayNumber).equals(((Matchday) obj).matchdayNumber);
}
#Override
public String toString() {
return Integer.toString(matchdayNumber);
}
}
TeamPlayer.java
package com.example;
import java.io.Serializable;
import org.apache.commons.lang3.builder.ToStringBuilder;
public class TeamPlayer implements Serializable {
private static final long serialVersionUID = -6057852081020631549L;
private int id;
private String name;
private String surname;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Override
public String toString() {
return new ToStringBuilder(this).append("id", id).append("name", name).append("surname", surname).build()
.toString();
}
}
Now if I define a custom map key deserializer for my class Matchday.java, it works like a charm if I do it like this.
KeyDeserializerTest.java
package com.example;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.SortedMap;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class KeyDeserializerTest {
public static void main(String[] args) throws IOException {
final ObjectMapper objectMapper = new ObjectMapper();
final SimpleModule mySimpleModule = new SimpleModule("dummy", new Version(0, 0, 0, "dummy", "dummy", "dummy"));
mySimpleModule.addKeyDeserializer(Matchday.class, new KeyDeserializer() {
#Override
public Object deserializeKey(String arg0, DeserializationContext arg1)
throws IOException, JsonProcessingException {
return new Matchday(Integer.valueOf(arg0));
}
});
objectMapper.registerModule(mySimpleModule);
final InputStream inputStream = new ByteArrayInputStream(
"{\"1\":[{\"id\": 1, \"name\": \"Arkadiusz\", \"surname\": \"Malarz\"}]}".getBytes());
SortedMap<Matchday, List<TeamPlayer>> map = objectMapper.readValue(inputStream,
new TypeReference<SortedMap<Matchday, List<TeamPlayer>>>() {
});
System.out.println(map);
}
}
It prints
{1=[com.example.TeamPlayer#3a8624[id=1,name=Arkadiusz,surname=Malarz]]}
But if I define both the object mapper and my deserializer instances as static attributes then I get the following exception!
KeyDeserializerStaticTest.java
package com.example;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.SortedMap;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class KeyDeserializerStaticTest {
public static final ObjectMapper OBJECT_MAPPER = createObjectMapper();
private static final KeyDeserializer MATCHDAY_KEY_DESERIALIZER = new KeyDeserializer() {
#Override
public Object deserializeKey(String key, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
return new Matchday(Integer.valueOf(key));
}
};
private static ObjectMapper createObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(createSimpleModule());
return objectMapper;
}
private static Module createSimpleModule() {
SimpleModule simpleModule = new SimpleModule("dummy", new Version(0, 0, 0, "dummy", "dummy", "dummy"));
simpleModule.addKeyDeserializer(Matchday.class, MATCHDAY_KEY_DESERIALIZER);
return simpleModule;
}
public static void main(String[] args) throws IOException {
final InputStream inputStream = new ByteArrayInputStream(
"{\"1\":[{\"id\": 1, \"name\": \"Arkadiusz\", \"surname\": \"Malarz\"}]}".getBytes());
SortedMap<Matchday, List<TeamPlayer>> map = OBJECT_MAPPER.readValue(inputStream,
new TypeReference<SortedMap<Matchday, List<TeamPlayer>>>() {
});
System.out.println(map);
}
}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class com.example.Matchday]
at [Source: java.io.ByteArrayInputStream#bbc1e0; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
at com.fasterxml.jackson.databind.DeserializationContext.reportMappingException(DeserializationContext.java:1234)
at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:585)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findKeyDeserializer(DeserializerCache.java:168)
at com.fasterxml.jackson.databind.DeserializationContext.findKeyDeserializer(DeserializationContext.java:499)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.createContextual(MapDeserializer.java:247)
at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:681)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:481)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3899)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3794)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2915)
at com.example.KeyDeserializerStaticTest.main(KeyDeserializerStaticTest.java:43)
What is wrong here? Semantically there is no difference between the above presented main methods. Is this a feature that is somewhere documented or is it simply a bug in Jackson?
The root problem here was the order of initialization of static variables.
It is
public static final ObjectMapper OBJECT_MAPPER = createObjectMapper();
private static final KeyDeserializer MATCHDAY_KEY_DESERIALIZER = new KeyDeserializer() {
#Override
public Object deserializeKey(String key, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
return new Matchday(Integer.valueOf(key));
}
};
while it should be
private static final KeyDeserializer MATCHDAY_KEY_DESERIALIZER = new KeyDeserializer() {
#Override
public Object deserializeKey(String key, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
return new Matchday(Integer.valueOf(key));
}
};
public static final ObjectMapper OBJECT_MAPPER = createObjectMapper();
This was hard to spot because the method addKeyDeserializer(Class<?>, KeyDeserializer) of the class SimpleModule silently adds null references to an internal key deserializers' map. In my opinion it should throw a NullPointerException upon trying adding a key deserializer reference that is null.
The Jackson code for it looks like this.
First addKeKeyDeserializer(Class<?>, KeyDeserializer)
public SimpleModule addKeyDeserializer(Class<?> type, KeyDeserializer deser)
{
if (_keyDeserializers == null) {
_keyDeserializers = new SimpleKeyDeserializers();
}
_keyDeserializers.addDeserializer(type, deser);
return this;
}
there is no check here whether deser is null.
Then it delegates to addDeserializer(Class, KeyDeserializer) of class SimpleKeyDeserializers.
public SimpleKeyDeserializers addDeserializer(Class<?> forClass, KeyDeserializer deser)
{
if (_classMappings == null) {
_classMappings = new HashMap<ClassKey,KeyDeserializer>();
}
_classMappings.put(new ClassKey(forClass), deser);
return this;
}
Here is the null reference also ignored and silently put into _classMappings map.
Here is the issue I posted on GitHub together with the discussion.

(Java) Transfering an Object to an application through Clipboard

How can I copy a Java object (with a couple of fields) to my clipboard in Java, and what is the best way to store these fields?
I have a simple object with a ΗashΜap for storage.
Also, I created a selection for this object, which it implements both Transferable and ClipboardOwner, as well as a DataFlavor for it.
What I'm trying to do is copy this object and paste it in another application. Keep in mind that I don't have access to the source code of this application, so I have to transfer this object in this particular way. Let's say this application is requiring these following fields:
Info (String)
Text (String in UTF-8 Format)
However, copying and pasting this object to the other application doesn't seem to work.
Below you can see my classes:
MyObject:
import java.util.HashMap;
public class MyObject {
private HashMap<Object, Object> data;
public MyObject()
{
data = new HashMap<Object, Object>();
}
public void setData(Object field, Object value)
{
data.put(field, value);
}
}
MyObjectFlavor:
import java.awt.datatransfer.DataFlavor;
public class MyObjectFlavor extends DataFlavor {
public MyObjectFlavor()
{
super(MyObject.class, null);
}
}
MyObjectSelection:
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class MyObjectSelection implements Transferable, ClipboardOwner {
final static DataFlavor myObjectFlavor = new MyObjectFlavor();
final static DataFlavor[] supportedDataFlavors = { myObjectFlavor };
private MyObject myObject;
public MyObjectSelection(MyObject myObject)
{
this.myObject = myObject;
}
public Object getTransferData(DataFlavor dataFlavor)
throws UnsupportedFlavorException, IOException
{
if (!isDataFlavorSupported(dataFlavor)) {
throw new UnsupportedFlavorException(dataFlavor);
}
// Passing data in a ByteArrayOutputStream.
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
objectStream.writeObject(myObject);
return byteStream.toByteArray();
}
public DataFlavor[] getTransferDataFlavors()
{
return supportedDataFlavors;
}
public boolean isDataFlavorSupported(DataFlavor dataFlavor)
{
for (int i = 0; i < supportedDataFlavors.length; i++) {
if (supportedDataFlavors[i].equals(dataFlavor)) {
return true;
}
}
return false;
}
public void lostOwnership(Clipboard arg0, Transferable arg1)
{
// Lost ownership.
}
}
Finally, my Main class is:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class Main {
public static void main(String args[]) throws IOException {
MyObject myObject = new MyObject();
MyObjectSelection selection = new MyObjectSelection(myObject);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard ();
String myUtfString = "This is a String in UTF-8";
myObject.setData("Info", "This is a Java Object.");
myObject.setData("Text", new ByteArrayInputStream(myUtfString.getBytes("UTF-8")));
clipboard.setContents(selection, selection);
}
}
I'm sorry for the long post, but I think providing all classes will help. I hope this question is not specific.
Thanks in advance!

A class that extends HashMap when adding new variable can't be write to json

ResultContentExt extends HashMap and has it's own variable testInt.
In main method, I write the ResultContentExt been to json.but can't write the variable
testInt to json.
I also rewrite writeObject method in ResultContentExt, which seems not be called...
package test.open.serial;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class ResultContentExt extends HashMap<String, Object> implements
Serializable {
private static final long serialVersionUID = 628377769976336650L;
public ResultContentExt() {
}
private int testInt;
public int getTestInt() {
return testInt;
}
public void setTestInt(int testInt) {
this.testInt = testInt;
}
public List<String> getRef_hot_status() {
return (List<String>) this.get("ref_hot_status");
}
#Override
public String toString() {
return "ResultContentExt [ref_hot_status=" + this.getRef_hot_status()
+ "]" + "ref_new_status=" + this.getRef_new_status()
+ this.getTestInt();
}
public void setRef_hot_status(List<String> ref_hot_status) {
if (ref_hot_status != null) {
this.put("ref_hot_status", ref_hot_status);
} else {
this.put("ref_hot_status", new LinkedList<Map<String, Integer>>());
}
}
public void setRef_new_status(List ref_new_status) {
if (ref_new_status != null) {
this.put("ref_new_status", ref_new_status);
} else {
this.put("ref_new_status", new LinkedList<Map<String, Integer>>());
}
}
public List<String> getRef_new_status() {
return (List<String>) this.get("ref_new_status");
}
public void writeObject(ObjectOutputStream s) throws IOException {
System.out.println("ResultContentExt begin...");
s.defaultWriteObject();
System.out.println("ResultContentExt end");
}
}
the result is {"ref_new_status":["bbbb","cccc"],"ref_hot_status":["aaa","侠盗飞"]}
why the testInt can't be write to json.
the main class
public class SearilazizeTest implements Serializable{
private static final long serialVersionUID = 5767426158258564918L;
private static Logger logger = Logger.getLogger(SearilazizeTest.class);
public static void main(String[] args){
try {
jsonObjectTrans();
} catch (Exception e) {
logger.error("", e);
}
}
public static void jsonObjectTrans(){
ResultContentExt rce = new ResultContentExt();
List<String> refHostStatus = new ArrayList<String>();
refHostStatus.add("aaa");
refHostStatus.add("侠盗飞");
rce.setRef_hot_status(refHostStatus);
List<String> refNewStatus = new ArrayList<String>();
refNewStatus.add("bbbb");
refNewStatus.add("cccc");
rce.setRef_new_status(refNewStatus);
rce.setTestInt(22);
System.out.println(rce.getTestInt());
JSONObject jsonArray = JSONObject.fromObject(rce);
System.out.println(jsonArray);
ResultContentExt packageVersionMaps = new ResultContentExt();
try {
JSONObject jsonObject = JSONObject.fromObject(jsonArray);
packageVersionMaps = (ResultContentExt) JSONObject.toBean(jsonObject,ResultContentExt.class);
} catch (Exception e) {
logger.error("", e);
}
System.out.println(packageVersionMaps);
}}

Categories

Resources