JAVA method return something then send email - java

Here is my code:
public String addxyz ()
{
String returnStatus = "";
DBConnection conn = new DBConnection();
returnStatus = conn.fun_GetData();
ArrayList<String> emailList = new ArrayList<String>();
emailList.add("xyz#gmail.com");
emailList.add("asd#hotmail.com");
for(String email : emailList)
{
SendEmail sendEmail = new SendEmail();
boolean statusEmail = sendEmail.SendingEmail(email);
}
return returnStatus;
}
I want to know what is the best way to send email to every email address after returning method status.
For example I have 100 email list so the above method is first sending 100 email then return status.
But i want to return something then send email so is that possible?

You have to send emails asynchronously then.
You can very well right a multi threaded program wherein you are sending emails in a different executor thread and main thread returns back with a status without getting blocked on sending the emails.
You can use Java Executors api for this one.

For multi threading you can do like this:
public String addxyz (String qweqw)
{
String returnStatus = "status";
ArrayList<String> emailList = new ArrayList<String>();
emailList.add("xyz#gmail.com");
emailList.add("asd#hotmail.com");
for(String email : emailList)
{
// create a thread
Thread th = new Thread(){
#Override
public void run(){
// Your SendMail logic
SendEmail sendEmail = new SendEmail();
boolean statusEmail = sendEmail.SendingEmail(email);
}
};
th.start(); // start the thread & continue to next email
}
return returnStatus;
}

From the snippet in your question, the status and parameter seem completely useless. So you could do:
// in main execution path
String returnStatus = "status";
new Thread( new Runnable() {
#Override public void run(){ addxyz("dummy"); }
} ).start();
But I really doubt that this will work out. I guess your example misses where and why status could be changed in the function. Then this solution is void!
UPDATE
From the point where your status won't change inside the function, you can wrap the rest in a Thread/Runnable and run it. For example:
....
returnStatus = conn.fun_GetData();
new Thread( new Runnable() { #Override public void run() {
ArrayList<String> emailList = new ArrayList<String>();
emailList.add("xyz#gmail.com");
emailList.add("asd#hotmail.com");
for(String email : emailList)
{
SendEmail sendEmail = new SendEmail();
boolean statusEmail = sendEmail.SendingEmail(email);
}
}}).start();
return returnStatus;
In Java 8 you can also use Lambda:
new Thread( () -> {
// your code here
} ).start();

Related

Return arraylist populated inside Callback

