Using an SWT Sash

Sash is the Swing equivalent of a JSplitPane. It is a widget that can be dragged to resize two areas in a GUI.

Here’s an example of a Sash in a JFace application.

Category.java:

import java.util.*;

public class Category {
   private String name;
   private Category parent;
   private ArrayList categories = new ArrayList();
   private ArrayList links = new ArrayList();
   
   public Category(String name, Category parent) {
      this.name = name;
      this.parent = parent;
   }
   
   public void addSubCategory(Category category) {
      categories.add(category);
   }
   
   public void addLink(Link link) {
      links.add(link);
   }
   
   public ArrayList getSubCategories() {
      return categories;
   }
   
   public ArrayList getLinks() {
      return links;
   }
   
   public boolean hasSubCategories() {
      return categories.size() > 0;
   }
   
   public boolean hasLinks() {
      return links.size() > 0;
   }
   
   public String getName() {
      return name;
   }
   
   public Category getParent() {
      return parent;
   }
}

Link.java:

public class Link {
   private String url;
   
   public Link(String url) {
      this.url = url;
   }
   
   public String getUrl() {
      return url;
   }
}

CategoryTreeContentProvider.java:

import org.eclipse.jface.viewers.*;
import java.util.*;

public class CategoryTreeContentProvider implements ITreeContentProvider 
{
   public Object[] getChildren(Object element) {
      Category category = (Category) element;
      System.out.println(category.getName());
      
      ArrayList children = new ArrayList();
      children.addAll(category.getSubCategories());
      children.addAll(category.getLinks());
            
      if (children.size() == 0) {
         return new Object[0];
      }
      
      return children.toArray();
   }
   
   public Object[] getElements(Object element) {
      return getChildren(element);
   }
   
   public boolean hasChildren(Object element) {
      if (element instanceof Category) {
         Category category = (Category) element;
      
         return category.hasSubCategories() || category.hasLinks();
      }
      
      return false;
   }
   
   public Object getParent(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getParent();
      }
      
      return null;
   }
   
   public void dispose() {
      
   }
   
   public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
      
   }
}

CategoryTreeLabelProvider.java:

import org.eclipse.jface.viewers.*;

public class CategoryTreeLabelProvider extends LabelProvider
{
   public String getText(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getName();
      }
      else if (element instanceof Link) {
         return ((Link) element).getUrl();
      }
      
      return "" + element;
   }
}

Main.java:

import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleControlSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

public class Main extends ApplicationWindow 
{
   private Category rootCategory;
   private OleAutomation automation = null;
   
   public Main() {
      super(null);
      
      // statically create categories
      rootCategory = new Category("Java", null);
      Category j2seCategory = new Category("J2SE", rootCategory);
      Link link = new Link("http://java.sun.com/j2se/");
      j2seCategory.addLink(link);
      Category j2eeCategory = new Category("J2EE", rootCategory);
      link = new Link("http://java.sun.com/j2ee/");
      j2eeCategory.addLink(link);
      Category j2meCategory = new Category("J2ME", rootCategory);
      link = new Link("http://java.sun.com/j2me/");
      j2meCategory.addLink(link);
      
      rootCategory.addSubCategory(j2seCategory);
      rootCategory.addSubCategory(j2eeCategory);
      rootCategory.addSubCategory(j2meCategory);
   }
   
   protected Control createContents(Composite parent) {
      SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL | SWT.NULL);
      
      TreeViewer treeViewer = new TreeViewer(sashForm);
      treeViewer.setContentProvider(new CategoryTreeContentProvider());
      treeViewer.setLabelProvider(new CategoryTreeLabelProvider());
      treeViewer.setInput(rootCategory);
      
      createIEControl(sashForm);
      
      treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
         public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            
            Object selectedObject = selection.getFirstElement();
            if (selectedObject instanceof Link) {
               goUrl(((Link) selectedObject).getUrl());  
            }
         }
      });
      
      return sashForm;
   }
   
   public static void main(String []args) {
      Main main = new Main();
      main.setBlockOnOpen(true);
      main.open();
      
      Display.getCurrent().dispose();
   }
   
   private void createIEControl(Composite parent) {     
      OleFrame frame = new OleFrame(parent, SWT.BORDER);
      FormData formData = new FormData();
      formData.top = new FormAttachment(0, 10);
      formData.left = new FormAttachment(0, 100);
      formData.right = new FormAttachment(100, 0);
      formData.bottom = new FormAttachment(100, -10);
      frame.setLayoutData(formData);
   
      OleControlSite controlSite = new OleControlSite(frame, SWT.NONE, "Shell.Explorer");
      controlSite.doVerb(OLE.OLEIVERB_SHOW);
      automation = new OleAutomation(controlSite);
      int[] rgdispid = automation.getIDsOfNames(new String[]{"GoHome"});
      int dispIdMember = rgdispid[0];
      automation.invoke(dispIdMember);
   }
   
   public void goUrl(String url) {
      int[] rgdispid = automation.getIDsOfNames(new String[]{"Navigate"});
      int dispIdMember = rgdispid[0];
      Variant[] rgvarg = new Variant[1]; // this is the URL parameter
      rgvarg[0] = new Variant(url);
      Variant pVarResult = automation.invoke(dispIdMember, rgvarg);      
   }   
}

