Java array of shared objects initialization error - java

I have a class Logger that uses 3 arraysas xhared variables
The arrays are initialized in the contructor
but when accessing them in any other method of the class, I get a
NullPointerException.
I need to know the reason and the solution.
Please see comments in the code.
file Logger.java
package logger_010.standard;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class Logger {
// declaration
private FileOutputStream[] files;
private PrintStream[] pss;
private String[] messages;
public Logger() {
// initialisation
try {
FileOutputStream[] files = {
new FileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger0.log"),
new FileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger1.log"),
new FileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger2.log"),
};
PrintStream[] pss = {
new PrintStream(files[0]),
new PrintStream(files[1]),
new PrintStream(files[2]),
};
String[] messages = {
new String ("Write error message to log file 0"),
new String ("Write error message to log file 1 + user"),
new String ("Write error message to log file 2 + user+ email"),
};
// Arrays instanciation is OK
System.out.println(files[0].toString());
System.out.println(files[1].toString());
System.out.println(files[2].toString());
System.out.println(pss[0].toString());
System.out.println(pss[1].toString());
System.out.println(pss[2].toString());
System.out.println(messages[0].toString());
System.out.println(messages[1].toString());
System.out.println(messages[2].toString());
System.out.println("++++++++++++");
} catch (Exception e) {
System.out.println("Exception " + e.getMessage());
} finally {
}
}
public void LogMessage(int level) {
// Here I get a Null pointer exception
System.out.println(files[0].toString());
System.out.println(files[1].toString());
System.out.println(files[2].toString());
System.out.println(pss[0].toString());
System.out.println(pss[1].toString());
System.out.println(pss[2].toString());
System.out.println(messages[0].toString());
System.out.println(messages[1].toString());
System.out.println(messages[2].toString());
System.out.println("++++++++++++");
// PrintStream[] files = OpenFiles();
WriteLogMessage(this.getPss(), level);
CloseFiles(pss);
}
private void CloseFiles(PrintStream[] pss2) {
// TODO Auto-generated method stub
}
private PrintStream[] OpenFiles() {
// TODO Auto-generated method stub
return null;
}
private void WriteLogMessage(PrintStream[] files, int level) {
this.getPss()[level].println(messages[level]);
this.getPss()[level].flush();
}
public FileOutputStream[] getFiles() {
return files;
}
public void setFiles(FileOutputStream[] files) {
this.files = files;
}
public PrintStream[] getPss() {
return pss;
}
public void setPss(PrintStream[] pss) {
this.pss = pss;
}
public String[] getMessages() {
return messages;
}
public void setMessages(String[] messages) {
this.messages = messages;
}
}
this is the file containing the main function
package logger_010.standard;
public class Start {
public static void main(String[] args) {
// TODO Auto-generated method stub
Logger l = new Logger();
for (int i = 0; i < 15; i++) {
int level = i % 2;
l.LogMessage(level);
}
}
}

You are declare a new files, message, pss variable inside constructor instead of using the variable already created of class => when using in the LogMessage method, it use the variable not init => cause the error

You never actualy bind your class attribut with the object you define in your constructor.
By defining FileOutputStream[] files = ... instead of files = ..., which is your object attribut, you are just making a local variable whose scope is only inside the constructor.
Your constructor should be :
public Logger() {
// initialisation
try {
files = {
new FileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger0.log"),
new FileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger1.log"),
new FileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger2.log"),
};
pss = {
new PrintStream(files[0]),
new PrintStream(files[1]),
new PrintStream(files[2]),
};
messages = {
new String ("Write error message to log file 0"),
new String ("Write error message to log file 1 + user"),
new String ("Write error message to log file 2 + user+ email"),
};
// Arrays instanciation is OK
System.out.println(files[0].toString());
System.out.println(files[1].toString());
System.out.println(files[2].toString());
System.out.println(pss[0].toString());
System.out.println(pss[1].toString());
System.out.println(pss[2].toString());
System.out.println(messages[0].toString());
System.out.println(messages[1].toString());
System.out.println(messages[2].toString());
System.out.println("++++++++++++");
} catch (Exception e) {
System.out.println("Exception " + e.getMessage());
} finally {
}
}

