Constantly print some info while executing a method in java - java

I have a scheduled java method which executes twice a day at a particular time, does some processing and usually takes around an hour to complete.
Now, during this hour, I need to print some method information out in a text file say every 15 minutes (basically serving as meta information, some variable value that changes during the processing), so this will print 4 times for a particular method.
I have written a separate method for printing but am not sure how to integrate it with my scheduled method above. Here is the code:
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class MainClass {
private static Timer timer = new Timer();
public static void print(){
timer.schedule (new MyTask(),0,1000*60*15);
}
}
class MyTask extends TimerTask {
public void run() {
PrintWriter writer = null;
String configurationFilePath ="job-configurations.txt";
try{
File file = new File(configurationFilePath);
if(!file.exists()){
file.createNewFile();
}
writer = new PrintWriter(file, "UTF-8");
writer.println("User Agent: "+ useragent);
writer.println("Location: "+country);
} catch (IOException e) {
LOGGER.error("Unable to add UA/Loc log file " + e.getMessage());
} finally {
if(writer != null){
writer.close();
}
}
}
}
How can i call this print method of main class and make it stop when the scheduled method completes execution.

You can make 2 static methods in Main class one to start print another to stop print and can call them from another class..
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Timer;
import java.util.TimerTask;
public class MainClass {
private static Timer timer = new Timer();
public static void startPrint(){
timer.schedule (new MyTask(),0,1000*60*15);
}
public static void stopPrint() {
timer.cancel();
}
}
class MyTask extends TimerTask {
public void run() {
PrintWriter writer = null;
String configurationFilePath ="job-configurations.txt";
try{
//start timer
MainClass.startPrint();
File file = new File(configurationFilePath);
if(!file.exists()){
file.createNewFile();
}
writer = new PrintWriter(file, "UTF-8");
writer.println("User Agent: "+ useragent);
writer.println("Location: "+country);
} catch (IOException e) {
LOGGER.error("Unable to add UA/Loc log file " + e.getMessage());
} finally {
if(writer != null){
writer.close();
}
//Stop Timer
MainClass.stopPrint();
}
}
}

Related

Jline input disrupted by System out

