Published Interface
by kirk knoernschild
Statement
Make a modules published interface well-known.
Description
Java provides two levels of visibility for classes and four levels of visibility for methods and attributes, all of which are discussed in detail in MinimizeVisibility. For components, however, no additional visibility modifiers are available, providing some limitations on how well you can insulate classes and behaviors within a component. Any class or method that can be accessed from other packages within a component can be accessed by any class using the component. However, you might not always desire the same level of visibility across components that you have across packages. It certainly would be wonderful if there were a way to restrict developers from using classes within a component where the use of the class is solely intended within the component. Unfortunately, this is not the case, but it is the general idea behind a PublishedInterface.
A component’s PublishedInterface is the set of public methods on the public classes within the module that you expect developers using the module to invoke and work with. A PublishedInterface is subtly different from a modules public interface, which is simply the complete set of public methods on public classes within the module. Given Java’s lack of language support for a PublishedInterface, we cannot distinguish between public methods on classes that are meant to be used within the modules versus those meant for external usage. We’re therefore required to resort to other means to expose only those classes and methods defined as published. Figure 1 illustrates a PublishedInterface.

Figure 1: PublishedInterface of a Module
Implementation Variations
The easiest way to restrict developers from working with a class or method is to give the class or method package visibility. This is done by ommitting the visibility modifier altogether. While the approach can work, it has a significant limitation. Not only will you prevent ethe component’s external classes from using the class or method, you’ll also prevent all other packages within the component from using the class or method. Such limited visibility may not always be feasible.
Another way to prevent external classes from accessing a class or method you do not want published is to use interfaces. The interface defines methods you want to expose, while the implementation within the component can define additional public methods. Users of the component should interact with the interface, not the implementation. Without casting, the component’s user will not be able to invoke these methods on the implementing class. This allows you to, a certain extent, hide public methods that you do not want invoked outside of the componet since component users will not know the concrete type of the class they are working with. Of course, with some investigative digging, they can always find out the name of the implementing class, and there isn’t much you can do about it.
The strongest form of enforcing a PublishedInterface is to define implementation classes at package scope. These implementation classes then implement an interface that is reference by external component users. Unfortunately, this strongest form of enforcement is not always feasible, given that other packages within the component may need to reference the implementing class to invoke it’s methods. However, it’s a good idea to begin with this approach, and then loosen it up as the needs demand.
The loosest way to define your component’s PublishedInterface is to express the desired published API in the component’s JavaDoc or in a UML diagram. When using JavaDoc, a common practice is to clearly express the class or method you prefer developers not use. If you want to discourage external classes from using an internal class, you’ll be required to present an interface for external classes to use, similar to what was discussed in the previous paragraph. The java.rmi.server.RemoteObjectInvocationHandler class, used with Java’s dynamic proxy feature in J2SE 1.5, is an example of using an interface to shield a public implementation class, while expressing in the JavaDoc that this class is desirably used only internally.
Combined with variations of each of the above, a ComponentFacade serves as a single point of entry to your component. In most situations, a facade will increase the ease with which other developers can integrate your component into their environment. The facade may also serve as the factory responsible for creating the component’s internal implementation classes.
Given the four variations discussed above, I’d recommend going with package scope classes initially. As their visibility of these classes move beyond their package, begin by exposing these methods via an interface. If you find the component needs additional behavior beyond that of what component users will need, then allow classes within the component to work with the concrete type , or define another interface within the component used by classes inside the component. With each of these approaches, I’d suggest making your intent clear in the JavaDoc for the classes, and only after the first two approaches have failed would I suggest using only JavaDoc to express your component’s PublishedInterface. Last, a ComponentFacade is useful to help increase the usability of your component, but of itself, is not a robust standalone solution, and should be combined in conjunction with the package scope or interface based approach.
Consequences
The greatest advantage of defining a component’s PublishedInterface is that you’re making the component easier to use by other developers. Even though a component may be well designed and offer valuable behavior, a cluttered API will undoubtedly scare most developers away. Unquestionably, offering a thinner and lighter component interface will allow developers to more quickly understand how to integrate the component. Keep in mind that, however unfortunate, there is no way to hide public methods within a component unless the class containing those public methods is defined at package scope, which is not always reasonable. Quite simply, Java has no language construct to accommodate this. However, effort to define a component’s PublishedInterface are undoubtedly still valuable.
The implementation variations above each have a different set of consequences. While defining package scope classes strictly enforces internal usage of the class, package scope may be too limiting. If classes in other packages within the component need to use the class, package scope will not work.
Exposing only interfaces, on the other hand, allows you to expose only the methods you want. However, you can never prevent another developer from using the implementation class directly, since the class is public. Using interfaces has another limitation too. For classes within the component to invoke methods on the implementation, it requires that the component’s internal classes work with a concrete type, preventing the component from working with plugin classes. Ultimately, you’re giving up internal component flexibility for external component usability. The consequences of this decision must be given careful consideration. Additionally, if the implementing class within the component is in a separate package from the component’s classes needing to use it, the implementation class must be declared public, and you can never really prevent other developers from using it directly, assuming they learn of the implementation class. However, the implementation class is still pretty well insulated, and it’s likely you can prevent most honest developers from referencing it directly.
Expecting to enforce your PublishedInterface via JavaDoc is difficult at best. While undoubtedly the easiest approach, since no additional programming is required, it’s also the least likely to be followed. I’d caution adopting an approach relying solely on JavaDoc. Likewise, a ComponentFacade is probably not a standalone solution, since the facade will likely expose a component’s expected implementation classes via the facade’s return types. However, a facade offers significant advantages in enchancing the usability of a component, as wel as the ease with which developers can learn about the component.
Sample Code
Let’s consider the domain objects for an application that must allow a customer to place orders. A customer has a list of filled and unfilled orders. For all new orders, the customer is given a discount, which is calculated based on the total number of items ordered by the customer. The new order placed counts toward this discount.
The Customer class has a createNewOrder method on it that accepts the quantity of items ordered and the charge amount of the order. This method creates a new order, adds that new order to the list of already placed orders, and then calculates the discount for that new order based upon all of the orders. The method then update the new order with the discount amount. Unfortunately, since the Customer and Order are in separate Java packages, the setDiscountAmount method must be made public, making it accessible to not only the customer, but also any other classes within the system. The code in Listing 1 shows the Customer class and highlights declaration of the Orders array and invocation of the setDiscountAmount method.
package com.extensiblejava.customer;
import com.extensiblejava.order.*;
import java.math.BigDecimal;
public class Customer {
private String fullName;
private Order[] orders;
private OrderBuilder builder;
public Customer(String fullName, OrderBuilder builder) {
this.fullName = fullName;
this.builder = builder;
}
public String getName() { return this.fullName; }
public Order[] getOrders() {
if (this.orders == null) {
this.orders = builder.build();
}
return this.orders;
}
public Order createNewOrder(Integer productQuantity, BigDecimal chargeAmount) {
int numOrders = this.getOrders().length + 1;
Order[] newOrders = new Order[numOrders];
System.arraycopy(this.orders, 0, newOrders, 0, this.orders.length);
newOrders[numOrders - 1] = new Order(productQuantity, chargeAmount);
this.orders = newOrders;
BigDecimal discount = this.calculateDiscount();
this.orders[numOrders - 1].setDiscountAmount(discount);
return this.orders[numOrders - 1];
}
private BigDecimal calculateDiscount() {
Order[] orders = this.getOrders();
int totalQuantity = 0;
for (int i = 0; i < orders.length; i++) {
totalQuantity += orders[i].getProductQuantity().intValue();
}
if (totalQuantity < 10) {
return new BigDecimal("0.05");
} else if ( (totalQuantity >= 10) && (totalQuantity < 100) ) {
return new BigDecimal("0.10");
} else if (totalQuantity >= 100) {
return new BigDecimal("0.25");
}
return new BigDecimal("0.00");
}
}
Listing 1: The Customer Class
In Listing 2, we see that the CustomerTest test case can update the discount amount for this order, something we do not want to allow. The discount amount is a derived attribute that we do not want exposed.
package com.extensiblejava.customer.test;
import junit.framework.*;
import junit.textui.*;
import com.extensiblejava.customer.*;
import com.extensiblejava.order.*;
import java.math.BigDecimal;
public class CustomerTest extends TestCase {
public static void main(String[] args) {
String[] testCaseName = { CustomerTest.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
protected void setUp() {}
public void testCustomerLoad() throws Exception {
CustomerBuilder builder = new DefaultCustomerBuilder();
Customer customer = builder.build();
assertNotNull(customer);
assertEquals("John Doe", customer.getName());
}
public void testCustomerOrderLoad() throws Exception {
CustomerBuilder builder = new DefaultCustomerBuilder();
Customer customer = builder.build();
Order[] orders = customer.getOrders();
assertEquals(orders.length, 3);
}
public void testPlaceOrder() {
CustomerBuilder builder = new DefaultCustomerBuilder();
Customer customer = builder.build();
Order order = customer.createNewOrder(new Integer(3), new BigDecimal("50.00"));
order.setDiscountAmount(new BigDecimal("0.50")); //I don't want to allow this.
assertEquals(order.getDiscountAmount(), new BigDecimal("0.50"));
}
}
Listing 2: CustomerTest Test Class
The relationships between the classes, and corresponding modules, can be seen in Figure 2. Just as any class within the custtest.jar module has access to the public methods on the Order class, so too would any other consuming module.

Figure 2: The Order Class with Public Methods Exposed
So how can we prevent anything except Customer, or other internal module classes from invoking setDiscountAmount? First, we’ll introduce a Customer interface to ensure we expose only the methods we want to publish. Listing 3 illustrates the Customer interface.
package com.extensiblejava.customer;
import com.extensiblejava.order.*;
import java.math.BigDecimal;
public interface Customer {
public String getName();
public Order[] getOrders();
public Order createNewOrder(Integer productQuantity, BigDecimal chargeAmount);
}
Listing 3: The Customer Interface
Likewise, we also create an Order interface. Note the ommission of the setDiscountAmount method on Order in Listing 4.
package com.extensiblejava.order;
import java.math.BigDecimal;
public interface Order {
public Integer getProductQuantity();
public BigDecimal getChargeAmount();
public BigDecimal getDiscountAmount();
}
Listing 4: The Order Interface
Now, we refactor the original Customer class and rename it to DefaultCustomer while implementing the Customer interface, as shown in Listing 5. Likewise, we refactor the original Order class and rename it to DefaultOrder while implementing the Order interface.
The DefaultCustomer implementation has also been changed slightly. It now directly instantiates the concrete DefaultOrder class, allowing it to call the setDiscountAmount method. However, because the array of Orders is of type Order, no consumer can invoke the setDiscountMethod unless it downcasts the Order to a DefaultOrder. Downcasting is certainly something we want to avoid. Again, the significant difference is that createNewOrder returns an array of type Order. Internally, the method still works with DefaultOrder instances. This exposes only the Order interface, but allows the Customer to work directly with the implementation.
public class DefaultCustomer implements Customer {
...
public Order createNewOrder(Integer productQuantity, BigDecimal chargeAmount) {
int numOrders = this.getOrders().length + 1;
Order[] newOrders = new Order[numOrders];
System.arraycopy(this.orders, 0, newOrders, 0, this.orders.length);
DefaultOrder newOrder = new DefaultOrder(productQuantity, chargeAmount);
newOrders[numOrders - 1] = newOrder;
this.orders = newOrders;
BigDecimal discount = this.calculateDiscount();
newOrder.setDiscountAmount(discount);
return this.orders[numOrders - 1];
}
...
}
Listing 5: The Refactored DefaultCustomer Class
The CustomerTest test case, shown in Listing 6, can no longer call the setDiscountAmount method because it is bound to the Order interface, not the DefaultOrder implementation. Attempting to invoke the setDiscountAmount method will now result in a compiler error because only internal module classes know of the DefaultOrder and it’s methods. While this type of casting is certainly undesirable, I’ve consciously decided to compromise my internal design in favor of more flexible usage.
package com.extensiblejava.customer.test;
import junit.framework.*;
import junit.textui.*;
import com.extensiblejava.customer.*;
import com.extensiblejava.customer.impl.*;
import com.extensiblejava.order.*;
import java.math.BigDecimal;
public class CustomerTest extends TestCase {
public static void main(String[] args) {
String[] testCaseName = { CustomerTest.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
...
public void testPlaceOrder() {
CustomerBuilder builder = new DefaultCustomerBuilder();
Customer customer = builder.build();
Order order = customer.createNewOrder(new Integer(3), new BigDecimal("50.00"));
//order.setDiscountAmount(new BigDecimal("0.50")); //No longer allowed.
assertEquals(order.getDiscountAmount(), new BigDecimal("0.25"));
}
}
Listing 6: The Refactored CustomerTest Class
When Customer.createNewOrder is called, I require productQuantity and chargeAmount to be passed in . I don’t want people changing these values on my Order instance either, so the Order instance must be created with these values passed to the constructor. Since the Customer is a factory for the Order instances, I’m protected. The final structure is illustrated in Figure 3, which shows that the setDiscountAmount method is encapsulated within the module.

Figure 3: Encapsulate DefaultOrder Implementation with Order Published Interface
Wrapping Up
Without a module system, such as OSGi, implementing and enforcing a PublishedInterface is unwieldy at best. I’ve certainly applied the pattern, though it leaves a certain code smell I don’t especially enjoy. With OSGi, however, we can enforce a PublishedInterface using OSGi Services. An OSGi bundle exports public packages and the published interface of a bundle represents the public methods on the public classes that are exported from a module and subsequently registered with the OSGi Service Registry. Sadly, without a module system, we are left with the somewhat sloppy sample illustrated above.
Comments
The ‘published interface’ is something that developers already use, such as when acquiring JDBC drivers. Further, I think the example here clouds the instantiation method.
One thing you probably ought to mention (if using the Order example) is that this will fail if someone passes a random-subclass-of-Order into the code. That is, whilst the client only knows of the type Order, it is constrained to only use Orders that were given to it by the module. I think that’s the smell you’re referring to here.
Hey Alex,
Published Interface is a perfect candidate for showing how OSGi can really help when implementing the patterns. I’m trying to be as careful as possible to avoid making this an OSGi tutorial and instead help people design modular software.
You make a perfect point, btw.