Efficient way for persisting data with effective performance of UI - java

Imagine a app showing the user statistics. I could have an Object like:
public class Statistic {
private int id,value;
}
Where the value should persist between different app executions. Using an database for the persistent system the databaseAdapter could have a:
public void saveStatisticValue(int id,int newValue);
public int getStatisticValue(int id);
Using that calls to the DataBase Adapter in the getter/setter method of the object could impact in the app performance if called from the UI thread due to the database delay. For example if I want to show an Activity with all the Statistics, the database delay of the getter of each Statistic object could result in a ANR.
public class Statistic {
....
public synchronized void setValue(int newValue) {
dbAdapter.saveStatisticValue(this.getId(),newValue);
}
public synchronized int getValue() {
return dbAdapter.getStatisticValue(this.getId());
}
....
}
Is there some kind of approach for reduce the database impact for this kind of models?
Thanks

As you already has observed, the geter/setter method to the Models should be asynchronized.
For example , the API to getter_statics could be :
Request getStatics(RequestCallback callback);
interface RequestCallback {
void notify(int id ,int value);
}
The requestCallback will be called in the same thread as the getStatics has been called, usually it is the UI thread.
Two class are provided in Android facilitate you to implement this common pattern: Handler and SyncTask. Please read the document to get a thorough understanding.
You can also to check out this article.

Related

How to stop repeating myself in Java

I use a method for more than one time in JavaScript by using callback method because JavaScript is an async language.
Example:
function missionOne () {
sumCalculation(1, 2, function (result) {
console.log(result) // writes 3
})
}
function sumCalculation (param1, param2, callback) {
let result = param1 + param2
// The things that take long time can be done here
callback(result)
}
I wonder if there is any way to stop myself in Java?
Edit: I remove several sentences that make more complex the question.
I may be reading too much into your question, but it seems that you're looking into how to handle asynchronous code in Android. There are a couple of native options (not considering any library). I'll focus on two, but keep in mind there are other options.
AsyncTasks
From the documentation
AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
Before writing one, you need to know which type of parameters it will receive, the type of progress it will publish during computation and what is its return type. These types are define via the AsyncTask generic Parameters AsyncTask<Params,Progress,Result>. If you don't need them any of them, set them to Void
Here's the basic gist of using an AsyncTask to compute the sum of two ints:
public void sumCalculation (int param1, int param2, Callback callback) {
new AsyncTask<Integer, Void, Integer>() {
#Override
public Integer doInBackground(Integer... params) {
int result = 0;
for (Integer param : params) {
result += param;
}
return result;
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
callback.onDone(integer);
}
}.execute(param1, param2);
}
doInBackground, as the name says, will execute a certain piece of code in a background thread. Please note that every AsyncTask will run on a ThreadPool of size 1, so they actually get in the way of other AsyncTasks.
onPostExecute brings the result back to the main thread, so you can update any UI componente. If you try to update the UI from a background thread, an exception will be thrown.
The down side of this particular example is the creation of a new AsyncTask every time that function is called.
Also you should use AsyncTask only if the task won't run for a very long time, couple of seconds at most.
Thread and Handler
Another option suggested on the documentation is using a thread and a handler to communicate between the main thread and a background thread. Although this provides greater flexibility, it also requires more responsibility as you will be responsible for managing the communication yourself, picking the right time to kill your threads and how to recover when something goes bad.
As a rule of thumb, you should only go this way if you really need the extra flexibility.
The overall idea is to create your own Handler and override its handleMessage method.
public class MyHandler {
#Override
public void handleMessage(Message inputMessage) {
int messageType = inputMessage.what;
Object extraData = inputMessage.obj;
...
}
}
public class MyTask extends Thread {
public static public int COMPUTATION_DONE = 0;
private MyHandler handler;
public MyTask(MyHandler handler) {
this.handler = handler;
}
#Override
public void run() {
//do your computation
Message message = handler.obtainMessage(COMPUTATION_DONE, your_result);
handler.sendMessage(message);
}
}
As you can see, this requiring parsing inputMessage.what and deciding what to do with it. Additionally, you need to cast inputMessage.obj to the right type and so on.
These are just two examples, but depending on what you're trying to do, you might need to dig deeper into Services or take a look at some reactive approach, such as RxJava2. However I encourage you to start with the basic before diving into something way more complicated.
Yes it is easy in Java. To take your example above you can write it in Java like this:
public static void main(String[] args) {
System.out.println(sumCalc(1,2));
}
private int sumCalc(int first, int second) {
return first + second;
}

