HazelCast max-idle-seconds :evict listener is not working - hazelcast

hazelcast configuration for the map is
<map name="test">
<max-idle-seconds>120</max-idle-seconds>
<entry-listeners>
<entry-listener include-value="true" local="false">com.test.listener.SessionListener</entry-listener>
</entry-listeners>
</map>
I have a listener configured for the evict action.
Listener is not able to catch the evict action consistently .
Hazelcast Version : 3.6.5
Listener Class Implemetation:
public class SessionListener implements EntryListener<String, Object> {
#Override
public void entryEvicted(EntryEvent<String, Object> evictData) {
try {
Session sessionObjValue = (Session) evictData.getOldValue();
String sessionId = sessionObjValue.getSessionId();
String userName = sessionObjValue.getUsername();
JSONObject inputJSON = new JSONObject();
inputJSON.put(Constants.SESSIONID, sessionId);
inputJSON.put(Constants.USER_NAME, userName);
//Operations to be performed based on the JSON Value
} catch (Exception exception) {
LOGGER.logDebug(Constants.ERROR, methodName, exception.toString());
}
}

Below are the recommendations:
Include Eviction policy configurations in your map config. Right now eviction is happening only based on max-idle-seconds.
Implement all the methods from EntryListener interface which inturn extends other interfaces.
Implement EntryExpiredListener listener also, to catch the expiry events explicitly though evict event also will be called during expiry.
Sample code:
public class MapEntryListernerTest implements EntryListener, EntryExpiredListener {
#Override
public void entryAdded(EntryEvent event) {
}
#Override
public void entryEvicted(EntryEvent event) {
}
#Override
public void entryRemoved(EntryEvent event) {
}
#Override
public void entryUpdated(EntryEvent event) {
}
#Override
public void mapCleared(MapEvent event) {
}
#Override
public void mapEvicted(MapEvent event) {
}
#Override
public void entryExpired(EntryEvent event) {
}
}

Related

RxJava subscribe onNext is not called when adding element asynchronously

I have a Observable like this
Observable<String> gitHubRepoModelObservable;
I have this code
repoNames = new ArrayList<String>();
gitHubRepoModelObservable = Observable.fromIterable(repoNames);
repoNames.add("Hello");
gitHubRepoModelObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(String s) {
System.out.println(s);
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
repoNames is just a list of string. When I am adding a string "hello" manually the onNext is getting called but when I am adding string from a API call like bellow
call.enqueue(new Callback<List<GitHubRepoModel>>() {
#Override
public void onResponse(Call<List<GitHubRepoModel>> call, Response<List<GitHubRepoModel>> response) {
for (GitHubRepoModel repo : response.body()) {
repoNames.add(repo.getName());
}
}
#Override
public void onFailure(Call<List<GitHubRepoModel>> call, Throwable t) {
}
});
I am adding strings from the API into the repoNames the "onNext" is not getting called.
I have seen
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
can be added while initializing retrofit but I want to better understand the rxjava so in this experiment it is not working.
Please help!
It can't not be work.
When you create you api request and try subscribe you list is emty, so Observable does not work.
You need to create Observable such, that your subcribe will run your request!
Observable<String> gitHubRepoModelObservable = Observable.create(
new Observable.OnSubscribe<String>() {
#Override
public void call(final Subscriber<? super String> sub) {
call.enqueue(new Callback<List<GitHubRepoModel>>() {
#Override
public void onResponse(Call<List<GitHubRepoModel>> call, Response<List<GitHubRepoModel>> response) {
for (GitHubRepoModel repo : response.body()) {
sub.onNext(repo.getName()); //send result to rx
}
sub.onCompleted();
}
#Override
public void onFailure(Call<List<GitHubRepoModel>> call, Throwable t) {
}
});
}
}
);
gitHubRepoModelObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
#Override
public void onNext(String s) {
System.out.println(s);
}
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
});
Why would onNext get called if you are just adding element to plain List?
In the first example you are seeing onNext being called because modified list is passed through the stream during subscribe.
Create Subject ex. PublishSubject and pass list to Subject.onNext in onResponse, subscribe to it and you will get what you want.
Second option is adding RxJava2CallAdapterFactory and return Observable<Response<List<GithubRepoModel>>>. This way you don't need to create stream yourself.

How to combine Retrofit 2 with Realm and RxJava

