Using comments in a JSP page

There are several ways to use comments in JSP:

1) JSP comments (not compiled nor executed)
   <%-- Counter is <%=counter%> --%>
 
or
2) Java comments (not compiled nor executed)
   <%
      // Calculate the counter
      /*
         Counter is <%=counter%>
      */
 
or
3)  HTML comments (compiled and executed, but not displayed
    by browser!)
 
   <!--
      Counter is <%=counter%> 
   -->

Using transactions with JDBC

SQL statements can be grouped together in a single statement to ensure the ACID (Atomicity, Consistency, Isolation, Durability) characteristics. By default, each SQL statement is auto-commited. In other words, it is treated as a transaction by itself and will be committed right away. This may not be desirable in cases where all the SQL statements need to be executed or none of them, if one fails. The way this can be done with JDBC is by turning off auto-commit mode before the group of statements and turn auto-commit back on after.

   conn.setAutoCommit(false);
   Statement stmt = conn.createStatement();
   stmt.executeUpdate("UPDATE accounts SET balance = 100 where accountid = 1");
   stmt.executeUpdate("UPDATE products SET itemsleft = 0 where prodid = 4");
   stmt.rollback();
   stmt.executeUpdate("UPDATE products SET itemsleft = 0 where prodid = 3");
   stmt.commit();
   conn.setAutoCommit(true);  

In this example, the first two updates will not affect the database table because of rollback. The last update is explicitely committed.

Typically, you would use commit and rollback in conjunction with Exception handling. eg.

   try {
      conn.setAutoCommit(false);
 
      updateInventory();
      updateBalance();
 
      conn.commit();
      conn.setAutoCommit(true);
   }
   catch(ShoppingException e) {
      e.printStackTrace();
      conn.rollback();
      conn.setAutoCommit(true);
   }

Using the Observable/Observer pattern

An Observable object is an object that contains data in which one or more Observer objects are interested in.
The Observers want to know when the state of the Observable object changes.

The implementation is simple. In the package java.util, you find the class Observable. The object that you want to be able to monitor should extend from it. For example, suppose we have a Mailbox object (that can only contain one email at a time) and we know that other objects may be interested in state changes:

import java.util.*;
 
class Mailbox extends Observable
{
   private String message;
 
   public void newMail(String message) {
      this.message = message;
      setChanged();
      notifyObservers();
   }   
 
   public String getMessage() {
      return message;
   }
}

Observable is a class that encapsulates the common details about the pattern, like being able to “register” an object that is interested. Whenever the method newMail is invoked, the state changes and the object is marked as being changed. A call to notifyObservers means to notify the Observer objects that have previously registered themselves through addObserver, a method inherited from Observable.

An Observer is an interface that all your observers need to implement to ensure the availability and accessibility of the method update(Observable obs, Object o).

In our example, suppose we have two observers to our Mailbox: a MailGui and MailLog.

class MailGui implements Observer
{
   public void update(Observable obs, Object o) {
      Mailbox mb = (Mailbox) obs;
      System.out.println("MailGui has received notification of new " +
                         "message: " + mb.getMessage());
   }
}
 
class MailLog implements Observer
{
   public void update(Observable obs, Object o) {
      Mailbox mb = (Mailbox) obs;
      System.out.println("MailLog has received notification of new " +
                         "message: " + mb.getMessage());
   }
}

The notifyObservers method in Observable will loop through a list of objects of type Observer and calls the method update sequentially on each one of them. It provides itself as the first parameter (so the Observer knows which Observable we’re talking about – it may have registered itself with different ones) and an optional object as a second parameter. This optional object comes from when you call the notifyObservers(Object o) variant.

Here’s the Main class:

import java.util.*;
 
public class Main {   
   public static void main(String[] args) {
      Mailbox mb = new Mailbox();
 
      MailGui gui = new MailGui();
      MailLog log = new MailLog();
 
      mb.addObserver(gui);
      mb.addObserver(log);
 
      mb.newMail("... email#1 ...");
      mb.newMail("... email#2 ...");
   }
}

and the output:

MailLog has received notification of new message: ... email#1 ...
MailGui has received notification of new message: ... email#1 ...
MailLog has received notification of new message: ... email#2 ...
MailGui has received notification of new message: ... email#2 ...

Decoupling

It is important to realize that when an Observable wants to notify Observers of a change through calling update on them, it is tighly coupled to it. If update decides to go do some calculations, surf the net or play SkateOrDie, all actions that take forever to complete, the Observable cannot go on notifying other interested Observers cause it happens all in the same thread.

To perform some decoupling, you should place some threaded FIFO datastructure in between the Observable and Observer. The FIFO object would then both be an Observable and Observer.
Before:

                 (update)
  [ Observer1 ] <--------- [            ]
  [ Observer2 ] <--------- [ Observable ]
  [ Observer3 ] <--------- [            ] 

After:

                 (update)
  [ Observer1 ] <--------- [                 ]  (update)
  [ Observer2 ] <--------- [ FIFO Observable ] <--------- [ Observable ]
  [ Observer3 ] <--------- [                 ]   

Turn off copy/paste in a JTextArea

Main.java:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() {
      JTextArea ta = new JTextArea();
      getContentPane().add(new JScrollPane(ta));
 
      ta.getInputMap().put(KeyStroke.getKeyStroke("control C"), "none");
      ta.getInputMap().put(KeyStroke.getKeyStroke("control V"), "none");
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

What is a Valve?

A Valve is not defined in the Servlet/JSP spec, it is Tomcat specific. From the Tomcat docs:
A Valve element represents a component that will be inserted into the request processing pipeline for the associated Catalina container (Engine, Host, or Context).

For example, with the valve Remove Address Filter, you can decide whether or not to continue processing the request based on a regular expression that takes as input the IP address of the client.

You associate a Valve with a particular container (Engine, Host, or Context) in server.xml.

Check out the Q/A’s on how to use the Valves that come with Tomcat, and how to write your own.

Using an ArrowButton 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.Composite;
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 ToggleButton Demonstration");
      shell.setLayout(new GridLayout());
 
      Group buttonGroup = new Group(shell, SWT.NONE);
      GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 4;
      buttonGroup.setLayout(gridLayout);
      buttonGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
      SelectionListener selectionListener = new SelectionAdapter () {
         public void widgetSelected(SelectionEvent event) {
            System.out.println("integer value for alignment: " + ((Button) event.widget).getAlignment());
         };
      };
 
      createArrowButton(buttonGroup, SWT.LEFT, selectionListener);
      createArrowButton(buttonGroup, SWT.RIGHT, selectionListener);
      createArrowButton(buttonGroup, SWT.UP, selectionListener);
      createArrowButton(buttonGroup, SWT.DOWN, selectionListener);
      
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
   }
   
   public static void createArrowButton(Composite parent, int alignment, 
                                          SelectionListener selectionListener) {
      GridData gridData = new GridData();
      gridData.widthHint = 30;
      gridData.heightHint = 30;
      Button button = new Button(parent, SWT.ARROW);
      button.setLayoutData(gridData);
      button.setAlignment(alignment);
      button.addSelectionListener(selectionListener);
   }
}

Using the SWT MessageDialog

SWT.OK


SWT.OK | SWT.CANCEL

SWT.ICON_INFORMATION

SWT.YES | SWT.NO | SWT.CANCEL | SWT.ICON_QUESTION

SWT.RETRY | SWT.CANCEL | SWT.ICON_ERROR

SWT.RETRY | SWT.ABORT | SWT.IGNORE | SWT.ICON_WARNING

Full working example: Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
 