Make a temporary data holder in java .spring . hibernate

I work on a project that makes service for mobile apps and also
I should make a project that monitor the Mobile Project.
I want to make some reports that show how many messages come in this moment
and some other reports like that.
but I don’t want to get queries in monitoring project directly from DB.
I want to make a temporary data holder in memory and save the last 10 minutes
data on it (like a variable or a list)
but I don’t know technically how?
I use Spring and Hibernate in my project.
First of all we assume that our program tries to refresh the reports of an entity called SampleEntity every 10 minutes. This is just a simple POJO.
public class SampleEntity
{
// your fields and their getters and setters
}
Next we have a class, I call it SampleEntityDA, which queries the records we need for our reports from db. As you use hibernate you can simply return the result as java.util.List (I think this is one your main problems).
public class SampleEntityDA
{
public List<SampleEntity> queryFromDB()
{
// fetch records you need for your reports here
Session session = ...
return session.createQuery("from sampleEntity").list();
}
}
And at last...
query from db every 10 minutes...
To query from db every 10 minutes, you can simply use java.util.Timer class.
public class ReportTimer extends Observable
{
private Timer timer;
public static void main(String[] args)
{
// Your program starts from here
new ReportTimer().start();
}
private void start()
{
// schedule method of Timer class can execute a task repeatedly.
// This method accepts a TimerTask interface instance as its first parameter.I implement
// it as an anonymous class. TimerTask interface has a run method. Code in this method will execute repeatedly.
// Its second parameter is delay before task gets started to execute.
// And its third parameter is the interval between each execution(10min in your case)
timer = new Timer();
timer.schedule(
new TimerTask()
{
#Override
public void run()
{
notifyObservers(
new SampleEntityDA().queryFromDB() // 10 minutes passed from the last query, now its time to query from db again...
);
}
}, 100, 600000); // 600000ms = 10min
}
public void finish()
{
// call me whenever you get tired of refreshing reports
timer.cancel();
}
}
At last you need to update the data holder of your reports every 10min.
You can do this simply by Observer Pattern. As you know in java this is done by Observer class and Observable interface.
So 1) ReportTimer needs to extend Observer class and 2) in TimerTask we need to notify the listeners; this is done by notifyObservers method.
Our last class has duty of refreshing reports. I call it ReportGenerator. This class refreshes the reports whenever you like. It also has a java.util.List field that has the most recent data of db. ReportGenerator updates this field whenever its Observer - I mean ReportTimer - notifies it.
public class ReportGenerator implements Observer
{
List<SampleEntity> list = new ArrayList<SampleEntity>();
#Override
public void update(Observable o, Object arg)
{
// This method will automatically!?! executed whenever its observer notifies him.
// The arg parameter consists the new records. you just need to put it in the list field.
List<SampleEntity> list = (List<SampleEntity>) arg;
}
public void refreshReport()
{
// you can easily refresh a report with data in list field
}
public void refreshAnotherReport()
{
// you can easily refresh a report with data in list field
}
}
use map, hashMap, or ConcurrentHashMap.
make a crone job that update Map after ten min.
Here is a link for map, HashMap, ConcurrentHashMAP

Double observer in java?