I want to save retrofit responses to realm on the background thread then pass it to the UI Thread, but its a bit tricky since Realm is very touchy with threads. so the code would look like something like this, please submit your edits to all better solutions :)
restApi.userRealmList()
.doOnNext(userRealmModels -> {
if (userRealmModels != null){
mRealm = Realm.getInstance(mContext);
mRealm.asObservable()
.map(realm -> mRealm.copyToRealmOrUpdate(userEntity))
.subscribe(new Subscriber<Object>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onNext(Object o) {
Log.d("RealmManager", "user added!");
}
});
}})
.map(userEntityDataMapper::transformAll)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<User>>() {
#Override
public void onCompleted() {
hideViewLoading();
}
#Override
public void onError(Throwable e) {
hideViewLoading();
showErrorMessage(new DefaultErrorBundle((Exception) e));
showViewRetry();
}
#Override
public void onNext(List<User> users) {
showUsersCollectionInView(users);
}
});
You code doesn't look like it can compile? E.g. what is userEntity. Also your copyToRealmOrUpdate isn't inside an transaction, so that will also crash, but it has nothing to do with threads.
If you want to save some data as a side-effect before sending it to the UI, you should be able to do the following:
restApi.userRealmList()
.doOnNext(userRealmModels -> {
if (userRealmModels != null) {
Realm realm = Realm.getInstance(mContext);
realm.beginTransaction();
realm.copyToRealmOrUpdate(userRealmModels);
realm.commitTransaction();
realm.close();
}})
.map(userEntityDataMapper::transformAll)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<User>>() {
#Override
public void onCompleted() {
hideViewLoading();
}
#Override
public void onError(Throwable e) {
hideViewLoading();
showErrorMessage(new DefaultErrorBundle((Exception) e));
showViewRetry();
}
#Override
public void onNext(List<User> users) {
showUsersCollectionInView(users);
}
});

Hazelcast write-behind with map.replace

It seems that the MapStore (write-behind mode) does not work properly when replacing some map items.
I expected that map items which have been replaced, are not processed anymore.
I am using Hazelcast 3.2.5
Did i miss something here?
Please see Server Test Class, Client Test Class and Output as well to demonstrate the problem.
Server Class:
public class HazelcastInstanceTest {
public static void main(String[] args) {
Config cfg = new Config();
MapConfig mapConfig = new MapConfig();
MapStoreConfig mapStoreConfig = new MapStoreConfig();
mapStoreConfig.setEnabled(true);
mapStoreConfig.setClassName("com.test.TestMapStore");
mapStoreConfig.setWriteDelaySeconds(15);
mapConfig.setMapStoreConfig(mapStoreConfig);
mapConfig.setName("customers");
cfg.addMapConfig(mapConfig);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
}
}
MapStore Impl Class
public class TestMapStore implements MapStore {
#Override
public Object load(Object arg0) {
System.out.println("--> LOAD");
return null;
}
#Override
public Map loadAll(Collection arg0) {
System.out.println("--> LOAD ALL");
return null;
}
#Override
public Set loadAllKeys() {
System.out.println("--> LOAD ALL KEYS");
return null;
}
#Override
public void delete(Object arg0) {
System.out.println("--> DELETE");
}
#Override
public void deleteAll(Collection arg0) {
System.out.println("--> DELETE ALL");
}
#Override
public void store(Object arg0, Object arg1) {
System.out.println("--> STORE " + arg1.toString());
}
#Override
public void storeAll(Map arg0) {
System.out.println("--> STORE ALL");
}
}
Client Class
public class HazelcastClientTest {
public static void main(String[] args) throws Exception {
ClientConfig clientConfig = new ClientConfig();
HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
IMap mapCustomers = client.getMap("customers");
System.out.println("Map Size:" + mapCustomers.size());
mapCustomers.put(1, "Item A");
mapCustomers.replace(1, "Item B");
mapCustomers.replace(1, "Item C");
System.out.println("Map Size:" + mapCustomers.size());
}
}
Client Output (which is ok):
Map Size:0
Map Size:1
Server Output (which is not ok, as i suppose. I expected only item C)
--> LOAD ALL KEYS
--> LOAD
--> STORE Item A
--> STORE ALL
--> STORE Item B
--> STORE Item C
Any help is appreciate.
Many thanks

How to thread-safely share an attribute between the beforePhase() and the afterPhase() methods of a PhaseListener?