I'm trying to use an arraylist of Tweets that has been populated inside a callback but I can't figure out how to return the built list. Whenever I try to use the built list it's empty.
I got some code from this post
public ArrayList<Tweet> tweetList() {
final ArrayList<Tweet> tweets = new ArrayList<>();
final UserTimeline userTimeline = new UserTimeline.Builder()
.screenName("xxxxxxxx")
.build();
userTimeline.next(null, new Callback<TimelineResult<Tweet>>() {
#Override
public void success(Result<TimelineResult<Tweet>> result) {
for(Tweet tweet : result.data.items){
tweets.add(tweet);
}
Log.d("Finished Tweet List", String.valueOf(tweets));
// when this is printed I can see the ArrayList and all tweets are there
}
#Override
public void failure(TwitterException exception) {
exception.printStackTrace();
}
});
Log.d("Tweet list returned", String.valueOf(tweets));
// the value of tweets is empty here for some reason
return tweets;
}
Instead of returning the empty ArrayList of Tweets, you can modify your method so another ArrayList of Tweets is updated when the response from the Callback succeeds.
So I suggest modifying your method as follows:
private ArrayList<Tweet> tweetList = new ArrayList<>();
public void tweetList() {
final ArrayList<Tweet> tweets = new ArrayList<>();
final UserTimeline userTimeline = new UserTimeline.Builder()
.screenName("xxxxxxxx")
.build();
userTimeline.next(null, new Callback<TimelineResult<Tweet>>() {
#Override
public void success(Result<TimelineResult<Tweet>> result) {
for(Tweet tweet : result.data.items){
tweets.add(tweet);
}
this.tweetList = tweets;
// execute the next sequence of instructions in your program here
// and make use of tweetList instead of tweets
}
#Override
public void failure(TwitterException exception) {
exception.printStackTrace();
}
});
}
Of course, the value of tweets is empty here !
The function userTimeline.next(null, new Callback<TimelineResult<Tweet>>() is not executed on the main thread (It is an asynchronous task).
So the return tweets is called before your ArrayList<Tweets> tweets has been filled.
You can only do operations on your list in the
#Override
public void success(Result<TimelineResult<Tweet>> result) {
//do whatever with your list here !
}
Hope I'll have been clear !

Google Cloud Endpoint execute async code in endpoints

I am trying to authenticate client token created by Firebase authentication library in Android in GCE endpoint.
The guide of how to do this can be found here
Basically I need to call this code snippet from the end point (i.e. server backend code not android code).
FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
// ...
}
});
Let say I want to execute that code and return the user to android client code. How should I do that?
This is my sample code that does not make sense. But it demonstrate what I want to do!
#ApiMethod(name = "serverAuth")
public MyUser serverAuth(#Named("token") String token) {
FirebaseAuth.getInstance().verifyIdToken(token)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
String email = decodedToken.getEmail();
String name = decodedToken.getName();
Map<String, Object> claims = decodedToken.getClaims();
String claimString = "";
for (Object claim : claims.values()) {
claimString += claims.toString();
}
MyUser user = new MyUser(uid, email, name, claimString);
//How to return this user?
}
});
//This is compile error since user varriable does not exist here
return user;
}
I have google search how to execute async code in GCE endpoints. But getting nowhere with that. What I get is something about code execution that is blocking until done and then return the user. But how to code so that async code as above become blocking?
CountDownLatch is the magic class you need. It will let you wait till the OnSuccessListener is actually completed.
Adapt your method this way: (I removed the steps that lead to MyUser's creation in order to focus on important points.)
#ApiMethod(name = "serverAuth")
public MyUser serverAuth(#Named("token") String token) {
final List<MyUser> users = new ArrayList<>();
final CountDownLatch cdl = new CountDownLatch(1);
FirebaseAuth.getInstance().verifyIdToken(token)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
// ... init uid, email, name and claimString
users.add(new MyUser(uid, email, name, claimString));
cdl.countDown();
}
});
try {
cdl.await(); // This line blocks execution till count down latch is 0
} catch (InterruptedException ie) {
}
if (users.size() > 0) {
return users.get(0);
} else {
return null ;
}
}
This is the basic version of what you need. IMHO, it requires 2 more improvements :
You should also take the possibility of failure into account :
FirebaseAuth.getInstance().verifyIdToken(token)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
cdl.countDown();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// log error, ...
cdl.countDown();
}
});
You should also take the possibility that none of the listeners are called. In this situation your method will never return. To avoid that, you can set a timeout on the await() method :
try {
// This line blocks execution till count down latch is 0
// or after 30 seconds.
cdl.await(30l, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
}
That's it. Hope this may help.

Java function returns empty string [duplicate]

This question already has answers here:
How to use Jsoup with Volley?
(3 answers)
Closed 6 years ago.
I'm trying to parse data from my server in Java with jsoup. I wrote a new function and it should return data in string format, but it returns blank string. Here is my code:
public String doc;
public String pare(final String url){
Thread downloadThread = new Thread() {
public void run() {
try {
doc = Jsoup.connect(url).get().toString();
}
catch (IOException e) {
e.printStackTrace();
}
}
};
downloadThread.start();
return doc;
}
You're returning the doc object immediately, before the thread has had a chance to add any data to it, so it should be no surprise that this returns empty. You can't return threaded information in this way, and instead will need to use some type of call-back mechanism, one that notifies you when the thread is done and when data is ready to be consumed.
On android platform, you shouldn't ask Jsoup to download anything for you. Under the hood, Jsoup make use of HttpUrlConnection. This class is notoriously slow and has some known issues.
Use a faster alternative instead: Volley.
Here is the function in your post taking advantage of Volley. In the following sample code, I'm using a CountDownLatch to wait for the data.
private static RequestQueue myRequestQueue = null;
public String pare(final String url) throws Exception {
final String[] doc = new String[1];
final CountDownLatch cdl = new CountDownLatch(1);
StringRequest documentRequest = new StringRequest( //
Request.Method.GET, //
url, //
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
doc[0] = Jsoup.parse(response).html();
cdl.coutDown();
}
}, //
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("MyActivity", "Error while fetching " + url, error);
}
} //
);
if (myRequestQueue == null) {
myRequestQueue = Volley.newRequestQueue(this);
}
// Add the request to the queue...
myRequestQueue.add(documentRequest);
// ... and wait for the document.
// NOTA: User experience can be a concern here. We shouldn't freeze the app...
cdl.await();
return doc[0];
}
I totally agree with the above answer. You can follow any of the below tutorials for fetching data from server
http://www.androidhive.info/2014/05/android-working-with-volley-library-1/
http://www.vogella.com/tutorials/Retrofit/article.html
These two are the best libraries for Network calls in android
Before the return statement add a downloadThread.join(). This will wait until the thread has finished and put the response into doc. But: Doing so you will loose all benefit from the asynchronous execution, it's behaving the same as you just would code:
public String pare(final String url){
return Jsoup.connect(url).get().toString();
}

Filtering latest tweets

