DJBinder Basic version


This page contains a complete, although brief, description of DJBinder Basic version. You can also visit the DJBinder Quick Guide to develop your first dynamic application on the spot. This page is divided in the following chapters :



In Java the only way to create a link between a class and an interface is to use the implements statement. For example the following line :

class Person implements Employee {...}

indicates that any Person object offers all the services defined in the Employee interface. The methods of this interface must be implemented within the definition of the Person class.

Assume that later on you want to add the notion of citizenship and therefore you decide to add a new Citizen interface to the same Person class :

class Person implements Employee, Citizen {...}

This way of doing is OK but it has three problems :

  1. You need the right to access and modify the source file of the Person class.
  2. You have to handle several versions of the Person class. Specially if there are some persistent objects.
  3. You have to deliver the new class file to all the sites where your application is executed.
These problems are mainly due to the modification of the original source file to add the new interface. This modification could be avoid by using the Java inheritance mechanism : instead of adding the Citizen interface directly to the Person class you could add it to a derived class.

class Person2 extends Person implements Citizen {...}

The inheritance mechanism solves the problems mentioned above but generates some new ones :

  1. You have to change the statements new Person(...); by new Person2(...); , at least for the objects that need to behave like citizens. This modification can touch several source files.
  2. Other classes that already derive from Person do not take advantage of the new citizenship services.

DJBinder solves these problems in an elegant and innovative way : It allows to creates runtime links between interfaces and classes. In other words it is possible to attach interface implementations to a class without recompiling it. DJBinder magic resides in the fact that interfaces implemented by special abstract classes can dynamically be associated to a different class at runtime. DJBinder achieves this within the strictest respect of Java syntax by using a naming convention. The naming convention groups classes into clusters. Each cluster has a main class that is the only class able to create objects, plus other abstract classes used to implement additional interfaces. Interfaces implemented by these classes are considered for almost all-practical effects, such as cast and instanceof operations, as directly implemented by the main class of the cluster.

Continuing the Person example, you can create the following class to implement the Citizen interface :

public abstract class DI_Person__Citizen implements Citizen {...}

If this class is available in the runtime environment then the following two expressions would initialize the c variable with a value different of null.

Person p = new Person("John", "Smith", 23) ;
Citizen c = (p instanceof Citizen ? (Citizen) p : null) ;

From the view point of the classes using the Citizen interface there is not difference between an interface dynamically implemented and an interface implemented directly by the Person class. Furthermore, existing classes do not have to be recompiled to take advantage of new dynamically implemented interfaces.

The chapter about dynamic interface implementations explains how DI_Person__Citizen can implement the Citizen interface for instances of the Person class. The most important fact is that the source file of the Person class does not have to be modified.

DJBinder is not a new dialect of Java. It is fully compatible with the Java 2 platform. It works with the Java standard tools and it does not require special pre-compilers, compilers, virtual machines nor development kits. DJBinder specifies a naming convention just like the JavaBeans specifies the name of the property accessor methods, or the Java serialization mechanism specifies that a class must implement a Serializable marker interface to be serialized.


Why use DJBinder

Each of the following situations would be an enough good reason to use DJBinder to implement a Y interface for an X class :

  • You do not have the right to access or modify the source file of the X class. For example if the X class was developed by a tier supplier. The tutorials explain step by step how integrate two Java components developed by different suppliers.

  • You do not want to recompile the X class because it is used in too many distributed sites and the Y interface implementation is required only by a small number of sites. Note that DJBinder enables you to package applications in a functional oriented way.

  • You have some persistent X objects and you do not want to manage several versions of the X class nor update all the persistent objects using a batch mechanism.

  • You do not want to touch a tested class that has been working OK for the last 18 months.

  • You want to increase the concurrent engineering capacity of your development team. Note that several developers can simultaneously implement different interfaces for the same class because they work on different source files. For example the DI_X__Y and DI_X__Z classes to implement the Y and Z interfaces.

  • You are looking for a multiple inheritance mechanism to implement several interfaces reusing existing classes. DBJbinder enables this because each dynamic interface implementation (the DI_* classes) can have a different super class.

  • You want to create an evolutive application. Designers working with DJBinder have the tendency to cut applications into small functional units (DI_* files) and program evolution is mainly done by creating new source files, instead of modifying existing ones. Applications using DJBinder can run for many years even in the most changing environment because DJBinder offers the most flexible infrastructure. This is better explained in Application life cycle.