public class Main {
   public static void main(String[] args) {
      Display display = new Display();
      Shell shell = new Shell(display);
 
      MessageBox dialog = new MessageBox(shell, SWT.OK);
      dialog.setMessage("The 11th of September has learned us...");
      dialog.setText("Information");
      printResult(dialog.open());
       
      dialog = new MessageBox(shell, SWT.OK | SWT.CANCEL);
      dialog.setMessage("that it's not cool to die from hunger.");
      dialog.setText("Information");
      printResult(dialog.open());
 
      dialog = new MessageBox(shell, SWT.ICON_INFORMATION);
      dialog.setMessage("Click CANCEL");
      dialog.setText("Information");
      printResult(dialog.open());
       
      dialog = new MessageBox(shell, SWT.YES | SWT.NO | SWT.CANCEL | SWT.ICON_QUESTION);
      dialog.setMessage("Do you really want to format your neighbor's drive?");
      dialog.setText("Question");
      printResult(dialog.open());
 
      dialog = new MessageBox(shell, SWT.RETRY | SWT.CANCEL | SWT.ICON_ERROR);
      dialog.setMessage("You don't have a neighbor.");
      dialog.setText("Error");
      printResult(dialog.open());
       
      dialog = new MessageBox(shell, SWT.RETRY | SWT.ABORT | SWT.IGNORE | SWT.ICON_WARNING);
      dialog.setMessage("Don't you really want to not discontinue the proceeding task?");
      dialog.setText("Warning");
      printResult(dialog.open());
       
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
       
      display.dispose();
   }
    
   public static void printResult(int result) {
      switch (result) {
         case SWT.OK:
            System.out.println("SWT.OK");
            break;
         case SWT.CANCEL:
            System.out.println("SWT.CANCEL");
            break;
         case SWT.YES:
            System.out.println("SWT.YES");
            break;
         case SWT.NO:
            System.out.println("SWT.NO");
            break;
         case SWT.ABORT: 
            System.out.println("SWT.ABORT");
            break;
         case SWT.RETRY:
            System.out.println("SWT.RETRY");
            break;
         case SWT.IGNORE:
            System.out.println("SWT.IGNORE");
            break;
         default:
            System.out.println(result);
            break;     
      } 
   }
}

Creating an SWT Tree with images

Main.java:

import java.io.FileInputStream;
import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
 
public class Main {
   public static void main(String[] args) throws Exception {
      Display display = new Display();
      Shell shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 300, 200);
      shell.setText("SWT Tree Demonstration");
      shell.setLayout(new GridLayout());
 
      Tree tree = new Tree(shell, SWT.BORDER);
       
      TreeItem node1 = new TreeItem (tree, SWT.NULL);
      node1.setText("My Computer");
      node1.setImage(getImage("mycomp.gif"));
       
      TreeItem node2 = new TreeItem(node1, SWT.NULL);
      node2.setText("Audio");
      node2.setImage(getImage("audio.gif"));
 
      TreeItem node3 = new TreeItem(node1, SWT.NULL);
      node3.setText("Control Panel");
      node3.setImage(getImage("controlpanel.gif"));
 
      TreeItem node4 = new TreeItem(node1, SWT.NULL);
      node4.setText("Folder");
      node4.setImage(getImage("folder.gif"));
       
      TreeItem node5 = new TreeItem(node1, SWT.NULL);
      node5.setText("Local Disk (C:)");
      node5.setImage(getImage("localdisk.gif"));
 
      TreeItem node6 = new TreeItem(node1, SWT.NULL);
      node6.setText("doc on '192.168.0.1' (Z:)");
      node6.setImage(getImage("network.gif"));
 
      tree.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
             
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
       
      display.dispose();
   }
    
   public static Image getImage(String location) throws IOException {
      ImageData source = new ImageData(Main.class.getResourceAsStream(location));
      ImageData mask = source.getTransparencyMask();
      return new Image(null, source, mask);   
   }           
}

Images used:





Logging AWT events

You can do so by subclassing EventQueue and adding logging functionality. Then replace the system event queue with that logging queue.

Main.java:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
 
class Main extends JFrame
{
   public Main() {
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
      getContentPane().add(new JButton("Test button"));
   }
 
   public static void main(String[] args) {
      Main main = new Main();
      main.setDefaultCloseOperation(EXIT_ON_CLOSE);
      main.setSize(200, 200);
 
      main.getToolkit().getSystemEventQueue().push(new LoggingEventQueue());
 
      main.setVisible(true);
   }
}

LoggingEventQueue.java:

import java.awt.*;
 
public class LoggingEventQueue extends EventQueue
{
   protected void dispatchEvent(AWTEvent event) {
      super.dispatchEvent(event);
      System.out.println(event);
   }
}