Make a temporary data holder in java .spring . hibernate - java

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

Related

What is the Android PhoneStateListener's Behavior When Called Multiple Times?

My service has a PhoneStateListener that overrides the onCellInfoChanged method. When running on Android Studio, it'll log whenever the method is called. Based on the logs, it seems that sometimes the method gets called consecutively (a couple milliseconds between logs).
public class OnCellChangeService extends Service
{
// other field declarations
private PhoneStateListener mPhoneStateListener = new PhoneStateListener()
{
#SuppressLint("DefaultLocale")
#Override
public void onCellInfoChanged(List<CellInfo> cellInfoList)
{
String timeStamp = simpleDateFormat.format(new Date());
List<CellNetwork> cellNetworks = setCellNetwork(cellInfoList);
String networkStrength = "";
int index = 1;
for (CellNetwork cell : cellNetworks)
networkStrength += String.format("%s (%d)%s\n", timeStamp, index++, cell.record());
try {
writer.write(networkStrength);
writer.flush();
Log.d("Phone Listener", "Cell Change");
} catch (Exception e) {
e.printStackTrace();
}
}
};
// rest of service
}
All the listener does is take the cellInfoList, calls another method to get a list that contains a list of custom class objects made from a subset of the original list. It writes to a file with a time stamp and other various pieces of information from each list object.
When the listener's method is called again while the same method is executing, does the current method stop and restart for the new call? Does it run in a separate thread of execution? Does it wait for the method to finish executing? If another call does halt or interfere with the same method executing, how could I implement threading and/or synchronization to make sure every called is executed in full while maintaining order?
The callbacks from PhoneStateListener are all made on the main (UI) thread. Therefore, each callback method will run to completion before the next one is called.

Spring: Not able to write to Autowired repository when using TimerTask

I have a method that should periodically update records in a database.
#Service
public class MyService {
#Autowired
private MyRepository myRepository;
private Boolean flag = false;
#Transactional
public int method1(Args args) {
// do something
if (!flag) {
method2()
}
return x;
}
#Transactional
public int method2(Args args) {
polling = true;
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
List<Records> records = myRepository.getRecords()
for (Record record : records ) {
// prints the Id of each record. Now, they are all have Id=1
System.out.println(record.getId());
// setting the record's Id to 5
record.setId(5);
// prints '5'
System.out.println(record.getId());
}
}
}, 10, 1000*60*4
}
}
Method1 calls Method2. Method2 executes the code inside the run() function every 4 minutes. The code inside run() works properly without scheduling (gets the Ids for each record, prints them, updates the db by setting Id to 5).
However, now, with my use of TimerTask, it still retrieves and prints the Ids, supposedly sets each record's Id to 5, and even prints out '5' at record.get(Id) which would lead me to believe the database was successfully updated with the new Id.
When I actually check my database, I find that the Ids actually haven't been updated to 5. The original Ids remain.
I'm not sure why this is happening, as it seemed like the Ids were being updated. Is this something to do with TimerTask creating a new thread?
The #Transational assumes that it is going to wrap ONE TRANSACTION against the DB, so you need to have your #Transactional functions where they do one thing, let and get out immediately. You know the DB will have either committed or rolled back. Depending on Transaction Isolation levels (another topic you may want to research, but probably don't need to) the thnigs that go on inside the #Transactional never get written to db until that function actually returns. That's probably all you are missing. Chrylis is right to use #Scheduled for 'repeating things' but the real problem is the one i stated, with all due respect to him/her.
Summary: Make your #Scheduled function call a #Transactional function (for each DB transaction you want to do), and then it will work.

How To Call A Method After A Certain Period