Dynamic interface implementations

An interface is dynamically implemented when it is not directly implemented by the class used to create the objects. For example, objects created by the following statement :

new Person ("John", "Smith", 23) ;

support the interfaces implemented by the Person class, but with DJBinder they also support the interfaces implemented by other classes. These classes are said to belong to the same cluster and must respect the following naming convention :

  1. They must belong to the same package (the chapter about Sealed Packages explains an exception to this rule).
  2. The base name is divided in 4 sections :
    • DI_
    • the base name of the class that creates the objects, also called main class. In this case Person.
    • __
    • the base name of the interface being dynamically implemented.

A last condition is that these classes must be public and abstract. In a cluster only the main class can be used in a new statement.

For example, if Citizen, ComponentListener and FocusListener are interfaces, then the following classes are valid dynamic implementations for the Person class :

public abstract class DI_Person__Citizen implements Citizen {...}

public abstract class DI_Person__ComponentListerner implements java.awt.event.ComponentListener {...}

public abstract class DI_Person__FocusListerner implements java.awt.event.FocusListener {...}

If two interfaces have the same base name but belong to different packages they have to be dynamically implemented by the same DI_* class. This risk of collision is not considered important enough to justify a more complex naming convention.

DJBinder allows a sort of multiple-inheritance without the problems traditionally associated with this mechanism. Each DI_* class can derive from a different super class, in other words each dynamic implementation can take advantage of other implementations already developed. For example if Person class dynamically implements ComponentListener and FocusListener then the corresponding DI_* classes can derived from ComponentAdapter and FocusAdapter :

import java.awt.event.* ;

public abstract class DI_Person__ComponentListerner extends ComponentAdapter implements ComponentListener {...}

public abstract class DI_Person__FocusListerner extends FocusAdapter implements FocusListener {...}

Although DI_* classes are abstract to concretize the fact that they can not be used in a new statement, they are automatically instantiated by DJBinder when needed. Particularly when an object is casted into the corresponding interface. For example the following code will create an instance of DI_Person__Citizen :

Person p = new Person ("John", "Smith", 23) ;
Citizen c = (Citizen) p ;

After creating the DI_Person__Citizen instance DJBinder calls the void init(Object) method which can be used to initialize the member fields. Normally the init method, like other methods of the DI_* class, needs to access the members of the main object. This can be done by casting the this reference, for more details see the chapter about Accessing members of the main class.

DJBinder warranties that every time that an object is casted into a given interface, the same instance of the corresponding DI_* class is used. For example, the following code will print "Casted into citizen" only twice, once for object p1 and another time for object p2.

abstract class DI_Person__Citizen implements Citizen

public void init (Object reserved)
System.out.println ("Casted into citizen") ;
// ...
// ...
public class test
public static void main (String[] args)
Citizen c1, c11, c2, c21 ;
Person p1 = new Person ("John", "Smith", 23) ;
c1 = (Citizen) p1 ; // prints "Casted into citizen"
c11 = (Citizen) p1 ;
Person p2 = new Person ("Bill", "Lennon", 15) ;
c2 = (Citizen) p2 ; // prints "Casted into citizen"
c21 = (Citizen) p2 ;


Finding the right implementation

Let p be a reference that is being casted into type I. DJBinder executes the following algorithm to find the interface implementation :

  1. If p is an instance of I then return p.
  2. If p is an instance of a DI_* class then do q = main object of p else q = p.
  3. If q is an instance of I then return q.
  4. If I is not an interface then throw an exception.
  5. Verify if q has already been dynamically casted into I, if that is the case then return the corresponding DI_* instance.
  6. Let a.b.c.T be the class of q, then try to load the class a.b.c.DI_T__I.
  7. If the a.b.c.DI_T__I class exists then create an instance of this class, call the init() method and return the new instance.
  8. If the a.b.c.DI_T__I class does not exist then repeat the steps 6, 7 and 8 with the super class of T.
  9. If none of the classes in the hierarchy of T satisfies step 7, then throw an exception.

This algorithm is actually a little more complex because of the sealed packages.


Java operations : casting, instanceof, object equality

Previous chapters have explained how DJBinder allows to cast an object of type T into an interface I, even if the T class does not directly implement the I interface. The only condition is to have a class named DI_T__I present in the runtime environment.

