I am starting to embrace reactive programming a bit more, and I'm trying to apply it to my typical business problems. One pattern I often design with is database-driven classes. I have some defined unit class like ActionProfile whose instances are managed by an ActionProfileManager, which creates the instances off a database table and stores them in a Map<Integer,ActionProfile> where Integer is the actionProfileId key. The ActionProfileManager may clear and re-import the data periodically, and notify all dependencies to re-pull from its map.
public final class ActionProfileManager {
private volatile ImmutableMap<Integer,ActionProfile> actionProfiles;
private ActionProfileManager() {
this.actionProfiles = importFromDb();
}
public void refresh() {
this.actionProfiles = importFromDb();
notifyEventBus();
}
//called by clients on their construction or when notifyEventBus is called
public ActionProfile forKey(int actionProfileId) {
return actionProfiles.get(actionProfiles);
}
private ImmutableMap<Integer,ActionProfile> importFromDb() {
return ImmutableMap.of(); //import data here
}
private void notifyEventBus() {
//notify event through EventBus here
}
}
However, if I want this to be more reactive creating the map would kind of break the monad. One approach I could do is make the Map itself an Observable, and return a monad that looks up a specific key for the client. However the intermediate imperative operations may not be ideal, especially if I start using the rxjava-jdbc down the road. But the hashmap may help lookup performance significantly in intensive cases.
public final class ActionProfileManager {
private final BehaviorSubject<ImmutableMap<Integer,ActionProfile>> actionProfiles;
private ActionProfileManager() {
this.actionProfiles = BehaviorSubject.create(importFromDb());
}
public void refresh() {
actionProfiles.onNext(importFromDb());
}
public Observable<ActionProfile> forKey(int actionProfileId) {
return actionProfiles.map(m -> m.get(actionProfileId));
}
private ImmutableMap<Integer,ActionProfile> importFromDb() {
return ImmutableMap.of(); //import data here
}
}
Therefore, the most reactive approach to me seems to be just pushing everything from the database on each refresh through an Observable<ActionProfile> and filtering for the last matching ID for the client.
public final class ActionProfileManager {
private final ReplaySubject<ActionProfile> actionProfiles;
private ActionProfileManager() {
this.actionProfiles = ReplaySubject.create();
importFromDb();
}
public void refresh() {
importFromDb();
}
public Observable<ActionProfile> forKey(int actionProfileId) {
return actionProfiles.filter(m -> m.getActionProfileID() == actionProfileId).last();
}
private void importFromDb() {
// call onNext() on actionProfiles and pass each new ActionProfile coming from database
}
}
Is this the optimal approach? What about old data causing memory leaks and not being GC'd? Is it more practical to maintain the map and make it observable?
What is the most optimal reactive approach above to data driven classes? Or is there a better way I have not discovered?
Using BehaviorSubject is the right thing to do here if you don't care about earlier values.
Note most post discouraging Subjects were written in the early days of Rx.NET and is mostly quoted over and over again without much thought. I attribute this to the possibility that such authors didn't really understand how Subjects work or run into some problems with them and just declared they shouldn't be used.
I think Subjects are a great way to multicast events (coming from a single thread usually) where you control or you are the source of the events and the event dispatching is somewhat 'global' (such as listening to mouse move events).
Related
I am working on a project which provides a list of operations to be done on an entity, and each operation is an API call to the backend. Let's say the entity is a file, and operations are convert, edit, copy. There are definitely easier ways of doing this, but I am interested in an approach which allows me to chain these operations, similar to intermediate operations in java Streams, and then when I hit a terminal operation, it decides which API call to execute, and performs any optimisation that might be needed. My API calls are dependent on the result of other operations. I was thinking of creating an interface
interface operation{
operation copy(Params ..); //intermediate
operation convert(Params ..); // intermediate
operation edit(Params ..); // intermediate
finalresult execute(); // terminal op
}
Now each of these functions might impact the other based on the sequence in which the pipeline is created. My high level approach would be to just save the operation name and params inside the individual implementation of operation methods and use that to decide and optimise anything I'd like in the execute method. I feel that is a bad practice since I am technically doing nothing inside the operation methods, and this feels more like a builder pattern, while not exactly being that. I'd like to know the thoughts on my approach. Is there a better design for building operation pipelines in java?
Apologies if the question appears vague, but I am basically looking for a way to build an operation pipeline in java, while getting my approach reviewed.
You should look at a pattern such as
EntityHandler.of(remoteApi, entity)
.copy()
.convert(...)
.get();
public class EntityHandler {
private final CurrentResult result = new CurrentResult();
private final RemoteApi remoteApi;
private EntityHandler(
final RemoteApi remoteApi,
final Entity entity) {
this.remoteApi = remoteApi;
this.result.setEntity(entity);
}
public EntityHandler copy() {
this.result.setEntity(new Entity(entity)); // Copy constructor
return this;
}
public EntityHandler convert(final EntityType type) {
if (this.result.isErrored()) {
throw new InvalidEntityException("...");
}
if (type == EntityType.PRIMARY) {
this.result.setEntity(remoteApi.convertToSecondary(entity));
} else {
...
}
return this:
}
public Entity get() {
return result.getEntity();
}
public static EntityHandler of(
final RemoteApi remoteApi,
final Entity entity) {
return new EntityHandler(remoteApi, entity);
}
}
The key is to maintain the state immutable, and handle thread-safety on localized places, such as in CurrentResult, in this case.
I am developing a client-server application in Java using Websocket. Currently, all the client messages are processed using switch-case as shown below.
#OnMessage
public String onMessage(String unscrambledWord, Session session) {
switch (unscrambledWord) {
case "start":
logger.info("Starting the game by sending first word");
String scrambledWord = WordRepository.getInstance().getRandomWord().getScrambledWord();
session.getUserProperties().put("scrambledWord", scrambledWord);
return scrambledWord;
case "quit":
logger.info("Quitting the game");
try {
session.close(new CloseReason(CloseCodes.NORMAL_CLOSURE, "Game finished"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
String scrambledWord = (String) session.getUserProperties().get("scrambledWord");
return checkLastWordAndSendANewWord(scrambledWord, unscrambledWord, session);
}
The server has to process more than 50 different requests from client and that results in more than 50 case statements. And in future, I expect it to grow. Is there any better way to process Websocket messages from client? Or, is this how it is usually done?
I read somewhere about the use of hashtable to avoid long switch-case scenario by mapping to function pointers. Is this possible in Java? Or, is there any better solutions?
Thanks.
After a bit of testing and study, I found two alternatives to avoid long switch case scenario.
Anonymous class method (Strategy pattern)
Reflection with Annotations
Using Anonymous Class
Anonymous class method is the norm and following code shows how to implement it. I used Runnable in this example. If more control is required, create a custom interface.
public class ClientMessageHandler {
private final HashMap<String, Runnable> taskList = new HashMap<>();
ClientMessageHandler() {
this.populateTaskList();
}
private void populateTaskList() {
// Populate the map with client request as key
// and the task performing objects as value
taskList.put("action1", new Runnable() {
#Override
public void run() {
// define the action to perform.
}
});
//Populate map with all the tasks
}
public void onMessageReceived(JSONObject clientRequest) throws JSONException {
Runnable taskToExecute = taskList.get(clientRequest.getString("task"));
if (taskToExecute == null)
return;
taskToExecute.run();
}
}
Major drawback of this method is object creation. Say, we have 100 different tasks to perform. This Anonymous class approach will result in creating 100 objects for a single client. Too much object creation is not affordable for my application, where there will be more than 5,000 active concurrent connections. Have a look at this article http://blogs.microsoft.co.il/gilf/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements/
Reflection with Annotation
I really like this approach. I created a custom annotation to represent the tasks performed by methods. There is no overhead of object creation, like in Strategy pattern method, as tasks are performed by a single class.
Annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface TaskAnnotation {
public String value();
}
The code given below maps the client request keys to the methods which process the task. Here, map is instantiated and populated only once.
public static final HashMap<String, Method> taskList = new HashMap<>();
public static void main(String[] args) throws Exception {
// Retrieves declared methods from ClientMessageHandler class
Method[] classMethods = ClientMessageHandler.class.getDeclaredMethods();
for (Method method : classMethods) {
// We will iterate through the declared methods and look for
// the methods annotated with our TaskAnnotation
TaskAnnotation annot = method.getAnnotation(TaskAnnotation.class);
if (annot != null) {
// if a method with TaskAnnotation is found, its annotation
// value is mapped to that method.
taskList.put(annot.value(), method);
}
}
// Start server
}
Now finally, our ClientMessageHandler class looks like the following
public class ClientMessageHandler {
public void onMessageReceived(JSONObject clientRequest) throws JSONException {
// Retrieve the Method corresponding to the task from map
Method method = taskList.get(clientRequest.getString("task"));
if (method == null)
return;
try {
// Invoke the Method for this object, if Method corresponding
// to client request is found
method.invoke(this);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
logger.error(e);
}
}
#TaskAnnotation("task1")
public void processTaskOne() {
}
#TaskAnnotation("task2")
public void processTaskTwo() {
}
// Methods for different tasks, annotated with the corresponding
// clientRequest code
}
Major drawback of this approach is the performance hit. This approach is slow compared to Direct Method calling approach. Moreover, many articles are suggesting to stay away from Reflection, unless we are dealing with dynamic programming.
Read these answers to know more about reflection What is reflection and why is it useful?
Reflection performance related articles
Faster alternatives to Java's reflection
https://dzone.com/articles/the-performance-cost-of-reflection
FINAL RESULT
I continue to use switch statements in my application to avoid any performance hit.
As mentioned in the comments, one of websockets drawback is that you'll to specify the communication protocol yourself. AFAIK, the huge switch is the best option. To improve code readability and maintenance, I'll suggest to use encoders and decoders. Then, your problem becomes: how should I design my messages?
Your game looks like Scrabble. I don't know how to play Scrabble so let's take the example of card game with money. Let's assume you have three types of actions:
Global action (join table, leave table ...)
Money action (place bet, split bet, ...)
Card action (draw card, etc)
Then your messages can look like
public class AbstractAction{
// not relevant for global action but let's put that aside for the example
public abstract void endTurn();
}
public class GlobalAction{
// ...
}
public class MoneyAction{
enum Action{
PLACE_BET, PLACE_MAX_BET, SPLIT_BET, ...;
}
private MoneyAction.Action action;
// ...
}
public class CardAction{
// ...
}
Once your decoder and encoders are properly defined, your switch would be easier to read and easier to maintain. In my project, the code would look like this:
#ServerEndPoint(value = ..., encoders = {...}, decoders = {...})
public class ServerEndPoint{
#OnOpen
public void onOpen(Session session){
// ...
}
#OnClose
public void onClose(Session session){
// ...
}
#OnMessage
public void onMessage(Session session, AbstractAction action){
// I'm checking the class here but you
// can use different check such as a
// specific attribute
if(action instanceof GlobalAction){
// do some stuff
}
else if (action instanceof CardAction){
// do some stuff
}
else if (action instance of MoneyAction){
MoneyAction moneyAction = (MoneyAction) action;
switch(moneyAction.getAction()){
case PLACE_BET:
double betValue = moneyAction.getValue();
// do some stuff here
break;
case SPLIT_BET:
doSomeVeryComplexStuff(moneyAction);
break;
}
}
}
private void doSomeVeryComplexStuff(MoneyAction moneyAction){
// ... do something very complex ...
}
}
I prefer this approach because:
The messages design can leverage your entities design (if you are using JPA behind)
As messages are not plain text anymore but objects, enumerations can be used and enumerations are very powerful in this kind of switch-case situation. With the same logic but in a lesser extend, class abstraction can be useful as well
The ServerEndPoint class only handles communication. The business logic is handled out of this class, either directly in Messages classes or in some EJB. Because of this split, code maintenance is much easier
Bonus: #OnMessage method can be read as a summary of the protocol but details should not be displayed here. Each case must contain few lines only.
I prefer avoid using Reflection: it'll ruin your code readability, in the specific scenario of websocket
To go further beyond code readability, maintenance and efficiency, you can use a SessionHandler to intercept some CDI event if this can improve your code. I gave an example in this answer. If you need a more advanced example, Oracle provides a great tutorial about it. It might help you to improve your code.
ok, so i'm trying to implement rxJava2 with retrofit2. The goal is to make a call only once and broadcast the results to different classes. For exmaple: I have a list of geofences in my backend. I need that list in my MapFragment to dispaly them on the map, but I also need that data to set the pendingIntent service for the actual trigger.
I tried following this awnser, but I get all sorts of errors:
Single Observable with Multiple Subscribers
The current situation is as follow:
GeofenceRetrofitEndpoint:
public interface GeofenceEndpoint {
#GET("geofences")
Observable<List<Point>> getGeofenceAreas();
}
GeofenceDAO:
public class GeofenceDao {
#Inject
Retrofit retrofit;
private final GeofenceEndpoint geofenceEndpoint;
public GeofenceDao(){
InjectHelper.getRootComponent().inject(this);
geofenceEndpoint = retrofit.create(GeofenceEndpoint.class);
}
public Observable<List<Point>> loadGeofences() {
return geofenceEndpoint.getGeofenceAreas().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.share();
}
}
MapFragment / any other class where I need the results
private void getGeofences() {
new GeofenceDao().loadGeofences().subscribe(this::handleGeoResponse, this::handleGeoError);
}
private void handleGeoResponse(List<Point> points) {
// handle response
}
private void handleGeoError(Throwable error) {
// handle error
}
What am I doing wrong, because when I call new GeofenceDao().loadGeofences().subscribe(this::handleGeoResponse, this::handleGeoError); it's doing a separate call each time. Thx
new GeofenceDao().loadGeofences() returns two different instances of the Observable. share() only applies to the instance, not the the method. If you want to actually share the observable, you'd have to subscribe to the same instance. You could share the it with a (static) member loadGeofences.
private void getGeofences() {
if (loadGeofences == null) {
loadGeofences = new GeofenceDao().loadGeofences();
}
loadGeofences.subscribe(this::handleGeoResponse, this::handleGeoError);
}
But be careful not to leak the Obserable.
Maybe it's not answering your question directly, however I'd like to suggest you a little different approach:
Create a BehaviourSubject in your GeofenceDao and subscribe your retrofit request to this subject. This subject will act as a bridge between your clients and api, by doing this you will achieve:
Response cache - handy for screen rotations
Replaying response for every interested observer
Subscription between clients and subject doesn't rely on subscription between subject and API so you can break one without breaking another
I need to check some data, whether or not to send a tracking info. This data is saved inside the Realm database. Here is the model:
public class RealmTrackedState extends RealmObject {
#PrimaryKey
private int id = 1;
private RealmList<RealmChat> realmChatsStarted;
private boolean isSupportChatOpened;
private boolean isSupportChatAnswered;
/* getters and setters */
}
The idea is - every chat that is not inside the realmChatsStarted should be tracked and then added to this list. Similar thing for isSupportChatOpened boolean - however because of the business logic this is a special case.
So - I've wrapped this inside one Realm object. And I've wrapped this into few shouldTrack() methods, like this:
#Override
public void insertOrUpdateAsync(#NonNull final RealmModel object, #Nullable OnInsertListener listener) {
Realm instance = getRealmInstance();
instance.executeTransactionAsync(realm -> realm.insertOrUpdate(object), () ->
notifyOnSuccessNclose(listener, instance),
error -> notifyOnErrorNclose(listener, error, instance));
}
#Override
public RealmTrackedState getRealmTrackedState() {
try (Realm instance = getRealmInstance()) {
RealmResults<RealmTrackedState> trackedStates = instance.where(RealmTrackedState.class).findAll();
if (!trackedStates.isEmpty()) {
return instance.copyFromRealm(trackedStates.first());
}
RealmTrackedState trackedState = new RealmTrackedState();
trackedState.setRealmChatsStarted(new RealmList<>());
insertOrUpdateAsync(trackedState, null);
return trackedState;
}
}
#Override
public boolean shouldTrackChatStarted(#NonNull RealmChat chat) {
if (getCurrentUser().isRecruiter()) {
return false;
}
RealmList<RealmChat> channels = getRealmTrackedState().getRealmChatsStarted();
for (RealmChat trackedChats : channels) {
if (trackedChats.getId() == chat.getId()) {
return false;
}
}
getRealmInstance().executeTransaction(realm -> {
RealmTrackedState realmTrackedState = getRealmTrackedState();
realmTrackedState.addChatStartedChat(chat);
realm.insertOrUpdate(realmTrackedState);
});
return true;
}
And for any other field inside RealmTrackedState model happens the same.
So, within the presenter class, where I'm firing a track I have this:
private void trackState(){
if(dataManager.shouldTrackChatStarted(chatCache)){
//track data
}
if(dataManager.shouldTrackSupportChatOpened(chatCache)){
//track data
}
if(dataManager.shouldTrackWhatever(chatCache)){
//track data
}
...
}
And I wonder:
a. How much of a performance impact this would have.
I'm new to Realm, but for me opening and closing a DB looks ... heavy.
I like in this implementation that each should(...) method is standalone. Even though I'm launching three of them in a row - in other cases I'd probably use only one.
However would it be wiser to get this main object once and then operate on it? Sounds like it.
b. I see that I can either operate on synchronous and asynchronous transactions. I'm afraid that stacking a series of synchronous transactions may clog the CPU, and using the series of asynchronous may cause unexpected behaviour.
c. #PrimaryKey - I used this because of the wild copy paste session. Assuming that this class should have only instance - is it a correct way to do this?
ad a.
Realm caches instances so opening and closing instances are not that expensive as it sounds. First time an app is opening a Realm file, a number of consistency checks are performed (primarily does model classes match classes on disk) but next time you open an instance, you don't do this check.
ad b.
If your transactions depend on each other, you might have to be careful. On the other hand, why have multiple transactions? An async transaction will notify you when it has completed which can help me to get the behaviour you except.
ad c.
Primary keys are useful when you update objects (using insertOrUpdate()) as the value is use to decide if you are creating/inserting or updating an object.
Our application is getting complex, it has mainly 3 flow and have to process based on one of the 3 type. Many of these functionalities overlap each other.
So currently code is fully of if-else statements, it is all messed up and not organised. How to make a pattern so that 3 flows are clearly separated from each other but making use of power of re-usability.
Please provide some thoughts, this is a MVC application, where we need to produce and consume web servicees using jaxb technology.
May be you can view the application as a single object as input on which different strategies needs to be implemented based on runtime value.
You did not specify what your if-else statements are doing. Say they filtering depending on some value.
If I understand your question correctly, you want to look at Factory Pattern.
This is a clean approach, easy to maintain and produces readable code. Adding or removing a Filter is also easy, Just remove the class and remove it from FilterFactory hashmap.
Create an Interface : Filter
public interface Filter {
void Filter();
}
Create a Factory which returns correct Filter according to your value. Instead of your if-else now you can just use the following :
Filter filter = FilterFactory.getFilter(value);
filter.filter();
One common way to write FilterFactory is using a HashMap inside it.
public class FilterFactory{
static HashMap<Integer, Filter> filterMap;
static{
filterMap = new HashMap<>();
filterMap.put(0,new Filter0());
...
}
// this function will change depending on your needs
public Filter getFilter(int value){
return filterMap.get(value);
}
}
Create your three(in your case) Filters like this: (With meaningful names though)
public class Filter0 implements Filter {
public void filter(){
//do something
}
}
NOTE: As you want to reuse some methods, create a FilterUtility class and make all your filters extend this class so that you can use all the functions without rewriting them.
Your question is very broad and almost impossible to answer without some description or overview of the structure of your application. However, I've been in a similar situation and this is the approach I took:
Replace conditions with Polymorphism where possible
it has mainly 3 flow and have to process based on this one of the 3
type. Many of these functionalities overlap each other.
You say your project has 3 main flows and that much of the code overlaps each other. This sounds to me like a strategy pattern:
You declare an interface that defines the tasks performed by a Flow.
public interface Flow{
public Data getData();
public Error validateData();
public void saveData();
public Error gotoNextStep();
}
You create an abstract class that provides implementation that is common to all 3 flows. (methods in this abstract class don't have to be final, but you definitely want to consider it carefully.)
public abstract class AbstractFlow{
private FlowManager flowManager
public AbstractFlow(FlowManager fm){
flowManager = fm;
}
public final void saveData(){
Data data = getData();
saveDataAsXMl(data);
}
public final Error gotoNextStep(){
Error error = validateData();
if(error != null){
return error;
}
saveData();
fm.gotoNextStep();
return null;
}
}
Finally, you create 3 concrete classes that extend from the abstract class and define concrete implementation for the given flow.
public class BankDetailsFlow extends AbstractFlow{
public BankDetailsData getData(){
BankDetailsData data = new BankDetailsData();
data.setSwiftCode(/*get swift code somehow*/);
return data;
}
public Error validateData(){
BankDetailsData data = getData();
return validate(data);
}
public void onFormSubmitted(){
Error error = gotoNextStep();
if(error != null){
handleError(error);
}
}
}
Lets take example, suppose you have model say "Data" [which has some attributes and getters,setters, optional methods].In context of Mobile application ,in particular Android application there can be two modes Off-line or On-line. If device is connected to network , data is sent to network else stored to local database of device.
In procedural way someone can , define two models as OnlineData,OfflineData and write code as[The code is not exact ,its just like pseudo code ]:
if(Connection.isConnected()){
OnlineData ond=new OnlineData();
ond.save();//save is called which stores data on server using HTTP.
}
else{
OfflineData ofd=new Onlinedata();
ofd.save();//save is called which stores data in local database
}
A good approach to implement this is using OOPS principles :
Program to interface not Implementation
Lets see How to DO THIS.
I am just writing code snippets that will be more effectively represent what I mean.The snippets are as follows:
public interface Model {
long save();//save method
//other methods .....
}
public class OnlineData extends Model {
//attributes
public long save(){
//on-line implementation of save method for Data model
}
//implementation of other methods.
}
public class OfflineData extends Model {
//attributes
public long save(){
//off-line implementation of save method for Data model
}
//implementation of other methods.
}
public class ObjectFactory{
public static Model getDataObject(){
if(Connection.isConnected())
return new OnlineData();
else
return new OfflineData();
}
}
and Here is code that your client class should use:
public class ClientClass{
public void someMethod(){
Model model=ObjectFactory.getDataObject();
model.save();// here polymorphism plays role...
}
}
Also this follows:
Single Responsibility Principle [SRP]
because On-line and Off-line are two different responsibilities which we can be able to integrate in Single save() using if-else statement.
After loong time I find opensource rule engine frameworks like "drools" is a great alternative to fit my requirement.