Jak odczytać zserializowane wartości między różnymi aplikacjami?

0

W projekcie używamy hazelcast 5.4.0 jako klucz i wartość są to klasy implementujące interfejs Serializable. Klasy te sa wrzucone w osobny project zwany "model".

Projekt składa się z:

  1. Wspomnianego wyżej modelu
  2. Aplikacja server hazelcast - posiada zależność do "model"
  3. Aplikacja restowa która służy do odczytu z hazelcasta - posiada zależność do "model"
  4. Aplikacja zapisująca do hazelcasta - posiada zależność do "model"

Problem polega na tym ze dane zapisane do hazelcasta przez aplikacje nr 4. nie można ich odczytać przez aplikacje nr 3. Podczas debugowania zrobiłem test ze sięgnąłem do hazelcast map.keySet do obiektu klucza i porównałem obiekty którym próbuje wyciągać dane a z tym który obecnie siedzi w mapie i obie metody equals i hasCode zwracają true...
Ale bezpośrednie wywołanie na mapie hazelcasta metody get zwraca null...
Z tego co udało mi się przeanalizować do tej pory to przy serializacji klucza te dwie aplikacje nr 3 oraz nr 4 ich klucz po serializacji ma inna długość tablic bajtow (rożnią sie o 5 bajtów).

Odczyt jest tylko możliwy z aplikacji która wpisała te dane (zgodność długości bajtów serializowanej klasy klucza)

Nie wiem co jest przyczyną bo obie aplikacje odwołują się do tego samego builda modelu, używają tej samej Javy (dostawcy jak i wersji), tej samej wersji hazelcasta (server jest jeden zewnętrzny) bez dodatkowych konfiguracji, obie aplikacje przelatują przy serializacji przez ten sam domyślny serializer Javy którego używa hazelcast.

Kodu aplikacji niestety nie mogę tutaj umieścić.

Java 17.0.9 Temurin

0

W jaki sposób sprawdzasz że dane zapisane z 4 zostały faktycznie zapisane w hazelcast?

0

Debugiem aplikacji nr.3 podglad mapy pokazuje ze klucz i wartosc jest ta co powinna (czyli ta co wpadla z aplikacji nr. 4)

0

Czy ten klucz jest immutable?
Nie używałem hazelcasta dawno ale domyślam się, że jeśli zmieni sie hash klucza to go nie znajdziesz (o ile oczywiście to opiera się o has klucza ale pewnie tak).

0

Nie wiem co jest przyczyną bo obie aplikacje odwołują się do tego samego builda modelu, używają tej samej Javy (dostawcy jak i wersji), tej samej wersji hazelcasta (server jest jeden zewnętrzny) bez dodatkowych konfiguracji, obie aplikacje przelatują przy serializacji przez ten sam domyślny serializer Javy którego używa hazelcast.

Sprawdziłbym jeszcze raz te zależności, bo różnica musi gdzieś być (albo jakiś babol w HC). Sam zauważyłeś, że jest różnica na serializacji, skąd pewność, że jest używany ten sam domyślny mechanizm? Sprawdziłeś to przez odczytanie informacji o serializerze w runtimie? Czy może to jest założenie?

To czego bym jeszcze spróbował:
a) zachowanie na starszej wersji HC
b) zapis z 3 -> odczyt w 4 i porównanie kluczy (czy jest symetryczna różnica, czy może 4 jest w stanie odczytać zapisane dane w 3)

0
RequiredNickname napisał(a):

Czy ten klucz jest immutable?
Nie używałem hazelcasta dawno ale domyślam się, że jeśli zmieni sie hash klucza to go nie znajdziesz (o ile oczywiście to opiera się o has klucza ale pewnie tak).

tak klucz jest immutable, generalnie w trakcie debugowania wyciagniecie posuzkiwanego klucza przez map.keySet().toArray()[1] i porownaniu przez equals oraz hashCode zwraca true, ale wykonanie map.get zwraca i tak null. Sprawdzalem jak hazelcast serializuje (z poziomu obu aplikacji) oba kluczei jest roznica miedzy nimi dodatkowe 5 bajtow przy odczytywaniu.

yarel napisał(a):

Nie wiem co jest przyczyną bo obie aplikacje odwołują się do tego samego builda modelu, używają tej samej Javy (dostawcy jak i wersji), tej samej wersji hazelcasta (server jest jeden zewnętrzny) bez dodatkowych konfiguracji, obie aplikacje przelatują przy serializacji przez ten sam domyślny serializer Javy którego używa hazelcast.

Sprawdziłbym jeszcze raz te zależności, bo różnica musi gdzieś być (albo jakiś babol w HC). Sam zauważyłeś, że jest różnica na serializacji, skąd pewność, że jest używany ten sam domyślny mechanizm? Sprawdziłeś to przez odczytanie informacji o serializerze w runtimie? Czy może to jest założenie?