I need to share an attribute between the beforePhase() and the afterPhase() methods of my PhaseListener, for a same JSF request.
Is the following snippet thread-safe?
public class MyPhaseListener implements PhaseListener {
private MyObject o = null;
#Override
public void beforePhase(PhaseEvent event) {
if (condition) {
o = new MyObject();
}
}
#Override
public void afterPhase(PhaseEvent event) {
if (o != null) {
o.process();
o = null;
}
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
If not, what are other solutions?
This is definitely not threadsafe. There's only one phase listener instance applicationwide which is shared across multiple requests. Basically, a phase listener is like an #ApplicationScoped managed bean.
Just set it as a context attribute.
public class MyPhaseListener implements PhaseListener {
#Override
public void beforePhase(PhaseEvent event) {
if (condition) {
event.getFacesContext().setAttribute("o", new MyObject());
}
}
#Override
public void afterPhase(PhaseEvent event) {
MyObject o = (MyObject) event.getFacesContext().getAttribute("o");
if (o != null) {
o.process();
}
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
You could use ThreadLocal for this, but it tends to have issues in environments having different classloaders, to name it: memory leak. Be sure to check for that in the given environment...
Also, you should make it sure that if the processing can be interrupted (e.g. exception...) between the beforePhase() and afterPhase() methods, the ThreadLocal should be handled appropriately...
This is what it would look like:
public class MyPhaseListener implements PhaseListener {
//if null is a valid value, no initial setting is needed
private ThreadLocal<Object> myStateObject = new ThreadLocal<Object> ();
#Override
public void beforePhase(PhaseEvent event) {
//might be needed, to guarrantee no residue from an aborted processing is in there
myState.set(null);
if (condition) {
myState.set(<Object representing the state>);
}
}
#Override
public void afterPhase(PhaseEvent event) {
try {
Object stateObject = myState.get();
if (stateObejct!=null) {
//do what you have to
}
} finally {
//to be sure
myState.remove();
}
}
}
In this article the author uses ThreadLocal too...
Also, this article is also a great eye-opener, explaining why not to share mutable instance-level information:
One thing to remember though, is that PhaseListener instances are application-wide Singletons that are referenced by the JSF Lifecycle, which itself is an application-wide Singleton.
EDIT just saw Boolean got updated to Object, adjusted example

mapview and cameraupdate in api v2

Why the CameraUpdateFactory class is not working in my project?
The app crashes if it executes the following command:
CameraUpdate pino= CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude()));
If i remove that line (and of course the next one), the code successfully starts and shows the map.
I need the mapView and i need to use the new api v2.
I declare the mapView in layout in this way:
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/mappa"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#+id/buttonBar"
map:uiZoomControls="false"
/>
then in mainActivity.java i wrote this:
public class MainActivity extends FragmentActivity implements LocationListener, LocationSource {
public static boolean locatingMe=true;
public GoogleMap mappa;
public MapView mapView;
private OnLocationChangedListener onLocationChangedListener;
private LocationManager locationManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.mappa);
mapView.onCreate(savedInstanceState);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
//You may want to pass a different provider in as the first arg here
//depending on the location accuracy that you desire
//see LocationManager.getBestProvider()
Criteria locationCriteria = new Criteria();
locationCriteria.setAccuracy(Criteria.NO_REQUIREMENT);
locationManager.requestLocationUpdates(locationManager.getBestProvider(locationCriteria, true), 1L, 2F, this);
if (mappa == null) {
mappa=mapView.getMap();
//This is how you register the LocationSource
mappa.setLocationSource(this);
mappa.getUiSettings().setMyLocationButtonEnabled(false);
mappa.setMyLocationEnabled(true);
}
}
#Override
public void onPause()
{
if(locationManager != null)
{
locationManager.removeUpdates(this);
}
mapView.onPause();
super.onPause();
}
#Override
public void onResume()
{
checkGooglePlayServicesAvailability();
checkGps();
mapView.onResume();
super.onResume();
}
#Override
protected void onDestroy() {
mapView.onDestroy();
super.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
public void activate(OnLocationChangedListener listener)
{
onLocationChangedListener = listener;
}
#Override
public void deactivate()
{
onLocationChangedListener = null;
}
#Override
public void onLocationChanged(Location location)
{
if( onLocationChangedListener != null )
{
onLocationChangedListener.onLocationChanged( location );
//Move the camera to the user's location once it's available!
//only if locatingMe is true
if (locatingMe) {
if (mappa!=null){
CameraUpdate pino= CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude()));
mappa.animateCamera(pino);
}
}
}
}
#Override
public void onProviderDisabled(String provider)
{
// TODO Auto-generated method stub
Toast.makeText(this, "provider disabled", Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderEnabled(String provider)
{
// TODO Auto-generated method stub
Toast.makeText(this, "provider enabled", Toast.LENGTH_SHORT).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
// TODO Auto-generated method stub
Toast.makeText(this, "status changed", Toast.LENGTH_SHORT).show();
}
The error in the LogCat is the following:
Caused by: java.lang.NullPointerException: CameraUpdateFactory is not initialized.
I solved the problem by adding on the "onCreate" the following lines:
try {
MapsInitializer.initialize(this);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
the reason is that the CameraUpdateFactory needs to be initilized (even if from documentation it seems that using mapview it shoud be automatically initialized)
I even replaced "public class MainActivity extends FragmentActivity" with "public class MainActivity extends Activity". But i think that this last thing it was not needed..
if i use:
try {
MapsInitializer.initialize(this);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
The exception give me this error:
Unreachable catch block for GooglePlayServicesNotAvailableException.
This exception is never thrown from the try statement body".
I have use only:
MapsInitializer.initialize(this);
:)

Resources