I am trying to filter the latest tweets with the words sad, okay, joyful.
When a tweet which has either word inside it, I would like it to print that tweet. But I would also like there to be a delay in the tweets which are printed. So about a 10 second delay between each tweet. For example:
If a tweet comes through : #joker im so sad today
Then I want that to print to the screen, and to the following message
System.out.println("*************************a sad tweet");
Then if a tweet comes through after this: #programmer im joyful
Then 10 seconds after the last tweet I want that tweet to come through with the following message drawn to the screen.
System.out.println("*************************a joyful tweet");
And so on.
Below, I have made some code which allows you to filter the tweets, but im unsure of how to test and print a separate message for each tweet. I tried storing this in an Arraylist and retrieving each tweet with a message, but this doesn't work. Is there a way to do this?
Im using processing 2 and twitter4j 3
Any suggestions? Solutions
void GetTweetsByKeywords()
{
List<String>mood = new ArrayList <String>();
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("XXXX");
cb.setOAuthConsumerSecret("XXX");
cb.setOAuthAccessToken("XXXX");
cb.setOAuthAccessTokenSecret("XXXX");
TwitterStream twitterStream = new TwitterStreamFactory(cb.build()).getInstance();
StatusListener statusListener = new StatusListener()
{
private int count = 0;
private long originalTweetId = 0;
#Override
public void onStatus(Status status)
{
System.out.println(status.getUser().getName() + " : " + status.getText());
} //en of the onStatus()
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice)
{
// should really remove deleted tweets here ...
}
public void onTrackLimitationNotice(int numberOfLimitedStatuses)
{
}
public void onScrubGeo(long userId, long upToStatusId) {
// should really remove deleted location information here ...
}
public void onStallWarning(StallWarning stallWarning) {
// should really do something about stalls here ...
}
#Override
public void onException(Exception ex)
{
ex.printStackTrace();
}
}; //end of the listener
String keywords[] = {"sad","okay","joyful"};
for(int i=0; i<keywords.length; i++)
{
FilterQuery fq = new FilterQuery();
fq.track(keywords);
twitterStream.addListener(statusListener);
twitterStream.filter(fq);
mood.add(//here i want to add the filtered tweets);
System.out.println("Heres a filter :" + mood.get(i));
if (mood.get(i).equals("sad"))
{
System.out.println("*********************************************a sad tweet");
}
else if (mood.get(i).equals("joyful"))
{
System.out.println("*********************************************a joyfull tweet");
}
else if(mood.get(i).equals("okay"))
{
System.out.println("*********************************************okay tweet");
}
}
}
The easiest is to use a separate thread and a queue. Do this:
final Queue<Status> queue = new LinkedBlockingQueue<Status>(10000);
new Thread(){
// In your status listener, post tweets to the queue
...
public void onStatus(Status status){
queue.offer(status);
}
...
// Create TwitterStream instance, add query
// and start listening
twitterStream.filter(fq);
}.start();
while(!Thread.currentThread().isInterrupted()){
Status nextTweet = queue.take();
System.out.println("Do stuff with tweet");
}

Synchronizing HttpURLConnection and KeyListener:

So, I'm trying to write code for a search JTextField that retrieves results from the web (kinda like Google's fancy search tips). The only problem is... probably my lack of programming experience. More specifically, I have it set up to whenever a user hits a key, it sends out a request with the JTextField input through an HttpURLConnection and retrieves the results then updates. But whenever the HttpURLConnection is running, it freezes the program for a couple seconds while it does its thing, which mainly prohibits entering in more characters into the search field if I didn't mind anything else. I've considered using separate threads, but I'm not sure how I would properly interrupt a thread and have it start over using new data while having everything else wait on it but still accepting new data. I've considered using
thread.stop();
to help manage the issue, but from what I've read, that seems taboo (am I right?). Anyways, here's pretty much what I'm using:
public class SearchField extends JTextField implements KeyListener {
public SearchField() {
addkeyListener(this);
}
public void updateData(ArrayList<String results) {
/*Pass the data off the the GUI*/
{
#Override
public void keyTyped(KeyEvent e) {
SearchQuery query = new SearchQuery(this.getText());
updateData(query.getResults());
}
}
public class SearchQuery {
ArrayList<String> results = new ArrayList<String>();
public SearchQuery(String search) {
String search_path = "http://www.whatever.com/" + search;
URL url = new URL(search_path);
conn = (HttpURLConnection) url.openConnection();
conn.addRequestProperty("User-Agent", "Mozilla/4.76");
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
StringBuffer buf = new StringBuffer();
int i;
while((i = in.read()) != -1) {
buf.append((char) i);
}
String data = buf.toString();
parse(data);
}
public void parse(String data) {
/*Parse a bunch of JSON, return the results in an array*/
results.add(data);
}
public ArrayList<String> getResults() {
return results;
}
}
I'm just at a loss for how to synchronise recieving continuous input while getting new results for each key stroke and dismissing unfinished connections and their respective data processing when it becomes invalid at the next key stroke.
You are doing the download in the same thread that responds to user events. You need to do the download in another thread, perhaps by making SearchQuery extend Thread and doing the query in the run method. When it comes time to update the text field, you can use SwingUtilities.invokeLater to update the text field. Here’s an example:
public class SearchQuery extends Thread {
private SearchField f;
public SearchQuery(JTextField f) {
this.f = f;
}
public void run() {
// do the query here
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.updateData(results);
}
});
}
}
Then change the line:
SearchQuery query = new SearchQuery(this.getText());
to this:
SearchQuery query = new SearchQuery(this);

Categories

Resources