Email using Singleton pattern - java

I have a webapp running on my server, which does some balance update. Once the balance is updated, I need to check if the balance is below 5000. In case, the balance goes below 5000, I should send an email alert. The point to note here is that, I need to send the alert only once in a day, alert should not keep going every time the balance is below 5000.
I believe, I should use singleton pattern for sending the mail, but I am not sure how to use this.
The program when sees the balance going below 5000, should call the singleton class which will have the function to send email alert, but how do you ensure that program will not call this function again when the balance goes down?
Can anyone guide me on this?

There is two separate things you need think about:
Email sending service.
Several ways to implement it. Yes, it could be Singleton, but it also could be a plain Java service. If you use Spring, then they have very simple and useful predefined implementations. Here is an example.
Your checking balance logic.
Depends on what you really need. If you need to check every balance update but send alerts not more that once per day, then it will be something like:
private Date lastAlertDate;
private static final BALANCE_LIMIT = 5000;
private void handleBalanceUpdated(long balance) {
if (balance < 5000) {
log.info("Balance has gone below {}", BALANCE_LIMIT);
int daysDifference = getDifferenceInDays(lastAlertDate, new Date());
if (daysDifference >= 1) {
log.info("Last alert was {} days ago, going to send email alert", daysDifference);
alertService.sendSimpleAlert("Balance has gone below " + BALANCE_LIMIT + "!");
lastAlertDate = new Date();
}
}
}

Singleton is a design pattern that makes sure only one instance of an object is created.
Doesn't sound like it has anything to do with what you need, you could add a flag in your DB like alert_sent=true/false and update it accordingly.

User Timer Task to send mail only once a day
Singleton Pattern

You do not need any "special" design patterns here. For instance you can store the date when the last email notification was sent, like:
Date lastEmail = ... // last email date
And when trying to send email chekc the condition:
If( ... ) // lastEmail is before current day
{ //send emal and update lastEmail }

Related

How to send push notifications to users that don't enter application more then 2 days?

I haven't my own server and client doesn't want a server. Can i do it with direbase notifications? And how i will calculate how amny days spent from last user session?
--------------------------------NEW ANSWER------------------------------------
You should be able to do this using the Firebase Console. When creating a Cloud Message you can select in the "Target" section "Last App Engagement" and select that you want the message to go to everyone that hasn't engaged with the app for say 1 day.
After that you set in Scheduling that you want it to be a recurring campaign and you set it to happen "Daily" at say 12pm and set that you want each user to get this only once. Now you have a campaign that every day at 12pm checks who wasn't in the App for 1d and sends him the campaign, but only sends it once to not spam the same guy every single day.
--------------------------------OLD ANSWER -----------------------------------
You could create for example a DailyJob within your app and that DailyJob could either on it's own check how many days since last session was active and create a local notification or you could use that DailyJob to send to say Firebase a custom attribute "days_since_last_login" and setup different campaigns for 2 days offline, 7 days offline, 31 days offline and so on in Firebase.
To easily create a DailyJob you can use Evernote Android Job library.
You can use firebase to make push notification.
In this case, you don't have any server to make push notification and track the last user session, I think you can follow this:
Use local notification (not push notification) to notify user.
Store user session to Shared Preferences.
Create a background service to trigger local notification base on the last session stored.
But you should have a clear view of notification on Android to understand how it works first.
This is simple: don't use Firebase or the internet at all.
This is what you want to do: every time the user logs into your app, Create an Alarm for 48 hours (2 days) from when onResume and cancel any previous alarms. Or cancel previous alarms during onResume and create a new one in onPause.
Then, setup the alarm receiver to send a local notification. AlarmManager with Notification Android
Every time the user opens your app, it pushes the local notification back. When they go 2 days without using it, they will get a notification at around the same time that they used it previously.
"Can I do it with firebase notifications?"
Yes, you can with cloud function code.
Just trigger an event after a new notification added to the database.
My below code trigger an event after a new notification added to DB and looks for a post older than 24hrs. You can use it and change it for 48hrs
The code work below:
Trigger event after data is added to DB.
Check the database for old notifications older than 24hrs.
Retrieve them and delete (by changing their value to null);
//DELETE OLD NOTIFICATION LESS THAN 24HRS /////////////////
exports.deleteOldItems = functions.database.ref('/notification/{user_id}/{notification_id}').onWrite((change) => {
const ref = change.after.ref.parent; // reference to the parent
const yesterday = Date.now() - 86400000;
const oldItemsQuery = ref.orderByChild('time').endAt(yesterday);
return oldItemsQuery.once('value').then((snapshot) => {
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
updates[child.key] = null;
});
return ref.update(updates);
// execute all updates in one go and return the result to end the function
});
});
////////////////////DELETE FUNCTION ENDED HERE//////////////////////
The most important part is how to calculate for 48hrs (which is 2 days)
PS: this is still 24hrs. I will update the answer when finding a way to convert for 48hrs.
const yesterday = Date.now() - 86400000;
EDIT:172800000 is for 2 days ago (24hrs)
Now, you subtract the current date from 2 days ago and compare it with the notification date.
const yesterday = Date.now() - 172800000;