I have a problem with Observer pattern.
First, I have a HttpHelper class to get data from server, I used it as Observerable.
public class HttpHelper extends Observable,Runnable{
public void run(){
//do long task to get data
String result = getData();
setChanged();
notifyObservers(result);
}
}
The DataManager class get data from HttpHerlper when completed, then do some business task.
public class DataManager implements Observer {
public void doTask(){
HttpHelper helper = new HttpHelper();
helper.addObserver(this);
Thread thread = new Thread(helper);
thread.start();
}
public void update(Observable obj, Object data) {
if (data instanceof String) {
// do some stuff with this data
// Then I want to notify the result to the view
Model model = doSomething(data);
notify(model)
}
}
}
Finaaly, View class will update data when DataManager complete task.
public class View{
private void getData(){
DataManager manager = new DataManager()
manager.doTask();
}
public void update(Observable obj, Object data) {
}
}
Should I use Observer again? And how can I do that?
P/s: for some reason, HttpHelper and DataManager must be separated.
Update: Here is the class structure
https://www.dropbox.com/s/givn6vzvqr4cgye/bkd.png
IMO, the relationship between HttpHelper and DataManager doesn't need an observer pattern. It seems to be just a callback to notify the manager that the processing is done. Observers are better suited for dispatching events to multiple, different listeners via a common interface, not to a single listener. Having said that, what you have will work. Check this article on implementing callbacks if you want to follow my advice
Now, for the relationship between the manager and the view i do agree that you should use an observer pattern, this will allow you to create different views that react differently to the same events. This means that it's DataManager that should extend Observable, and every view listening it should implement Observer
Finally, i have to say that if you plan on having different types of events, the JDK observable and observer (java.util) mechanism is not very clean. My biggest criticism is that the second argument of update is an Object, so you end up with a huge list of if else where you need to check instanceof like in your example, which in general is not good practice. An alternative is to use the event notification mechanism from the UI classes (like EventObject and EventListener) , they are part of the UI classes but are really more generic than just UIs. see this other question
Oh and if you can, try to avoid cascading events. It makes code hard to read and debug. Maybe the view could observe directly the HttpHelper??
I think you can make the View an Observable but that chain of Observation may make your code complex.
The immediate solution came to me is:
Make an Observer controller
class Controller implements Observer{
DataManager dm;
View v;
void update(...){
Data d = dm.getData();
v.loadData(d);
}
}
and make your Controller observe HttpHelper.

How often is a thread executed? My Observer pattern gone wrong?

The following is a simplified version of my current code. I am pretty sure I am not doing any thing wrong syntax-wise, and I can't locate my conceptual mistake.
This is sort of an observer pattern I tried to implement. I could not afford to inherit from Java.utils.observable as my class is already complicated and inherits from another class.
There are two parts here:
There's a Notifier class implementing Runnable :
public class Notifier implements Runnable{
public void run()
{
while(true)
{
MyDataType data = getData();
if(data.isChanged()==true)
{
refresh();
}
}
}
}
And then there is my main class which needs to respond to changes to MyDataType data.
public class abc {
private MyDataType data;
public void abc(){
Notifier notifier = new Notifier();
Thread thread = new Thread(notifier);
thread.start();
}
public MyDataType getData(){
return this.data;
}
public void refresh(){
MyDatatype data = getData();
//Do something with data
}
}
The problem : What's happening is that the notifier is calling refresh() when 'data' changes. However inside refresh(), when I do getData(), I am getting the old version of 'data'!
I should mention that there are other parts of the code which are calling the refresh() function too.
What am I overlooking?
Any other better solutions to this problem?
How should I approach designing Subject-Observer systems if I can't apply the default Java implementation out of the box?
when I do getData(), I am getting the old version of 'data'!
Your data field is shared among more than one thread so it must be marked with the volatile keyword.
private volatile MyDataType data;
This causes a "memory barrier" around the read and the the write that keeps the value visible to all threads. Even though the notifier thread is calling getData(), the value for data is being retrieved out if its memory cache. Without the memory barrier, the data value will be updated randomly or never.
As #JB mentioned in the comments, the volatile protects you against a re-assignment of the data field. If you update one of the fields within the current data value, the memory barrier will not be crossed that the notifier's memory will not be updated.
Looking back at your code, it looks like this is the case:
if(data.isChanged()==true)
{
refresh();
}
If data is not being assigned to a new object then making data to be volatile won't help you. You will have to:
Set some sort of volatile boolean dirty; field whenever data has been updated.
Update or read data within a synchronize block each and every time.
First, your data variable might be cached, so you will always need to get the latest value by making it volatile.
Second, what you are doing here is a producer / consumer pattern. This pattern is usually best implemented with messages. When you receive new data, you could create an immutable object and post it to the consumer thread (via a thread safe queue like a BlockingQueue) instead of having a shared variable.
Something along these lines:
public class Notifier extends Thread{
private BlockingQueue<E> consumerQueue = null;
public setConsumerQueue(BlockingQueue<E> val){
consumerQueue = val;
}
// main method where data is received from socket...
public void run(){
while(!interrupted()){
data = ... // got new data here
if(!data.isChanged()) continue;
// Post new data only when it has changed
if(consumerQueue!=null) consumerQueue.offer(data);
}
}
}
public class Consumer extends Thread{
private BlockingQueue<E> consumerQueue = new BlockingQueue<E>();
public Consumer (Producer val){
val.setConsumerQueue(consumerQueue);
}
public void run(){
while(!interrupted()){
data = consumerQueue.take();// block until there is data from producer
if(data !=null) processData(data);
}
}
}

