Monday, September 24, 2012

Reusable UI

One of the objectives of this project is to build a reusable test UI, which is not only available for the TPC test, but also for users' self-defined tests.

To achieve this objective, I use properties files of Java.According to the Java API, Properties are configuration values managed as key/value pairs. In each pair, the key and value are both String values. The key identifies, and is used to retrieve, the value, much as a variable name is used to retrieve the variable's value.

I let uses to browse the system and choose the properties files. In each properties file, a property called 'testClassName' is required. The 'testClassName' is the name of the java class which implement the test function. Program searches the default directory to find the java class file and run the test.

Sunday, September 2, 2012

Embed Swing and AWT in SWT

I am looking for a way to draw dynamic diagrams in SWT. I have found a very power Java library called JFreeChart. Unfortunately it support Swing better than SWT. Therefore I need a way to embed Swing into my SWT GUI.

I have discovered that SWT provides an very easy way to do so.For many SWT components, they have a attribute called SWT.EMBEDDED. By adding this attribute, the component knows that another application is plugged in.

Here is an example of this function.

Display display = new display();
Shell shell = new shell(display, SWT.EMBEDDED);
Frame frame = SWT_AWT.new_Frame(shell);
frame.add(new JLabel("This is a Java Swing Label"));

Sunday, August 19, 2012

Be careful with Java Thread.join() in GUI design

I was stuck by a problem for about a week. Every time I tried to run the GUI,the GUI was frozen, no buttons, menus or any other operations could be done until all the back-end computations finished.
Finally I figured out the cause of the problem. Since I'm using parallel programming. I created a thread when a new transaction was required, and I joined all the threads when they finished. I created threads with following code:


Thread threadArray[] = new Thread[testThreadNmuber];
for(int i=0; i<testThreadNmuber; i++)
{
    threadArray[i] = new Thread(testDriver);
    threadArray[i].start();  
}

Above code worked fine. I thought I should be able to use the similar way to join the threads. Therefore I wrote following code:

for(int i=0; i<testThreadNmuber; i++)
{
    threadArray[i].join();
    System.out.println("Thread-" +i+ " : exited\n");
}
However, the join() function caused a critical error. I didn't realize the problem of join(), because it was the common way to implement in Java parallel programming. While I understood the problem by reading the Java API. In Java API the explanation of join() is 'Waits for this thread to die'. As I called the join() in the main thread, the main thread would wait for all the sub-threads to die. In GUI design, the main thread is the thread that draw the interface. If the interface waits all the sub-threads to die the main thread will hold up and the interface will not response any operations. Therefore, I should not use join() in GUI programming.


However this cause another problem. If I don't use join(), how I can know if all the jobs finish? One simple solution is to create a integer, if one thread finish, the integer plus one. When this integer is equal to the number of threads, all the thread finish. But this integer must be locked when one thread is updating it, otherwise the race condition may occur.


Saturday, August 11, 2012

Progress Bar

The performance testing requires a very long time, we need to know the progress of the testing.
Progress bar is a common choice.Progress bar is provided as a component by Java SWT. To add a progress bar, following steps can be used:
1. Create ProgressBar object, and choose the style, such as: ProgressBar bar1 = new ProgressBar (shell, SWT.HORIZONTAL | SWT.SMOOTH);.
2. Set the maximum value and minimum value, bar1.setMaximum(100);
3. Set the progress of the ProgressBar in a long time task, progressBar.getSelection() + 1.

Progress bar should be used with thread. The threads that are not UI thread cannot write the UI directly, otherwise the UI will be frozen, no more operations can be done with the UI. It is the same reason that the progress bar must update the UI in a separate thread.

Here is how I did to create the progress bar:

final ProgressBar progressBar = new ProgressBar(composite, SWT.SMOOTH);
    FormData fd_progressBar = new FormData();
    fd_progressBar.top = new FormAttachment(0);
    fd_progressBar.right = new FormAttachment(100, -42);
    progressBar.setLayoutData(fd_progressBar);
    class ProgressBarRunning extends Thread{
         long testRuntime = Integer.parseInt(text_1.getText());
         public void run() {
      for (int i = 0; i < 100; i++) {
  try {
                    Thread.sleep(testRuntime/100);
                } catch (InterruptedException e) {
               e.printStackTrace();
}
display.asyncExec(new Runnable() {
      public void run() {
if (progressBar.isDisposed())
    return;
progressBar.setSelection(progressBar.getSelection() + 1);
        }
   });
  }
  }
}