This is a powerful mechanism but it would be incomplete without the corresponding instanceof statement. Therefore DJBinder warranties that if the expression :

(I) p

does not throw an exception, then the statement :

(p instanceof I)

returns true. And the other way around if (I)p throws an exception then (p instanceof I) returns false.

Concerning object equality in Java it is expected that a reference to an object is equal to another reference to the same object independently of the reference type. For example, the following expression should always be true (if the casts are valid) :

(I1) p == (I2) p

DJBinder warranties this behavior even when one, or both, of the references correspond to DI_* instances.

In short, the use of dynamic interface implementations does not break the consistency between the cast operation, the instanceof operation and the objects equality.


Accessing members of the main class

When an interface is dynamically implemented its methods are defined in a class different of the class used to create the object. Sometimes these methods need to access the members of the main class of the objet. The this reference can be cast into the main class of the object to access the public and package members.

For example the dynamic implementation of Citizen interface can access the public getAge() method of the Person class in the following way :

public abstract class DI_Person__Citizen implements Citizen

private boolean canVote_ = false ;
public void init(Object reserved)
int age = ((Person)(Object)this).getAge() ;
canVote_ = (age >= 18 ? true : false) ;
// ...

Java does not accept to cast this directly into Person, that is why a middle cast into Object is used.

By default DJBinder does not allow to access protected and private members of the main class, but there is a way to declare that some protected and private members can be accessed from DI_* classes. The declaration is done within special DA_* classes (DA stands for DynamicAuthorization). Members of a T class become accessible from all DI_T__* classes if they are declared as public members of the DA_T class.

DA_* classes should be considered as a new visibility scope, they allow to declare a member as accessible from all dynamic interface implementations of a class, just like the public, protected and private keywords are used to declare that a member is accessible or not from another class.

For example if the Person class has a private salary_ field and a protected setSalary method then it is possible to declare these members as accessible from all DI_Person__* classes using the following DA_Person class definition :

public class Person

private int salary_ ;
protected void setSalary(int newSalary) {...}
// ...
abstract class DA_Person
public int salary_ ;
public abstract void setSalary(int s) ;

Methods of a DA_* class should be declared as abstract and the name and type of the members must be exactly the same one declared in the main class. The only possible difference is the visibility modifier.

The this reference must be casted into DA_Person to access these members from the DI_Person__Citizen class. For example the method calculateTax of the Citizen interface could be defined in the following way :

public abstract class DI_Person__Citizen

// ...
private float taxRate_ ;
public int calculateTax ()
return ((DA_Person)(Object)this).salary_ * taxRate_ ;
// ...

Another possible way is to use a variable of type DA_Person:

public abstract class DI_Person__Citizen

// ...
private float taxRate_ ;
private DA_Person daThis_ ;
public void init (Object reserved)
daThis_ = (DA_Person)(Object)this ;
public int calculateTax ()
return daThis_.salary_ * taxRate_ ;
// ...

It is important to highlight the fact that the members actually accessed are the ones of the Person class, even if the type of the reference is DA_Person. In this aspect, as in some others, dynamic implementations are similar to inner classes. The greatest difference being that inner classes have to be defined in the same source file as the main class.

DJBinder warranties that DA_Person references are used only within DI_Person__* classes. A runtime exception is thrown if they are used somewhere else.


Sealed packages

DJBinder specifies that DI_* and DA_* classes must belong to the same package of the main class. For example if the Person class belongs to the a.b.c package then the DI_Person__Citizen and DA_Person classes must also belong to the a.b.c package.

This is not possible if the package of the main class is sealed. In that case these classes must be placed in a sub-package called djbinder. For example a.b.c.djbinder.DI_Person__Citizen and a.b.c.djbinder.DA_Person.


Serialization and Cloning

In the DJBinder Basic version the serialization and cloning of dynamic interface implementations is not fully supported. If an object is serialized, only the fields of its main class are included in the resulting stream. When the object will be rebuilt from the data contained in the stream, the dynamic interface implementations will not be automatically recreated. They are going to be created from scratch at each cast operation. The init method will be re-executed and the previous value of the member fields will be lost.

