How to initiate a change event for a TreeModel in Java? - java

Suppose you got a JTree with a model that implements TreeModel, and all nodes implement TreeNode.
Suppose then that something happens in the background with the model (not through the GUI) like a CRUD-event, that update the model and should update the JTree.
Since the model is CRUD-affected from other views it does not seems like a good idea to use the DefaultTreeModel for this task, correct me if I'm wrong.
I guess you need to signal the change to the TreeModel in somehow, like fire some event in some way?
Btw I have not managed to implement the methods:
public void addTreeModelListener( TreeModelListener l )
public void removeTreeModelListener( TreeModelListener l )
I guess these methods need to be implemented for such a feature.

I like to use this kind of generic ListenerList:
public class ListenerList {
private final List<Object> list = new ArrayList<Object>();
public ListenerList() {
}
public void addListener(Object listener) {
list.add(listener);
}
public void removeListener(Object listener) {
list.remove(listener);
}
public <T> T getNotifier(Class<T> intf) {
ClassLoader cl = intf.getClassLoader();
return intf.cast(Proxy.newProxyInstance(cl, new Class[] {intf},
(Object proxy, Method method, Object[] args)
-> actualInvoke(method, args)));
}
private Object actualInvoke(Method method, Object args[]) {
Object result = null;
for (Object listener: list) {
try {
result = method.invoke(listener, args);
} catch (IllegalAccessException e) {
LOG.error("Error invoking listener method", e);
} catch (InvocationTargetException e) {
LOG.error("Error invoking listener method", e);
}
}
return result;
}
}
That I use in my model class:
public class MyTreeModel implements TreeModel {
private final ListenerList listeners = new ListenerList();
private final TreeModelListener notifier = listeners.getNotifier(TreeModelListener.class);
public void addTreeModelListener( TreeModelListener l ) {
listeners.addListener(l);
}
public void removeTreeModelListener( TreeModelListener l ) {
listeners.removeListener(l);
}
protected void fireTreeNodesChanged(TreeModelEvent e) {
notifier.treeNodesChanged(e);
}
protected void fireTreeNodesInserted(TreeModelEvent e) {
notifier.treeNodesInserted(e);
}
protected void fireTreeNodesRemoved(TreeModelEvent e) {
notifier.treeNodesRemoved(e);
}
protected void fireTreeStructureChanged(TreeModelEvent e)
notifier.treeStructureChanged(e);
}
...
}

Related

Run method inside a method in java