If I initialize the FileOutputStream array with a sub class of FileOutputStream and a constructor that throws a FileNotFoundException I get this compilation error
"Default constructor cannot handle exception type FileNotFoundException thrown by implicit super constructor. Must define an explicit constructor".
I finally solved the problem by using a function (makeFileOutputStream) and this function call the FileOutputStream constructor in a try/catch block
here is the code for my class Blogger
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class Logger {
// declarations
private FileOutputStream[] files = {
makeFileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger0.log"),
makeFileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger1.log"),
makeFileOutputStream("G:\\Users\\TarekEZZAT\\Documents\\logs\\logger2.log"),
};
private PrintStream[] pss = {
new PrintStream(files[0]),
new PrintStream(files[1]),
new PrintStream(files[2]),
};
private String[] messages = {
new String("Write error message to log file 0"),
new String("Write error message to log file 1 + user"),
new String("Write error message to log file 2 + user+ email"),
};
private FileOutputStream makeFileOutputStream(String string) {
// TODO Auto-generated method stub
FileOutputStream fos = null;
try {
fos = new FileOutputStream(string);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return fos;
}
public void LogMessage(int level) {
WriteLogMessage(this.getPss(), level);
}
public void CloseFile(PrintStream[] files, int level){
// TODO Auto-generated method stub
this.getPss()[level].close();
}
private void WriteLogMessage(PrintStream[] files, int level) {
this.getPss()[level].println(messages[level]);
this.getPss()[level].flush();
}
// Getters and Setters
public FileOutputStream[] getFiles() {
return files;
}
public void setFiles(FileOutputStream[] files) {
this.files = files;
}
public PrintStream[] getPss() {
return pss;
}
public void setPss(PrintStream[] pss) {
this.pss = pss;
}
public String[] getMessages() {
return messages;
}
public void setMessages(String[] messages) {
this.messages = messages;
}
}

Related

Observer with RxJava/Quarkus

I started a Quarkus project, which (in part) shall watch for file changes on a text-file, read the added line(s) and then sends the added line(s) through a websocket connection to a client.
For watching the file changes and reading those I created the following class:
public class McServerService {
private String directory;
private List<String> currentLog;
private Observable<List<String>> observableLog;
private Thread logObserverThread;
public McServerService (String directory) {
this.currentLog = new ArrayList<String>();
this.observableLog = Observable.fromCallable(() -> this.currentLog);
this.directory = directory;
}
public void startWatching () {
this.logObserverThread = new Thread(new LogObserverThreadImpl(this.directory));
this.logObserverThread.start();
}
public void subscribeToLog (Observer<? super List<String>> observer) {
this.observableLog.subscribe(observer);
}
private class LogObserverThreadImpl implements Runnable {
BufferedReader br;
WatchService watchService;
private LogObserverThreadImpl (String directory) {
try {
this.br = new BufferedReader(new java.io.FileReader(directory + "\\" + "latest.log"));
String nextLine;
while ((nextLine = this.br.readLine()) != null) {
McServerService.this.currentLog.add(nextLine);
System.out.println(nextLine);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
Path path = Paths.get(directory);
try {
System.out.println("entered try");
this.watchService = FileSystems.getDefault().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey key;
while ((key = this.watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
if (event.context().toString().equals("latest.log")) {
String line = this.br.readLine();
McServerService.this.currentLog.add(line);
System.out.println(line);
}
}
key.reset();
}
System.out.println("after while");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Now the websocket would be handled by this class:
#ServerEndpoint("/test")
#ApplicationScoped
public class McServerWebSocket {
Map<String, Session> sessions = new ConcurrentHashMap<>();
McServerService mss = new McServerService("D:\\Spiele\\Minecraft");
#OnOpen
public void onOpen(Session session, #PathParam("name") String name) {
sessions.put(name, session);
}
#OnClose
public void onClose(Session session, #PathParam("name") String name) {
sessions.remove(name);
}
#OnError
public void onError(Session session, #PathParam("name") String name, Throwable throwable) {
sessions.remove(name);
}
#OnMessage
public void onMessage(String message, #PathParam("name") String name) {
Session c_session = sessions.get(name);
c_session.getAsyncRemote().sendObject("insert");
}
private class ConsoleLogObserverImpl implements Observer<List<String>>{
private ConsoleLogObserverImpl () {
}
#Override
public void onSubscribe(#NonNull Disposable d) {
// TODO Auto-generated method stub
System.out.println("subscribed");
}
#Override
public void onNext(#NonNull List<String> t) {
System.out.println(t.toString());
}
#Override
public void onError(#NonNull Throwable e) {
// TODO Auto-generated method stub
}
#Override
public void onComplete() {
// TODO Auto-generated method stub
System.out.println("finished");
}
}
}
I didnt implement the websocket yet, because my problem lies with observing the changes of
private List<String> currentLog; in the McServerServive class.
Unfortunately I deleted the main method in McServerWebSocket, that I used to test this, but that main method would essentially just create an instance of McServerWebSocket and then call the startWatching() method of its McServerService mss = new McServerService("D:\\Spiele\\Minecraft"); and its
public void subscribeToLog (Observer<? super List<String>> observer) {
this.observableLog.subscribe(observer);
}
method with the inner class:
private class ConsoleLogObserverImpl implements Observer<List<String>>
But the behaviour was not as I would have exspected. The output was:
subscribed
[]
finished
The observable was imediately terminating. Did I do something wrong when creating the Observable or did I completly misunderstand the usage RxJava?
How can I create an Observable class field and an Observer that triggers an action when the Observable is changed with RxJava/some Quarkus extension?

Serialization of String[]: how to convert String value to String[] one?

here is code for main
public static void main(String[] args) {
Container container= new Container();
Serializator serializator = new Serializator();
container.setvalue("1st val");
serializator.serialization(container);
}
here is code for container
public class Container implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Holds the elements of a container.
*/
private String[] values;
public String[] getvalue() {
return values;
}
public void setvalue(String[] values) {
this.values=values;
}
}
here is code for a serializator
public class Serializator {
public boolean serialization(Container container) {
boolean flag=false;
File file= new File("C:/conatiner.data");
ObjectOutputStream oos = null;
try {
FileOutputStream fos= new FileOutputStream(file);
if(fos != null) {
oos= new ObjectOutputStream(fos);
oos.writeObject(container);
flag=true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return flag;
}
}
Well, the program should be working in a following way: you create a container that has an array of strings,(you can set the values in it) and then the program must serialize it. but the problem is that the tutorial worked with the String value, but not the String[] one. how can i make it understand the String[] value and insert it?
The crashlog is the following
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method setvalue(String[]) in the type Container is not applicable for the arguments (String)
at ua.khpi.oop.taradai06.program6.main(program6.java:7)
"container.setvalue("1st val");"
First, let's focus on the bug:
In the container, you promised you will send an array of string in the function setValue, but you are sending a single string.
There are two things you could do;
keep the container code as it is and send array of strings from main
Change the container code and let setValue get a single string value and add it to the values array
And you main question related with serialisation please check that post
In order to accept both String and String[] as an input parameter to Container::setvalue method, the varargs should be used, then a single String is accepted as an array consisting of one element.
Also, Java naming conventions for getters/setters of Java Beans specify to capitalize the property names after get/set verb: Getter and setter method names are composed of the word get or set, respectively, plus the property name with the first character of each word capitalized, so the methods should be names as getValues/setValues:
// Container class
public void setValues(String... values) {
this.values = values;
}
Then this method can be invoked as follows without additional overloading:
container.setValues(); // empty array new String[0]
container.setValues("a string"); // new String[1]{"a string"}
container.setValues("a", "b"); // new String[2]{"a", "b"}
container.setValues(new String[]{"1", "2", "3"}); // common array
If you promised you'll use the String[] parameter, then you should note that.
The following version of using setvalue does this work perfectly
container.setvalue(new String[] {"1st val","2nd val","3rd val"});
OK I hope I helped you look in the class "Container" in "setvalue" function, you gived it the parameter "1st value"(Its one string) but it needs a String array. So you can replace your code with this:
main class:
public class main {
public static void main(String[] args) {
Container container= new Container();
Serializator serializator = new Serializator();
container.setvalue("1st value", 0);
serializator.serialization(container);
}
}
Container class:
import java.io.Serializable;
public class Container implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Holds the elements of a container.
*/
int AnyNumberYouWant = 100;
private String[] values = new String[AnyNumberYouWant];
public String[] getvalue() {
return values;
}
public void setvalue(String value, int index) {
this.values[index]=value;
}
}
Serializator class
import java.io.*;
public class Serializator {
public boolean serialization(Container container) {
boolean flag=false;
File file= new File("C:/Container/container.data");
ObjectOutputStream oos = null;
try {
FileOutputStream fos= new FileOutputStream(file);
if(fos != null) {
oos= new ObjectOutputStream(fos);
oos.writeObject(container);
flag=true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return flag;
}
}
And I solved another errors that was there in the code. So I tried it and worked correctly. I hope that I helped you.

Mock FileInputStream using Mockito/PowerMockito without having an existing file

I am writing a JUnit for a method that uses FileInputStream and in the constructor only the file name is passed. The file is created as part of a servlet request and this file is not stored any where.
I am trying to Mock FileInputStream using PowerMockito so that it gives me a mocked file object. Unfortunately I get FileNotFoundException which is valid but I am not sure how to test this method then because the file doesn't exist.
Method under test:
public String viewReport() throws Exception {
this.inputStream = new FileInputStream(DOCUSIGN_REPORT_FILE);
try {
boolean returnReport = validateRequest();
if (returnReport) {
intgList = this.generateViewIntegrationReportData(getESignUIConfig());
this.createCSVFile(intgList, new FileWriter(DOCUSIGN_REPORT_FILE));
} else {
failureResponse(msgs, 400);
return null;
}
} catch (Exception e) {
e.printStackTrace();
msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR,
UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
failureResponse(msgs, 500);
return null;
}
return UiIntegrationKeyConstants.REPORT_REPSONSE;
}
JUnit test so far.
#Test
public void testViewReport() throws Exception {
Map<String, Object> actionMap = new HashMap<>();
actionMap.put("application", "ESignatureIntegrationAction");
ActionContext.setContext(new ActionContext(actionMap));
FileInputStream inputStream = Mockito.mock(FileInputStream.class);
PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(inputStream);
action = new ESignatureIntegrationAction();
action.viewReport();
}
I get an exception when the code reaches to new FileInputStream(DOCUSIGN_REPORT_FILE);
Thanks for the help.
I would suggest to refactor your code in a way that allows testing without a mocking framework.
It could look somewhat like this:
public class YourClass {
// ...
public String viewReport() {
try {
boolean isValidRequest = validateRequest();
if (isValidRequest) {
IntegrationReportCsvFileHandler fileHandler = new IntegrationReportCsvFileHandler();
IntegrationReportData inputData = fileHandler.readData(new FileInputStream(DOCUSIGN_REPORT_FILE));
IntegrationReportGenerator generator = new IntegrationReportGenerator();
IntegrationReportData outputData = generator.processData(inputData, getESignUIConfig());
fileHandler.writeReport(outputData, new FileWriter(DOCUSIGN_REPORT_FILE));
} else {
failureResponse(msgs, 400);
return UiIntegrationKeyConstants.FAILURE_RESPONSE;
}
} catch (Exception e) {
e.printStackTrace();
msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR,
UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
failureResponse(msgs, 500);
return UiIntegrationKeyConstants.FAILURE_RESPONSE;
}
return UiIntegrationKeyConstants.REPORT_RESPONSE;
}
// ...
}
public class IntegrationReportData {
// your custom data structure
// may as well just be a List<Data>
// may be different for input and output
}
public class IntegrationReportException extends Exception {
// your custom exception
public IntegrationReportException(String message) { super(exception); }
}
public class IntegrationReportGenerator {
public IntegrationReportData processData(IntegrationReportData data, ESignConfig config) throws IntegrationReportException {
// here's your logic that requires testing
}
}
public class IntegrationReportCsvFileHandler {
public IntegrationReportData readData(InputStream input) throws IOException {
// read data from given input stream
}
public void writeData(IntegrationReportData data, OutputStreamWriter outputWriter) throws IOException {
// write data to given output stream
}
}
That way the IntegrationReportGenerator would be easily testable.

The method getApplication() is undefined for the type (my class)

I am using a global variables "GlobalVariables" in a separated class and I am try to use it in the following code but it is always gives me the error :
The method getApplication() is undefined for the type UploadPicture
I tried the following but still have error:
((GlobalVariables) this.getApplication()).set_FileUploading(false);
The qustion was already asked here but unfortunatlly all the answors didn't work with me and gave me same error! any suggestion please?
public class UploadPicture extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private String mErrorMsg;
private File outFiles;
public UploadPicture(Context context, DropboxAPI<?> api, String dropboxPath, File file) {
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
}
#Override
protected Boolean doInBackground(Void... params) {
try {
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + outFiles.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
return 500;
}
#Override
public void onProgress(long bytes, long total) {
//publishProgress(bytes);
}
}
);
if (mRequest != null) {
mRequest.upload();
((GlobalVariables) UploadPicture.this.getApplication()).set_FileUploading(false);
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
Edit: I am adding now my "VariableGlobales" calss:
public class GlobalVariables extends Application {
private Boolean _IsIOIORunning=false;
private Boolean _FileUploading=false;
public Boolean get_IsIOIORunning()
{
return _IsIOIORunning;
}
public void set_IsIOIORunning(Boolean _IsIOIORunning)
{
this._IsIOIORunning = _IsIOIORunning;
}
public Boolean get_FileUploading()
{
return _FileUploading;
}
public void set_FileUploading(Boolean _FileUploading)
{
this._FileUploading = _FileUploading;
}
It's normal UploadPicture doesn't extend GlobalVariables but it extend AsyncTask.
That it's my "GlobalVariables "
public class AppInfo extends Application {
private static Context context;
private static String user;
public void onCreate(){
super.onCreate();
AppInfo.context = getApplicationContext();
user = null;
}
public static Context getAppContext() {return AppInfo.context;}
public static String getUser() {return user;}
public static void setUser(String user) {AppInfo.user = user;}
}
And I call it everywhere like that:
AppInfo.getUser();
Edit:
GlobalVariables should use static method and variables:
public class GlobalVariables extends Application {
private static Boolean _IsIOIORunning=false;
private static Boolean _FileUploading=false;
public static Boolean get_IsIOIORunning() {
return _IsIOIORunning;
}
public static void set_IsIOIORunning(Boolean _IsIOIORunning) {
GlobalVariables._IsIOIORunning = _IsIOIORunning;
}
public static Boolean get_FileUploading(){
return _FileUploading;
}
public static void set_FileUploading(Boolean _FileUploading){
GlobalVariables._FileUploading = _FileUploading;
}
}

Issue invoking WatchService inside a singleton bean

we wanted to watch a file periodically for changes, we are using jboss 7 . Following is my code snippet. I initialized the watcher in the postconstruct method of singleton bean and scheduled a method to poll watch events. I could observe the changes when i modify the file very first time, however the subsequent modifications to the file are not recieved . Can anyone please let me know what could be the issue
#Startup
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
#Interceptors(NonThrowingPostConstructInterceptor.class)
#Singleton
#Service
#LocalBinding(jndiBinding=IHeartBeatProducerService.JNDI_LOCAL_BINDING)
public class HeartBeatProducerService extends EMSingletonService implements IHeartBeatProducerService{
#EJB(mappedName=IMessageService.JNDI_LOCAL_BINDING)
public IMessageService messageService;
#EJB(mappedName=ICommandExecutionService.JNDI_LOCAL_BINDING)
public ICommandExecutionService commandService;
private final static String LAST_OPERATION_COMPLETED="Last Operation Completed";
private final static String STATUS="Status";
private WatchService watcher;
private Path dir;
private String concServer;
public static final String TOPIC="foo";
private IMLogger logger = new IMLogger("foo");
private String content=null;
#PostConstruct
#Override
public void init() {
// TODO Auto-generated method stub
super.init();
try {
watcher = FileSystems.getDefault().newWatchService();
dir=Paths.get("/shared/foo");
dir.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
logger.entering(0, IHeartBeatProducerService.class.getSimpleName(), "Initializing Heart Beat", new String[]{"Entered"});
} catch (IOException e) {
e.printStackTrace();
}
}
#Schedule(second="*/10", minute = "*", hour="*")
private void checkStatus()
{
logger.entering(0, IHeartBeatProducerService.class.getSimpleName(), "Checking Status", new String[]{"Entered"});
final String[] command={"pidof","server"};
commandService.run(command, null, false);
concServer=(commandService.getExitCode()==0)?"UP":"DOWN";
if(concServer.equals("UP"))
{
watch();
}
else
{
content="foo:Failed";
}
produce();
}
public void watch()
{
logger.entering(0, IHeartBeatProducerService.class.getSimpleName(), "Entering watch()", new String[]{"Entered"});
WatchKey key = null;
try
{
key = watcher.take();
}
catch (InterruptedException e)
{
logger.error(HeartBeatProducerService.class.getSimpleName(),"Interupted Exception " + e.getMessage());
}
for ( WatchEvent<?> event: key.pollEvents())
{
WatchEvent.Kind kind = event.kind();
logger.info(HeartBeatProducerService.class.getSimpleName(),"Watch Event :" + kind.name());
if(kind.name().equals("OVERFLOW"))
{
continue;
}
if(kind.name().equals("ENTRY_MODIFY"))
{
Path concLog = (Path) event.context();
logger.info(HeartBeatProducerService.class.getSimpleName(),"Modified File Name:" + concLog.getFileName());
if(concLog.endsWith("current_status.txt"))
{
logger.info(HeartBeatProducerService.class.getSimpleName(), "Reading Status");
readStatus();
}
}
}
boolean valid = key.reset();
if ( !valid)
{
logger.error(HeartBeatProducerService.class.getSimpleName(),"Key Unregistered");
}
}
private void parse(String output)
{
// parse file contents
}
private void readStatus() {
//read status and parse()
}
private void produce()
{
try {
messageService.publish(TOPIC, content, PublishType.ASync);
} catch (MessageException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
There is already a link explaining the same with #Asynchronous tag (EJB 3.1 and NIO2: Monitoring the file system) . however I need to know what could be wrong in this approach.
Your watch method needs to run in an infinite loop. What's happening now is that after
try {
key = watcher.take();
}
you process the event and then the watch() method is finished. Try the effect of
for(;;) {
before the above lines, ending the for block after the validity check. Did you see the example at The Java Tutorials?

Categories