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.
Related
I am using Watcher service to monitor a directory in Windows. If a change is done to a file, I'd like to write a timestamp to the same file. Of course, this is yet another modification to the directory and watcher then processes the event again. Is there a way to suspend watcher so I can update the file, then restart it so it can wait for the next event?
Perhaps there's a better suggestion???
package net.codejava.io;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.sql.Timestamp;
import java.util.Date;
public class DirectoryWatchDemo {
static String logfile = "C:/Temp/log.txt";
volatile static boolean suspended = false;
public static void main(String[] args) {
try {
WatchService watcher = FileSystems.getDefault().newWatchService();
Path dir = Paths.get("C:/Temp/");
dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
// System.out.println("Watch Service registered for dir: " +
// dir.getFileName());
while (true) {
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException ex) {
return;
}
if (!suspended) {
resume();
} else {
updateFile();
suspend();
}
if (key.isValid())
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
#SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
System.out.println(kind.name() + ": " + fileName);
}
boolean valid = key.reset();
if (!valid) {
System.out.println("Watch service invalid");
break;
}
}
} catch (IOException ex) {
System.err.println(ex);
}
}
private static void suspend() {
suspended = false;
}
private static void resume() {
suspended = true;
}
public static void updateFile() {
try {
File outfile = new File(logfile);
if (!outfile.exists()) {
System.out.println("No file exists...writing a new file");
outfile.createNewFile();
}
FileWriter fw = new FileWriter(outfile.getAbsoluteFile(), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("TimeStamp: " + new Timestamp(new java.util.Date().getTime()).toString() + "\r\n");
bw.flush();
bw.close();
System.out.println("done");
} catch (IOException e) {
e.printStackTrace();
}
}
}
You need to interrupt the thread that is using the watch service, because that's the only way you get out of watcher.take(). Example with old-school threads:
public void start() {
thread = new Thread(directoryWatchDemo::watch);
thread.start();
}
public void pause() throws InterruptedException {
if (thread.isAlive()) {
thread.interrupt();
thread.join();
}
}
See ExecutorService like Executors.newSingleThreadExecutor() and Future.cancel() for more flexibility.
Alternatively, you can take() all events and ignore them based on a volatile boolean.
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");
}
I want to capture an AXIS camera & stream it. I am quite new to RED5. I get the following error:
Exception in thread "main" java.lang.NullPointerException at
org.vikulin.rtmp.publisher.Publisher2.packetReceived(Publisher2.java:23)
at
org.red5.server.presentation.output.flv.FLVStream.dispatchEvent(FLVStream.java:243)
at
org.red5.server.presentation.output.flv.FLVStream.sendAVCDecoderConfig(FLVStream.java:162)
at
org.red5.server.presentation.output.flv.FLVStream.addEvent(FLVStream.java:76) at
org.red5.server.presentation.MediaPresentation.onMediaEvent(MediaPresentation.java:43)
at
org.red5.server.presentation.input.avp.codecs.H264.addPacket(H264.java:206)
at
org.red5.server.presentation.RTSPStream.onRTSPEvent(RTSPStream.java:100)
at
org.red5.server.net.rtsp.proxy.RtspTcp.setupAndPlay(RtspTcp.java:287)
at org.red5.server.presentation.RTSPStream.onSDP(RTSPStream.java:138)
at
org.red5.server.net.rtsp.proxy.RtspTcp.parseDescription(RtspTcp.java:128)
at org.red5.server.net.rtsp.proxy.RtspTcp.describe(RtspTcp.java:64)
at
org.red5.server.presentation.RTSPStream.startInput(RTSPStream.java:77)
at org.red5.server.presentation.RTSPStream.start(RTSPStream.java:82)
at org.vikulin.rtmp.publisher.Publisher2.main(Publisher2.java:49)
Here is the code:
import java.io.IOException;
import org.red5.server.api.stream.IBroadcastStream;
import org.red5.server.api.stream.IStreamListener;
import org.red5.server.api.stream.IStreamPacket;
import org.red5.server.net.rtmp.event.VideoData;
import org.red5.server.presentation.RTSPStream;
import org.red5.server.stream.message.RTMPMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Publisher2 implements IStreamListener {
PublishClient client;
#Override
public void packetReceived(IBroadcastStream arg0, IStreamPacket arg1) {
System.out.println("" + arg1);
VideoData data = new VideoData(arg1.getData());
RTMPMessage message = RTMPMessage.build(data);
try {
client.pushMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
Logger log = LoggerFactory.getLogger(Publisher2.class);
String publishName = "testb";
String host = "127.0.0.1";
int port = 1935;
String app = "live";
PublishClient client = new PublishClient();
client.setHost(host);
client.setPort(port);
client.setApp(app);
client.start(publishName, "live", null);
while (client.getState() != PublishClient.PUBLISHED) {
Thread.sleep(500);
}
Publisher2 test = new Publisher2();
final RTSPStream camera = new RTSPStream("192.168.254.115", 554,
"rtsp://192.168.254.115/axis-media/media.amp?videocodec=h264&videokeyframeinterval=30&fps=30");
camera.addStreamListener(test);
new Thread(new Runnable() {
#Override
public void run() {
camera.start();
}
}).start();
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
camera.stop();
try {//wait for write out.
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
client.stop();
}
}
If you have any idea please help me!
You declared a client variable in your main method, but in your packetReceived method, you reference the class variable. The class variable is still null at that point. So, possibly change this line:
PublishClient client = new PublishClient();
to this:
client = new PublishClient();
or pass the client in to your method, and remove variable declaration from your class.
I have tried nearly everything to get this work, but it seems that I don't get the right direction.
Here is the actual Situation: I use JSF2.2 with GlashFish7 under Netbeans7.3. My JSF application should create an second thread to run(Asynchronously) an endless loop. In this endless loop I use the WatchService (NIO) to check a specific folder for changes.
The WatchService function works fine in a single thread driven jsf page. But I will do other stuff and during the loop, so I need this methode async, but i'm not able to run it in a seperad thread.
Here is my java class:
#Stateless
public class NewFile {
#Asynchronous
public void showNewFile() throws IOException{
WatchService watchService = FileSystems.getDefault().newWatchService();
WatchKey watchKey = Paths.get("/home/user/input").register(watchService,new WatchEvent.Kind<?>[] { ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE });
while (true) {
try {
watchKey = watchService.take();
} catch (InterruptedException ex) {
System.out.println("InterruptedException: " + ex);
}
for (WatchEvent<?> watchEvent : watchKey.pollEvents()) {
System.out.println(watchEvent.kind() + " " + ((Path) watchEvent.context()));
}
watchKey.reset();
}
}
}
In this class I call the methode:
#Named("startWatcher")
public class StartWatcher {
private NewFile newFile;
public void runSearcher() throws IOException{
newFile.showNewFile();
}
}
and the relevant section from thy index.xhtml
<h:commandButton actionListener="#{startWatcher.runSearcher()}" value="test"/>
I hope you understand my problem, I know my english isn't very good. i'm looking forward to receive a hint what i'm doing wrong.
Typically, you should start a watchservice thread when your GlassFish domain is deployed by defining a #WebListener, for example:
import static java.nio.file.StandardWatchEventKinds.*;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
#WebListener
public class MyServletContextListener implements ServletContextListener {
private final NewFileRunner runner = new NewFileRunner();
#Override
public void contextInitialized(ServletContextEvent sce) {
runner.startThread();
}
#Override
public void contextDestroyed(ServletContextEvent arg0) {
runner.stopThread();
}
class NewFileRunner implements Runnable {
private volatile Thread thread;
private final WatchService watchService;
public NewFileRunner() {
watchService = FileSystems.getDefault().newWatchService();
Paths.get("/home/user/input").register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
}
/**
* Start a worker thread to listen for directory changes.
*/
public void startThread() {
thread = new Thread(this);
thread.start();
}
/**
* Flag worker thread to stop gracefully.
*/
public void stopThread() {
if (thread != null) {
Thread runningThread = thread;
thread = null;
runningThread.interrupt();
}
}
#Override
public void run() {
Thread runningThread = Thread.currentThread();
while (runningThread == thread) {
WatchKey watchKey = null;
try {
watchKey = watchService.take();
if (watchKey != null) {
for (WatchEvent<?> watchEvent : watchKey.pollEvents()) {
System.out.println(watchEvent.kind() + " " + ((Path) watchEvent.context()));
}
watchKey.reset();
}
} catch (InterruptedException e) {
e = null;
}
}
}
}
}
Of course, I'd refactor this out into multiple classes, but this will point you in the right direction.
I'm encountering a weird issue in Java at the moment that I've never seen before.
The error is "No enclosing instance of type Server is accessible. Must qualify the allocation with an enclosing instance of type Server (e.g. x.new A() where x is an instance of Server)."
The line I've commented on is where the error occurs.
package game;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
public class Server {
private static List<ThreadModtagClient> clients;
class ReceiveDataListener implements SocketListener {
#Override
public void dataReceived(ThreadModtagClient client, String data) {
}
}
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
clients = new ArrayList<ThreadModtagClient>();
ServerSocket welcomeSocket = new ServerSocket(16567);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
ThreadModtagClient client = new ThreadModtagClient(connectionSocket);
ReceiveDataListener listener = new ReceiveDataListener(); // <--- this is where the error occurs
client.addSocketListener(listener);
clients.add(client);
}
}
}
class ThreadModtagClient extends Thread implements SocketThread {
private BufferedReader inFromClient;
private DataOutputStream outToClient;
private Player player;
private List<SocketListener> listeners;
public ThreadModtagClient(Socket connection) throws IOException {
inFromClient = new BufferedReader(new InputStreamReader(connection.getInputStream()));
outToClient = new DataOutputStream(connection.getOutputStream());
listeners = new ArrayList<SocketListener>();
}
public void addSocketListener(SocketListener listener) {
listeners.add(listener);
}
public void removeSocketListener(SocketListener listener) {
listeners.remove(listener);
}
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public void sendData(String data) throws IOException {
outToClient.writeChars(data);
}
public void run() {
while (true) {
try {
String data = inFromClient.readLine();
for(SocketListener listener : listeners) {
listener.dataReceived(this, data);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(NoSuchElementException e1) {
e1.printStackTrace();
}
}
}
}
Server.ReceiveDataListener is a (non-static) inner class. You are creating it from a static context. You need to supply an instance of Server to be the outer instance. However, almost certainly you want ReceiveDataListener to be a static nested class, or probably an outer class.
well the error tells you exactly what needs to be done. ReceiveDataListener is a non-static inner class and must be accessed via an object of the outer class (Server). You have three options:
1. take the compiler's advice (access via an object of Server)
2. make ReceiveDataListener static
3. pull ReceiveDataListener out to a separate .java and use it.
HTH
You cannot instantiate a non-static inner class from a static context like main.
This is because you're trying to create a ReceiveDataListener from a static method, and since ReceiveDataListener is not a static class, it needs to be attached to an instance of Server.