An object that has dynamic interface implementations cannot be cloned. An exception is thrown if the clone() method is called for an object with dynamic interface implementations. The reason is that DJBinder does not make the difference between the DI_* instances of the original object and the DI_* instances of the new object and therefore some wear behavior could happen if the cloning were allowed.

These two Java functionalities will be fully supported in the DJBinder Professional version that will be available in the second semester 2000.


Running applications

To activate DJBinder when running a Java application you must execute the amslib.djbinder.Start class with the following arguments :

  1. main class of the application
  2. first argument of the application
  3. second argument of the application
  4. other arguments ...

For example if demo.Smallest is a Java application that prints the smallest number among a series of 4 numbers then it can be run with the following command line (under Windows):

c:\java\myclasses> c:\jdk1.2\bin\java.exe amslib.djbinder.Start demo.Smallest 13 45 26 8

This example uses the JDK1.2 of SUN, but the mechanism is the same with any other Java virtual machine.

You must grant all the security authorizations to the djbinder.jar file or install it as an extension of the Java virtual machine. To install the djbinder.jar file as an extension you have to copy it to a special directory :

under unix: {JRE_DIRECTORY}/lib/ext

under Windows: {JRE_DIRECTORY}\lib\ext

You can find more information about installing extensions in the following documents of : The Java Extensions Mechanism and its tutorial.


Running applets

Follow this check list to run an applet using DJBinder :

  1. Be sure that your browser or applet runner uses a virtual machine compatible with the JDK1.2. If that is not the case you can install the Plug-In functionality of, that warranties that you always have the most recent version of the JDK. See JavaTM Plug-in for more information about the Plug-In functionality.
  2. In the HTML page run the amslib.djbinder.AppletStart applet with the following parameter :
  3. <param name="APPLET_NAME" value="yourAppletName">

  4. Also include all the parameters needed by your applet.
  5. Place the djbinder.jar file in a directory accessible during the applet execution. A trivial solution is to place it in the same directory as your applet.
  6. Use the ARCHIVE parameter to indicate the URL of the djbinder.jar file.

For example to run the DrawTest applet furnished as a demo with the standard JDK1.2 of you can use the following HTML page. This page was generated by the Plug-In converter tool :

<title>Draw Test (1.1)</title>

<h1>Draw Test (1.1)</h1>
<hr> <!--"CONVERTED_APPLET"-->

<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" WIDTH = 400 HEIGHT = 400 codebase=",2,0,0">
<PARAM NAME = CODE VALUE = AppletStart.class >
<PARAM NAME = ARCHIVE VALUE = "djbinder.jar" >
<PARAM NAME="type" VALUE="application/x-java-applet;version=1.2">
<EMBED type="application/x-java-applet;version=1.2" java_CODE = AppletStart.class java_ARCHIVE = "djbinder.jar" WIDTH = 400 HEIGHT = 400 APPLET_NAME = "DrawTest" pluginspage=""><NOEMBED></COMMENT>
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!

<APPLET CODE = AppletStart.class ARCHIVE = "djbinder.jar" WIDTH = 400 HEIGHT = 400 >
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!


This demo applet does not use any dynamic interface implementation but if you run this HTML page you would verify that DJBinder does not affect the normal execution of existing Java programs.

You can also use this HTML page to run your own applets, you only need to change DrawTest by the name of your applet and optionally add other parameters.


Application life cycle

There are basically two kind of modifications done to a program after it has been delivered :

  1. Corrective modifications. They are done to correct some problems found during the productive life of the program. They are usually quite common and expensive at the beginning of the program life, but fortunately the number fells down after the main problems have been corrected.
  2. Functional enhancements. They are done because new needs are discovered or because the environment has changed and the program needs to communicate with other entities or using different formats.

A big problem about functional enhancements is that they can touch some parts of the program where corrective modifications have became rare. A well known fact about programming is that each new line added to a program has a high probability to generate a new problem. Therefore, an enhancement functionality can generate some new problems.

DJBinder approach is to use dynamically implemented interfaces for the functional enhancements. In this way very few existing source files have to be modified and the risk to generate new problems is reduced. In other words functional enhancements are done by the creation of new files instead of taking the risk of modifying existing ones.

This approach is resumed by : "Write Once, Run Forever", which means that delivered source files should be modified the least as possible. Excepting of course for the necessary corrective modifications.

top of this page

DJBinder downloads tutorials consulting contact us links Amslib