From ADempiere ERP Wiki
Jump to navigationJump to search

I am new to the community and have not been involved into former debates. So the analysis below is an high-level view and may miss some aspects. Nevertheless, to the newbie, the modularizations problems do not seem to be that hard and I just wanted to express that.

The Problem[edit]

Adempiere is the only real community-based open source ERP project.

As such, the community decides about goals and way, about preferrable extensions, subprojects, bugs and fixes. This is great.

Adempiere even provides (borrowed from Compiere) a solid technological foundation: The dictionary, where data structures and the corresponding user interfaces are stored and can be changed on-site. It even contains references to business logic (writting perferrably in Java): Callouts (onChange events in the UI) and Processes (onClick events on Buttons, if you want).

Now in day-to-days live, it turns out that these tools are not sufficient: Too often it is nessecary to change parts of the core code to get customer requirements satisfied. For example, if one wants the current user name to be printable on docs (, one is required to code that in a print control class in the core. While the requirement is perfect and the solution, too, it can only be delivered to the customer as a "patch" or a "customization", jars that are put to the classpath in front of the core classes, overwriting them.

The drawback of this approach is obvious: Only one change can be deployed at a time. If you want more, you have to merge patches.

The alternative would be to commit the solution to the trunk and use it (dangerous) or wait for it to be released (slow).

What in reality often is the last resort: Branch. Apply the patch here and use the branch. But while this seems to be a viable approach (I love branches), it too often lead to forks: Branches that became incompatible and can only be re-integrated at great expense. While frequent update merges could solve this, functionally conflicting changes enforce forks in this approach.

The Solution[edit]

Given the above, the solution is obvious:

  • Define the extent of the ADempiere "framework"
  • Seperate framework requirements from functional ones.
  • Add hooks in the framework code so, that functional expects can easily be implemented

Only framework requirements would than suffer from the problems described above. The fewer framework requirements exist, the better. That means: The smaller the framework is, the better.

One may then talk about two roles (each developper may take both):

  • The framework developer makes changes to the framework
  • The implementor implements functional requirements

Given a customer requirement, the developper has to perform a triage:

  • Has it aspects that can only be implemented as a framework change? - Bad! He must go the hard way and do a framework change (himself or find a framework developer for it) in trunk and wait for it to be released.
    • Is it a singular framework change (something that needs to be better and does not need to be customized): Implement the change
    • Is it a lack of customization capability: Enhance the framework interface (by adding a new hook or modifying an existing one)
  • If not, one may happily go along and implement the requirement on top of the framework and deliver it to the customer immediately.

As stated above: The fewer framework requirements, the better...


  • Many functional enhancements can easily be installed on one site.
  • It is easy to spot conflicting enhancements.
  • It is easier to implement functional enhancements, because they rely on well-documented and easy interfaces.
  • The framework is stable. Always.


  • If a functional requirement requires a framework update, it cannot be implemented fast.
  • The community has to agree upon framework extent and proposed changes.
  • The current forks need to be re-integrated.

Get Concrete[edit]

The concrete proposal is:

  • Identify functionalities subject to change: Callout, Process, Docaction, ....
  • Convert them to a service: Create an interface if none exists
  • Use the service locator pattern (see eg. [1])

The advantages are:

  • Modularization is seperated from infrastructure:
    • community can immediately start modularizing
    • several infrastructures can be tested: plain jars, OSGI, EJB, whatever

The service locator should be flexible enough not only to be used for known core services (like Callout), but also as an extension mechanism that can be used by future plugin also:

public interface IService {
  // Tagging only
public class ServiceQuery {
  set(String param, String value);
  orderBy(String name);
public interface IServiceLocator {
  public <T extends IService> List<T> locate(Class<T> type, ServiceQuery q);
public class Service {
  public static <T extends IService> List<T> locate(Class<T> type, ServiceQuery q);

This could be used by the column change process code in the core as simple as follows:

  ServiceQuery q = new ServiceQuery();
  q.set("tableName", "AD_User");
  q.set("columnName", "Name");
  Callout callout = Service.locate(Callout.class, q);

A simple Hashmap based service locator could immediately be implemented. Another implementation for OSGi is on its way (the only advantage being that usage of the locator can be enforced in OSGi).

The very first step would be to identify possible services:

  • Callout
  • Process
  • ModelValitor
  • DocAction
  • PersistentObject
  • Form (both Swting and ZKWeb, and GWT, and...)
  • add more here...

The Steps[edit]

How could Adempiere get from the current situation to the world depicted above? Here my proposal:

  • Freeze 3.4.2 as the current "framework"
  • Create a "plugin directory", where new plugins may be published (remember: in binary form, no need for customers to recompile anything)
  • Add to the Commit_Committee the responsibility to decide about framework API changes (that would be formulated by SF trackers of a new category)
  • Release 3.6.x, functionally equivalent to 3.4.2 including an extension framework
  • Address the currently existing branches and convert them to plugins (merging their framework aspects into the framework), eg. Libero manufacturing, German enhancements or Web Services
  • Address the framework, try to identify pluggable features and extract them to plugins

Side Notes[edit]

  • This Roadmap relies on the creation of an extension framework. This can but is not required to be Equinox_Integration.
  • Framework changes have a business perspective (that always existed, but now gets explicit): The implementor gets paid, not the framework developer. The community has to cope with that: Finding a developer for a required change may be hard. Do it yourself, find a nice guy, or even pay him for the change.

Further Reading[edit]