Is there any way to know the progress of a EJB Asynchronous process?

I'm trying to get the percentage of the progress from a EJB Asynchronous process. Is this possible?
Does anyone have an idea how I could do this?
To get to know the progress of asynchronous processes is always tricky, especially if you don't know if they have actually started yet.
The best way I have found is to write another function that just gets the progress, so, if you have some unique id for each call, then update a hashmap with the current process. You may want to look at Concurrent Hashmap (http://download-llnw.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html)
Then this other lookup function will just take the unique id, and return the progress back to the client.
If it hasn't been started, you can also return that, and ideally you may want to also be able to return any error messages that came up in the processing.
Then, when it has finished, and you returned the error message or success, then delete it from the hashmap, the client got the information, and that info won't change, so no point it keeping it around.
UPDATE:
In your interface make a new function
String progressDone(String id);
You will then refer to that synchronously, as it just goes out and comes right back, so it can look up the id in the hashmap and return either the percentage done or an error message.
But, this means that your actually worker function needs to every so often put information in the hashmap as to where it is, which is why I suggested using the concurrent hashmap, so that you don't have to worry about concurrent writes, and so locking considerations.
The solution I have found is an context object shared between asynchronous method and main thread. Here is an example:
Asynchronous job itself:
#Stateless
public class AsyncRunner implements AsyncRunnerLocal {
#Asynchronous
public Future<ResultObject> doWorkAsynchronous(WorkContext context) {
context.setRunning(true);
for (int i = 0; i < 100; i++) {
//Do the next iteration of your work here
context.setProgress(i);
}
context.setRunning(false);
return new AsyncResult(new ResultObject());
}
}
Shared context object. Important thing here is volatile keyword. Field values will be locally cached in each thread without it and progress will not be visible in main thread:
public class WorkContext {
//volatile is important!
private volatile Integer progress = 0;
private volatile boolean running = false;
//getters and setters are omitted
}
Usage example:
public class ProgressChecker {
#EJB
private AsyncRunnerLocal asyncRunner;
private WorkContext context;
private Future<ResultObject> future;
public void startJob() {
this.context = new WorkContext();
future = asyncRunner.doWorkAsynchronous(this.context);
//the job is running now
while (!future.isDone()) {
System.out.println("Progress: " + this.context.getProgress());
Thread.sleep(1000); //try catch is omitted
}
}
}
In EJB3.1 #Asynchronous method-calls can return java.util.concurrent.Future, this interface provides information boolean isCancelled() or boolean isDone(), but no information if the execution started. From my point of view, there is no way to get the information if the process started its execution via the EJB-Container in standard ways.

Categories