Java in Notes/Domino Explained: Dynamic class loading


When coding in Java you do not need to know the class you want to instantiate at compile time. You can have the program decide which class to instantiate, ask the user or let it be a configurable parameter. The only caveat with dynamic class loading is that the class you instantiate has to have a no-argument, public constructor.

To use the functionality you need two core Java language features:

  • Classloading
  • The ability to cast an object reference

Dynamic class loading is a much used feature when creating frameworks in Java since it allows you to specify the class to use in a property file outside the code. In the Notes/Domino world it is even easier since you can let the user choose the class to use in a database profile. To use dynamic class loading you use the forName() method of the java.lang.Class class (highlighted in bold):

Class clazz = Class.forName("java.util.Date");
Date date = (Date)clazz.newInstance();
System.out.println(date);

The above example is a little stupid since it simply creates a Date object and prints the date to the console but it shows how to use dynamic class loading.

In the Notes/Domino world you can use dynamic class loading to let the user select the behaviour he/she wants from a profile document. To to this you would write the different behaviours as a couple of different classes all implementing a common interface and then having the user choose which class to use in a profile document. Your agent could then read the classname from the profile document and instantiate the class specified there:

import lotus.domino.*;

public class JavaAgent extends AgentBase {

   public void NotesMain() {

      try {
         Session session = getSession();
         AgentContext ac = session.getAgentContext();

         // get database and profile document
         Database db = ac.getCurrentDatabase();
         Document doc_profile = db.getProfileDocument("JavaClassLoading", null);

         // get classname as a string
         String classname = doc_profile.getItemValueString("DBProfileClassname");

         // have Java load the class
         Class clazz = Class.forName(classname);

         // instantiate the class (we assume the class implements
         // the NameLoader interface specified in the agent)
         NameLoader nl = (NameLoader)clazz.newInstance();
         nl.loadNames();

      } catch(Exception e) {
         e.printStackTrace();
      }
   }
}

public interface NameLoader {
   public void loadNames();
}

I have used this approach many times by designing an interface and having multiple classes implement the interface. Then the actual class to use is selectable on a profile document making the application very configurable.

Another example of where you use dynamic class loading “in the wild” is for JDBC (database access from Java). Here you use the dynamic classloading and dynamic object instantiation of Java to tell the DriverManager (the class creating the actual connection to the database) which class to use for the JDBC connection. The below example creates a connection the SAMPLE database that comes with DB2 using the JDBC Application driver.

// load DB2 JDBC driver
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");

// create connection to sample database
Connection con = DriverManager.getConnection("jdbc:db2:sample");

// create statement
Statement stmt = con.createStatement();

// execute query
ResultSet rs = stmt.executeQuery("select * from employee");
...
...

Published by

lekkim

Positive, competent, out-spoken, frank and customer focused architect and developer with a strong foundation in web, cloud and product development. I'm a strong advocate for API first and cloud based solutions and development. I have a knack for being able to communicate and present technically complicated matters in conference, customer and training settings. I've previously acted as team member and leader in a product organisation.