package org.infinispan.marshall;
import static org.infinispan.test.TestingUtil.extractGlobalMarshaller;
import static org.infinispan.test.TestingUtil.k;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
import java.io.ByteArrayInputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import org.infinispan.Cache;
import org.infinispan.atomic.impl.AtomicHashMap;
import org.infinispan.commands.CommandInvocationId;
import org.infinispan.commands.ReplicableCommand;
import org.infinispan.commands.read.GetKeyValueCommand;
import org.infinispan.commands.remote.ClusteredGetCommand;
import org.infinispan.commands.tx.CommitCommand;
import org.infinispan.commands.tx.PrepareCommand;
import org.infinispan.commands.tx.RollbackCommand;
import org.infinispan.commands.tx.totalorder.TotalOrderCommitCommand;
import org.infinispan.commands.tx.totalorder.TotalOrderNonVersionedPrepareCommand;
import org.infinispan.commands.tx.totalorder.TotalOrderRollbackCommand;
import org.infinispan.commands.tx.totalorder.TotalOrderVersionedCommitCommand;
import org.infinispan.commands.tx.totalorder.TotalOrderVersionedPrepareCommand;
import org.infinispan.commands.write.ClearCommand;
import org.infinispan.commands.write.InvalidateCommand;
import org.infinispan.commands.write.InvalidateL1Command;
import org.infinispan.commands.write.PutKeyValueCommand;
import org.infinispan.commands.write.PutMapCommand;
import org.infinispan.commands.write.RemoveCommand;
import org.infinispan.commands.write.ReplaceCommand;
import org.infinispan.commons.hash.MurmurHash3;
import org.infinispan.commons.marshall.AdvancedExternalizer;
import org.infinispan.commons.marshall.NotSerializableException;
import org.infinispan.commons.marshall.PojoWithJBossExternalize;
import org.infinispan.commons.marshall.PojoWithSerializeWith;
import org.infinispan.commons.marshall.SerializeWith;
import org.infinispan.commons.marshall.StreamingMarshaller;
import org.infinispan.commons.util.EnumUtil;
import org.infinispan.commons.util.FastCopyHashMap;
import org.infinispan.commons.util.Immutables;
import org.infinispan.commons.util.Util;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.container.entries.ImmortalCacheEntry;
import org.infinispan.container.entries.ImmortalCacheValue;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.MortalCacheEntry;
import org.infinispan.container.entries.MortalCacheValue;
import org.infinispan.container.entries.TransientCacheEntry;
import org.infinispan.container.entries.TransientCacheValue;
import org.infinispan.container.entries.TransientMortalCacheEntry;
import org.infinispan.container.entries.TransientMortalCacheValue;
import org.infinispan.container.versioning.EntryVersionsMap;
import org.infinispan.context.Flag;
import org.infinispan.distribution.ch.impl.DefaultConsistentHash;
import org.infinispan.distribution.ch.impl.DefaultConsistentHashFactory;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.marshall.core.ExternalPojo;
import org.infinispan.marshall.core.JBossMarshallingTest.CustomReadObjectMethod;
import org.infinispan.marshall.core.JBossMarshallingTest.ObjectThatContainsACustomReadObjectMethod;
import org.infinispan.metadata.EmbeddedMetadata;
import org.infinispan.remoting.MIMECacheEntry;
import org.infinispan.remoting.responses.ExceptionResponse;
import org.infinispan.remoting.responses.UnsuccessfulResponse;
import org.infinispan.remoting.responses.UnsureResponse;
import org.infinispan.remoting.transport.Address;
import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
import org.infinispan.statetransfer.StateRequestCommand;
import org.infinispan.test.AbstractInfinispanTest;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.infinispan.test.fwk.TestInternalCacheEntryFactory;
import org.infinispan.transaction.xa.GlobalTransaction;
import org.infinispan.transaction.xa.TransactionFactory;
import org.infinispan.util.ByteString;
import org.infinispan.commons.util.SmallIntSet;
import org.infinispan.util.concurrent.TimeoutException;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.jboss.marshalling.TraceInformation;
import org.jgroups.stack.IpAddress;
import org.jgroups.util.UUID;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@Test(groups = "functional", testName = "marshall.VersionAwareMarshallerTest")
public class VersionAwareMarshallerTest extends AbstractInfinispanTest {
private static final Log log = LogFactory.getLog(VersionAwareMarshallerTest.class);
private StreamingMarshaller marshaller;
private EmbeddedCacheManager cm;
private final TransactionFactory gtf = new TransactionFactory();
public VersionAwareMarshallerTest() {
gtf.init(false, false, true, false);
}
@BeforeClass
public void setUp() {
// Use a clustered cache manager to be able to test global marshaller interaction too
GlobalConfigurationBuilder globalBuilder = GlobalConfigurationBuilder.defaultClusteredBuilder();
globalBuilder.serialization().addAdvancedExternalizer(new PojoWithExternalAndInternal.Externalizer());
globalBuilder.serialization().addAdvancedExternalizer(new PojoWithExternalizer.Externalizer());
globalBuilder.serialization().addAdvancedExternalizer(new PojoWithMultiExternalizer.Externalizer());
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.clustering().cacheMode(CacheMode.DIST_SYNC);
cm = TestCacheManagerFactory.createClusteredCacheManager(globalBuilder, builder);
marshaller = extractGlobalMarshaller(cm);
}
@AfterClass
public void tearDown() {
cm.stop();
}
public void testJGroupsAddressMarshalling() throws Exception {
JGroupsAddress address = new JGroupsAddress(UUID.randomUUID());
marshallAndAssertEquality(address);
}
public void testGlobalTransactionMarshalling() throws Exception {
JGroupsAddress jGroupsAddress = new JGroupsAddress(UUID.randomUUID());
GlobalTransaction gtx = gtf.newGlobalTransaction(jGroupsAddress, false);
marshallAndAssertEquality(gtx);
}
public void testListMarshalling() throws Exception {
List<GlobalTransaction> l1 = new ArrayList<>();
List<GlobalTransaction> l2 = new LinkedList<>();
for (int i = 0; i < 10; i++) {
JGroupsAddress jGroupsAddress = new JGroupsAddress(new IpAddress("localhost", 1000 * i));
GlobalTransaction gtx = gtf.newGlobalTransaction(jGroupsAddress, false);
l1.add(gtx);
l2.add(gtx);
}
marshallAndAssertEquality(l1);
marshallAndAssertEquality(l2);
}
public void testMapMarshalling() throws Exception {
Map<Integer, GlobalTransaction> m1 = new HashMap<>();
Map<Integer, GlobalTransaction> m2 = new TreeMap<>();
Map<Integer, GlobalTransaction> m3 = new HashMap<>();
Map<Integer, GlobalTransaction> m4 = new FastCopyHashMap<>();
for (int i = 0; i < 10; i++) {
JGroupsAddress jGroupsAddress = new JGroupsAddress(UUID.randomUUID());
GlobalTransaction gtx = gtf.newGlobalTransaction(jGroupsAddress, false);
m1.put(1000 * i, gtx);
m2.put(1000 * i, gtx);
m4.put(1000 * i, gtx);
}
Map m5 = Immutables.immutableMapWrap(m3);
marshallAndAssertEquality(m1);
marshallAndAssertEquality(m2);
byte[] bytes = marshaller.objectToByteBuffer(m4);
Map<Integer, GlobalTransaction> m4Read = (Map<Integer, GlobalTransaction>) marshaller.objectFromByteBuffer(bytes);
for (Map.Entry<Integer, GlobalTransaction> entry : m4.entrySet()) {
assert m4Read.get(entry.getKey()).equals(entry.getValue()) : "Writen[" + entry.getValue() + "] and read[" + m4Read.get(entry.getKey()) + "] objects should be the same";
}
marshallAndAssertEquality(m5);
}
public void testSetMarshalling() throws Exception {
Set<Integer> s1 = new HashSet<>();
Set<Integer> s2 = new TreeSet<>();
for (int i = 0; i < 10; i++) {
Integer integ = 1000 * i;
s1.add(integ);
s2.add(integ);
}
marshallAndAssertEquality(s1);
marshallAndAssertEquality(s2);
}
public void testTreeSetWithComparator() throws Exception {
Set<Human> treeSet = new TreeSet<>(new HumanComparator());
for (int i = 0; i < 10; i++) {
treeSet.add(new Human().age(i));
}
marshallAndAssertEquality(treeSet);
}
public void testSingletonListMarshalling() throws Exception {
GlobalTransaction gtx = gtf.newGlobalTransaction(new JGroupsAddress(UUID.randomUUID()), false);
List<GlobalTransaction> l = Collections.singletonList(gtx);
marshallAndAssertEquality(l);
}
public void testImmutableResponseMarshalling() throws Exception {
marshallAndAssertEquality(UnsuccessfulResponse.EMPTY);
marshallAndAssertEquality(UnsureResponse.INSTANCE);
}
public void testReplicableCommandsMarshalling() throws Exception {
ByteString cacheName = ByteString.fromString(EmbeddedCacheManager.DEFAULT_CACHE_NAME);
ClusteredGetCommand c2 = new ClusteredGetCommand("key", cacheName,
EnumUtil.EMPTY_BIT_SET);
marshallAndAssertEquality(c2);
// SizeCommand does not have an empty constructor, so doesn't look to be one that is marshallable.
GetKeyValueCommand c4 = new GetKeyValueCommand("key", EnumUtil.EMPTY_BIT_SET);
marshallAndAssertEquality(c4);
PutKeyValueCommand c5 = new PutKeyValueCommand("k", "v", false, null,
new EmbeddedMetadata.Builder().build(), EnumUtil.EMPTY_BIT_SET,
CommandInvocationId.generateId(null));
marshallAndAssertEquality(c5);
RemoveCommand c6 = new RemoveCommand("key", null, null, EnumUtil.EMPTY_BIT_SET,
CommandInvocationId.generateId(null));
marshallAndAssertEquality(c6);
// EvictCommand does not have an empty constructor, so doesn't look to be one that is marshallable.
InvalidateCommand c7 = new InvalidateCommand(null, EnumUtil.EMPTY_BIT_SET, CommandInvocationId.generateId(null), "key1", "key2");
marshallAndAssertEquality(c7);
InvalidateCommand c71 = new InvalidateL1Command(null, null, null, EnumUtil.EMPTY_BIT_SET, CommandInvocationId.generateId(null), "key1", "key2");
marshallAndAssertEquality(c71);
ReplaceCommand c8 = new ReplaceCommand("key", "oldvalue", "newvalue",
null, new EmbeddedMetadata.Builder().build(), EnumUtil.EMPTY_BIT_SET,
CommandInvocationId.generateId(null));
marshallAndAssertEquality(c8);
ClearCommand c9 = new ClearCommand();
marshallAndAssertEquality(c9);
Map<Integer, GlobalTransaction> m1 = new HashMap<>();
for (int i = 0; i < 10; i++) {
GlobalTransaction gtx = gtf.newGlobalTransaction(new JGroupsAddress(UUID.randomUUID()), false);
m1.put(1000 * i, gtx);
}
PutMapCommand c10 = new PutMapCommand(m1, null, new EmbeddedMetadata.Builder().build(), EnumUtil.EMPTY_BIT_SET, CommandInvocationId.generateId(null));
marshallAndAssertEquality(c10);
Address local = new JGroupsAddress(UUID.randomUUID());
GlobalTransaction gtx = gtf.newGlobalTransaction(local, false);
PrepareCommand c11 = new PrepareCommand(cacheName, gtx, true, c5, c6, c8, c10);
marshallAndAssertEquality(c11);
CommitCommand c12 = new CommitCommand(cacheName, gtx);
marshallAndAssertEquality(c12);
RollbackCommand c13 = new RollbackCommand(cacheName, gtx);
marshallAndAssertEquality(c13);
TotalOrderNonVersionedPrepareCommand c14 = new TotalOrderNonVersionedPrepareCommand(cacheName, gtx, c5, c6, c8, c10);
marshallAndAssertEquality(c14);
TotalOrderVersionedPrepareCommand c15 = new TotalOrderVersionedPrepareCommand(cacheName, gtx, Arrays.asList(c5, c10), true);
c15.setVersionsSeen(new EntryVersionsMap());
marshallAndAssertEquality(c15);
TotalOrderRollbackCommand c16 = new TotalOrderRollbackCommand(cacheName, gtx);
marshallAndAssertEquality(c16);
TotalOrderCommitCommand c17 = new TotalOrderCommitCommand(cacheName, gtx);
marshallAndAssertEquality(c17);
TotalOrderVersionedCommitCommand c18 = new TotalOrderVersionedCommitCommand(cacheName, gtx);
marshallAndAssertEquality(c18);
}
public void testStateTransferControlCommand() throws Exception {
Cache<Object,Object> cache = cm.getCache();
ByteString cacheName = ByteString.fromString(EmbeddedCacheManager.DEFAULT_CACHE_NAME);
ImmortalCacheEntry entry1 = (ImmortalCacheEntry) TestInternalCacheEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, -1, System.currentTimeMillis(), -1);
Collection<InternalCacheEntry> state = new ArrayList<>();
state.add(entry1);
Address a1 = new JGroupsAddress(UUID.randomUUID());
Address a2 = new JGroupsAddress(UUID.randomUUID());
Address a3 = new JGroupsAddress(UUID.randomUUID());
List<Address> oldAddresses = new ArrayList<>();
oldAddresses.add(a1);
oldAddresses.add(a2);
DefaultConsistentHashFactory chf = new DefaultConsistentHashFactory();
DefaultConsistentHash oldCh = chf.create(MurmurHash3.getInstance(), 2, 3, oldAddresses, null);
List<Address> newAddresses = new ArrayList<>();
newAddresses.add(a1);
newAddresses.add(a2);
newAddresses.add(a3);
DefaultConsistentHash newCh = chf.create(MurmurHash3.getInstance(), 2, 3, newAddresses, null);
StateRequestCommand c14 = new StateRequestCommand(cacheName, StateRequestCommand.Type.START_STATE_TRANSFER, a1, 99, new SmallIntSet());
byte[] bytes = marshaller.objectToByteBuffer(c14);
marshaller.objectFromByteBuffer(bytes);
bytes = marshaller.objectToByteBuffer(c14);
marshaller.objectFromByteBuffer(bytes);
bytes = marshaller.objectToByteBuffer(c14);
marshaller.objectFromByteBuffer(bytes);
}
public void testInternalCacheEntryMarshalling() throws Exception {
ImmortalCacheEntry entry1 = (ImmortalCacheEntry) TestInternalCacheEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, -1, System.currentTimeMillis(), -1);
marshallAndAssertEquality(entry1);
MortalCacheEntry entry2 = (MortalCacheEntry) TestInternalCacheEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, 200000, System.currentTimeMillis(), -1);
marshallAndAssertEquality(entry2);
TransientCacheEntry entry3 = (TransientCacheEntry) TestInternalCacheEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, -1, System.currentTimeMillis(), 4000000);
marshallAndAssertEquality(entry3);
TransientMortalCacheEntry entry4 = (TransientMortalCacheEntry) TestInternalCacheEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, 200000, System.currentTimeMillis(), 4000000);
marshallAndAssertEquality(entry4);
}
public void testInternalCacheValueMarshalling() throws Exception {
ImmortalCacheValue value1 = (ImmortalCacheValue) TestInternalCacheEntryFactory.createValue("value", System.currentTimeMillis() - 1000, -1, System.currentTimeMillis(), -1);
byte[] bytes = marshaller.objectToByteBuffer(value1);
ImmortalCacheValue rvalue1 = (ImmortalCacheValue) marshaller.objectFromByteBuffer(bytes);
assert rvalue1.getValue().equals(value1.getValue()) : "Writen[" + rvalue1.getValue() + "] and read[" + value1.getValue() + "] objects should be the same";
MortalCacheValue value2 = (MortalCacheValue) TestInternalCacheEntryFactory.createValue("value", System.currentTimeMillis() - 1000, 200000, System.currentTimeMillis(), -1);
bytes = marshaller.objectToByteBuffer(value2);
MortalCacheValue rvalue2 = (MortalCacheValue) marshaller.objectFromByteBuffer(bytes);
assert rvalue2.getValue().equals(value2.getValue()) : "Writen[" + rvalue2.getValue() + "] and read[" + value2.getValue() + "] objects should be the same";
TransientCacheValue value3 = (TransientCacheValue) TestInternalCacheEntryFactory.createValue("value", System.currentTimeMillis() - 1000, -1, System.currentTimeMillis(), 4000000);
bytes = marshaller.objectToByteBuffer(value3);
TransientCacheValue rvalue3 = (TransientCacheValue) marshaller.objectFromByteBuffer(bytes);
assert rvalue3.getValue().equals(value3.getValue()) : "Writen[" + rvalue3.getValue() + "] and read[" + value3.getValue() + "] objects should be the same";
TransientMortalCacheValue value4 = (TransientMortalCacheValue) TestInternalCacheEntryFactory.createValue("value", System.currentTimeMillis() - 1000, 200000, System.currentTimeMillis(), 4000000);
bytes = marshaller.objectToByteBuffer(value4);
TransientMortalCacheValue rvalue4 = (TransientMortalCacheValue) marshaller.objectFromByteBuffer(bytes);
assert rvalue4.getValue().equals(value4.getValue()) : "Writen[" + rvalue4.getValue() + "] and read[" + value4.getValue() + "] objects should be the same";
}
public void testLongPutKeyValueCommand() throws Exception {
PutKeyValueCommand c = new PutKeyValueCommand(
"SESSION_173", "@TSXMHVROYNOFCJVEUJQGBCENNQDEWSCYSOHECJOHEICBEIGJVTIBB@TVNCWLTQCGTEJ@NBJLTMVGXCHXTSVE@BCRYGWPRVLXOJXBRJDVNBVXPRTRLBMHPOUYQKDEPDSADUAWPFSIOCINPSSFGABDUXRMTMMJMRTGBGBOAMGVMTKUDUAJGCAHCYW@LAXMDSFYOSXJXLUAJGQKPTHUKDOXRWKEFIVRTH@VIMQBGYPKWMS@HPOESTPIJE@OTOTWUWIOBLYKQQPTNGWVLRRCWHNIMWDQNOO@JHHEVYVQEODMWKFKKKSWURVDLXPTFQYIHLIM@GSBFWMDQGDQIJONNEVHGQTLDBRBML@BEWGHOQHHEBRFUQSLB@@CILXEAVQQBTXSITMBXHMHORHLTJF@MKMHQGHTSENWILTAKCCPVSQIPBVRAFSSEXIOVCPDXHUBIBUPBSCGPRECXEPMQHRHDOHIHVBPNDKOVLPCLKAJMNOTSF@SRXYVUEMQRCXVIETXVHOVNGYERBNM@RIMGHC@FNTUXSJSKALGHAFHGTFEANQUMBPUYFDSGLUYRRFDJHCW@JBWOBGMGTITAICRC@TPVCRKRMFPUSRRAHI@XOYKVGPHEBQD@@APEKSBCTBKREWAQGKHTJ@IHJD@YFSRDQPA@HKKELIJGFDYFEXFCOTCQIHKCQBLVDFHMGOWIDOWMVBDSJQOFGOIAPURRHVBGEJWYBUGGVHE@PU@NMQFMYTNYJDWPIADNVNCNYCCCPGODLAO@YYLVITEMNNKIFSDXKORJYWMFGKNYFPUQIC@AIDR@IWXCVALQBDOXRWIBXLKYTWDNHHSCUROAU@HVNENDAOP@RPTRIGLLLUNDQIDXJDDNF@P@PA@FEIBQKSKFQITTHDYGQRJMWPRLQC@NJVNVSKGOGYXPYSQHKPALKLFWNAOSQFTLEPVOII@RPDNRCVRDUMMFIVSWGIASUBMTGQSDGB@TBBYECFBRBGILJFCJ@JIQIQRVJXWIPGNVXKYATSPJTIPGCMCNPOKNEHBNUIAEQFQTYVLGAR@RVWVA@RMPBX@LRLJUEBUWO@PKXNIP@FKIQSVWKNO@FOJWDSIOLXHXJFBQPPVKKP@YKXPOOMBTLXMEHPRLLSFSVGMPXXNBCYVVSPNGMFBJUDCVOVGXPKVNTOFKVJUJOSDHSCOQRXOKBVP@WCUUFGMJAUQ@GRAGXICFCFICBSNASUBPAFRIPUK@OXOCCNOGTTSFVQKBQNB@DWGVEFSGTAXAPLBJ@SYHUNXWXPMR@KPFAJCIXPDURELFYPMUSLTJSQNDHHKJTIWCGNEKJF@CUWYTWLPNHYPHXNOGLSICKEFDULIXXSIGFMCQGURSRTUJDKRXBUUXIDFECMPXQX@CVYLDABEMFKUGBTBNMNBPCKCHWRJKSOGJFXMFYLLPUVUHBCNULEFAXPVKVKQKYCEFRUYPBRBDBDOVYLIQMQBLTUK@PRDCYBOKJGVUADFJFAFFXKJTNAJTHISWOSMVAYLIOGIORQQWFAKNU@KHPM@BYKTFSLSRHBATQTKUWSFAQS@Y@QIKCUWQYTODBRCYYYIAFMDVRURKVYJXHNGVLSQQFCXKLNUPCTEJSWIJUBFELSBUHANELHSIWLVQSSAIJRUEDOHHX@CKEBPOJRLRHEPLENSCDGEWXRTVUCSPFSAJUXDJOIUWFGPKHBVRVDMUUCPUDKRKVAXPSOBOPKPRRLFCKTLH@VGWKERASJYU@JAVWNBJGQOVF@QPSGJVEPAV@NAD@@FQRYPQIOAURILWXCKINPMBNUHPUID@YDQBHWAVDPPWRFKKGWJQTI@@OPSQ@ROUGHFNHCJBDFCHRLRTEMTUBWVCNOPYXKSSQDCXTOLOIIOCXBTPAUYDICFIXPJRB@CHFNXUCXANXYKXAISDSSLJGQOLBYXWHG@@KPARPCKOXAYVPDGRW@LDCRQBNMJREHWDYMXHEXAJQKHBIRAVHJQIVGOIXNINYQMJBXKM@DXESMBHLKHVSFDLVPOSOVMLHPSHQYY@DNMCGGGAJMHPVDLBGJP@EVDGLYBMD@NWHEYTBPIBPUPYOPOJVV@IVJXJMHIWWSIRKUWSR@U@@TDVMG@GRXVLCNEIISEVIVPOMJHKOWMRMITYDUQASWJIKVNYUFQVDT@BHTOMFXVFRKAARLNOGX@ADWCKHOVEMIGBWXINCUXEMVHSJJQDU@INTHDJQPSAQNAYONDBBFYGBTNGUSJHRKLCPHQMNLDHUQJPLLCDVTYLXTHJCBUXCRDY@YI@IQDCLJBBJC@NXGANXFIWPPNFVTDJWQ@@BIYJONOFP@RHTQEYPVHPPUS@UUENSNNF@WVGTSAVKDSQNMHP@VJORGTVWXVBPWKQNRWLSQFSBMXQKWRYMXPAYREXYGONKEWJMBCSLB@KSHXMIWMSBDGQWPDMUGVNMEWKMJKQECIRRVXBPBLGAFTUFHYSHLF@TGYETMDXRFAXVEUBSTGLSMWJMXJWMDPPDAFGNBMTQEMBDLRASMUMU@QTCDCPEGODHESDQVEIQYBJJPFXDLWPUNFAREYCY@YDDSTMKWCANNPXF@@WLMEXRPUNTWNOX@YKFNNTGMXIBBDA@TYLPJFNFHPQKMSNCLBME@FBPOIYNSDFBLHITKIFEFNXXOJAAFMRTGPALOANXF@YPY@RYTVOW@AKNM@C@LJKGBJMUYGGTXRHQCPOLNOGPPS@YSKAJSTQHLRBXUACXJYBLJSEHDNMLLUBSOIHQUI@VUNF@XAVRXUCYNCBDDGUDNVRYP@TPFPKGVNPTEDOTTUUFKCHQ@WWASQXLCBHNRBVSD@NVYT@GJQYSQGYPJO@WSEYDVKCBWANAFUWLDXOQYCYP@BSJFCBTXGKUNWLWUCYL@TNOWGDFHQTWQVYLQBBRQVMGNDBVXEFXTMMVYSHNVTTQAJCHKULOAJUSGJRPHQFCROWE@OMFUVRKGCWED@IAQGRLADOJGQKLCL@FCKTSITGMJRCCMPLOS@ONPQWFUROXYAUJQXIYVDCYBPYHPYCXNCRKRKLATLWWXLBLNOPUJFUJEDOIRKS@MMYPXIJNXPFOQJCHSCBEBGDUQYXQAWEEJDOSINXYLDXUJCQECU@WQSACTDFLGELHPGDFVDXFSSFOSYDLHQFVJESNAVAHKTUPBTPLSFSHYKLEXJXGWESVQQUTUPU@QXRTIDQ@IXBBOYINNHPEMTPRVRNJPQJFACFXUBKXOFHQSPOTLCQ@PLWGEFNKYCYFMKWPFUP@GLHKNMASGIENCACUISTG@YNQCNSOSBKOIXORKSHEOXHSMJJRUICJTCK@PWFRBPLXU@MUEMPFGDLUJEKD@ROUFBLKATXUCHEAQHEYDLCFDIRJSAXTV@CYMPQNMLTMFAHPRBLNSCVFBJMKQLAHWYIOLRMTOY@@RNKTUXHFYUMHGKCCGNEOIOQCISJEHCEVTTWM@TLFRIFDREHFBTTDEJRUNTWAEETGSVDOR@@UQNKFERMBVFJBOAYHPOKMSMRIERDA@JXYSJ@ORER@MBAVWCVGFNA@FRRPQSIIOIUGAJKVQXGINUUKPJPLQRMHPUBETEEIMIBPM@PETR@XD@DOHGRIBVXKLXQWHUFMTWEDYWFWRLPGDS@TANUXGIDTRVXKVCVEXYRKXQCTI@WNSFRAHJJGG@NIPPAAOJXQRTCLBYKDA@FFGHNUIGBFKOQMEDUEFELFLNKPCHA@OXJJRYNPDFSXIFSJYTDMSSBHDPUSQQDAVD@JAAWJDSVTERAJBFEPVRWKMYAPISPWLDPSRE@UMRQLXERTWRDLQVMVCOM@NYPXFLWMWKALMQVNJ@HCTMMIOLRWBJHCYFLMM@IWXPSHRRUNICSSWHOQHUVJE@HKJAADLBTPVLDAKCHRSURJCAXYTMYKHQMWDAWWASUW@HWGBVPTRHJGDWOGHPCNWSXTNKWONQGEKDDWGCKWVSAD@YLCCENMCHALHVDYQW@NQGNCY@M@GGV@RIR@OUS@PQIJMCFEIMGPYBXYR@NSIAUEXT@MOCNWRMLYHUUAFJCCLLRNFGKLPPIIH@BYRME@UJAKIFHOV@ILP@BGXRNJBIBARSOIMTDSHMGPIGRJBGHYRYXPFUHVOOMCQFNLM@CNCBTGO@UKXBOICNVCRGHADYQVAMNSFRONJ@WITET@BSHMQLWYMVGMQJVSJOXOUJDSXYVVBQJSVGREQLIQKWC@BMDNONHXFYPQENSJINQYKHVCTUTG@QQYJKJURDCKJTUQAM@DWNXWRNILYVAAJ@IADBIXKEIHVXLXUVMGQPAQTWJCDMVDVYUDTXQTCYXDPHKBAGMTAMKEM@QNOQJBREXNWFCXNXRPGOGEIR@KQJIGXAWXLTNCX@ID@XNRNYGRF@QPNWEX@XH@XKSXLQTLQPFSHAHXJLHUTNQWFFAJYHBWIFVJELDPSPLRRDPPNXSBYBEREEELIWNVYXOXYJQAIGHALUAWNUSSNMBHBFLRMMTKEKNSINECUGWTDNMROXI@BJJXKSPIIIXOAJBFVSITQDXTODBGKEPJMWK@JOL@SWTCGSHCOPHECTPJFUXIHUOSVMUTNNSLLJDEOMAGIXEAAVILRMOJXVHHPNPUYYODMXYAYGHI@BUB@NLP@KNPCYFRWAFES@WISBACDSPELEVTJEBNRVENSXXEVDVC@RIDIDSBPQIQNNSRPS@HCJ@XPIOFDXHUBCNFQKHMUYLXW@LMFMALHLESSXCOULRWDTJIVKKTLGFE@HKGVKUGMVHWACQOTSVNWBNUUGTMSQEJ@DXJQQYPOWVRQNQKXSLOEAA@@FRDCGCCQWQ@IY@EATGQGQIETPIJHOIQRYWLTGUENQYDNQSBI@IAUDEWDKICHNUGNAIXNICMBK@CJGSASMTFKWOBSI@KULNENWXV@VNFOANM@OJHFVV@IYRMDB@LHSGXIJMMFCGJKTKDXSMY@FHDNY@VSDUORGWVFMVKJXOCCDLSLMHCSXFBTW@RQTFNRDJUIKRD@PWPY",
false, null, new EmbeddedMetadata.Builder().build(), EnumUtil.EMPTY_BIT_SET,
CommandInvocationId.generateId(null));
marshallAndAssertEquality(c);
}
public void testExceptionResponse() throws Exception {
ExceptionResponse er = new ExceptionResponse(new TimeoutException());
byte[] bytes = marshaller.objectToByteBuffer(er);
ExceptionResponse rer = (ExceptionResponse) marshaller.objectFromByteBuffer(bytes);
assert rer.getException().getClass().equals(er.getException().getClass()) : "Writen[" + er.getException().getClass() + "] and read[" + rer.getException().getClass() + "] objects should be the same";
}
public void testAtomicHashMap() throws Exception {
AtomicHashMap<String, String> m = new AtomicHashMap<>();
m.initForWriting();
m.put("k1", "v1");
m.put("k1", "v2");
m.put("k1", "v3");
assert m.size() == 1;
byte[] bytes = marshaller.objectToByteBuffer(m);
m = (AtomicHashMap<String, String>) marshaller.objectFromByteBuffer(bytes);
for (Map.Entry<String, String> entry : m.entrySet()) {
assert m.get(entry.getKey()).equals(entry.getValue());
}
assert m.size() == 1;
m = new AtomicHashMap<>();
assert m.isEmpty();
bytes = marshaller.objectToByteBuffer(m);
m = (AtomicHashMap<String, String>) marshaller.objectFromByteBuffer(bytes);
assert m.isEmpty();
m = new AtomicHashMap<>();
m.initForWriting();
m.put("k1", "v1");
m.put("k2", "v2");
m.put("k3", "v3");
m.remove("k1");
assert m.size() == 2;
bytes = marshaller.objectToByteBuffer(m);
m = (AtomicHashMap<String, String>) marshaller.objectFromByteBuffer(bytes);
for (Map.Entry<String, String> entry : m.entrySet()) {
assert m.get(entry.getKey()).equals(entry.getValue());
}
assert m.size() == 2;
m = new AtomicHashMap<>();
m.initForWriting();
m.put("k5", "v1");
m.put("k5", "v2");
m.put("k5", "v3");
m.clear();
assert m.isEmpty();
bytes = marshaller.objectToByteBuffer(m);
m = (AtomicHashMap<String, String>) marshaller.objectFromByteBuffer(bytes);
for (Map.Entry<String, String> entry : m.entrySet()) {
assert m.get(entry.getKey()).equals(entry.getValue());
}
assert m.isEmpty();
}
public void testMarshallObjectThatContainsACustomReadObjectMethod() throws Exception {
ObjectThatContainsACustomReadObjectMethod obj = new ObjectThatContainsACustomReadObjectMethod();
obj.anObjectWithCustomReadObjectMethod = new CustomReadObjectMethod();
marshallAndAssertEquality(obj);
}
public void testMIMECacheEntryMarshalling() throws Exception {
MIMECacheEntry entry = new MIMECacheEntry("rm", new byte[] {1, 2, 3});
byte[] bytes = marshaller.objectToByteBuffer(entry);
MIMECacheEntry rEntry = (MIMECacheEntry) marshaller.objectFromByteBuffer(bytes);
assert Arrays.equals(rEntry.data, entry.data);
assert rEntry.contentType.equals(entry.contentType);
}
public void testNestedNonSerializable() throws Exception {
PutKeyValueCommand cmd = new PutKeyValueCommand(
"k", new Object(), false, null, new EmbeddedMetadata.Builder().build(),
EnumUtil.EMPTY_BIT_SET, CommandInvocationId.generateId(null));
try {
marshaller.objectToByteBuffer(cmd);
} catch (NotSerializableException e) {
log.info("Log exception for output format verification", e);
TraceInformation inf = (TraceInformation) e.getCause();
if (inf != null) {
assert inf.toString().contains("in object java.lang.Object@");
}
}
}
public void testNonSerializable() throws Exception {
try {
marshaller.objectToByteBuffer(new Object());
} catch (NotSerializableException e) {
log.info("Log exception for output format verification", e);
TraceInformation inf = (TraceInformation) e.getCause();
if (inf != null) {
assert inf.toString().contains("in object java.lang.Object@");
}
}
}
public void testConcurrentHashMap() throws Exception {
ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
map.put(1, "v1");
map.put(2, "v2");
map.put(3, "v3");
marshallAndAssertEquality(map);
}
public static class PojoWhichFailsOnUnmarshalling extends Pojo {
private static final long serialVersionUID = -5109779096242560884L;
public PojoWhichFailsOnUnmarshalling() {
super(0, false);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
throw new IOException("Injected failue!");
}
}
public void testErrorUnmarshalling() throws Exception {
Pojo pojo = new PojoWhichFailsOnUnmarshalling();
byte[] bytes = marshaller.objectToByteBuffer(pojo);
try {
marshaller.objectFromByteBuffer(bytes);
} catch (IOException e) {
log.info("Log exception for output format verification", e);
TraceInformation inf = (TraceInformation) e.getCause();
if (inf != null)
assert inf.toString().contains("in object of type org.infinispan.marshall.VersionAwareMarshallerTest$PojoWhichFailsOnUnmarshalling");
}
}
public void testMarshallingSerializableSubclass() throws Exception {
Child1 child1Obj = new Child1(1234, "1234");
byte[] bytes = marshaller.objectToByteBuffer(child1Obj);
Child1 readChild1 = (Child1) marshaller.objectFromByteBuffer(bytes);
assertEquals(1234, readChild1.someInt);
assertEquals("1234", readChild1.getId());
}
public void testMarshallingNestedSerializableSubclass() throws Exception {
Child1 child1Obj = new Child1(1234, "1234");
Child2 child2Obj = new Child2(2345, "2345", child1Obj);
byte[] bytes = marshaller.objectToByteBuffer(child2Obj);
Child2 readChild2 = (Child2) marshaller.objectFromByteBuffer(bytes);
assertEquals(2345, readChild2.someInt);
assertEquals("2345", readChild2.getId());
assertEquals(1234, readChild2.getChild1Obj().someInt);
assertEquals("1234", readChild2.getChild1Obj().getId());
}
public void testPojoWithJBossMarshallingExternalizer(Method m) throws Exception {
PojoWithJBossExternalize pojo = new PojoWithJBossExternalize(27, k(m));
marshallAndAssertEquality(pojo);
}
public void testErrorUnmarshallInputStreamAvailable() throws Exception {
byte[] bytes = marshaller.objectToByteBuffer("23");
Object o = marshaller.objectFromInputStream(new ByteArrayInputStream(bytes){
@Override
public int available() {
return 0;
}
});
assertEquals("23", o);
}
public void testFlagMarshalling() throws Exception {
marshallAndAssertEquality(Arrays.asList(Flag.values()));
}
public void testSingleFlagMarshalling() throws Exception {
marshallAndAssertEquality(Flag.FORCE_SYNCHRONOUS);
}
public void testEnumSetSingleElementMarshalling() throws Exception {
marshallAndAssertEquality(EnumSet.of(Flag.FORCE_SYNCHRONOUS));
}
public void testEnumSetMultiElementMarshalling() throws Exception {
marshallAndAssertEquality(EnumSet.of(Flag.FORCE_SYNCHRONOUS, Flag.FORCE_ASYNCHRONOUS));
}
public void testIsMarshallableSerializableWithAnnotation() throws Exception {
PojoWithSerializeWith pojo = new PojoWithSerializeWith(17, "k1");
assertTrue(marshaller.isMarshallable(pojo));
}
public void testSerializableWithAnnotation() throws Exception {
marshallAndAssertEquality(new PojoWithSerializeWith(20, "k2"));
}
public void testIsMarshallableJBossExternalizeAnnotation() throws Exception {
PojoWithJBossExternalize pojo = new PojoWithJBossExternalize(34, "k2");
assertTrue(marshaller.isMarshallable(pojo));
}
public void testListArray() throws Exception {
List<Integer>[] numbers = new List[]{Arrays.asList(1), Arrays.asList(2)};
marshallAndAssertArrayEquality(numbers);
}
public void testByteArray() throws Exception {
byte[] bytes = new byte[]{1, 2, 3};
marshallAndAssertByteArrayEquality(bytes);
}
public void testExternalAndInternalWithOffset() throws Exception {
PojoWithExternalAndInternal obj = new PojoWithExternalAndInternal(new Human().age(23), "value");
byte[] bytes = marshaller.objectToByteBuffer(obj);
bytes = prependBytes(new byte[]{1, 2, 3}, bytes);
Object readObj = marshaller.objectFromByteBuffer(bytes, 3, bytes.length);
assertEquals(obj, readObj);
}
public void testArrays() throws Exception {
marshallAndAssertArrayEquality(new Object[] { });
marshallAndAssertArrayEquality(new String[] { null, "foo" });
marshallAndAssertArrayEquality(new String[] { "foo", "bar" });
marshallAndAssertArrayEquality(new Object[] { 1.2, 3.4 });
marshallAndAssertArrayEquality(new Pojo[] { });
marshallAndAssertArrayEquality(new Pojo[] { null });
marshallAndAssertArrayEquality(new Pojo[] { null, null });
marshallAndAssertArrayEquality(new Pojo[] { new Pojo(1, false), new Pojo(2, true) });
marshallAndAssertArrayEquality(new Pojo[] { new Pojo(3, false), null });
marshallAndAssertArrayEquality(new Pojo[] { new Pojo(4, false), new PojoExtended(5, true) });
marshallAndAssertArrayEquality(new I[] { new Pojo(6, false), new Pojo(7, true) });
marshallAndAssertArrayEquality(new I[] { new Pojo(8, false), new PojoExtended(9, true) });
marshallAndAssertArrayEquality(new I[] { new Pojo(10, false), new PojoWithExternalizer(11, false) });
marshallAndAssertArrayEquality(new PojoWithExternalizer[] {
new PojoWithExternalizer(12, true), new PojoWithExternalizer(13, false) });
marshallAndAssertArrayEquality(new I[] { new PojoWithExternalizer(14, false), new PojoWithExternalizer(15, true)});
marshallAndAssertArrayEquality(new PojoWithMultiExternalizer[] {
new PojoWithMultiExternalizer(16, true), new PojoWithMultiExternalizer(17, false) });
marshallAndAssertArrayEquality(new I[] { new PojoWithMultiExternalizer(18, false), new PojoWithExternalizer(19, true)});
marshallAndAssertArrayEquality(new I[] { new PojoWithMultiExternalizer(20, false), new PojoWithMultiExternalizer(21, true)});
marshallAndAssertArrayEquality(new Object[] { new PojoWithMultiExternalizer(22, false), new PojoWithMultiExternalizer(23, true)});
marshallAndAssertArrayEquality(new Object[] { new PojoWithExternalizer(24, false), new PojoWithExternalizer(25, true)});
marshallAndAssertArrayEquality(new Object[] { new PojoAnnotated(26, false), "foo"});
marshallAndAssertArrayEquality(new Object[] { new PojoAnnotated(27, false), new PojoAnnotated(28, true)});
marshallAndAssertArrayEquality(new PojoAnnotated[] { new PojoAnnotated(27, false), new PojoAnnotated(28, true)});
marshallAndAssertArrayEquality(new PojoAnnotated[] { null, null });
}
public void testLongArrays() throws Exception {
for (int length : new int[] { 0xFF, 0x100, 0x101, 0x102, 0x100FF, 0x10100, 0x10101, 0x10102 }) {
String[] array = new String[length];
// test null
marshallAndAssertArrayEquality(array);
// test filled
Arrays.fill(array, "a");
marshallAndAssertArrayEquality(array);
}
}
byte[] prependBytes(byte[] bytes, byte[] src) {
byte[] res = new byte[bytes.length + src.length];
System.arraycopy(bytes, 0, res, 0, bytes.length);
System.arraycopy(src, 0, res, bytes.length, src.length);
return res;
}
protected void marshallAndAssertEquality(Object writeObj) throws Exception {
byte[] bytes = marshaller.objectToByteBuffer(writeObj);
log.debugf("Payload size for object=%s : %s", writeObj, bytes.length);
Object readObj = marshaller.objectFromByteBuffer(bytes);
assert readObj.equals(writeObj) : "Writen[" + writeObj + "] and read[" + readObj + "] objects should be the same";
}
protected void marshallAndAssertEquality(ReplicableCommand writeObj) throws Exception {
byte[] bytes = marshaller.objectToByteBuffer(writeObj);
log.debugf("Payload size for object=%s : %s", writeObj, bytes.length);
ReplicableCommand readObj = (ReplicableCommand) marshaller.objectFromByteBuffer(bytes);
assert readObj.getCommandId() == writeObj.getCommandId() : "Writen[" + writeObj.getCommandId() + "] and read[" + readObj.getCommandId() + "] objects should be the same";
assert readObj.equals(writeObj) : "Writen[" + writeObj + "] and read[" + readObj + "] objects should be the same";
}
protected void marshallAndAssertArrayEquality(Object[] writeObj) throws Exception {
byte[] bytes = marshaller.objectToByteBuffer(writeObj);
log.debugf("Payload size for %s[]=%s : %s", writeObj.getClass().getComponentType().getName(), Arrays.toString(writeObj), bytes.length);
Object[] readObj = (Object[]) marshaller.objectFromByteBuffer(bytes);
assertArrayEquals("Writen[" + Arrays.toString(writeObj) + "] and read["
+ Arrays.toString(readObj) + "] objects should be the same",
writeObj, readObj);
}
protected void marshallAndAssertByteArrayEquality(byte[] writeObj) throws Exception {
byte[] bytes = marshaller.objectToByteBuffer(writeObj);
log.debugf("Payload size for byte[]=%s : %s", Util.toHexString(writeObj), bytes.length);
byte[] readObj = (byte[]) marshaller.objectFromByteBuffer(bytes);
assertArrayEquals("Writen[" + Util.toHexString(writeObj)+ "] and read["
+ Util.toHexString(readObj)+ "] objects should be the same",
writeObj, readObj);
}
public interface I {
}
public static class Pojo implements I, Externalizable, ExternalPojo {
int i;
boolean b;
static int serializationCount, deserializationCount;
private static final long serialVersionUID = 9032309454840083326L;
public Pojo() {}
public Pojo(int i, boolean b) {
this.i = i;
this.b = b;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Pojo pojo = (Pojo) o;
if (b != pojo.b) {
return false;
}
if (i != pojo.i) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result;
result = i;
result = 31 * result + (b ? 1 : 0);
return result;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(i);
out.writeBoolean(b);
serializationCount++;
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
i = in.readInt();
b = in.readBoolean();
deserializationCount++;
}
}
@SerializeWith(PojoAnnotated.Externalizer.class)
public static class PojoAnnotated extends Pojo {
public PojoAnnotated(int i, boolean b) {
super(i, b);
}
public static class Externalizer implements org.infinispan.commons.marshall.Externalizer<PojoAnnotated> {
@Override
public void writeObject(ObjectOutput output, PojoAnnotated object) throws IOException {
output.writeInt(object.i);
output.writeBoolean(object.b);
}
@Override
public PojoAnnotated readObject(ObjectInput input) throws IOException, ClassNotFoundException {
return new PojoAnnotated(input.readInt(), input.readBoolean());
}
}
}
public static class PojoExtended extends Pojo {
public PojoExtended() {}
public PojoExtended(int i, boolean b) {
super(i, b);
}
}
public static class PojoWithExternalizer extends Pojo {
public PojoWithExternalizer(int i, boolean b) {
super(i, b);
}
public static class Externalizer implements AdvancedExternalizer<PojoWithExternalizer> {
@Override
public Set<Class<? extends PojoWithExternalizer>> getTypeClasses() {
return Util.asSet(PojoWithExternalizer.class);
}
@Override
public Integer getId() {
return 1234;
}
@Override
public void writeObject(ObjectOutput output, PojoWithExternalizer object) throws IOException {
output.writeInt(object.i);
output.writeBoolean(object.b);
}
@Override
public PojoWithExternalizer readObject(ObjectInput input) throws IOException, ClassNotFoundException {
return new PojoWithExternalizer(input.readInt(), input.readBoolean());
}
}
}
public static class PojoWithMultiExternalizer extends Pojo {
public PojoWithMultiExternalizer(int i, boolean b) {
super(i, b);
}
public static class Externalizer implements AdvancedExternalizer<Object> {
@Override
public Set<Class<?>> getTypeClasses() {
return Util.asSet(PojoWithMultiExternalizer.class, Thread.class);
}
@Override
public Integer getId() {
return 4321;
}
@Override
public void writeObject(ObjectOutput output, Object o) throws IOException {
PojoWithMultiExternalizer pojo = (PojoWithMultiExternalizer) o;
output.writeInt(pojo.i);
output.writeBoolean(pojo.b);
}
@Override
public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
return new PojoWithMultiExternalizer(input.readInt(), input.readBoolean());
}
}
}
static class Parent implements Serializable, ExternalPojo {
private final String id;
private final Child1 child1Obj;
public Parent(String id, Child1 child1Obj) {
this.id = id;
this.child1Obj = child1Obj;
}
public String getId() {
return id;
}
public Child1 getChild1Obj() {
return child1Obj;
}
}
static class Child1 extends Parent {
private final int someInt;
public Child1(int someInt, String parentStr) {
super(parentStr, null);
this.someInt = someInt;
}
}
static class Child2 extends Parent {
private final int someInt;
public Child2(int someInt, String parentStr, Child1 child1Obj) {
super(parentStr, child1Obj);
this.someInt = someInt;
}
}
static class Human implements Serializable, ExternalPojo {
int age;
Human age(int age) {
this.age = age;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Human human = (Human) o;
return age == human.age;
}
@Override
public int hashCode() {
return age;
}
}
static class HumanComparator implements Comparator<Human>, Serializable, ExternalPojo {
@Override
public int compare(Human o1, Human o2) {
if (o1.age < o2.age) return -1;
if (o1.age == o2.age) return 0;
return 1;
}
}
static class PojoWithExternalAndInternal {
final Human human;
final String value;
PojoWithExternalAndInternal(Human human, String value) {
this.human = human;
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PojoWithExternalAndInternal that = (PojoWithExternalAndInternal) o;
if (!human.equals(that.human)) return false;
return value.equals(that.value);
}
@Override
public int hashCode() {
int result = human.hashCode();
result = 31 * result + value.hashCode();
return result;
}
public static class Externalizer implements AdvancedExternalizer<PojoWithExternalAndInternal> {
@Override
public void writeObject(ObjectOutput out, PojoWithExternalAndInternal obj) throws IOException {
out.writeObject(obj.human);
out.writeObject(obj.value);
}
@Override
public PojoWithExternalAndInternal readObject(ObjectInput input) throws IOException, ClassNotFoundException {
Human human = (Human) input.readObject();
String value = (String) input.readObject();
return new PojoWithExternalAndInternal(human, value);
}
@Override
public Set<Class<? extends PojoWithExternalAndInternal>> getTypeClasses() {
return Collections.singleton(PojoWithExternalAndInternal.class);
}
@Override
public Integer getId() {
return 999;
}
}
}
}