I have a Java GUI application from which another java GUI application is invoked using reflection and loading. It works fine the only problem faced is, on closing the JFrame of invoked application the Main GUI application frame also closes. How can I prevent the main application (frame) from closing??
I cannot change the defaultCloseOperation of the invoked application, However a change to the main application can be made. Does it have any thing to do with threads??
This is my applications code that executes a target application
public class ClassExecutor{
private ClassLoaderOfExtClass classLoader;
private byte[][] ArrayOfClasses;
private String[] ArrayOfBinaryNames;
#SuppressWarnings("rawtypes")
private ArrayList<Class> loadedClasses;
private ArrayList<String> loadedClasesNames;
private Object[] parameters;
#SuppressWarnings("rawtypes")
public ClassExecutor() {
classLoader = new ClassLoaderOfExtClass();
new ArrayList<Class>();
loadedClasses = new ArrayList<Class>();
loadedClasesNames = new ArrayList<String>();
}
#SuppressWarnings("unchecked")
public void execute(File[] file, String[] binaryPaths) {
Object[] actuals = { new String[] { "" } };
Method m = null;
try {
Field classesx=ClassLoaderOfExtClass.class.getDeclaredField("classes");
classesx.setAccessible(true);
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
}
/*for (int i = 0; i < file.length; i++) {
for (int j = 0; j < file.length; j++) {
try {
#SuppressWarnings("rawtypes")
Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);
//Fied classex=classLoader.getResource("classes");
}catch(Exception e){
}
}
}
Class<?>[]classesxx= getLoadedClasses(classLoader);
System.out.println("Loaded classes have size "+ classesxx.length);*/
for (int i = 0; i < file.length; i++) {
try {
#SuppressWarnings("rawtypes")
Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
} else {
System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
// System.out.println("Main not found!!!");
// System.out.println("M here");
// e.printStackTrace(); // not printing stack trace
} catch (SecurityException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
System.out.println("No such class definition exist!!");
// TODO Auto-generated catch block
// e.printStackTrace();
}
}
try {
m.invoke(null, actuals);
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public void execute(ArrayList<byte[]> stuffedFiles,
ArrayList<String> binaryPaths) {
convertToArray(stuffedFiles, binaryPaths);
loadAllClasses(ArrayOfClasses, ArrayOfBinaryNames);
Object[] actuals = { new String[] { "" } };
Method m = null;
/*
* Method[] m1= new Method[10]; for (Class c : loadedClasses) {
* m1=c.getMethods(); } for(Method m2: m1){
* System.out.println(m2.getName()); }
*/
/* System.out.println(loadedClasses.size()); */
for (Class c : loadedClasses) {
/*
* System.out.println(c.toString());
* System.out.println(c.getConstructors());
*/
// for (int i = 1; i < file.size(); i++) {
/*
* for(Method meth : c.getMethods()){ meth.setAccessible(true);
*
* }
*/
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
break;
} else {
// System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
System.out.println("Program does not contain main");
} catch (SecurityException e) {
e.printStackTrace();
}
}
try {
if(parameters==null){
m.invoke(null, actuals);
}
else{
try {
System.out.println("It Fails Here");
m.invoke(null, parameters);
} catch (Exception e) {
System.out.println("Illegal arguments");
}
}
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
You'll want to use the DISPOSE_ON_CLOSE operation, so it would be setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
EXIT_ON_CLOSE would be the option that closes all windows which I believe is what you are currently experiencing.
You have the following options for the defaultCloseOperation:
DO_NOTHING_ON_CLOSE - The do-nothing default window close operation;
HIDE_ON_CLOSE - The hide-window default window close operation;
DISPOSE_ON_CLOSE - The dispose-window default window close operation.
EXIT_ON_CLOSE - The exit application default window close operation. Attempting to set this on Windows that support this, such as JFrame, may throw a SecurityException based on the SecurityManager. It is recommended you only use this in an application.
The Option DISPOSE_ON_CLOSE could be used in order to avoid to close all windows, closing just the one you want.
If you don't have direct access to JFrame object as you have with the last posted code, you could use Window.getWindows() in order to receive all windows instance (as JFrame is a Window too it will be listed too). And then set the defaultCloseOperation on that.
Possibly you will need to use threads because the defaultCloseOperation needs to be set after invoke main method.
Theoretically it works, so I think this is a good shot ;)
I am not allowed to make changes to the application being invoked.
That was a comment in reply to #JeffLaJoie just to clarify, it would not require any changes to the code of the other app., just an extra method call or two by your app. at run-time to set the close operation of the 3rd party frame.
Failing that, the best solution I can think of is to start the new frame in a separate Process that starts a new JVM, when the user closes the other app., it and the 2nd JVM will end, while leaving the original app. on-screen.
Related
I'm having trouble mocking a static method in a third-party library. I keep receiving a null-pointer exception when running the test, but I'm not sure why that is.
Here is the class and the void method that invokes the static method I'm trying to mock "MRClientFactory.createConsumer(props)":
public class Dmaap {
Properties props = new Properties();
public Dmaap() {
}
public MRConsumerResponse createDmaapConsumer() {
System.out.println("at least made it here");
MRConsumerResponse mrConsumerResponse = null;
try {
MRConsumer mrConsumer = MRClientFactory.createConsumer(props);
System.out.println("made it here.");
mrConsumerResponse = mrConsumer.fetchWithReturnConsumerResponse();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return mrConsumerResponse;
}
}
Below is the test that keeps returning a null-pointer exception. The specific line where the null-pointer is being generated is: MRClientFactory.createConsumer(Mockito.any(Properties.class));
#RunWith(PowerMockRunner.class)
#PrepareForTest(fullyQualifiedNames = "com.vismark.PowerMock.*")
public class DmaapTest {
#Test
public void testCreateDmaapConsumer() {
try {
Properties props = new Properties();
PowerMockito.mockStatic(MRClientFactory.class);
PowerMockito.doNothing().when(MRClientFactory.class);
MRClientFactory.createConsumer(Mockito.any(Properties.class));
//MRClientFactory.createConsumer(props);
Dmaap serverMatchCtrl = new Dmaap();
Dmaap serverMatchCtrlSpy = spy(serverMatchCtrl);
serverMatchCtrlSpy.createDmaapConsumer();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Please follow this example carefully: https://github.com/powermock/powermock/wiki/MockStatic
Especially you are missing a
#PrepareForTest(Dmaap.class)
…to denote the class which does the static call.
I'm trying to get a thread to run for a swing application on button click, but the value isn't updating.
It supposed to grab the computer name I'm searching, but in order for the value to update I have to launch a new instance of the GUI.
I created a thread, but for some reason it's not working. Any help is appreciated.
(t.start is at end of code block)
searchComputerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread t = new Thread("my non EDT thread") {
public void run() {
//my work
testLabel.setText(CN);
}
};
String line;
BufferedWriter bw = null;
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(tempFile));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// String lineToRemove = "OU=Workstations";
String s = null;
Process p = null;
/*
* try { // p = Runtime.getRuntime().exec(
* "cmd /c start c:\\computerQuery.bat computerName"); } catch
* (IOException e1) { // TODO Auto-generated catch block
* e1.printStackTrace(); }
*/
try {
p = Runtime.getRuntime().exec("c:\\computerQuery.bat");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
StringBuffer sbuffer = new StringBuffer();
BufferedReader in = new BufferedReader(new InputStreamReader(p
.getInputStream()));
try {
while ((line = in.readLine()) != null) {
System.out.println(line);
// textArea.append(line);
String dn = "CN=FDCD111304,OU=Workstations,OU=SIM,OU=Accounts,DC=FL,DC=NET";
LdapName ldapName = new LdapName(dn);
String commonName = (String) ldapName.getRdn(
ldapName.size() - 1).getValue();
}
ComputerQuery.sendParam();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidNameException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally
{
try {
fw.close();
}
catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
try {
in.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ComputerQuery.sendParam();
t.start();
}
});
UPDATE
private void threadStart() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
testLabel.setText(CN);
}
});
And I put the method here
JButton searchComputerButton = new JButton("Search");
searchComputerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
threadStart();
String line;
Be aware of the Swing Thread https://docs.oracle.com/javase/tutorial/uiswin/concurrency/
Have a look here:
http://www.javamex.com/tutorials/threads/invokelater.shtml
You must enqueue your JLabel update method invocation using the Method
SwingUtilities.invokeLater(???).
Following example does it
Further more i think that is has something to do with the .batch file invocations. Have a look here: How do I run a batch file from my Java Application?
Runnable task = new UpdateJob("Query: " + i);
SwingUtilities.invokeLater(task);
To make it more understandable.
Swing manages all draw-Operations, within one Thread.
It provides a queue. If you call a method from outside of that queue the behaviour is completely unpredictable.. NullPointer... RuntimeExc....
But if you call SwingUtilities.invokeLater(...) your method will be enqueued into the Swing-Queue and invoked as soon as possible!
UPDATE due to comment:
check your mainthread (GUI)
check your threads.
when a sub-thread (e.g a ActionListener) want to call JLabel::setText
it has to use the method SwingUtils::InvokeLater("...");
That means invokeLater() has to be call within all threads which not directly belong to the main threads.
UPDATE due to Question
In my oppinion you current't code doesn't need SwingUtilities.invok.. at all.
Did you change the Code assigned to you your question.
i am facing a problem regrading specifying the return data type. I have the FOComp class which implements callabale, the call() method of the 'FOComp' returns data type List<ArrayList<Mat>> as shown in the code of 'FOComp' class below.
and the method 'getResults()' returns data of type ArrayList<Mat> as shown in the code below. and currently, at run time, when I execute the code, I receive the folowing error:
Multiple markers at this line
The return type is incompatible with Callable<ArrayList<Mat>>.call()
The return type is incompatible with Callable<List<Mat>>.call()
kindly please let me know how to fix it.
'FOComp' class:
static class FOComp implements Callable<List<Mat>> {//should return list contains 4 mats(0,45,90,135)
private ArrayList<Mat> gaussianMatList = null;
private List<ArrayList<Mat>> results_4OrientAngles_List = null;
public FOComp(ArrayList<Mat> gaussianMatList) {
// TODO Auto-generated constructor stub
this.gaussianMatList = gaussianMatList;
this.results_4OrientAngles_List = new ArrayList<ArrayList<Mat>>();
}
public List<ArrayList<Mat>> call() throws Exception {
// TODO Auto-generated method stub
try {
featOrient = new FeatOrientation(this.gaussianMatList);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
featOrient.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.results_4OrientAngles_List.add(featOrient.getResults());
return results_4OrientAngles_List;
}
}
'getResults':
public ArrayList<Mat> getResults() {
if (this.crossAddOrientMapsList != null) {
if (!this.crossAddOrientMapsList.isEmpty()) {
if (this.crossAddOrientMapsList.size() == 4) {
double[] theta = new double[4];
theta[0] = 0;
theta[1] = 45;
theta[2] = 90;
theta[3] = 135;
for (int i = 0; i < this.crossAddOrientMapsList.size(); i++) {
MatFactory.writeMat(FilePathUtils.newOutputPath("FinalCrossAdd_" + theta[i]+"_degs"), this.crossAddOrientMapsList.get(i));
//ImageUtils.showMat(this.crossAddOrientMapsList.get(i), "OrientMap_" + theta[i] + " degs");
}
return this.crossAddOrientMapsList;
} else {
Log.WTF(TAG, "getResults", "crossAddOrientMapsList != 4 !!");
return null;
}
} else {
Log.E(TAG, "getResults", "crossAddOrientMapsList is empty.");
return null;
}
} else {
Log.E(TAG, "getResults", "crossAddOrientMapsList is null");
return null;
}
}
class FOComp implements Callable<List<Mat>>
and
public List<ArrayList<Mat>> call()
aren't really compatible... Your call() method should be
#Override public List<Mat> call()
Also, it is good practice to avoid implementation classes in method signatures, use the interfaces instead (in this case, use List rather than ArrayList). That will also fix your problem with one of the "multiple markers" :-)
Cheers,
You class declaration says that you are going to return a List of Mat (FOComp implements Callable<List<Mat>>), but your call method signature says you are going to return a List of ArrayList of Mat (List<ArrayList<Mat>>).
You will need to make them consistent.
I have an API that I use to retrieve daily schedules on the live cable-tv for various channels. I have a scenario in which I need a guidance as to which approach should work here.
Lets say I need schedules for 10 different channels from the API.
Should I execute 10 different async tasks for the retrieval of the required data?
Problem:
How would I collect the data in an arraylist and return it once all execution is completed?
How will I access the arraylist in my main function once onpostexecute returns the result?
Or I should just provide the list of channels to my single async task and make it build a single output of arraylist for my main function invoking it?
Problem:
Since I will be accessing a webservice for this purpose, will it make it run slow as compared to my 1st approach?
Second problem with this approach is the same as I am having with my 1st one, I need to know when and how to get the complete resultset once the execution of the task is completed?
Here is some code to explain the problem:
//going with the first approach
//invoking my asynctask from an activity or another class
//I need a global arraylist which I can use after postexecute returns its result
ArrayList<String> channels = channelManager.getAllChannelsByRegion("xyz");
final ArrayList<ChannelSchedule> schedules = new ArrayList<ChannelSchedule>();
final ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
for (int i = 0; i < channels.size(); ++i){
AsyncInvokeURLTask task = null;
try {
task = new AsyncInvokeURLTask(
channels.get(i), context, new AsyncInvokeURLTask.OnPostExecuteListener() {
#Override
public void onPostExecute(String result) {
// TODO Auto-generated method stub
try {
//Need to add results to arraylist here...But cannot know when it ends completely
ChannelSchedule schedule = mapper.readValue(result, ChannelSchedule.class);
Log.v("channel name", schedule.getChannelName());
Log.v("channel date", schedule.getDate());
Log.v("channel thumb", schedule.getListOfShows().get(0).getShowThumb());
Log.v("channel time", schedule.getListOfShows().get(0).getShowTime());
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
task.execute();
}
Please let me know if something is not clear or missing.
Launching 10 AsyncTask is perfectly fine.
You can keep a count of the number of pending requests. As OnPostExecute is run on the UI thread there are no risks of race condition.
private int numberOfPendingRequests;
public void MyFunc() {
ArrayList<String> channels = channelManager.getAllChannelsByRegion("xyz");
final ArrayList<ChannelSchedule> schedules = new ArrayList<ChannelSchedule>();
final ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
numberOfPendingRequests = channels.size();
for (int i = 0; i < channels.size(); ++i) {
schedules.add(null);
}
for (int i = 0; i < channels.size(); ++i) {
AsyncInvokeURLTask task = null;
final int index = i; // final so it can be used in the onPostExecute.
try {
task = new AsyncInvokeURLTask(
channels.get(i), context, new AsyncInvokeURLTask.OnPostExecuteListener() {
#Override public void onPostExecute(String result) {
try {
ChannelSchedule schedule = mapper.readValue(result, ChannelSchedule.class);
Log.v("channel name", schedule.getChannelName());
Log.v("channel date", schedule.getDate());
Log.v("channel thumb", schedule.getListOfShows().get(0).getShowThumb());
Log.v("channel time", schedule.getListOfShows().get(0).getShowTime());
schedules.set(index, schedule);
numberOfPendingRequests--;
if (numberOfPendingRequests == 0) {
// Everything is received, do stuff here.
}
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
task.execute();
}
}
I'm trying to load the radio version of the Android device using reflection. I need to do this because my SDK supports back to API 7, but Build.RADIO was added in API 8, and Build.getRadioVersion() was added in API 14.
// This line executes fine, but is deprecated in API 14
String radioVersion = Build.RADIO;
// This line executes fine, but is deprecated in API 14
String radioVersion = (String) Build.class.getField("RADIO").get(null);
// This line executes fine.
String radioVersion = Build.getRadioVersion();
// This line throws a MethodNotFoundException.
Method method = Build.class.getMethod("getRadioVersion", String.class);
// The rest of the attempt to call getRadioVersion().
String radioVersion = method.invoke(null).toString();
I'm probably doing something wrong here. Any ideas?
Try this:
try {
Method getRadioVersion = Build.class.getMethod("getRadioVersion");
if (getRadioVersion != null) {
try {
String version = (String) getRadioVersion.invoke(Build.class);
// Add your implementation here
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
Log.wtf(TAG, "getMethod returned null");
}
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
What Build.getRadioVersion() actually does is return the value of gsm.version.baseband system property. Check Build and TelephonyProperties sources:
static final String PROPERTY_BASEBAND_VERSION = "gsm.version.baseband";
public static String getRadioVersion() {
return SystemProperties.get(TelephonyProperties.PROPERTY_BASEBAND_VERSION, null);
}
According to AndroidXref this property is available even in API 4. Thus you may get it on any version of Android through SystemProperties using the reflection:
public static String getRadioVersion() {
return getSystemProperty("gsm.version.baseband");
}
// reflection helper methods
static String getSystemProperty(String propName) {
Class<?> clsSystemProperties = tryClassForName("android.os.SystemProperties");
Method mtdGet = tryGetMethod(clsSystemProperties, "get", String.class);
return tryInvoke(mtdGet, null, propName);
}
static Class<?> tryClassForName(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
return null;
}
}
static Method tryGetMethod(Class<?> cls, String name, Class<?>... parameterTypes) {
try {
return cls.getDeclaredMethod(name, parameterTypes);
} catch (Exception e) {
return null;
}
}
static <T> T tryInvoke(Method m, Object object, Object... args) {
try {
return (T) m.invoke(object, args);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getTargetException());
} catch (Exception e) {
return null;
}
}