I'm sending more than 1 request to a web service, below there is an example of that requests. Its important for my application to get the answer from the web service so if there is an exception application will try couple of times to get the answer.
Because of that getting something simple like
deviceList = serviceAdapter.getDevices(); is turn into below code.
boolean flag = true;
int counter = 1;
List<Device> deviceList = null;
while (flag) {
try {
deviceList = serviceAdapter.getDevices();
flag = false;
} catch (Exception e) {
try {
if (counter == 5) {
System.out.println("Timeout Occured!");
flag = false;
} else {
Thread.sleep(1000 * counter);
counter++;
}
} catch (InterruptedException e1) {
}
}
}
And in my application i have lots of requests which means there will be more ugly codes. Is there a way where i will call my request methods as parameter for another method something like this:
deviceList = wrapperMethod(serviceAdapter.getDevices());
Problem is there will be different type of requests, so they will return different type objects (list,array,string,int) and their paramaters will change. Is there a suitable solution in java for this problem?
You can pass a Supplier<T> to the wrapperMethod:
public static <T> T wrapperMethod (Supplier<T> supp) {
boolean flag = true;
int counter = 1;
T value = null;
while (flag) {
try {
value = supp.get();
flag = false;
} catch (Exception e) {
try {
if (counter == 5) {
System.out.println("Timeout Occured!");
flag = false;
} else {
Thread.sleep(1000 * counter);
counter++;
}
} catch (InterruptedException e1) {
}
}
}
}
And call it with:
List<Device> deviceList = wrapperMethod (() -> serviceAdapter.getDevices());
I'm afraid, though, that it will limit the methods you call within the lambda expression to throw only RuntimeExceptions.
You can use some command implementation to execute some specific codes :
Here is a simple example of a command
interface Command{
void run();
}
And a couple of implementations :
class SayHello implements Command{
#Override
public void run() {System.out.println("Hello World");}
}
class KillMe implements Command{
public void run() { throw new RuntimeException();};
}
All we have to do to execute those method is to receive an instance of Command and run the method :
public static void execCommand(Command cmd) {
cmd.run();
}
And to use this
public static void main(String[] args) {
execCommand(new SayHello());
execCommand(new KillMe());
}
Hello World
Exception in thread "main" java.lang.RuntimeException
It also accepts lambda expression :
execCommand(() -> System.out.println("Say goodbye"));
And method reference :
public class Test{
public static void testMe() {
System.out.println("I work");
}
}
execCommand(Test::testMe);
Note that I didn't specify that this could throw Exception so I am limited to unchecked exception like RuntimeException but of course void run() throws Exception could be a solution. That way you can do what ever you want.
Full example (with exceptions) :
public class Test {
public static void main(String[] args) {
try {
execCommand(new SayHello());
execCommand(() -> System.out.println("Say goodbye"));
execCommand(Test::testMe);
execCommand(new KillMe());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void testMe() throws IOException{
System.out.println("I work");
}
public static void execCommand(Command cmd) throws Exception {
cmd.run();
}
}
interface Command{
void run() throws Exception;
}
class SayHello implements Command{
#Override
public void run() {System.out.println("Hello World");}
}
class KillMe implements Command{
public void run() { throw new RuntimeException();};
}
Output:
Hello World
Say goodbye
I work
Exception in thread "main" java.lang.RuntimeException
at main.KillMe.run(Test.java:39)
at main.Test.execCommand(Test.java:25)
at main.Test.main(Test.java:17)
You can use #RetryOnFailure annotation from jcabi-aspects
Create a wrapper method then annotate it to enable auto retry upon Exception
As an example:
#RetryOnFailure(attempts = 5)
List<Device> retryWhenFailed(ServiceAdapter serviceAdapter) throws Exception {
return serviceAdapter.getDevices();
}
This solution uses Generics to be able to handle different Object with most of the same code and a Runnable to execute the fetching.
With this solution, you would need only to write the different adapters extending from ServiceAdapter<T extends Fetchable> to implement the logic to fetch the data for each different class (which would have to implement Fetchable).
Define an interface that abtracts the objects that can be fetched by the different services.
package so50488682;
public interface Fetchable {
}
The ojbect that are to be retrieved implement this interface so you can use the same code for different classes.
package so50488682;
public class Device implements Fetchable{
private String id;
public Device(String id) {
this.id = id;
}
public String toString() {
return "I am device " + id;
}
}
Define an abstract ServiceAdapter that the different service adapters will extend to implement the logic for each kind of object to be retrieved. We add throws Exception to the get() method so this method cand just delegate the exception handling to the FetcherService and decide if it should retry or fail.
package so50488682;
import java.util.List;
public abstract class ServiceAdapter<T extends Fetchable> {
public abstract List<T> get() throws Exception;
}
This is an example of an implementation done to get objects of class Device.
package so50488682;
import java.util.ArrayList;
import java.util.List;
public class DeviceServiceAdapter extends ServiceAdapter<Device>{
#Override
public List<Device> get() throws Exception{
List<Device> rtn = new ArrayList<>();
// fetch the data and put it into rtn, this is a mock
Device d = new Device("1");
rtn.add(d);
d = new Device("2");
rtn.add(d);
d = new Device("3");
rtn.add(d);
//
return rtn;
}
}
Finally this is a generic solution to run the different service adapters.
public class FetcherService<T extends Fetchable> implements Runnable{
List<T> result = new ArrayList<>();
ServiceAdapter<T> serviceAdapter;
#Override
public void run() {
boolean flag = true;
int counter = 1;
while (flag) {
try {
result = serviceAdapter.get();
flag = false;
} catch (Exception e) {
try {
if (counter == 5) {
System.out.println("Timeout Occured!");
flag = false;
} else {
Thread.sleep(1000 * counter);
counter++;
}
} catch (InterruptedException e1) {
throw new RuntimeException("Got Interrupted in sleep", e);
}
}
}
}
public List<T> getResult() {
return result;
}
public void setResult(List<T> result) {
this.result = result;
}
public void setAdapter(ServiceAdapter<T> adapter) {
this.serviceAdapter = adapter;
}
}
From the main or calling program it work like this:
package so50488682;
import java.util.List;
public class SO50488682 {
public static void main(String args[]) {
try {
DeviceServiceAdapter deviceServiceAdapter = new DeviceServiceAdapter();
FetcherService<Device> deviceFetcherService = new FetcherService<>();
deviceFetcherService.setAdapter(deviceServiceAdapter);
deviceFetcherService.run();
List<Device> devices = deviceFetcherService.getResult();
for(Device device : devices) {
System.out.println(device.toString());
}
}catch(Exception e) {
System.out.println("Exception after retrying a couple of times");
e.printStackTrace();
}
}
}

Overrided method in subclass is not called

I have an abstract superclass AsyncActor which extends the Actor class. This superclass contains two abstract methods, notifySuccess and notifyFailure. notifyFailure is overriden in AsyncActor, but notifySuccess isn't because it's implementation changes from subclass to subclass. I have two actors, CreateObjActor and DeleteObjActor. Each extends AsyncActor and overrides notifySuccess. The execute method located in AsyncTask calls notifySuccess, but nothing happens.
public class AsyncActor extends Action<String> {
private Future future;
private final Action action;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
public AsyncActor(Action action) {
this.action = action;
}
public Action getAction() {
return action;
}
public Future getFuture() {
return future;
}
public void execute() {
if(action.execute()) {
executeAsynchronously();
}
}
public void executeAsynchronously() {
ServiceFw.log.debug("Writing directory to file...");
Callable<String> asyncTask = () -> {
try {
ServiceFw.entryManager.writeBack();
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
ServiceFw.log.debug("Exception thrown during asynchronous wait");
e.printStackTrace();
} catch (BusinessException e) {
notifyFailure();
}
return "write back operation";
};
future = executor.submit(asyncTask);
Runnable poll = () -> {
if(future!=null) {
notifySuccess();
} else {
error.setSeverity(ExtendedError.Severity.Warning);
notifyFailure(error);
}
};
poll.run();
}
#Override
public void notifySuccess() {
}
#Override
public void notifyFailure() {
ServiceFw.log.error("Error with asynchronous processing of write back" );
ServiceFw.entryManager.deleteActor(this);
}
}
public class CreateObjActor extends AsyncActor {
public CreateObjActor(Action action) {
super(action);
}
#Override
public void notifySuccess() {
try {
ServiceFw.log.debug("Finished asynchronous operation: " + getFuture().get());
Entry entry = getAction().getEntryModel();
if (getAction().isNotify()) {
Notification notification = new Notification(entry);
ServiceFw.notificationDispatcher.dispatchNotification(notification);
try {
ServiceFw.eventFramework.dispatchEvent("entry-added");
} catch (BusinessException e) {
ServiceFw.log.error("Event could not be dispatched for newly added entry: " + entry.toString());
}
}
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
ServiceFw.entryManager.deleteActor(this);
}
}
}
I've tried making AsyncActor not abstract and providing an empty implementation of notifySuccess, but this didn't work either. Is there a way I can call the method from the superclass? The execute method contains a lot of code (not shown here) that would result in a lot of duplicate code if it had to be placed in each subclass.

What to do about "unchecked call to generic class?"

I have this class:
package Main;
public abstract class Click123<T extends java.awt.Component> ////////////////
{
boolean debugging = false;
public abstract void singleClick(java.awt.event.MouseEvent e); ////////////////
public abstract void doubleClick(java.awt.event.MouseEvent e); ////////////////
public abstract void tripleClick(java.awt.event.MouseEvent e); ////////////////
public abstract void manyClick(java.awt.event.MouseEvent e); ////////////////
public abstract int getFreq();// how long thread sleeps; i.e., click interval
public Click123(T target) ////////////////
{
target.addMouseListener ////////////////
(
new java.awt.event.MouseAdapter() ////////////////
{
Thread cp = null;
public void mouseClicked(final java.awt.event.MouseEvent e)
{
if (cp != null && cp.isAlive())
cp.interrupt();
if (e.getClickCount() == 1)
{
cp = new Thread(new ClickProcessor(new java.util.concurrent.Callable<Void>() {
#Override public Void call() throws Exception {
singleClick(e); //////////////////////////////////////////
return null;
}
}));
cp.start();
}
else if (e.getClickCount() == 2)
{
cp = new Thread(new ClickProcessor(new java.util.concurrent.Callable<Void>() {
#Override public Void call() throws Exception {
doubleClick(e); //////////////////////////////////////////
return null;
}
}));
cp.start();
}
else if (e.getClickCount() == 3)
{
cp = new Thread(new ClickProcessor(new java.util.concurrent.Callable<Void>()
{
#Override public Void call() throws Exception {
tripleClick(e); //////////////////////////////////////////
return null;
}
})
);
cp.start();
}
else manyClick(e); //////////////////////////////////////////
} // mouseClicked
} // new MouseAdapter
); // add mouseListener
} // Click123
class ClickProcessor implements Runnable
{
java.util.concurrent.Callable<Void> eventProcessor;
ClickProcessor(java.util.concurrent.Callable<Void> eventProcessor)
{
this.eventProcessor = eventProcessor;
}
#Override public void run()
{
try
{
System.out.println("About to sleep " + getFreq());
Thread.sleep(getFreq()); // this value comes from implementation
eventProcessor.call();
} catch (InterruptedException e) { System.out.println(e);}
catch (Exception e) { System.out.println(e);}
} // run
} // class ClickProcessor
} // class Click123
The only warning I get from Netbeans is about the "package visible inner class" ClickProcessor.
I compiled my project using this command line:
javac -Xlint:unchecked -classpath main\*.java gbl\*.java
It gave warnings about "unchecked call to Click123<T> as a member of raw type Click123" in several places, including the reference to it in this class:
public class GridCell extends JTextField {
int row,
col;
char content;
Color foreground,
background;
GridCell(){
content = ' ';
foreground = Color.BLACK;
background = Color.WHITE;
disableKeyCombo(KeyEvent.VK_A, KeyEvent.VK_C, KeyEvent.VK_V, KeyEvent.VK_X,
KeyEvent.VK_H);
new Click123(this) ////////// flagged warning unchecked call to Click123
{
#Override
public void singleClick(MouseEvent e) {
if(SwingUtilities.isRightMouseButton(e))
{
if( ! Game.getAvailable().contains("*"))
Game.changeSMBorder(e.getComponent().getX(),
e.getComponent().getY());
else
Game.changeSbBackground(e.getComponent().getX(),
e.getComponent().getY());
}
Game.btnClearBorders.setEnabled(true);
}
#Override public void doubleClick(MouseEvent e){
if(SwingUtilities.isRightMouseButton(e))
{
if(btnUndo.isEnabled())
btnUndo.doClick();
}
}
#Override
public void tripleClick(MouseEvent e) {
if(SwingUtilities.isRightMouseButton(e))
{
if(btnRedo.isEnabled())
btnRedo.doClick();
}
}
#Override
public void manyClick(MouseEvent e) {
}
#Override
public int getFreq() {
return CLICK_FREQUENCY;
}
};
}
... class goes on much further
}
What, if anything, can/should I do?
Try changing
new Click123(this)
to
new Click123<GridCell>(this)
Click123 is a generic class which means it has a type parameter, written between angular brackets. For Click123 the type parameter T must be a subclass of Component, which GridCell is.
Using a raw type like List or Set should be avoided. A raw type is a generic type that is used without type parameters. When generics were introduced, raw types were only allowed for compatibility with code written before generics.
However, looking at your class it looks like there is no reason why Click123 should be generic at all. Couldn't the constructor just take a Component rather than a T?
It looks like you're not fully using the Generics try:
new Click123<GridCell>(this)
How to fix unchecked call warning in Java?