Right way to make payment via bitcoinj

I am trying to make transaction via bitcoinj (version 0.14.3) and i am expecting to get change back after payment. I am working with testnet, it's not real bitcoins.
I have next code:
Transaction tx = new Transaction(this.networkParameters);
Coin coinToSent = Coin.valueOf(Config.APP_COST);
Coin coinToChange = Coin.valueOf(walletBalance.getValue() - coinToSent.getValue());
tx.addOutput(coinToSent, appAddress);
tx.addOutput(coinToChange, changeAddress);
SendRequest request = SendRequest.forTx(tx);
try {
this.walletAppKit.wallet().completeTx(request);
} catch (InsufficientMoneyException e) {
e.printStackTrace();
return false;
}
this.walletAppKit.wallet().commitTx(request.tx);
this.walletAppKit.peerGroup().broadcastTransaction(request.tx);
So, i am putting two outputs into transaction:
Address to sending money
Address of my wallet for getting change back
To the first address i send some money. And to the second address i send next value: all available money on my wallet minus money received to first address.
But after broadcasting i had an unexpected result. After making a few transactions with this scheme, I've noticed wrong values withdrawing from my wallet. What is surprising, sometimes money is withdrawing but sometimes money coming to wallet.
Here is the link to testnet explorer
Can someone explain what i am doing wrong and how to fix it?
The reason that the transaction is not working as expected is that the Bitcoinj Wallet class is doing a lot of things in the background for you - in this case, it is automatically generating a change address where is would store the change for the transaction. The other factor is that bitcoinj calculates a fee that it will give the miners to process the transaction, which is why you're seeing the change address getting less coin that you requested (on the production network it will throw an exception if you don't have enough funds to cover the fee).
I think the best solution here, for cases which are relatively simple, is to work with the Wallet API and let it do the work of generating change address automatically (It's using a deterministic keychain so all the addresses and keys can be regenerated in case you lose the wallet). For example:
public static Transaction send(Wallet wallet,
String destinationAddress,
long satoshis) throws Exception {
Address dest = Address.fromBase58(params, destinationAddress);
SendRequest request = SendRequest.to(dest, Coin.valueOf(satoshis));
SendResult result = wallet.sendCoins(request);
Transaction endTransaction = result.broadcastComplete.get();
return endTransaction;
}
After sendCoins is completed and the transaction is broadcasted, the wallet will maintain the rest (you can save it to a file after the transactin is complete if you really want to make sure you have the keys for the change addresses), here's a way you can see a list of 10 change addresses and their public/private keys :
NetworkParameters params = new MainNetParams();
List<DeterministicKey> keys = wallet.freshKeys(KeyChain.KeyPurpose.CHANGE, 10);
keys.forEach(key -> {
Address address = new Address(params, key.getPubKeyHash());
System.out.println(address +" : " + key.toStringWithPrivate(params));
});

Spring : Send automated email to member and admin after timer expires

I am working on a Spring-MVC application in which there is Service desk functionality I am working on. So, as a part of Service desk, users can create issues and assign a support-team member. In that, they can also assign in how much time issue needs to be resolved. I am setting the time in java.sql.TimeStamp.
Now, when the time expires, I would like to send an email to the support-team admin, the person who created the issue and the support-team member responsible for resolving the issue.
If it was a normal scheduled or cron job, I can just write a #Scheduled method and get it over with, but here, I would like to check for example after 6 hours if the issue was resolved or not. How do I accomplish that? I have no idea to be honest.
Here is service layer part the SupportRequest :
#Service
#Transactional
public class SupportRequestServiceImpl implements SupportRequestService{
private final SupportRequestDAO supportRequestDAO;
#Autowired
public SupportRequestServiceImpl(SupportRequestDAO supportRequestDAO){
this.supportRequestDAO = supportRequestDAO;
}
#Autowired
private SupportTeamService supportTeamService;
#Override
public int addSupportRequest(SupportRequest supportRequest, int assignedTeamId, Long groupId) {
SupportTeam supportTeam = this.supportTeamService.getSupportTeamMemberById(assignedTeamId);
if(!(supportTeam == null)){
supportRequest.setCreationTime(new Timestamp(System.currentTimeMillis()));
supportRequest.setAssignedTeamMemberId(supportTeam.getTeamId());
return this.supportRequestDAO.addSupportRequest(supportRequest,groupId);
}
return 0;
}
}
I don't know what else to show. Thanks a lot.
Update
Will something like this work?
long delay = 1000*60*60*12; // after 12 hrs
Timer timer = new Timer();
Calendar cal = Calendar.getInstance();
timer.schedule(new TimerTask() {
public void run() {
// Task here ...
System.out.println("inside the main");
Integer id = new Integer(10);
Assert.assertNotNull(id);
}
}, delay);
For these kind of scenario, there should be background process running. That process will check for issues that has not been fixed in given time. Then this process will send a message to whoever you want and then continue running in background.
There are different ways of doing this.
1. Batch Process
You can make batch process. Batch process will be running on your server, it will check for expired issues and then send mail to the support-team admin.
2. Techniques for Real-time Updates
You can also you real time update techniques in spring. Using this technique you will fire request after every given period that will check for expire issues. If any issue found that has not been fixed you can send mail. Please read the related document here : Spring MVC 3.2 Preview: Techniques for Real-time Updates
3. Web Socket
Web socked can also be useful for these kind of task. Find the good source here :
SPRING FRAMEWORK 4.0 M2: WEBSOCKET MESSAGING ARCHITECTURES

validate and expire the link using gwt - java

My Requirement is to sent a mail to the concerned users when a record is created. The mail contains a link to our system that lets the user interacting with the system without login. The link expires after a certain time. The mailing is done using javax.mail.
How can I expire the link?
Use Timer#schedule(int):
// Schedule the timer to run once in 1 minute.
new Timer()
{
#Override
public void run()
{
if(remove)
{
// Either remove it
anchor.removeFromParent();
}
else
{
// Or disable it
anchor.setEnabled(false);
}
}
}.schedule(60 * 1000);
I would generate a key/ID that you add to the link and also store to a database. With filters (web.xml) you can check if the URL (ID) is still valid and pass it on to the desired page.
If you provide us with more details, we can give you a more detailed answer.

What is a good strategy to manage sessions for beta webapplication?

I am trying to create a webapplication using Spring. The webapplication is a beta/demo site, which is invitation only. So, I need to generate a link to the webapplication url, appending a unique id, which would be valid for 24 hours. User can use that link for 24 hours and make use of the (I kind of also have plans of restricting the user by ip)
To achieve such token generation and expiry, should I just rely on the container with session time out to do it? or does it make sense to create spring backed service layer with token creation and expiry services?
EDIT
Now that I have a bounty on this to draw more attention, I thought I will rephrase the question so that it makes more sense - what would be a good strategy to force users out of a web application after a certain period of time?
Relying on session timeout would not be sufficient solution .
I am not acquaint with Spring . I would put my generic solution as below for any web application having requirement as yours :
Invitation is assumed to include a link to the Web Application .
The link is assumed to include the unique id .
The Beta/Demo user table is assumed to have a beta-expiry ( datetime ) column to hold the expiry date and time .
When your web application is accessed using the link in the invitation , update the beta-expiry column for that unique_id considering 24 hrs from then .
When a Beta/Demo user attempts to sign in , check the beta-expiry column for that particular user and allow access if the expiry is not reached . Display appropriate message in case of expiry .
Whenever a signed in Beta/Demo user performs subsequent accesses to your web application , check the beta-expiry column for that particular user and allow access if the expiry is not reached . Display appropriate message in case of expiry .
If seems useful , display a countdown timer showing the left over time somewhere in the header area .
In case of extension of Beta usage for all or a portion of users , you could update the beta_expiry column appropriately .
Additionally you could also have an invitation-expiry column to hold invitation expiry considering a particular duration for eg. a 48 hrs from when the invitation was sent .
We use a little bit similar solution to sign out ( signed in ) users from our SaaS application after a particular duration of no access .
I think that you should rely more in the back-end rather than a session on a cookie, imagine the case that you set the cookie for 24 hours expiration but the client deletes the cookies from the browser, (depending on your logic) your link will generate a new session or the request will be blocked.
IMHO you can store a session cookie on the client but you need to have a second source of comparison in the server, maybe a database, no-sql document, a collection in cache, something that you can compare and check the latest access to the client.
just to put all together imagine the following use case:
the user get the invitation link and click on it
the system check if the first time they log into the system, and save that date as a "start date" and another one as "last access"
the system sets an authentication cookie with 24 hours expiration
the system track every post back/ ajax call to the server and update "last access" date
if user deletes the cookie the system check the "last access" and make a comparison with the current server date
if valid the system creates a new auth cookie with the remaining hours
if not valid the system sends a message to the user.
for the user the cookie will expire according to the time left (calculation between start date and last access)
I hope this helps.
regards
One strategy is to keep track of expiry date-time of all the users by storing the relevant data in DB and using a cache library (to reduce DB hits while checking for the expiry date). Here is a small example:
Create a DB table with columns to map user id to expiry date: id, unique_user_id, expiry_date_time. You need to create the unique user id in your code and save it in DB before sending the URL to the user with this id. You can keep null as the initial value for expiry_date_time. Create a class to represent this mapping in Java:
class UserIdWithExpiryDate{
private String userId;
private Date expiryDateTime;
...
}
Define a Service with a cacheable method that will return an instance of this for a given userId :
public interface CacheableService {
#Cacheable("expiryDates")
public UserIdWithExpiryDate getUserIdWithExpiryDate(String id);
public void updateUserIdWithExpiryDate(String userId);
}
import org.joda.time.DateTime;
#Service
public class CacheableServiceImpl implements CacheableService {
#Autowired
private YourDao dao;
#Override
public UserIdWithExpiryDate getUserIdWithExpiryDate(String id) {
return dao.getUserIdWithExpiryDate(id);
}
public void updateUserIdWithExpiryDate(String userId){
Date expiryDate = new Date(new DateTime().plusHours(24).getMillis());
dao.update(userId, expiryDate);
}
}
The result of getUserIdWithExpiryDate method is stored into the cache so on subsequent invocations (with the same argument), the value in the cache is returned without having to actually execute the method.
Next step is to check the user's expiry date while accessing the site. This can be done using OncePerRequestFilter:
#Component("timeoutFilter")
public class TimeoutFilter extends OncePerRequestFilter {
#Autowired
CacheableService cacheableService;
// Here you need to decide whether to proceed with the request or not
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(request, response);
}
}
Steps that can be taken inside the doFilterInternal method to check the validity of the user:
Get the user Id from request
Execute: cacheableService.getUserIdWithExpiryDate(userId)
If step 2 returns null, there is no user present with this id. You should not proceed with the request.
If step 2 returns an instance of UserIdWithExpiryDate, check the value of "expiryDateTime"
If the value of "expiryDateTime" is null,it means user is accessing the site for the first time.Update "userExpiryDate":cacheableService.updateUserIdWithExpiryDate(userId) and proceed with the request.
If "expiryDateTime" is not null, compare this with current date_time. If expiryDateTime.isAfter(currentDateTime), proceed with the request.
For caching, you can use Spring Cache Abstraction with EHCACHE.
Tokens
For this marketing purposes we generate tokens upfront, store them in a database alongside all information like restrictions to certain user account, ip ranges (for certain mobile carriers), the date and time ranges of use and so on.
In case of one time codes we just mark it as being used in the database.
To generate those codes we use Random Numbers or encode some information and use (SHA-1 or better). Then we use bigInteger.toString(36) or a different scheme and group the first 16 letters to let it look like a license key.
If we express information with it like useraccount/name or carrier (mobile) or whatever we can even validate the token without a database.
Forcing User Out
Just check for the validity of the token the first time the user starts a session or logs in. Throughout the session you just check if the token has expired (store a value in the session if you have one, append it (encrypted) in the url or whatever or check against a database.
So on every request you just check if the user has permission to access your site otherwise you block the user with an error / info page.
You can also add a java script to each page. The script can determine whether the users permission to use your site has expired by:
Encrypt the relative time that the token is valid in a hidden div and calculate the absolute time using the users local time. Then compare the absolute expire time with the user time every now and than (lets say every 3 seconds) and you can yourself all those polling and pushing (comet, ajax, websockets) behaviour.
Once the java script program notice the token has become expired remove the content sections and replace it (or mark a hidden div as visible) with the info / error page content. This way every time the user revisits pages still stored in the browser history are destroyed also. (if this is a necessity for you).
Summary
Use random tokens and a database or encrypt information (like the day the token can be used) and SHA-1.
Check the tokens validity every time the user requests a page (store the timeframe in a session / url to save roundtrips to the database)
Provide a java script that destroys local pages in the history on revisit.
Here I can think of two use cases that I have seen.
1.) This kind of management is used in applications like online tests or email verifications, where user is provided a link with some token. This link and the token is valid for some fixed period of time and can be used only once. (Ex. online tests or password reset-emails)
2.) Another use case is to provide link with a token which are also valid for a fixed period of time, but in this case the link and the token can be used any number of time within the time period allowed (Ex. Online registration forms for test or some university enrollments).
So, definitely managing this using a session only will not be a good choice as the browsers can be cleared.
So you need to maintain the pair of the link and the token at the server (May be in a DB) with some other information like last accessed time, creation date and time, Valid upto .
To be more flexible validity time for link and the token can be set differently (eg. link can be used for a set of users, but the tokens are unique to a user).
So you can use this info on every user visit to check whether the link or token is still valid and what are their last accessed time. If it turn out to be expired then you can show the relevant error message.
What about "deleting the user's account" (depends on how you are building your logging system) after 24 hours.
Coupling this with checking user's account every time (s)he loads the page, will force him/her out at the first refreshing after the 24 hours threshold passses.
You can store the id with expiration time and when a request comes in with that id check if
it's still valid
and if you are trying to accomplish something like id is valid say 5 hrs after first request then store time when the first request is made and for each subsequent request check if it's still valid

Categories

Resources