Using SWT JFace TreeViewer

Create a ContentProvider for the TreeViewer: implement the methods in ITreeContentProvider. The following example shows you how to do this. The business objects are Category and Link. (For an extension of this code, check the Q&A How do I use a Sash?

Category.java:

import java.util.*;
 
public class Category {
   private String name;
   private Category parent;
   private ArrayList categories = new ArrayList();
   private ArrayList links = new ArrayList();
   
   public Category(String name, Category parent) {
      this.name = name;
      this.parent = parent;
   }
   
   public void addSubCategory(Category category) {
      categories.add(category);
   }
   
   public void addLink(Link link) {
      links.add(link);
   }
   
   public ArrayList getSubCategories() {
      return categories;
   }
   
   public ArrayList getLinks() {
      return links;
   }
   
   public boolean hasSubCategories() {
      return categories.size() > 0;
   }
   
   public boolean hasLinks() {
      return links.size() > 0;
   }
   
   public String getName() {
      return name;
   }
   
   public Category getParent() {
      return parent;
   }
   
   public String toString() {
      return name;
   }
}

Link.java:

public class Link {
   private String url;
   
   public Link(String url) {
      this.url = url;
   }
   
   public String getUrl() {
      return url;
   }
   
   public String toString() {
      return url;
   }
}

CategoryTreeContentProvider.java:

import org.eclipse.jface.viewers.*;
import java.util.*;
 
public class CategoryTreeContentProvider implements ITreeContentProvider 
{
   public Object[] getChildren(Object element) {
      Category category = (Category) element;
      System.out.println(category.getName());
      
      ArrayList children = new ArrayList();
      children.addAll(category.getSubCategories());
      children.addAll(category.getLinks());
            
      if (children.size() == 0) {
         return new Object[0];
      }
      
      return children.toArray();
   }
   
   public Object[] getElements(Object element) {
      return getChildren(element);
   }
   
   public boolean hasChildren(Object element) {
      if (element instanceof Category) {
         Category category = (Category) element;
      
         return category.hasSubCategories() || category.hasLinks();
      }
      
      return false;
   }
   
   public Object getParent(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getParent();
      }
      
      return null;
   }
   
   public void dispose() {
      
   }
   
   public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
      
   }
}

Main.java:

import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.*;
import org.eclipse.swt.widgets.*;
 
public class Main extends ApplicationWindow 
{
   private Category rootCategory;
   
   public Main() {
      super(null);
      
      // statically create categories
      rootCategory = new Category("Java", null);
      Category j2seCategory = new Category("J2SE", rootCategory);
      Link link = new Link("http://java.sun.com/j2se/");
      j2seCategory.addLink(link);
      Category j2eeCategory = new Category("J2EE", rootCategory);
      link = new Link("http://java.sun.com/j2se/");
      j2eeCategory.addLink(link);
      Category j2meCategory = new Category("J2ME", rootCategory);
      link = new Link("http://java.sun.com/j2se/");
      j2meCategory.addLink(link);
      
      rootCategory.addSubCategory(j2seCategory);
      rootCategory.addSubCategory(j2eeCategory);
      rootCategory.addSubCategory(j2meCategory);
   }
   
   protected Control createContents(Composite parent) {
      TreeViewer treeViewer = new TreeViewer(parent);
      treeViewer.setContentProvider(new CategoryTreeContentProvider());
      treeViewer.setInput(rootCategory);
      
      return treeViewer.getTree();
   }
   
   public static void main(String []args) {
      Main main = new Main();
      main.setBlockOnOpen(true);
      main.open();
      
      Display.getCurrent().dispose();
   }
}

The contents that is displayed in the tree using the toString() method in Category and Link. This is not a clean separation of model and view. Instead, you can use a LabelProvider, a helper class with a callback method getText(Element).

CategoryTreeLabelProvider.java:

import org.eclipse.jface.viewers.*;
 
public class CategoryTreeLabelProvider extends LabelProvider
{
   public String getText(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getName();
      }
      else if (element instanceof Link) {
         return ((Link) element).getUrl();
      }
      
      return "" + element;
   }
}