I have a MySQL database running on my localhost. To this database I have JDBC-connection. Over a RESTful WebService a softwareagent puts results into this database. I implemented a garbage collector in Java and want to execute that garbage collector after a certain period. My aim is that I do not have too many entries in the table.
The Garbage Collector looks as follows:
public void collectGarbageResults() {
ArrayList<Integer> ids = new ArrayList<Integer>();
ResultSet rs = this.execQuery("SELECT * FROM results");
try {
while (rs.next()) {
if ( (System.currentTimeMillis()) - (Timestamp.valueOf(rs.getString("tmstmp")).getTime()) > Long.parseLong(appconfigs.get("resultstableactuality")) ) {
ids.add(rs.getInt("id"));
}
}
for (Integer i : ids) {
this.deleteResultsWhereId(i);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
The method I call looks as follows:
private void deleteResultsWhereId(int id) {
retint = this.updateQuery("DELETE FROM results WHERE id=" + id + ";");
}
I am using JSF in an Eclipse's Dynamic Web Project and these methods are implemented in a managed bean. I am going to store the interval in an XML-file which I use for my application's configuration. Over the variable appconfigs I call the method 'get' and ask for the node containing my interval.
Now my question:
How can I call the method of the garbage collector after a certain period in my WebApp?
If you have any questions do not hesitate to comment.
My Solution :
#WebListener
public class BackgroundJobManager implements ServletContextListener{
private ScheduledExecutorService scheduler;
#Override
public void contextInitialized(ServletContextEvent event) {
long delayToStart = 0;
long numberOfUnits = 60;
TimeUnit tu = TimeUnit.SECONDS;
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new ExecuteGarbageCollector(), delayToStart, numberOfUnits, tu);
}
#Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
The class I call implements Runnable as follows:
public class ExecuteGarbageCollector implements Runnable{
#Override
public void run() {
DAO dao = new DAO();
dao.collectGarbageResults();
}
}
You could use ScheduledExecutorService or Quartz
Quartz has a lot of facilities, but If you choose ScheduledExecutorService you don't have to add any new dependencies to your project. and as you just want this scheduled task, it's simple.
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(...);
Take a look at some comments about both in: Quartz vs. ScheduledExecutorService in Java web application
Check out a scheduler library. You can use Quartz for example.
Call Java from MySQL. You could either have this kicked off by a job or trigger
Just stick to SQL and ignore running this in Java. Probably the easiest if you are good at SQL. Then you can encapsulate this in a SPROC or trigger.
It's your choice whether this should live in your web-app or in your database. I've used both methods for executing timed SQL calls and tend to prefer the code oriented approach
The actual question could have well been how to call a function after a specific interval of time?
Take a look at :
How to call a method after some specific interval of time in Java
and
java: run a function after a specific number of seconds

How do I manage hibernate transactions in a timertask?

I am currently trying to make a hibernate query inside of a TimerTask (Runnable). This task makes no saves or updates to the database. It just retrieves a list of jobs. Anytime I run this task, I get HibernateException: Unable to locate current JTA transaction.
I believe this has to do with the fact that it's being started from a runnable because I use this same query outside of this TimerTask.
I can't share the code I am working with because it is for work and proprietary. My research on this issue has only really led me to solutions with Spring, but I am not able to use Spring for this work.
I will attempt to make some pseudo code.
public class JobManager extends TimerTask {
#Override
public void run() {
...
List<String> jobs = Handler.getJobs();
...
}
}
public class Handler {
public static List<String> getJobs() {
return DAO.getJobs();
}
}
public class DAO {
public List<Object> getJobs() {
try {
session = HibernateManager.getSessionFactory().getCurrentSession();
Query myQuery = session.createQuery("query string");
List = myQuery.list();
} catch(HibernateException he) {
log.error(he);
}
return list;
}
}
The exception occurs when the runnable calls getJobs(). This method work everywhere else outside of the TimerTask.
I understand that this is limited information to work with. I can try to accommodate for any other information if it is needed.
I believe every transaction has some time out, so you can not put the regular timer task code inside the running transaction. As it is just reading the data you wont need to start the transaction, just session is enough
I have encountered the same problem and solved by creating the new session
session = sessionFactory.openSession();
EDIT
session.getCurrentSession() takes the current session from the current thread, so it wont work inside timer task. Use openSession()

Efficient way for persisting data with effective performance of UI

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.

Categories