I am solving this issue:
In my Java application (installed on Windows OS machine) I have to catch Win32 Event which is created by another application on same machine. This app is written in C++ and there is no way to change it. I have information that I have to use OpenEvent function. I started as is metioned in:
Calling OpenEvent fails through JNA
Here is my code:
public class WinEventListener {
private Logger logger = LoggerFactory.getLogger(WinEventListener.class);
static {
Native.register("kernel32");
}
public static native HANDLE OpenEventW(int access, boolean inheritHandle, WString name);
public static native int WaitForSingleObject(HANDLE hHandle, int dwMilliseconds);
public static native boolean CloseHandle(HANDLE hObject);
public static class HANDLE extends PointerType {
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
}
static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{
super.setPointer(Pointer.createConstant(-1));
}
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
public void listen() throws Exception {
HANDLE handle = null;
do {
//logger.debug("Wainting for handle");
handle = OpenEventW(2, false, new WString("VLIT_SERVER_DATA"));
logger.debug("Handle:" + handle.toString());
Thread.sleep(1000);
} while (handle == null);
logger.debug("Handle obtained");
while(true){
int result = WaitForSingleObject(handle,Integer.MAX_VALUE);
if(result == 0){
logger.debug("Handle signalized");
VLITProcceserThread thread = new VLITProcceserThread();
thread.start();
CloseHandle(handle);
}
}
}
}
Basiclly I want in listen() method wait for HANDLE create by other program and if its created then wait for its signalized state, do some action and release handle.
BUt I have no success. Can anybody point me to right way?
Thans a lot!
If it is the opening of the handle that is failing it is most likely an issue with privileges. Is your program running as a service? I was trying to do something similar and was able to get this program running and working when i called it via a system call inside a program that was running as a service.
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.WString;
import com.sun.jna.FromNativeContext;
public class WinEventListener {
static {
Native.register("kernel32");
}
public static native HANDLE OpenEventW(int access, boolean inheritHandle, WString name);
public static native int WaitForSingleObject(HANDLE hHandle, int dwMilliseconds);
public static native boolean CloseHandle(HANDLE hObject);
public static class HANDLE extends PointerType {
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
}
static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{
super.setPointer(Pointer.createConstant(-1));
}
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
public void listen() {
try {
HANDLE handle = null;
do {
handle = OpenEventW(2031619, false, new WString("event_name"));
if(handle == null) {
System.out.print("Handle is null\n");
}
Thread.sleep(500);
} while (handle == null);
while(true){
// 50 second timeout
int result = WaitForSingleObject(handle, 50000);
if(result == 0){
System.out.print("Handle signaled\n");
}
else if (result == 258){
System.out.print("Timed out\n");
}
else{
System.out.print("Handle not signaled\n");
System.out.print(result);
}
System.out.print(result);
//System.out.print(handle);
Thread.sleep(100);
}
}
catch (Exception exc)
{
System.out.print(exc);
//Thread.sleep(10000);
//writer.writeln(exc);
}
}
public static void main(String[] args) {
WinEventListener listener = new WinEventListener();
listener.listen();
}
}
Related
New to this topic and right now I'm stuck at a brick wall. I have 2 classes, parent class: Controller.java and subclass: GreenhouseControls.java. I need to serialize a GreenhouseControls object but also an instance variable (eventList) from its superclass Controller.java.
My serialization happens when an inner class of GreenhouseControls.java throws a custom ControllerException, which is caught in the main method. Before terminating the program, the GreenhouseControls object should be saved (including the field from its superclass).
Why is a NotSerializableException thrown by the inner class WindowMalfunction of GreenhouseControls? Anyone have any ideas, as I am seriously stuck?
What I tried is the following:
Implement serializable on Controller.java. This is because if the superclass is serializable, then subclass is automatically serializable, however this throws java.io.NotSerializableException: GreenhouseControls$WindowMalfunction, (WindowMalfunction is the inner class that throws the initial exception to begin the serialization processs).
Implement serializable on GreenhouseControls.java and implement custom serialization by overriding writeObject() and readObject() to save the field from the superclass. This approach yet again throws the same exception as the approach 1.
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
Controller.java
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class Controller {
// THIS IS THE VARIABLE I NEED TO SAVE
protected List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() throws ControllerException {
while (eventList.size() > 0)
// Make a copy so you're not modifying the list
// while you're selecting the elements in it:
for (Event e : new ArrayList<Event>(eventList))
if (e.ready()) {
System.out.println(e);
e.action();
eventList.remove(e);
}
}
public static void shutDown() { }
}
GreenhouseControls.java class (note I have removed the inner classes and other code from it and only left related info)
public class GreenhouseControls extends Controller implements Serializable {
private int errorcode = 0;
public class WindowMalfunction extends Event {
public WindowMalfunction(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
windowok = false;
throw new ControllerException("Window malfunction");
}
public String toString() {
return "Window malfunction";
}
}
public class PowerOut extends Event {
public PowerOut(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
poweron = false;
throw new ControllerException("Power out");
}
public String toString() {
return "Power out";
}
}
// Various other inner classes that extend event exist
public static void serializeObject(GreenhouseControls gc) {
FileOutputStream fileOut;
ObjectOutputStream out;
try {
fileOut = new FileOutputStream("dump.out");
out = new ObjectOutputStream(fileOut);
out.writeObject(gc);
System.out.println("WERRROR code: " + gc.getError());
out.close();
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
#SuppressWarnings("unchecked")
public static <T extends List<?>> T cast(Object obj) {
return (T) obj;
}
public int getError() {
return errorcode;
}
public Fixable getFixable(int errorcode) {
switch (errorcode) {
case 1:
return new FixWindow();
case 2:
return new PowerOn();
default:
return null;
}
}
public static void main(String[] args) {
GreenhouseControls gc = null;
try {
String option = args[0];
String filename = args[1];
if (!(option.equals("-f")) && !(option.equals("-d"))) {
System.out.println("Invalid option");
printUsage();
}
// gc = new GreenhouseControls();
if (option.equals("-f")) {
gc = new GreenhouseControls();
gc.addEvent(gc.new Restart(0, filename));
}
gc.run();
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid number of parameters");
printUsage();
} catch (ControllerException e) {
String errormsg;
if (e.getMessage().equals("Window malfunction")) {
gc.errorcode = 1;
errormsg = "Window malfunction event occurred Error code: " + gc.errorcode;
} else {
gc.errorcode = 2;
errormsg = "Power out event occurred Error code: " + gc.errorcode;
}
logError(errormsg);
serializeObject(gc);
gc.displayEventList();
shutDown();
}
}
}
Event.java
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() { // Allows restarting
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public abstract void action() throws ControllerException;
Event has to be Serializable too.
Change
public abstract class Event {
to
public abstract class Event implements Serializable {
I'm building a GUI application in Java using an application framework (Netbeans Platform) which requires a large amount of nearly identical classes to implement extremely similar Action classes. I've spent a lot of time attempting to generate these actions programmatically. Although I'm able to generate the Actions, the framework utilizes annotations during compile time to generate other internal cache/data files which I've been unable to reproduce using a programmatic approach.
I'm wondering if code generation tools are a better solution, or perhaps some custom annotations which wrap the framework annotations. Perhaps something like Lombok, or maybe a maven plugin. But don't know where to start and am not sure if this is even a good path to explore. Ideally, I think it would be great to define the actions in a data file and generate the java code at compile time.
The project is open source, and a number of other actions are on github. Here is an example of what the template might look like, the pieces I would need to inject replaced with {{string}}, {{code}} and {{int}}:
// imports omitted
#ActionID(
category = {{string}},
id = {{string}})
#ActionRegistration(
iconBase = {{string}},
displayName = "resources.MessagesBundle#" + {{string}},
lazy = false)
#ActionReferences({
#ActionReference(
path = {{string}},
position = {{int}})
})
public final class {{string}} extends AbstractAction implements UGSEventListener {
public static final String ICON_BASE = {{string}};
private BackendAPI backend;
public SoftResetAction() {
this.backend = CentralLookup.getDefault().lookup(BackendAPI.class);
this.backend.addUGSEventListener(this);
putValue("iconBase", ICON_BASE);
putValue(SMALL_ICON, ImageUtilities.loadImageIcon(ICON_BASE, false));
putValue("menuText", {{string}});
putValue(NAME, {{string}});
}
#Override
public void UGSEvent(UGSEvent cse) {
java.awt.EventQueue.invokeLater(() -> setEnabled(isEnabled()));
}
#Override
public boolean isEnabled() {
{{code}}
}
#Override
public void actionPerformed(ActionEvent e) {
{{code}}
}
}
You should try a code generator like Telosys ( http://www.telosys.org/ )
This tool is designed for this kind of situation, you just have to create a template for each type of repetitive class and launch the generation.
For more information see the templating principles : http://www.telosys.org/templates.html
Everything is free and open source, so you can reuse existing templates and adapt them according to your needs.
Some interresting posts about this tool :
https://modeling-languages.com/telosys-tools-the-concept-of-lightweight-model-for-code-generation/
https://dzone.com/articles/telosys-a-code-generation-tool-by-laurent-guerin
You can design a public Action class for common using just like blow. This is only a section of sample code. If some modules has its own biz logical, you can implements this PubAction to any subclass.
import java.awt.event.ActionEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.AbstractAction;
public abstract class PubAction
extends AbstractAction
implements AppEventListener
{
protected ActionInterceptor interceptor;
protected IExceptionHandler exceptionHandler;
protected IActionStatusJudge actionStatusJudge = null;
public static final String TOOLBAR_SHOWNAME_KEY = "TOOLBAR_SHOWNAME_KEY";
public PubAction()
{
setShowNameInToolbar(false);
}
public String getBtnName() {
return (String)getValue("Name");
}
public void setBtnName(String btnName) {
putValue("Name", btnName);
}
public void setCode(String code)
{
putValue("Code", code);
}
public void handleEvent(AppEvent event)
{
updateStatus();
}
public void updateStatus()
{
boolean isEnable = isActionEnable();
setEnabled(getActionStatusJudge() == null ? isEnable : getActionStatusJudge().isActionEnable(this, isEnable));
}
protected boolean isActionEnable() {
return true;
}
public void setShowNameInToolbar(boolean isShow)
{
putValue("TOOLBAR_SHOWNAME_KEY", isShow ? Boolean.TRUE : Boolean.FALSE);
}
public void actionPerformed(ActionEvent e) {
Logger.debug("Entering " + getClass().toString() + ".actionPerformed");
beforeDoAction();
try
{
if ((interceptor == null) || (interceptor.beforeDoAction(this, e)))
{
try
{
doAction(e);
if (interceptor != null) {
interceptor.afterDoActionSuccessed(this, e);
}
} catch (Exception ex) {
if ((interceptor == null) || (interceptor.afterDoActionFailed(this, e, ex)))
{
if (getExceptionHandler() != null)
{
processExceptionHandler(ex);
}
else if ((ex instanceof RuntimeException))
{
throw ((RuntimeException)ex);
}
throw new RuntimeException(ex);
}
}
}
}
finally
{
Logger.debug("Leaving " + getClass().toString() + ".actionPerformed");
}
}
protected void processExceptionHandler(Exception ex)
{
new ExceptionHandlerUtil().processErrorMsg4SpecialAction(this, getExceptionHandler(), ex);
}
protected void beforeDoAction()
{
Method[] ms = getClass().getMethods();
for (Method m : ms)
{
Class<?> clazz = m.getReturnType();
if (AbstractUIAppModel.class.isAssignableFrom(clazz)) {
try
{
AbstractUIAppModel model = (AbstractUIAppModel)m.invoke(this, null);
if (model == null)
return;
LoginContext ctx = model.getContext();
if (ctx == null)
break;
ShowStatusBarMsgUtil.showStatusBarMsg("", ctx);
} catch (IllegalArgumentException e) {
Logger.debug(e.getMessage());
} catch (IllegalAccessException e) {
Logger.debug(e.getMessage());
} catch (InvocationTargetException e) {
Logger.debug(e.getMessage());
}
}
}
}
public abstract void doAction(ActionEvent paramActionEvent) throws Exception;
public ActionInterceptor getInterceptor()
{
return interceptor;
}
public void setInterceptor(ActionInterceptor interceptor) {
this.interceptor = interceptor;
}
public IExceptionHandler getExceptionHandler() {
return exceptionHandler;
}
public void setExceptionHandler(IExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
public IActionStatusJudge getActionStatusJudge() {
return actionStatusJudge;
}
public void setActionStatusJudge(IActionStatusJudge actionStatusJudge) {
this.actionStatusJudge = actionStatusJudge;
}
}
I'm trying to implement this workflow with rxJava but i'm sure if i'm misusing or doing stuff wrong.
User asks to login
If a loginResult is available in cache then "emit" the cached LoginResult
Else actually perform the request to the webservice and cache the result if everything is successfull
If an error occurs retry at most 3 times and if there is a 4th time then purge the cache.
Here is my full snippet of code.
public class LoginTask extends BaseBackground<LoginResult> {
private static CachedLoginResult cachedLoginResult = new CachedLoginResult();
private XMLRPCClient xmlrpcClient;
private UserCredentialsHolder userCredentialsHolder;
#Inject
public LoginTask(XMLRPCClient client, UserCredentialsHolder userCredentialsHolder) {
this.xmlrpcClient = client;
this.userCredentialsHolder = userCredentialsHolder;
}
#Override
public LoginResult performRequest() throws Exception {
return UserApi.login(
xmlrpcClient,
userCredentialsHolder.getUserName(),
userCredentialsHolder.getPlainPassword());
}
#Override
public Observable<LoginResult> getObservable() {
return cachedLoginResult.getObservable()
.onErrorResumeNext(
Observable.create(
((Observable.OnSubscribe<LoginResult>) subscriber -> {
try {
if (!subscriber.isUnsubscribed()) {
subscriber.onNext(performRequest()); // actually performRequest
}
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
})
)
.doOnNext(cachedLoginResult::setLoginResult)
.retry((attempts, t) -> attempts < 3)
.doOnError(throwable -> cachedLoginResult.purgeCache())
);
}
private static class CachedLoginResult {
private LoginResult lr = null;
private long when = 0;
private CachedLoginResult() {
}
public boolean hasCache() {
return lr != null && when + TimeUnit.MILLISECONDS.convert(30, TimeUnit.MINUTES) > System.currentTimeMillis();
}
public void setLoginResult(LoginResult lr) {
if (lr != null) {
this.lr = lr;
this.when = System.currentTimeMillis();
}
}
public void purgeCache() {
this.lr = null;
this.when = 0;
}
public Observable<LoginResult> getObservable() {
return Observable.create(new Observable.OnSubscribe<LoginResult>() {
#Override
public void call(Subscriber<? super LoginResult> subscriber) {
if (!subscriber.isUnsubscribed()) {
if (hasCache()) {
subscriber.onNext(lr);
subscriber.onCompleted();
} else {
subscriber.onError(new RuntimeException("No cache"));
}
}
}
});
}
}
}
Since i wan't able to find any similar examples and i started "playing" with rxjava just 1 day ago i'm unsure of my implementation.
Thank you for your time.
I think this code is alright, good job :)
You were right to use Observable.create in your LoginTask because otherwise result of the call could be cached internally, and then retry wouldn't help much...
This is I think however unnecessary for the CachedLoginResult's Observable. Here you can simplify your code by using Observable.justand Observable.error utility methods, something like:
public Observable<LoginResult> getObservable() {
if (hasCache()) {
return Observable.just(lr);
} else {
return Observable.error(new RuntimeException("No cache"));
}
}
Note: just stores the value you tell it to emit internally, so that resubscriptions will always produce this value. This is what I hinted above, you shouldn't do Observable.just(performRequest()).retry(3) for example, because the performRequest will only ever be called once.
If I understand correctly, you want to perform the login once and cache the result in a reactive manner? If so, here is an example how I would do this:
import java.util.concurrent.ThreadLocalRandom;
import rx.*;
import rx.schedulers.Schedulers;
import rx.subjects.AsyncSubject;
public class CachingLogin {
static class LoginResult {
}
/** Guarded by this. */
AsyncSubject<LoginResult> cache;
public Observable<LoginResult> login(String username, String password) {
AsyncSubject<LoginResult> c;
boolean doLogin = false;
synchronized (this) {
if (cache == null || cache.hasThrowable()) {
cache = AsyncSubject.create();
doLogin = true;
}
c = cache;
}
if (doLogin) {
Observable.just(1).subscribeOn(Schedulers.io())
.map(v -> loginAPI(username, password))
.retry(3).subscribe(c);
}
return c;
}
public void purgeCache() {
synchronized (this) {
cache = null;
}
}
static LoginResult loginAPI(String username, String password) {
if (ThreadLocalRandom.current().nextDouble() < 0.3) {
throw new RuntimeException("Failed");
}
return new LoginResult();
}
}
I just want to ask, if it is possible to check if a void method "cancelled" itself by calling return;?
For example in my main I call calculate(myArray);, which is defined as follows:
public static void calculate(Object[] array) {
if (array == null)
return;
// do stuff
}
Is their a way to know, if it returned or not? My thoughts were making a "global" boolean which is changed to true right before we return and then check its value in main or just change the return type to something like int and when it returned at the beginning we use return -1; and at the end of the method return 0;
Both is possible but I think neither of them is very good style. Is there an alternative?
You are right that the practices you described are considered bad in Java (and other modern languages).
The most common acceptable practices for your scenario are:
Make the method throw an exception. Do this if the "failing" code path shouldn't happen under normal circumstances.
Make the method's return type bool to indicate success or failure. Do this if the "failing" code path can happen under normal circumstances as well.
No, you cannot. From The Oracle Java tutorials - Returning a Value from a Method:
Any method declared void doesn't return a value. It does not need to contain a return statement, but it may do so. In such a case, a return statement can be used to branch out of a control flow block and exit the method and is simply used like this:
return;
There is no way from method invocation to determine if the void method was completed by a fall-through block or a return; statement.
Most other methods includes a return type of boolean and returns false when something went wrong, or simply throws an IllegalArgumentException.
You can utilize publisher - listener pattern :)
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;
public class Sample {
private interface Event {
}
private static class ExitEvent implements Event {
}
private static class SucceedEvent implements Event {
}
private interface EventListener {
void eventPerformed(Event e);
}
private static List<EventListener> listeners = new LinkedList<EventListener>();
private static void addActionListener(EventListener l) {
listeners.add(l);
}
private static void fireEvent(Event event) {
for (EventListener l : listeners) {
l.eventPerformed(event);
}
}
public static void calculate(Object[] array) {
if (array == null) {
fireEvent(new ExitEvent());
return;
}
fireEvent(new SucceedEvent());
}
public static void main(String[] args) {
addActionListener(new EventListener() {
public void eventPerformed(Event e) {
if (e instanceof ExitEvent) {
System.out.println("Exit");
} else if (e instanceof SucceedEvent) {
System.out.println("Success");
}
}
});
calculate(null);
calculate(new Object[] {});
}
}
Output:
Exit
Success
You can go much farther and remove those ugly ifs, by utilizing visitor pattern
import java.util.LinkedList;
import java.util.List;
public class Sample {
private interface EventVisitor {
void visit(ExitEvent event);
void visit(SucceedEvent event);
}
private interface Event {
void accept(EventVisitor visitor);
}
private static class ExitEvent implements Event {
public void accept(EventVisitor visitor) {
visitor.visit(this);
}
}
private static class SucceedEvent implements Event {
public void accept(EventVisitor visitor) {
visitor.visit(this);
}
}
private interface EventListener {
void eventPerformed(Event e);
}
private static List<EventListener> listeners = new LinkedList<EventListener>();
private static void addActionListener(EventListener l) {
listeners.add(l);
}
private static void fireEvent(Event event) {
for (EventListener l : listeners) {
l.eventPerformed(event);
}
}
public static void calculate(Object[] array) {
if (array == null) {
fireEvent(new ExitEvent());
return;
}
fireEvent(new SucceedEvent());
}
public static void main(String[] args) {
addActionListener(new EventListener() {
public void eventPerformed(Event e) {
e.accept(new EventVisitor() {
public void visit(SucceedEvent event) {
System.out.println("Success");
}
public void visit(ExitEvent event) {
System.out.println("Exit");
}
});
}
});
calculate(null);
calculate(new Object[] {});
}
}
Output:
Exit
Success
I'm having an issue with my configuration management class, it is not getting reloaded.
Let me show you part of my code:
public class ConfigurationManager extends XMLConfiguration
{
private static final Logger log = LoggerFactory.getLogger(ConfigurationManager.class);
private static final long serialVersionUID = 1L;
public static final String CONFIG_FILE_PATH = "/config.xml";
private static volatile ConfigurationManager instance = null;
private static Object lock = new Object();
// Instance management methods
public static ConfigurationManager getInstance()
{
return getInstance(CONFIG_FILE_PATH);
}
public static ConfigurationManager getInstance(String cfg)
{
if(instance == null)
{
synchronized(lock)
{
if(instance == null)
{
try
{
instance = new ConfigurationManager(cfg);
instance.dumpConfigurationToLog();
}
catch(Exception e)
{
log.error("Error calling getInstance. Method params", e);
}
}
}
}
return instance;
}
private Object loadedCfg;
private int reloadInterval;
private void dumpConfigurationToLog()
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
this.save(bos);
bos.flush();
}
catch(Exception e)
{
log.error("Error calling dumpConfigurationToLog. Method params", e);
}
}
#Override
public void configurationChanged(ConfigurationEvent event)
{
log.info("Enter Method configurationChanged params: {}", event);
if(event.isBeforeUpdate() == false)
{
makeUpdates();
log.info("Configuration file: {} has changed and reloaded...", loadedCfg);
dumpConfigurationToLog();
}
log.info("Return Method configurationChanged");
}
private void updateReloadInterval()
{
int newReloadInterval = getInt("global.reloadInterval") * 1000;
if(reloadInterval != newReloadInterval)
{
reloadInterval = newReloadInterval;
if(getReloadInterval() > 0)
{
FileChangedReloadingStrategy reloadStrategy = new FileChangedReloadingStrategy();
reloadStrategy.setRefreshDelay(getReloadInterval());
this.setReloadingStrategy(reloadStrategy);
}
else
if(getReloadInterval() == 0)
{
this.setReloadingStrategy(new InvariantReloadingStrategy());
}
else
{
log.error("Invalid reload interval for ConfigurationManager: {}", getReloadInterval());
}
}
}
private ConfigurationManager(String cfgFile) throws Exception, ConfigurationException
{
super();
loadedCfg = cfgFile;
if(System.class.getResource(cfgFile) != null)
this.setURL(System.class.getResource(cfgFile));
else
this.setURL(getClass().getResource(cfgFile));
this.load();
makeUpdates();
this.addConfigurationListener(this);
this.setThrowExceptionOnMissing(true);
}
private void makeUpdates()
{
updateReloadInterval();
}
public int getReloadInterval()
{
return reloadInterval;
}
}
Now that code works perfectly fine, I can read the configuration file, and work with it with no major problems, the issue is that it never gets reloaded on configuration changes. I've tried setting breakpoints and so, but it never gets into configurationChanged method.
Does anybody see something wrong here?
Well, after testing and analyzing, I've got to this conclusion, in order to have configurationChanged called, I need to make an explicit call to get values from configuration.
And that is something I was not doing.
The thing got fixed when I did that.
You're calling makeUpdates() after setting your ConfigurationListener.
Additionally, calling load() is no guarantee that an Event will get fired.
Lastly, is there anything actually calling addProperty(), etc for this extended class?
Only a small side issue: resource bundles are cached, you can call clearCache, unfortunately not per bundle but per class loader.