Modify your Main class:

   treeViewer.setLabelProvider(new CategoryTreeLabelProvider());

Writing a Hello World JFace application

Main.java:

import org.eclipse.jface.window.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.*;
 
public class Main extends ApplicationWindow 
{
   public Main() {
      super(null);
   }
   
   protected Control createContents(Composite parent) {
      Label label = new Label(parent, SWT.PUSH);
      label.setText("Hello, world!");
      return label;
   }
   
   public static void main(String []args) {
      Main main = new Main();
      main.setBlockOnOpen(true);
      main.open();
      
      Display.getCurrent().dispose();
   }
}

Receiving messages asynchronously from a JMS queue

I used openjms to develop this example. Check out this Q&A first!

The following example receives a message asynchronously from the testqueue queue. The acknowledgement mode is set to AUTO_ACKNOWLEDGE, which means that the session will automatically acknowledges a client’s receipt of a message. With asynchronous reception, the onMessage method of your implementation of MessageListener is called when there is a message available on the queue.

To receive message synchronously, check this Q&A.

Main.java:

import javax.naming.*;
import java.util.*;
 
import javax.jms.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,"org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory");
      env.put(Context.PROVIDER_URL, "rmi://localhost:1099/JndiServer");
      Context ctx = new InitialContext(env);
  
      QueueConnectionFactory cnxFactory = (QueueConnectionFactory) ctx.lookup("JmsQueueConnectionFactory");
 
      Connection connection = ((QueueConnectionFactory) cnxFactory).createQueueConnection();
      QueueSession session = ((QueueConnection) connection).createQueueSession(
                                   false, Session.AUTO_ACKNOWLEDGE);
      Queue queue = session.createQueue("testqueue");
      QueueReceiver receiver = session.createReceiver(queue);
  
      MyMessageConsumer consumer = new MyMessageConsumer();
      receiver.setMessageListener(consumer);
 
      connection.start();
   }
}
 
class MyMessageConsumer implements MessageListener
{
   public void onMessage(Message message) {
      System.out.println("Message received: " + message);
   }
}

Receiving messages synchronously from a JMS queue

I used openjms to develop this example. Check out this Q&A first!

The following example receives a message from the testqueue queue. The acknowledgement mode is set to AUTO_ACKNOWLEDGE, which means that the session will automatically acknowledges a client’s receipt of a message. It also receives message synchronously: the call to receiver.receive() is a blocking call. However, you can also use the variation receiver.receive(long) where you can specify a timeout. The call will then only block for that specified value.

To receive messages asynchronously, check out this Q&A.

Main.java:

import javax.naming.*;
import java.util.*;
 
import javax.jms.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,"org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory");
      env.put(Context.PROVIDER_URL, "rmi://localhost:1099/JndiServer");
      Context ctx = new InitialContext(env);
  
      QueueConnectionFactory cnxFactory = (QueueConnectionFactory) ctx.lookup("JmsQueueConnectionFactory");
 
      Connection connection = ((QueueConnectionFactory) cnxFactory).createQueueConnection();
      QueueSession session = ((QueueConnection) connection).createQueueSession(
                                   false, Session.AUTO_ACKNOWLEDGE);
      Queue queue = session.createQueue("testqueue");
      QueueReceiver receiver = session.createReceiver(queue);
  
      connection.start();
 
      // blocks until message received
      Message message = receiver.receive();
      System.out.println("Message received: " + message);

      System.exit(1);
   }
}

Sending messages to a JMS queue

I used openjms to develop this example. Download it, start up the server (startup.sh/bat) and create a queue testqueue (admin.sh/bat).

The following example sends a TextMessage to the testqueue queue in PERSISTENT delivery mode, meaning that the JMS server will store the message on secondary storage to prevent loosing the message with server failures or crashes. The message stays there until delivered to all the consumers.

Main.java:

import javax.naming.*;
import java.util.*;
 
import javax.jms.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      // Load Context for OpenJMS
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,"org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory");
      env.put(Context.PROVIDER_URL, "rmi://localhost:1099/JndiServer");
      Context ctx = new InitialContext(env);
  
      QueueConnectionFactory cnxFactory = (QueueConnectionFactory) ctx.lookup("JmsQueueConnectionFactory");
 
      Connection connection = ((QueueConnectionFactory) cnxFactory).createQueueConnection();
      QueueSession session = ((QueueConnection) connection).createQueueSession(
                                   false, Session.CLIENT_ACKNOWLEDGE);
      Queue queue = session.createQueue("testqueue");
      QueueSender sender = session.createSender(queue);
      sender.setDeliveryMode(javax.jms.DeliveryMode.PERSISTENT);
 
      TextMessage textMsg = session.createTextMessage();
      textMsg.setText("Hello world!");
      sender.send(textMsg);
      System.out.println("Message sent!");
  
      System.exit(1);
   }
}