In the above code, the first thread decides how long the progress bar increase. The second thread updates the progress bar.


Friday, August 3, 2012

Introducing Java SWT

I have been using Java Swing for a while, I have some personal view of points about Swing.

It is very hard for a beginner to build a good looking GUI with Swing. Without further knowledge of Swing, the GUI doesn't look like a proper software.The  appearance doesn't fit the current system.

Swing is not thread-safe. Thread is the core of front-end design of this project. I need to care about which thread is updating GUI. If something goes wrong, some unpredictable behaviors will happen.

I have introduced Java SWT into my GUI design base on following reasons.

Java SWT always fits the current operation system. The GUI is friendly to users.

Java SWT will throw exceptions when threads go wrong which is better than the uncertainty of Java Swing.

Java SWT runs faster than Java Swing, since my job is performance test, I want to reduce the influence of GUI to the performance of the test.

However Java SWT is not perfect. I need to worry about the compatibility of Java SWT on the Non-Windows platforms. The Java SWT is not included in the standard JRE package, it needs to be installed.

Wednesday, May 23, 2012

java Class.forName(className) ClassNotFoundException


package test;

 public void run()
    {

        if(debug) jTextArea2.append(Thread.currentThread().getName() + " started !");
       
        try
        {
            String testThreadID = Thread.currentThread().getName();
            if(debug) jTextArea2.append("To instance a test class with name = " + testClassName);
            IRunner testRunner = (IRunner) Class.forName("HelloTester").newInstance();
            testRunner.init();
            testRunner.GetText(jTextArea2);
           
            if(testWarmup>0)  Test(testRunner, (long)(testRuntime*testWarmup/100.0), false,jTextArea2);
                                Test(testRunner, (long)(testRuntime*(100.0-testWarmup-testCooldown)/100.0), true,jTextArea2);
            if(testCooldown>0)Test(testRunner, (long)(testRuntime*testCooldown/100.0), false,jTextArea2);
        }
        catch(Exception e)
        {
            System.err.println(e.toString());
        }
    }

After compiled, I got exceptions:

java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester
java.lang.ClassNotFoundException: HelloTester

The problem was caused by the red line:
 IRunner testRunner = (IRunner) Class.forName("HelloTester").newInstance();
Correction:
 IRunner testRunner = (IRunner) Class.forName("test.HelloTester").newInstance();


Thinking:
Although the item can be used directly within the same package. But the package name is added by the compiler by default. When the item is loaded by the Class.forName(ClassName), it searches the item in the default package. Therefore the package name should be added with the ClassName.

Sunday, May 6, 2012

JAVA Thread

I did some work on JAVA Thread this week. I found two ways to use thread in JAVA.

public class ThreadA extends Thread{
   public void run(){
      //code
   }
}

public class ThreadB implements Runnable{
   public void run(){
      //code
   }
}

I wrote a piece of code with the first method.


class MyThread extends Thread{
        private int threadID;
        public MyThread(int id){
            this.threadID=id;
        }
        public void run(){
            int random = (int)(Math.random()*10000);
            try
            {
                Thread.sleep(random);
                jTextArea1.append("thread: "+this.threadID+" slept "+random+"ms"+"\n");
                jTextArea1.setCaretPosition(jTextArea1.getDocument().getLength() - 1);
            }
            catch(Exception e)
            {
                System.err.println(e.toString());
                System.exit(1);
            }
        }
    }

private void StartActionPerformed(java.awt.event.ActionEvent evt) {
        num_of_client = Integer.parseInt(jTextField1.getText());     
        for (int i=0;i<num_of_client;i++){
            t.add(new MyThread(i));
            t.get(i).start();
}
The output of above code looked like:
thread: 4 slept 1204ms
thread: 7 slept 2472ms
thread: 6 slept 4397ms
thread: 9 slept 6533ms
thread: 3 slept 7535ms
thread: 5 slept 7589ms
thread: 2 slept 8443ms
thread: 1 slept 8455ms
thread: 8 slept 9379ms
thread: 0 slept 9457ms
  

I was not clear what the difference between those two methods. According to the JAVA api, The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run.


Normally the better way is implementing Runnable interface, because if the thread class you are creating is to be subclass of some other class, it can’t extend from the Thread class. This is because Java does not allow a class to inherit from more than one class. In such a case one can use Runnable interface to implement threads.