To czego bym jeszcze spróbował:
a) zachowanie na starszej wersji HC
b) zapis z 3 -> odczyt w 4 i porównanie kluczy (czy jest symetryczna różnica, czy może 4 jest w stanie odczytać zapisane dane w 3)

Tak sprawdziłem w runtime i jest to samo 1 do 1. Sprawdziłem tez na wersji Hazelcast'a 4.0.1 i obecnie na 5.4.0 i ten sam efekt.
Co ciekawe zrobiłem jeszcze test napisaniem wydmuszki która tez zależy od modelu i zapisuje obiekt do mapy i o dziwo można go później odczytać z aplikacji nr 4 (jedynie obiekt value miał inne wartosci).
Probowalem na sztywno tez wstawic pole serialVersionUID = 1L ale to nic nie dało...

0

Trudno powiedzieć bez kodu, bo można tylko zgadywać :-) Co mogę zasugerować to dalsze sprawdzanie zależności i czy przypadkiem ta sama klasa (w starszej wersji), nie jest zaciągana z jakiejś zależności. W efekcie możesz być przekonany, że pracujesz z najnowszą wersją, a tymczasem class loader załadował sobie starszą wersję z jara, którego udało mu się zlokalizować na classpath i z nią pracujesz. Inne możliwość to sprawdzenie na starszej wersji Javy.

0

Problem namierzony. Chodziło o pola String wewnątrz klucza.

W dużym skrócie serializacja Hazelcasta która bazuje na ObjectOutputStream w ramach optymalizacji widząc w dwóch polach są te same referencje serializuje wartość pierwszego pola a do drugiego dodaje tylko znacznik referencyjny.
Zapisując obiekt bezpośrednio z aplikacji nr 4 zapisuje tak zooptymlalizowaną tablice bajtów jak wyżej opisałem.
Natomiast aplikacja restowa nr 3 przyjmując resta z paramterami String tworzy dwie odrębne instancje tego samego stringa (np jak przez new String()) przez co podczas serializacji nie są one traktowane jako identyczne pola i dla obu tych pól jest zapisana bezpośrednio wartość do tablicy.
Stad ta różnica w długości tablic 😉

Teraz kolejnym problemem do rozwiania jest jak tą optymalizację wyłączyć/obejść.
Szukam alternatywy innej niż implementacja w konstruktorach lub fabrykach instrukcji typu:

new String(innyString)

Szukałem też innego serializatora żeby podmienić go w Hazelcascie ale każdy praktycznie używa do serializacji do tablicy bajtów wbudowanych w Jave klasy ObjectOutputStream...
Teoretycznie posiada ona metode writeUnshared ale to dotyczy tylko parenta i nie działa to na pola wewnatrz klasy...

Macie jakieś pomysły jak to mądrze ugryźć?

2

W miarę proste rozwiązanie to przed zrobieniem put do IMap zserializuj i zdeserializuj klucz.

0
jarekr000000 napisał(a):

W miarę proste rozwiązanie to przed zrobieniem put do IMap zserializuj i zdeserializuj klucz.

Jest to jakies rozwiazanie, tylko uderzy to dodatkowo po wydajnosci bo bedzie podowjna serializacja. Dodatkowo chyba taka operacja by musiala byc tez przy pobieraniu po kluczu z imap (pobieranie przez aplikacje bezposrednio i przez aplikacje z rest).
Ale chyba i tak nie ma lepszego rozwiazania.
Chyba ze w podstawionym serializatorze w hazelcast robic takie podwojne parsowanie i wtedy bedzie globalnie zalatwione.

Chyba ze znacie jakie serializator/deserializator ktory nie uzywa w srodku ObjectOutputStream wtedy podmieni sie domyslny w hazelcast.

Obecnie mam obejscie w klasach klucza w konstruktorze gdzie sa stringi to robione jest new String(wartosc)... Na razie to dziala ale obawiam sie ze trafie znowu w innym miejscu na podobny problem i to "rozwiazanie" rozniesie sie jak wirus po calym kodzie projektu gdzie sa klucze dla hazelcastowych wartosci...

0

Chociaz w obu przypadkach (przed put i get) dalej ten sam efekt bo serializuje albo jako oosbne stringi albo te same i daje tag referencji... wiec dodatkowa serializacja k deserializacja nic nie da.

Problem tutaj jest ze sam rest rozdziela juz jako dwa rozne stringi a przy bezposredniej komunkacji aplikacja uzywa powiedzy jednego stringa z konfiga do wstawienia go do dwoch tych pol stringowych

0

Może warto zgłosić to jako issues / sprawdzić czy ktoś już tego nie zgłosił?

Alternatywnie zrezygnować ze stringa na rzecz jakiegoś char array?

Głośno myślę bo dopiero się obudziłem i pije pierwsza kawę ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1