I'm having some trouble with Jline and not quite understanding how to work it properly, everything seems to work from the examples but when i attempt to move it into my console application things go weird.
I've come across two issues:
When you write input into the console while something else is logging a message via System out, the written input gets broken. (View: https://i.imgur.com/ZAJDjTI.png)
I attempted to sync the commands to the main thread since the reader thread will be blocking, but this time you'll find that this causes the output text to take over the commands input space.
((Green text is the input, white is output)View: https://i.imgur.com/CdKiIYy.png)
The output i expected was for input coming from the bottom of the console to be unaffected by the output of the console, leaving a smooth input text layer at the bottom. (View: https://i.imgur.com/HfH5l8U.png?1)
Here's an example class i wrote to demonstrate the two problems I'm having:
import jline.console.ConsoleReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.ReentrantLock;
public class Example {
private ConsoleReader consoleReader;
private LinkedList<Runnable> syncQueue = new LinkedList<>();
private ReentrantLock lock = new ReentrantLock();
public Example() {
try {
this.consoleReader = new ConsoleReader();
this.consoleReader.setExpandEvents(false);
} catch (IOException e) {
e.printStackTrace();
}
//If you enable this, Jline seems to be disrupted by the System out.
// startStopwatch();
setupJline();
//Ticker, its ugly i know
while (true) {
lock.lock();
try {
while (syncQueue.size() > 0) {
Runnable runnable = syncQueue.poll();
try {
runnable.run();
} catch (Exception e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void setupJline() {
new Thread("Console Thread") {
#Override
public void run() {
while (true) {
try {
String line = consoleReader.readLine(">");
if (line != null && line.trim().length() > 0) {
//Lets pass this on as an instruction to our program
//Sync seems okay, output wise
handleInstructionSynced(line);
//async seems to mess things up though, comment the handleInstructionSynced method and
//uncomment the Async one to see what i mean.
//handleInstructionAsync(line);
}
consoleReader.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
}
//Just a dummy example instruction handler
private void handleInstructionAsync(String input) {
System.out.println("You've input \"" + input + "\" as your instruction.");
}
private void handleInstructionSynced(String input) {
runSync(() -> System.out.println("You've input \"" + input + "\" as your instruction."));
}
private void runSync(Runnable runnable) {
lock.lock();
try {
syncQueue.add(runnable);
} finally {
lock.unlock();
}
}
private void startStopwatch() {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
int time = 0;
#Override
public void run() {
System.out.println(time + " seconds counted");
time++;
}
};
timer.scheduleAtFixedRate(timerTask, 0, 1000);
}
public static void main(String[] args) {
new Example();
}
}
Any solutions?

Java reference from static class

Sorry, this question has probably been asked before, but I couldn't find any with an answer in the context that applies specifically enough to my problem for me to apply the solution.
Anyways, I'm working on a program that uses a file. When that file is updated, I want it to replace the File variable with the current one. I set up a main class that will work with the file, then I set up another class with a different thread that listens for the file update. When the file is updated, I want the variable in the main class to be updated.
That means that the update listener class has to have the instance of the main class, but when I try to send it during initiation of the update listener class, a warning says the main class cannot be referenced from a static context.
Here's the code:
Main Class
package me.xeyler;
import com.sun.media.jfxmedia.logging.Logger;
import javax.swing.*;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import static java.nio.file.StandardWatchEventKinds.*;
/**
* Created by Brigham on 10/19/2016.
*/
public class ViewerMain {
static FileHandler fileHandler;
static File skinFile;
public static void main(String[] args) {
boolean bool = false;
fileHandler = new FileHandler(this);
fileHandler.start();
while(true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(bool);
}
}
public void setSkinFile(File skinFile) {
this.skinFile = skinFile;
}
}
File Listener Class
package me.xeyler;
import com.sun.media.jfxmedia.logging.Logger;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
/**
* Created by Brigham on 10/19/2016.
*/
public class FileHandler implements Runnable {
private Thread fileThread;
private String threadName;
WatchService watcher = null;
private ViewerMain main;
public FileHandler(ViewerMain main) {
this.main = main;
this.threadName = "FileThread";
}
public void watchFile(Path path) {
}
public void watchFile(File file) {
watchFile(Paths.get(file.getPath()));
}
public void close() {
try {
watcher.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void start () {
if (fileThread == null) {
System.out.println("Starting new thread...");
fileThread = new Thread (this, threadName);
fileThread.start();
System.out.println("Started thread: " + threadName);
}
}
#Override
public void run() {
System.out.println("Running thread...");
Path dir = Paths.get(System.getProperty("user.home"),"documents");
try {
watcher = FileSystems.getDefault().newWatchService();
WatchKey key = dir.register(watcher,
ENTRY_MODIFY);
} catch (IOException x) {
x.printStackTrace();
}
for (;;) {
// wait for key to be signaled
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
// The filename is the
// context of the event.
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path filename = ev.context();
if (filename.endsWith("text.txt")) {
System.out.println("File has changed");
//TODO: Update File variable in ViewerMain
main.setSkinFile(filename.toFile());
}
}
// Reset the key -- this step is critical if you want to
// receive further watch events. If the key is no longer valid,
// the directory is inaccessible so exit the loop.
boolean valid = key.reset();
if (!valid) {
// TODO: Handle inaccessible directory
break;
}
}
}
}
I suspect the answer is really obvious, but thanks for the patience!
If I understand correctly, you need an instance of the ViewerMain class.
this cannot be applied in a static context.
public static void main(String[] args) {
ViewerMain viewer = new ViewerMain(); // an instance
fileHandler = new FileHandler(viewer);
Same for skinFile
public File skinFile; // Remove static
public void setSkinFile(File skinFile) {
this.skinFile = skinFile;
}
You can not do this:
public void setSkinFile(File skinFile) {
this.skinFile = skinFile;
}
since skinFile is static, it would be better if you set that property as public static File skinFile; and then you accesed the property directly from the FileHandler:
ViewerMain.skinFile = filename.toFile()
given that it is a static property you dont need an instance of the class to access it, you can use the class directly.

Use Catch with a timer to return to the function

I am using the GitHub API, but it throws an exception because of the rate limit.
I use catch to catch this exception, but I want to use a timer count 1 hour and continue the function from where it stopped.
try{
// my function
}
catch (NoSuchPageException e ) {
Thread.sleep(3600 * 1000);
System.out.println("Waiting the timer");
}
How can I continue my function after the timer ends?
I suppose you can use a while loop.
boolean continueFunc = false;
while (!continueFunc)
try{
//my function
continueFunc = true;
}
catch (NoSuchPageException e ){
Thread.sleep(3600 * 1000);
System.out.println("Waiting the timer");
}
}
Your question is unclear but if you wish to retrieve html content but continue if you content is not there 1 hour later after calling the function you can use futures:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
public class FutureExample {
static class RetrieveHTMLThingy implements Callable<String> {
#Override
public String call() throws Exception {
System.out.println("Getting HTML Stuff");
Thread.sleep(2000);
return "html stuff";
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
FutureTask<String> getHTML = new FutureTask<String>(new RetrieveHTMLThingy());
executor.execute(getHTML);
try {
System.out.println(getHTML.get(1, TimeUnit.HOURS));
} catch (Exception e) {
e.printStackTrace();
}
}
}

Notification popup doesn't run with single instance

I want to display notification pop up when user attempts to run application second time , So I create NotificationPop obj and call the method to display the dialog within my single instance class ,but , it doesn't display popup when application runs second time there is no problem with my NotificationPop window it functions normal however when I call it within Single Instance doesn't display. in output window of Netbeans it displays dialog is closed as well. Do i miss any step here ?
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class SingleInstance {
public static File f;
public static FileChannel channel;
public static FileLock lock;
public static TrayCon trayobj;
public static boolean checkstatus;
public static NotificationPop obj;
public static void main(String args[]) throws IOException {
try {
f = new File("key");
if (f.exists()) {
f.delete();
}
channel = new RandomAccessFile(f, "rw").getChannel();
lock = channel.tryLock();
if (lock == null) {
obj = new NotificationPop();
obj.displaypopupmessage();
System.exit(0);
channel.close();
throw new RuntimeException("Only 1 instance can run");
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
trayobj = new TrayCon();
trayobj.CreateTrayCon(trayobj);
}
});
} catch (IOException ex) {
}
}
}
ok I have added thread sleep 6 seconds , fixed the issue
if (lock == null) {
obj = new NotificationPop();
obj.proragramstatuswarning();
Thread.sleep(6000);
System.exit(0);
channel.close();
throw new RuntimeException("Only 1 instance can run");
}

How does a program run after main() exits?

I have written a program that uses the twitter stream to write tweets in Realtime to a File via a BufferedWriter.
But the bufferedWriter does not write the text until i call the close() method at the end of the main function.
Now, when i run the program, the file is closed at first and then the tweets start coming. How does this thing work after main exits???
Here is the Code:
package analytics;
import twitter4j.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
public final class Trial_Filters {
static String Tweet;
static FileWriter output;
static BufferedWriter writer;
public static void main(String[] args) throws TwitterException,IOException {
if (args.length < 1) {
System.out.println("Usage: java twitter4j.examples.PrintFilterStream [follow(comma separated numerical user ids)] [track(comma separated filter terms)]");
System.exit(-1);
}
output= new FileWriter("Log.txt");
writer=new BufferedWriter(output);
StatusListener listener = new StatusListener() {
public void onStatus(Status status) {
StringBuilder temp;
//System.out.print("<sta>"); // Start Status -- helps for parsing two lines tweet;<sta> and </sta> used as tweet delimiters
temp=new StringBuilder("<sta>");
if(status.isRetweet())
temp.append("%");//System.out.print("%"); // easier to identify ReTweets
//System.out.println("#" + status.getUser().getScreenName() + " - " + status.getText());
temp.append("#" + status.getUser().getScreenName() + " - " + status.getText());
//System.out.print("</sta>"); //End Status
temp.append("</sta>");
Tweet=temp.toString();
this.add_to_Log();
}
private void add_to_Log(){
// TODO Auto-generated method stub
try{
output= new FileWriter("Log.txt");
writer=new BufferedWriter(output);
writer.write(Tweet);
System.out.println(Tweet);
}
catch(Exception e)
{
System.out.println(e);
}
}
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
System.out.println("Got a status deletion notice id:" + statusDeletionNotice.getStatusId());
}
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
System.out.println("Got track limitation notice:" + numberOfLimitedStatuses);
}
public void onScrubGeo(long userId, long upToStatusId) {
System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId);
}
public void onException(Exception ex) {
ex.printStackTrace();
}
};
TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
twitterStream.addListener(listener);
ArrayList<Long> follow = new ArrayList<Long>();
ArrayList<String> track = new ArrayList<String>();
for (String arg : args) {
if (isNumericalArgument(arg)) {
for (String id : arg.split(",")) {
follow.add(Long.parseLong(id));
}
} else {
track.addAll(Arrays.asList(arg.split(",")));
}
}
long[] followArray = new long[follow.size()];
for (int i = 0; i < follow.size(); i++) {
followArray[i] = follow.get(i);
}
String[] trackArray = track.toArray(new String[track.size()]);
// filter() method internally creates a thread which manipulates TwitterStream and calls these adequate listener methods continuously.
twitterStream.filter(new FilterQuery(0, followArray, trackArray));
try{
System.out.println("bye");
writer.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
private static boolean isNumericalArgument(String argument) {
String args[] = argument.split(",");
boolean isNumericalArgument = true;
for (String arg : args) {
try {
Integer.parseInt(arg);
} catch (NumberFormatException nfe) {
isNumericalArgument = false;
break;
}
}
return isNumericalArgument;
}
}
The virtual machine terminates all activity and exits after the last non-daemon thread ("User Thread") has terminated (or some thread invoked System.exit()). That last User thread doesn't have to be the main thread.
The tweets (packets) are sent to a local socket and the socket is only bound as long as the virtual machine is up and running (in case the socket hasn't been closed manually). So the feed may be sending but the computer won't accept the data and the tweet source will receive errors.
The TwitterStream Object will start a thread, and that thread will call back on the StatusListener. The program will run until there is a thread running, even if the main thread seems to have finished, it waits for all other threads to stop, before the main thread stops, and the program exits.
It does not matter if you close the writer or not on the end of main. The reference of the writer will be rewritten on each call to add_to_log. That means on each new status a new writer gets instantiated, writes out the message into the bufferedwriter.
The following two lines at the beginning of the code are irrelevant:
output= new FileWriter("Log.txt");
writer=new BufferedWriter(output);
However it would be better to call flush() or close() in add_to_log to make sure everything gets written to disk.
When you close a program with a bufferedWriter activated, the system triggers the buffered writer to flush its output to whatever endpoint it's hooked up to, be it a file or stdout. Over time, what could be happening, is that documents are arriving on the socket and getting placed into the bufferedwriter, but your the writer just stores them up because you haven't called flush() from the code or the writer threshold for doing a dump hasn't been crossed. When you call close, under the hood, it calls flush and forces the output to dump--even if the program is "closed".

Categories

Resources