Using raw type with interface in Java

I'm trying to find information about raw types and is it possible to use with interface following way:
public class GlobalConverter {
public interface Listener {
void onReady(Object t);
}
public void convert(String string, Class<?> resultClass, Listener listener) {
try {
listener.onReady(resultClass.newInstance());
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
}
}
public void test() {
convert("Test", MyClass.class, new Listener() {
#Override
public void onReady(Object object /* Possible to be MyClass object ? */) {
}
});
}
}
What I'm trying to achieve would be like above, but for the end user the onReady callback would return the resultClass type of object. Any hints/explanations highly appreciated.
Thanks.
I'll make the Listener itself generic:
public interface Listener<T> {
void onReady(T t);
}
And then the convert method should also be generic:
public <T> void convert(String string, Class<T> resultClass, Listener<T> listener) {
try {
listener.onReady(resultClass.newInstance());
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
}
}
And call it like:
convert("Test", MyClass.class, new Listener<MyClass>() {
#Override
public void onReady(MyClass object) {
}
});

Obtain object from overriden method

public class Job_GUI extends javax.swing.JFrame {
private JobDTO jdto;
public Job_GUI() {
initComponents();
}
private void menuEditJobActionPerformed(java.awt.event.ActionEvent evt) {
editJob.setVisible(true);
//here I want to obtain the updated dto.
}
}
public class JobDTO extends BaseDTO {
//setters and getters
}
class ListDataUI {
private void initListeners() {
summaryTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
summaryTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
final int selectedRowIndex = summaryTable.getSelectedRow();
if (selectedRowIndex != -1) {
BaseDTO dto = data.get(summaryTable.convertRowIndexToModel(selectedRowIndex));
} else {
}
}
}
});
}
}
I am not sure how to obtain the BaseDTO object dto to menuEditJobActionPerformed method so I can display all the values of the object. How do I pass this from valueChanged when event occurs? I'm simply using a table, when a row is selected, the dto state changes, need to pass this new state to the class Job_GUI actionperformed method
Declare dto right after your class GUI { declaration.
That way it will have global scope so all your functions can see it.
class GUI {
BaseDTO dto;
private void menuEditJobActionPerformed(java.awt.event.ActionEvent evt) {
editJob.setVisible(true);
//Now you can access "dto"
}
}
class ListDataUI {
private void initListeners() {
summaryTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
summaryTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
final int selectedRowIndex = summaryTable.getSelectedRow();
if (selectedRowIndex != -1) {
/*BaseDTO */dto = data.get(summaryTable.convertRowIndexToModel(selectedRowIndex));
//not declaring a new object
} else {
}
}
}
});
}
}

Categories

Resources