Starting up a background server process when Tomcat starts

[Servlet 2.3] You can implement the ServletContextListener. When a servlet context is initialized/destroyed, the container invokes the callback methods contextInitialized/contextDestroyed.

The following example schedules a Task every 30 seconds.

TaskScheduler.java:

package com.esus.test;
 
import javax.servlet.*;
import java.util.*;
 
public class TaskScheduler implements ServletContextListener {
   private ServletContext context = null;
   private Timer timer = null;
 
   public TaskScheduler() {
   }
 
   public void contextInitialized(ServletContextEvent event) {
      this.context = event.getServletContext();
 
      System.out.println("Context of Web Application has been started!");
 
      MyTask task = new MyTask();
      timer = new Timer();
      timer.schedule(task, 1000, 30000);
 
      //possibility to make TaskScheduler available to servlets/JSP's
      //event.getServletContext().setAttribute("TaskScheduler", this);
   }
 
   public void contextDestroyed(ServletContextEvent event) {
      this.context = null;
 
      if (timer != null) {
         timer.cancel();
      }
      System.out.println("Context of Web Application has been destroyed");
   }
}
 
class MyTask extends TimerTask
{
   public MyTask() {
   } 
 
   public void run() {
      System.out.println("Executing MyTask...");
   }
}

Then you have to refer to this class in web.xml:

<?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>
   <listener>
      <listener-class>
         com.esus.test.TaskScheduler
      </listener-class>
   </listener>
   . . .
</web-app>

Notice that TaskScheduler can be made available to servlets/JSP’s by using

   getServletContext().setAttribute

Getting a list of referenced types in a .class file

Compile the following Java source file with java -g.

Test.java:

public class Test
{
   private int          privateMember = 10;
   protected float      protectedMember = 20;
   public double        publicMember = 30.0;
 
   public Test() {
   }
   
   private void privateMethod(String argument) {
      int localMember = 40;
   }
  
   protected String protectedMethod() {
      String localMember = "Hello, World!";
 
      return localMember;
   }
  
   public void publicMethod() {
   }
}

Make sure Test.class in on your classpath and run Main:
Main.java:

import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.*;
 
public class Main
{
   public static void main(String []args) {
      JavaClass clazz = Repository.lookupClass("Test");
      ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool());
 
      Field[] fields = clazz.getFields();
      for (int i=0; i<fields.length; i++) {
         System.out.println(fields[i].getSignature());
      }
 
      Method[] methods = clazz.getMethods();
      for (int i=0; i<methods.length; i++) {
         Code code = methods[i].getCode();
         LocalVariableTable localVariableTable = code.getLocalVariableTable();
         if (localVariableTable != null) {            
            LocalVariable[] localVars = localVariableTable.getLocalVariableTable();
            for (int j=0; j<localVars.length; j++) {
               System.out.println(localVars[j].getSignature());
            }
         }
      }
   }
}

output:

I
F
D
LTest;
Ljava/lang/String;
Ljava/lang/String;
LTest;
LTest;
LTest;

Getting context initialization parameters in JSP

Context initialization parameters are parameters defined in the web.xml deployment descriptor and are available to all servlets of your webapplication.

web.xml example:

<?xml version="1.0" encoding="ISO-8859-1"?>
 
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
 
<web-app>
   <context-param>
      <param-name>name1</param-name>
      <param-value>value1</param-value>
   </context-param>
   <context-param>
      <param-name>name2</param-name>
      <param-value>value2</param-value>
   </context-param>
</web-app>

getparams.jsp:

<%
   ServletContext context = config.getServletContext();
   String value1 = context.getInitParameter("name1");
   String value2 = context.getInitParameter("name2");
%>
 
Value of name1: <%=value1%><br>
Value of name2: <%=value2%>

Logging strings or exceptions to the JSP engine

The HttpServlet class extends from the GenericServlet superclass. This latter has two useful log methods:

   log(String)
   log(String, Throwable)

You can use these methods to write messages to the logs of your JSP/Servlet engine (they implement it all differently).
For example, the following JSP

<%
   log("Check your log, eg catalina_log...");
   log("An exception", new Exception());
%>
Lines logged!

logged the following in my current log file catalina_log.2003-04-01.txt:

2003-04-01 17:45:47 jsp: Check your log, eg catalina_log...
2003-04-01 17:45:47 jsp: An exception
java.lang.Exception
        at org.apache.jsp.logtest$jsp._jspService(logtest$jsp.java:56)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:107)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
        at org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServlet.java:201)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:381)
. . .

Look at the Tomcat category or documentation to see how you can change the file you want to log to.