Creating an editable JList

Courtesy of Nobuo Tamemasa (http://www2.gol.com/users/tame/swing/examples/JTableExamples1.html)



EditableListExample.java:

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
 
/**
 * @version 1.0 12/24/98
 */
public class EditableListExample extends JFrame {
 
  public EditableListExample() {
    super("Editable List Example");
    
    String[] data = {"a","b","c","d","e","f","g"};
    
    JList list = new JList( data );
    JScrollPane scrollList = new JScrollPane( list );
    scrollList.setMinimumSize(new Dimension(100,80));
    Box listBox = new Box(BoxLayout.Y_AXIS);
    listBox.add(scrollList);
    listBox.add(new JLabel("JList"));
         
    DefaultTableModel dm = new DefaultTableModel();
    Vector dummyHeader = new Vector();
    dummyHeader.addElement("");
    dm.setDataVector(
      strArray2Vector(data),
      dummyHeader);
    JTable table = new JTable( dm );
    table.setShowGrid(false);
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    JScrollPane scrollTable = new JScrollPane( table );
    scrollTable.setColumnHeader(null);
    scrollTable.setMinimumSize(new Dimension(100,80));
    Box tableBox = new Box(BoxLayout.Y_AXIS);
    tableBox.add(scrollTable);
    tableBox.add(new JLabel("JTable"));
    
    Container c = getContentPane();
    c.setLayout(new BoxLayout(c, BoxLayout.X_AXIS));
    c.add(listBox);
    c.add(new JSeparator(SwingConstants.VERTICAL));
    //c.add(new JLabel("test"));
    //c.add(new JSeparator(SwingConstants.HORIZONTAL));
    c.add(tableBox);
    setSize( 220, 130 );
    setVisible(true);
  } 
   
  private Vector strArray2Vector(String[] str) {
    Vector vector = new Vector();
    for (int i=0;i<str.length;i++) {
      Vector v = new Vector();
      v.addElement(str[i]);
      vector.addElement(v);
    }
    return vector;
  }

  public static void main(String[] args) {
    final EditableListExample frame = new EditableListExample();
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent e ) {
        System.exit(0);
      }
    });
  }
}

Using the JDBCRealm

Tomcat supports Container Managed Security. You don’t need to package your Servlets or JSPs with ugly authentication code, let Tomcat do it for you!

A Realm is a simply a collection of usernames, passwords and roles. This Q/A deals with how to store this information in a database table and integrate it with Tomcat.

A user has a password and can have multiple roles. You can give access to a resource (or a set of resources, eg. *.jsp) by associating it with one or more roles.

For example: suppose you want all JSP’s under the subdirectory /protected to be accessible by only the users that have the (custom) role member. You can declaratively do this in web.xml:

<web-app>   
   <security-constraint>      
      <web-resource-collection>         
         <web-resource-name>admin</web-resource-name>         
         <url-pattern>/protected/*.jsp</url-pattern>      
      </web-resource-collection>      
      <auth-constraint>         
         <role-name>member</role-name>         
      </auth-constraint>   
   </security-constraint>   
</web-app>

So, where are the users/passwords that have the member role? That depends on the type of Realm you’re using. A MemoryRealm stores this information in a file (see TOMCAT-HOME/conf/tomcat-users.xml). A JDBCRealm uses a database.

So let’s create a web application with the protected directory protected. All members having either role silver or role gold are allowed to access the resources in that directory.

Here is how our new web.xml looks like:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">

<web-app>   
   <security-constraint>      
      <web-resource-collection>         
         <web-resource-name>admin</web-resource-name>         
         <url-pattern>/protected/*</url-pattern>      
      </web-resource-collection>      
      <auth-constraint>         
         <role-name>Silver</role-name>         
         <role-name>Gold</role-name>         
      </auth-constraint>   
   </security-constraint>
   
   <login-config>
      <auth-method>BASIC</auth-method>      
      <realm-name>Log In</realm-name>
   </login-config>
</web-app>

Note the login-config tag. It specifies how a user should authenticate. We use BASIC authentication which will cause a popup to appear whenever an unauthenticated user tries to access one of the protected resources:

Authentication information will be stored in a database and accessed with a JDBC driver. In this example, we use mysql with the driver MySQL Connector/J (formerly mm.mysql).
Download the JAR file (mm.mysql-2.0.4-bin.jar) and store it in [TOMCAT-HOME]/common/lib, if it will be only visible by your web applications or [TOMCAT-HOME]/server/lib if it’s used by Tomcat 4 as well.

Modify [TOMCAT-HOME]/conf/server.xml to configure Tomcat to use the database as an authentication mechanism. You can host the following tag in the Engine, Host or Context element, depending on the scope you want (inside Engine = share across all web applications and all virtual hosts, inside Host = share accross all web applications of that particular host, inside Context = use this Realm only for this web application).

      <Realm className="org.apache.catalina.realm.JDBCRealm" debug="00"
             driverName="org.gjt.mm.mysql.Driver"
             connectionURL="jdbc:mysql://localhost/esusdb"
             connectionName=""
             connectionPassword=""
             userTable="members"
             userNameCol="username"
             userCredCol="password"
             userRoleTable="memberroles"
             roleNameCol="role" /> 
  • driverName specifies the JDBC driver to be used (added previously to the lib directory).
  • connectionURL specifies the database URL to connect to.
  • connectionName and connectionPassword are needed if your database is password protected.
  • userTable specifies the table in your database in which authentication information is stored. It should contain a user per row, with the username/password stored in the columns specified in userNameCol and userCredCol.
  • userRoleTable specifies the table in your database that contains an association between the users and their roles. It should contain at least the columns specified in userNameCol and roleNameCol.

Now create the necessary mysql database tables:

C:mysqlbin>mysql
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 5 to server version: 3.23.47-nt
 
Type 'help;' or 'h' for help. Type 'c' to clear the buffer.
 
mysql> create database esusdb;
Query OK, 1 row affected (0.00 sec)
 
mysql> use esusdb;
Database changed
mysql> create table members (uid int(10) not null primary key, username varchar(
20) not null, password varchar(20) not null);
Query OK, 0 rows affected (0.00 sec)
 
mysql> create table memberroles (username varchar(20) not null, role varchar(10)
 not null, primary key (username, role));
Query OK, 0 rows affected (0.01 sec)
 
mysql> desc members;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| uid      | int(10)     |      | PRI | 0       |       |
| username | varchar(20) |      |     |         |       |
| password | varchar(20) |      |     |         |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
 
mysql> desc memberroles;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| username | varchar(20) |      | PRI |         |       |
| role     | varchar(10) |      | PRI |         |       |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.02 sec)
 
mysql>

…and insert some data:

 
mysql> insert into members values (1, 'John', '123456');
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into members values (2, 'Lisa', '654321');
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into memberroles values ('John', 'Gold');
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into memberroles values ('Lisa', 'Silver');
Query OK, 1 row affected (0.00 sec)
 
mysql>

We have created two users: John with role Gold and Lisa with role Silver.

Our web application will use the JDBCRealm to connect to this database and authenticate users.
To create the example web application, create a directory structure as follows:

loginexample2
   |
   +- index.jsp
   |
   +--- protected
   |       |
   |       +- confidential.jsp
   |
   +--- WEB-INF
           |
           +- web.xml

Use the deployment descriptor web.xml that is shown above. The rest of the example JSP’s can be cut’n’pasted here:

loginexample2/index.jsp:

<html>
<body>
Access <a href="./protected/confidential.jsp">protected resource</a>
</body>
</html>

loginexample2/protected/confidential.jsp:

<html>
<body>
<%
   if (request.isUserInRole("Gold")) {
%>
   You have the GOLD role<br>
<% 
   }
   if (request.isUserInRole("Silver")) {
%>
   You have the SILVER role<br>
<%
   }
%>
<br> 
You have successfully accessed the protected resource!
</body>
</html>

Go to http://localhost:8080/loginexample2/index.jsp and try to access the protected resource. A popup window will show up. Notice that, once you’re logged in, you cannot log out, except by closing the browser window.

Using a RadioButton in SWT

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
 
public class Main {
   public static void main(String[] args) {
      Display display = new Display();
      Shell shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 300, 200);
      shell.setText("SWT RadioButton Demonstration");
      shell.setLayout(new GridLayout());
 
      Group buttonGroup = new Group(shell, SWT.NONE);
      GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 1;
      buttonGroup.setLayout(gridLayout);
      buttonGroup.setLayoutData(new GridData(GridData.FILL_VERTICAL));
      
      SelectionListener selectionListener = new SelectionAdapter () {
         public void widgetSelected(SelectionEvent event) {
            Button button = ((Button) event.widget);
            System.out.print(button.getText());
            System.out.println(" selected = " + button.getSelection());
         };
      };
            
      Button button1 = new Button(buttonGroup, SWT.RADIO);
      button1.setText("orange");
      button1.addSelectionListener(selectionListener);
      Button button2 = new Button(buttonGroup, SWT.RADIO);
      button2.setText("pear");
      button2.addSelectionListener(selectionListener);
      Button button3 = new Button(buttonGroup, SWT.RADIO);
      button3.setText("apple");
      button3.addSelectionListener(selectionListener);
      
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
   }
}

Creating an SWT FontDialog?

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
 
public class Main { 
   static Display display;
   static Shell shell;
   static Color color;
    
   public static void main(String[] args) {
      display = new Display();
      shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 400, 200);
      shell.setText("SWT FontDialog Demonstration");
      shell.setLayout(new GridLayout());
 
      final Group buttonGroup = new Group(shell, SWT.NONE);
      GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 3;
      buttonGroup.setLayout(gridLayout);
      buttonGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
       
      final Button directoryDialogButton = new Button(buttonGroup, SWT.PUSH);
      directoryDialogButton.setText("Open FontDialog");
      Label label1 = new Label(buttonGroup, SWT.NONE);
      label1.setText("Font selected:");
      final Label label2 = new Label(buttonGroup, SWT.NONE);      
      label2.setText("");
 
      SelectionListener selectionListener = new SelectionAdapter () {
         public void widgetSelected(SelectionEvent event) {
            FontDialog dialog = new FontDialog (shell, SWT.MODELESS);
            dialog.setText("Select Font");
            FontData result = dialog.open();
            label2.setText("" + result);
            buttonGroup.layout();
         };
      };
       
      directoryDialogButton.addSelectionListener(selectionListener);
       
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      if (color != null && !color.isDisposed()) {
         color.dispose();
      }
      display.dispose();
   }
}

Creating a Styled Text(area)

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
 
public class Main {
   public static void main(String[] args) {
      Display display = new Display();
      Shell shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 300, 200);
      shell.setText("SWT Text Demonstration");
      shell.setLayout(new GridLayout());
 
      shell.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
      StyledText styledText = new StyledText(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
      styledText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
       
      styledText.setText("Did you know..." +
                         "nn" +
                         "It is impossible to lick your elbow." +
                         "nnnnnnnnnnnnnnn" +
                         "Over 75% of people who read thisn" +
                         "will try to lick their elbow.");
  
      StyleRange boldStyle = new StyleRange(0, 20, null, null, SWT.BOLD);
      styledText.setStyleRange(boldStyle);
 
      Color foreColor = display.getSystemColor (SWT.COLOR_RED);
      StyleRange foreStyle = new StyleRange(20, 20, foreColor, null, SWT.NORMAL);
      styledText.setStyleRange(foreStyle);
       
      Color backColor = display.getSystemColor (SWT.COLOR_DARK_YELLOW);
      StyleRange backStyle = new StyleRange(40, 20, null, backColor, SWT.NORMAL);
      styledText.setStyleRange(backStyle);
 
      StyleRange foreBackStyle = new StyleRange(60, 20, foreColor, backColor, SWT.NORMAL);
      styledText.setStyleRange(foreBackStyle);
             
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
       
      display.dispose();
   }
}

Dispatching an event to a Component

You can do so directly by calling the method dispatchEvent(AWTEvent event) on the Component. The following example dispatches the events to a button programmatically (as if they would come from the user clicking the mouse).

Main.java:

mport java.awt.event.*;
import java.awt.*;
 
public class Main extends Frame
{
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      Button button1 = new Button("Click me!");
      final Button button2 = new Button("Don't bother me...");
 
      setLayout(new FlowLayout(FlowLayout.LEFT)); 
      add(button1);
      add(button2);
      setSize(200, 200);
 
      button1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            button2.dispatchEvent(new MouseEvent(button2,
                                                 MouseEvent.MOUSE_PRESSED,
                                                 System.currentTimeMillis(),
                                                 0, 5, 5, 1, false));
 
            try {
               Thread.sleep(100);
            }
            catch(InterruptedException e) { } 
 
            button2.dispatchEvent(new MouseEvent(button2,
                                                 MouseEvent.MOUSE_RELEASED,
                                                 System.currentTimeMillis(),
                                                 0, 5, 5, 1, false));
           
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
   }
}

Creating your own JSP exception page

If exceptions occur in JSP pages that are not handled, you can make the engine redirect to an JSP or HTML error page. You can even have access to the exception occurred (the “implicit exception object”) if you set the isErrorPage attribute to true.

A divide by zero JSP:

<%-- Redirect all uncaught exceptions to errorpage.jsp --%>
<%@ page errorPage="errorpage.jsp"%>

<%
   int h = 10 / 0;
%>

errorpage.jsp:

<%-- provides access to the implicit exception object --%>
<%@ page isErrorPage="true" %>
<html>
<body>
   <h3>An error occurred!</h3>
   <%=exception%>
</body>
</html>

Test it out here:
Divide by zero JSP

Embedding a JTextArea and ImageIcon in a JTable cell

JTextAreaTableExample.java:

import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
  
public class JTextAreaTableExample extends JFrame {
 
  public JTextAreaTableExample() {
    super( "JTextAreaTableExample Example" );
  
    DefaultTableModel dtm = new DefaultTableModel() {
       // make first cell uneditable
       public boolean isCellEditable(int row, int column)
       {
          return !(column == 0);
       }
    };
 
    dtm.setDataVector(new Object[][]{{ "JTextArea1", "This is a testnon long linesn" },
                                     { "JTextArea2", "Hello, world!" }},
                      new Object[]{ "String","JTextArea"});
                     
    JTable table = new JTable(dtm);
    table.getColumn("JTextArea").setCellRenderer(new TextAreaRenderer());
    table.getColumn("JTextArea").setCellEditor(new TextAreaEditor());
 
    table.setRowHeight(80);
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
 
    setSize( 400, 250 );
    setVisible(true);
  }
 
  public static void main(String[] args) {
    JTextAreaTableExample frame = new JTextAreaTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
  
class TextAreaRenderer extends JScrollPane implements TableCellRenderer
{
   JTextArea textarea;
 
   public TextAreaRenderer() {
      textarea = new JTextArea();
      textarea.setLineWrap(true);
      textarea.setWrapStyleWord(true);
      textarea.setBorder(new TitledBorder("This is a JTextArea"));
      JPanel panel = new JPanel();
      panel.setLayout(new BorderLayout());
      panel.add(BorderLayout.WEST, new JLabel(new ImageIcon("TrafficRed.gif")));
      panel.add(BorderLayout.CENTER, textarea);
      getViewport().add(panel);
   }
 
   public Component getTableCellRendererComponent(JTable table, Object value,
                                  boolean isSelected, boolean hasFocus,
                                  int row, int column)
   {
      if (isSelected) {
         setForeground(table.getSelectionForeground());
         setBackground(table.getSelectionBackground());
         textarea.setForeground(table.getSelectionForeground());
         textarea.setBackground(table.getSelectionBackground());
      } else {
         setForeground(table.getForeground());
         setBackground(table.getBackground());
         textarea.setForeground(table.getForeground());
         textarea.setBackground(table.getBackground());
      }
 
      textarea.setText((String) value); 
      textarea.setCaretPosition(0);
      return this;
   }
}
 
class TextAreaEditor extends DefaultCellEditor {
   protected JScrollPane scrollpane;
   protected JTextArea textarea; 
 
   public TextAreaEditor() {
      super(new JCheckBox());
      scrollpane = new JScrollPane();
      textarea = new JTextArea();  
      textarea.setLineWrap(true);
      textarea.setWrapStyleWord(true);
      textarea.setBorder(new TitledBorder("This is a JTextArea"));
      JPanel panel = new JPanel();
      panel.setLayout(new BorderLayout());
      panel.add(BorderLayout.WEST, new JLabel(new ImageIcon("TrafficRed.gif")));
      panel.add(BorderLayout.CENTER, textarea);
      scrollpane.getViewport().add(panel);
   }
 
   public Component getTableCellEditorComponent(JTable table, Object value,
                                   boolean isSelected, int row, int column) {
      textarea.setText((String) value);
 
      return scrollpane;
   }
 
   public Object getCellEditorValue() {
      return textarea.getText();
   }
}

Image used:

Using a ProxySelector

Here’s a working example that says everything. MyProxySelector is automatically contacted when URLConnection is about to make a connection.

Main.java:

import java.net.*;
import java.io.*;
import java.util.*;

public class Main
{
   public static void main(String []args) throws Exception {
      if (args.length != 1) {
         System.err.println("Usage: java Main <URL>");
         System.exit(0);
      }
      
      System.out.println("Old ProxySelector: " + ProxySelector.getDefault());
      ProxySelector.setDefault(new MyProxySelector());
      System.out.println("New ProxySelector: " + ProxySelector.getDefault());
          
      URL url = new URL(args[0]);
      URLConnection connection = url.openConnection();
 
      connection.setConnectTimeout(5000);
      connection.connect();
   }
}

class MyProxySelector extends ProxySelector
{
   public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
      System.out.println("connectFailed: " + ioe.getMessage());
   }
   
   public List<Proxy> select(URI uri) {
      ArrayList<Proxy> list = new ArrayList<Proxy>();
      Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.esus.com", 8080));
      list.add(proxy);

      return list;
   }
}

Catching exceptions in threads in JDK1.5

Sometimes, a thread may abruptly terminate, for example due to a NullPointerException. In large applications, a bug due to a thread that vanished just like that may be very hard to spot. In JDK1.5, there is a new inner interface Thread.UncaughtExceptionHandler that will make it a lot easier to detect exceptions.

When a thread is about to terminate because of an uncaught exception, the thread’s uncaughtExceptionHandler is called. If the thread’s uncaughtExceptionHandler is null, the thread’s ThreadGroup (which implements UncaughtExceptionHandler) is called. The ThreadGroup‘s uncaughtExceptionHandler calls the Thread DefaultUncaughtExceptionHandler if it is set otherwise it prints out the exception to System.err.

Excerpt from ThreadGroup.java:

    public void uncaughtException(Thread t, Throwable e) {
	if (parent != null) {
	    parent.uncaughtException(t, e);
	} else {
            Thread.UncaughtExceptionHandler ueh = 
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
		System.err.print("Exception in thread ""
				 + t.getName() + "" ");
                e.printStackTrace(System.err);
            }
        }
    }

The following example forces a NullPointerException in a Thread which is dealt with with our own MyUncaughtExceptionHandler.

Main.java:

public class Main
{
   public static void main(String []args) {
      Thread t = new Task();
      t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
      t.start();
   }
}
 
class Task extends Thread
{
   private Object o = null;
 
   public void run() {
      o.toString();
   }
}
 
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler
{
   public void uncaughtException(Thread t, Throwable e) {
      System.out.println("Exception occurred in Thread " + t);
 
      e.printStackTrace();
   }
}