Académique Documents
Professionnel Documents
Culture Documents
E N G I N E E R I N G
REDHUAN D. OON
ADEMPIERE COMMUNITY
www.adempiere.com
3.
Online Interaction - 30
4.
Doing Assignments - 18
5.
Examination Preparation - 18
B.
Teaching Method: Self Independent Study, Tutorial and On-line Participation
C. Assessment Detail:
COPYRIGHT NOTICE:
RED1 - www.red1.org
i
2.10 Private Forking from Anyone Else
52
Quiz
54
Glossary
54
Summary
55
References
56
ii
4.2 SourceCode Layout
129
4.3 Checking Out Source
130
4.4 Deploying from Source
133
4.5 Persistence Object
136
4.6 Application Dictionary Overview
139
4.7 Application Dictionary Technicals
142
4.8 Query Refactoring
146
Summary
150
Quiz
151
Glossary
151
References
152
iii
Introduction
203
Fitnesse Testing Framework
204
Hudson Build Server
205
Logical Bugs
208
JUnit Testing
209
Quiz
212
Glossary
212
Summary
213
References
214
iv
“It's OK to figure out murder mysteries, but you
shouldn't need to figure out code. You should be
able to read it.”
- Steve McConnell
REFERENCES:
v
MODULE 4 - ERP Software Engineering
This module, while introducing the student to the engine and engineering behind the
Open Source ERP, ADempiere application, potrays a landscape of the present issues and
future challenges with ERP software engineering.
Module Outline
This module not only brings the student to the heart of an ERP software such as its
design, sourcecode, and reasonings, but the chaotic wisdom of a mob community in
maintaining and growing it. The ADempiere project is apt due to a living community
been able to carry on what many companies would have spent millions figuring it out.
Learning is fun Graduating is more fun Ultimate fun when your life is fulfilled
Prior Knowledge
This course module assumes basic software engineering hands-on skills including basic
java programming and have followed the 2nd module about setting up ADempiere and
using it.
Module Objectives
1. To appreciate the challenge facing the creation and maintenance of ERP Software
2. To get under the hood of an actual ERP Software
3. To have hands-on capability in handling such software right up to deploying
changes
4. To grasp the importance of a dynamic global community behind a FOSS ERP project
Learning Objectives
By the end of this chapter, the student shall be able to:
3. Detail some of the ways such issues are overcome by the ADempiere project.
1. To setup a Linux operating system, you take one hour; To setup an ERP system, you
take one year.
2. If the operating system fails, blame the software; If the ERP system fails, blame the
people.
We can say still see the same condition pervalent today and it is exarberated by the
following factors:
3. The social forces that lead to more afluent demand for near perfect quality in
consuming and expressing preferences.
However the web also bring about some of its medicine besides its poison. The concept
of Web 2.0 where consumers also produce information or human capital in resolving
some of this crisis as proven in the Free and Open Source Movement has brought about
a vast phenomena to producing quality software thus circumventing somewhat the
above-mentioned crisis.
Nevertheless, software engineering is not a layman skill and you can find less advocates
of it then for example to find volunteer editors for wikipedia, the most famous example
of Web 2.0 social phenomena.
Figure 1.1 - Software has its hidden cost from the start
In the ADempiere project example, we can see how fast it gain prominence and the ease
of bringing in resources at short notice, but there is a bottle-neck at the software
maintenance or upgrading stage. Deep and experienced brains are needed besides just
mere eyeballs looking out for bugs[4]. Nevertheless, having a volunteer community
around a free open source project alleviates most of this constraint of limited human
brain power in relative competition to proprietary projects.
The systems or architectural aspects of software are still been hotly debated and have
yet to become true independant standards. The dominant role of vendors also add to
the chaos as each vendor wishes to brand its own standard against the other
competitors in the market. There are unifying groupings such as OMG (Object
Modelling Group) and WfMC (Workflow Management Coalition) where competing
vendors participate and collaborate with a singular standard, but its implementation
may be proprietary and fast changing due to technological advancements that
shufflings still occur at a fast pace leaving often the standards behind. One example is
during the emergence of e-banking in the mid 1990s, SET was thought to be the
standard agreed upon by the banking system integrators, but SSH gate-crashed into the
marketplace and became the defacto standard for encrypted data transmission sending
SET into oblivion.
Many experts have written on a more holistic approach to the crisis. Bernard Boar in his
book “Practical Steps for Aligning Information Technology with Business Strategies:
How to Achieve a Competitive Advantage” (Wiley 1994), painted the way forward with
lots of standardised artifacts or drawings with ready to reuse blank boxes in a more
formalised way, so that architects can design the intricacies with more precise language
and semantics.
The right way of understanding a software is to understand not only what it is needed
for but how it has to be done. ERP has to follow these constraints and requirements:
4. It has to carry processes and data across departments to satisfy different users;
6. It has to present data in very well formated user-friendly tone and design;
8. It has to interface with latest web technologies and external 3rd party
applications;
10. It has to follow design of business and operational rules governing its data
from different authorities be they internal, external or regulatory;
The early Compiere project has established a clear defnition of the model that it is using
in its ERP application when it first debuts in 1999, about ten years ago. It recognises that
an ERP application has to interface with its users along a standard presentation and
From the above design we can deduce its underlying complexity of sourcecode
packages and model requirements. There will be an elaborate array of data models to
capture the properties of this design and processes to facilititate its functions.
2. A process that acts upon each field value within that model.
This progammatical capability of the field is happening at the application layer and not
at the business or functional layer handling business processes such as Sales Order,
Inventory movement or accounts posting. In other words the above is related to the
layer managing the application. From there you can see that it is demarcating the whole
application into clearly defined areas of focus. The Menu View addresses the
Such a design allow fast prototyping or changes to the application. For example any
new data model can be added at the stipulated area. A new process can be attached to a
column. For more sophisticated new vertical to be added onto this ERP horizontal, we
can create a new document type with its own document process without concern about
the sourcecode scaffolding.
This above diagram (figure 1.2) showing the Application Data Model (described in the
2nd course module on ERP Application Setup) is based on meta-data so that any
changes to the model is done without changes to sourcecode.
The new module is incorporated via the Application Dictionary to define the new
model of tables and fields, and its properties. The new model can be transfered to a new
client via XML files such as using ADCK contributed by Trifon Trifonov from Bulgaria.
It can also be transfered via 2Pack exporter/importer contributed by Robert Klein of
USA. The legacy data of this module if any can be imported into the ERP via import
loaders. In later chapters we will go through the mechanics of how the migration of the
new model is done.
What about the disadvantage of such a framework described above? What I can think of
at the moment is that the user interface is a bit limited and rigid and not as aesthetic as
other software (see figure below). There are only 2 columns per row for single record
display and each Tab for each window does not have box panels or embedded panels
besides the normal roll down groups of data columns.
This Order Window above shows two tabs, Order and OrderLine. The later is for detail
transactions where each one will describe the product and its quantity ordered. Each
line may carry a pricing information too. Other matters such as commission, discounts,
and tax are often included.
As can be seen from the main Order tab, it is quite elaborate and cluttered. Many of
these fields may not be needed and can be removed easily via the SystemAdmin
application dictionary windows such as via the Table & Column window.
CC CC
Code Data
Component Object
CC DO DO
SIMPLE CC
DO
DO
COMPLEX
The motivation behind all this is the quest for simplicity. The cause is having too much
integrated into the codebase in the first place. The more powerful an ERP system the
more software features are built into it. Many of them are built from the ground up
together with the framework of the application. As such they are tightly coupled and
work in concert as a single application. This would make it bulky and unwieldy to
Why we are concerned about the sheer size (about 3.4 million lines of code for
ADempiere) is the constraints when it comes to maintaining it. Software will always
need to be maintained and changed from time to time if not day to day. There are many
business logic that are still too generic or too specific and whenever a change is
proposed it may affect other aspects of the sourcecode or funtionality.
The period of which Compiere was first written is speculated to be around the late
1990s when Java frameworks has yet to reach a higher maturity as it has today. Today
developers who combed its sourcecode complained that it is not efficient to maintain
and is not scalable and some even claimed that it is not 3-tier. However its main
strength remains to be its abundance of features and unique combinations of tools that
makes it a full fledge ERP solution of subtantial market quality and appeal. Some even
claimed that Compiere can rival SAP B1, Navision, or Oracle Financials.
Among the features inbuilt into the Compiere family of ERP software are:
4. Dual automatic user interface for both Java client and HTML client
5. Workflow engine
6. Printformat engine
9. Scheduler engine
1. Good separation of classes according to packages and functions such as M classes for
model activity, AD classes for application dictionary level activity and X classes for
model persistence activity;
Ever since the Compiere project was forked by the community into ADempiere in
September 2006, countless amount of minute changes have also occured:
1. Bug fixes ranging from the very critical security level to minor typo mistakes;
2. Ajax’s cool html user interface that makes the web page looks amazing
4. Web services where any 3rd party system can talk to any other system
6. Extensibility via ModelValidator, more open Callouts, JSR 233 open scripting and
OSGI componentisation.
The good news is that ADempiere has achieved many of the above except for true n-tier
architecture. About database independence we manage to port to PostgreSQL and
IBM’s DB2 free edition. PostgreSQL is open source and free-licensed which is good
enough for the community. Previously Compiere as locked to Oracle’s database which
became one of the bad points of the Open Source ERP project. During the effort of
making ADempiere talk to PostgreSQL, much embedded codings that are Oracle
specific or of a certain SQL standard are been converted to more open and standardised
formats. This means that ADempiere has made one major jump to be more agnostic to
database flavours.
The most exciting thing to come out recently as announced in the 2nd Berlin Conference
in June 2009 is that Joerg Viola of Object Code GMBH, has succesfully implemented a
pluggable regime into ADempiere sourcecode using Eclipse’s Equinox that follows the
OSGI framework. However while attempting to integrate Libero Manufacturing with
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 16
Trifon Trifonov and me myself as observers in his Luenen office nearby Dortmund, he
discovered that Libero does not synch well with the classloading mechanism of the
plugin. He told us that it can be done but a lot more proving and testing will be needed.
He gave some idea that it may take someone like him a full one month to resolve the
plugin mechanism to fit into ADempiere. This is an example of how exciting new
technology is fine but not so when attempting to integrate to a ready made monster
such as ADempiere. More work is always needed to move forward.
One way to make future integration a lesser hassle than it is, is to upgrade the software
right now with better coding practice. We have started to introduce substantial changes
to the coding patterns and upgrade management such as:
2. Implementing new Query class that removes SQL scripts from Model classes;
3. Ideal migration path by logging all DB meta-data changes and numbering them;
5. Refactoring redundant methods particularly for the new Ajax Web UI mostly done by
Low Heng Sin of Malaysia;
At the same time, technical improvements are not the bulk of the game. In fact the bulk
of the challenge is having good visibility of the project such as good release
documentation. That we have done by publishing in http://www.adempiere.com/
index.php/Category:Release. By having good documentation, other developers and
more newer ones can follow its progress rather easily and participate further.
Taking this challenge of been visible a bit further, the main crisis with software
development and maintenance over time is that if it is proprietary, it will be largely
invisible to a non-paying community. In doing so, it will have to incur tremendous cost
in fixing or responding to technological changes in the market. We can now see the
proof of this theory in the ADempiere project itself. Every bug fix is freely done and cost
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 17
nothing to the project. But it will cost a lot of hours of developers’ time if they are
employed by us.
Now one catchy idea looming in the horizon over this cumbersome complexity is the
technology to provide ERP Software as a service (SaaS) rather than inhouse deployed.
This indeed can save alot of time but again there are killer issues with end-users.
Among them are:
1. Security of database. End-users are worried about fraud occuring from the outside
and they cannot control it as their private data is sitting somewhere in the world and
not at their premises.
2. Responsiveness to change. Again being very complex, ERP will need to adapt to
changes with alot of effort. Having it at a remote site with remote experts may not
help cut such a cost down.
ERP is too complex for SaaS[6] and have to be broken down to simpler stacks for specific
business functions and for very small businesses that do not mind exposing their data
to danger. An SaaS can address the above stated issue by giving local repository of the
client’s data instead of having it at the data centre which acts only a backup and should
be encrpted to protect it.
Open source software has removed the goal posts in the game to present options to a
global market. Allowing end-users to adopt, adapt and improvise will mean an upward
path of progress where software becomes better as the need to reinvent the wheel began
to minimise over time. Open source allows solutions to converge, as no code hiding are
preventing them from sharing and consolidating repetitive functionalities.
Since no software solution is perfect match for general users, or perfect fitting ones are
too exhorbitant in pricing, more generic ones that are open to modification will become
more attractive. There will be software that are highly configurable with good
interoperatibility. Proprietary applications are finding it hard to do all this as it dilutes
their patent or control over intellectual property. They either market their products in
terms of services or produce more niche products that are not easily duplicated by open
source. The chances are whatever proprietary vendors can produce, there are almost
equivalent open source and free ones. Though this may put a strain on software
vendors it provides the market more choice and freedom to examine competing
products out there.
The era of Web 2.0 is making or pushing software development more to the public or
community of end-users who may not pay directly to the FOSS vendors but indirectly
support the projects via user review, bug reports and remedies and code contributions
and enhancements. The ADempiere project is a perfect example where there is no
proprietary vendor owning it directly except an open community of users, system
integrators and independent software vendors providing continuity and growth. We
shall examine more of how open source could be finally resolving the software crisis
and may push software engineering to a whole new level outside the walls of expert
developers into the hands of an army of lay users who may bring about better quality in
the end. As Linus Torvalds is said to have said, “More eyeballs make any bug shallow”.
Useful Quotes
The following are famous selected quotes that can provide much wisdom and some
insight, besides needed humour into the challenge of modern software engineering
projects.
2. “Standards are always out of date. That’s what makes them standards.” – Alan
Bennett
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 19
3. “Looking at code you wrote more than two weeks ago is like looking at code you
are seeing for the first time.” – Dan Hurvitz
4. “Less than 10% of the code has to do with the ostensible purpose of the system; the
rest deals with input-output, data validation, data structure maintenance, and
other housekeeping.” – Mary Shaw
5. “When you are stuck in a traffic jam with a Porsche, all you do is burn more gas in
idle. Scalability is about building wider roads, not about building faster cars.” –
Steve Swartz
7. “Today, most software exists, not to solve a problem, but to interface with other
software.” – IO Angell
8. “As a rule, software systems do not work well until they have been used, and have
failed repeatedly, in real applications.” – Dave Parnas
9. “When debugging, novices insert corrective code; experts remove defective code.” –
Richard Pattis
10. The bearing of a child takes nine months, no matter how many women are
assigned. Many software tasks have this characteristic because of the sequential
nature of debugging. - Fred Brooks
11. The belief that complex systems require armies of designers and programmers is
wrong. A system that is not understood in its entirety, or at least to a significant
degree of detail by a single individual, should probably not be built. - Niklaus Wirt
12. Design and programming are human activities; forget that and all is lost. - Bjarne
Stroustrup
13. Up to a point, it is better to just let the snags [bugs] be there than to spend such
time in design that there are none. - Alan M. Turing
15. If you cannot grok the overall structure of a program while taking a shower, you
are not ready to code it. - Richard Pattis
1. Firstly they forked a project in reverse. Well, forks are in fact alright but they have to
be built upon, improving on what good is done, usually incrementally. In OpenBravo
case, they studied the limitations of Compiere and using own resources, did a huge
reverse-engineering of it and announced their own project as if it is their own almost
entirely by virtue of declaring that they did 90% of the fresh coding. This is not paying
homage to the true values they forked from as pointed out by Oleg Gryb (2007) in his
white paper[7].
2. They did not ride on the community. By being an entirely new commercial project,
they tried to form a new community on their own accord. This is not continuing the
roots that were already there. What ADempiere did was to continue from the
Compiere community, addressing their concerns and decide on a collective basis
without commercial considerations.
This is what OpenBravo did in early 2006 a few months before ADempiere was born. It
was financed by a 3rd party, which of course will exact venture capitalistic returns of
about say 25% per annum on their investments. It is reputed to have taken on in excess
of 10 million euros in fundings! Now that is a big debt to repay. This will mean eventual
closing of some selective parts of their codings for direct royalty arrangements that they
will impose on the free market. This immediately put them at a disadvantage vis-a-vis
an unabatedly free one such as ADempiere.
Nevertheless, OpenBravo in its website and forums, also did try to engage the
community by offering more freedom and acknowledgement of contributions done by
outsiders. Still it did not win complete trust from the community. Those who eventually
did join in did not find substantial activity from the rest. Most were dependent on the
said commercial entity to get things going. This proves that open source communal
spirit is like a fragile but evolutionary plant. It will grow, but it takes a true surrounding
of natural ingredients only a self-learned untouched community can provide.
In a way this is like a misfitful religious phenomena when it comes to describing the
community project. But then would anyone have a better idea to address the software
crisis? Do you have a better idea on how to setup a top notched, highly active, global
software development team that is 24 by 7 and works seemingly without pay?
1.
Glossary
Term Description
ADempiere An open source project forked from Compiere due to the later
closing up certain source from free access and download
Modularization Making software into smaller components that can fit into each
other in a standard fashion easily
3-tier a 3-tier architecture where the database can exist in one server
and the application service in another, leaving the web interface
operating its own logic at the client side.
2. An open source community can resolve many issues in maintaining and expanding a
complex software such as an ERP application.
3. The ADempiere project has many ideas working with other available technologies to
provide better options to reduce the costs of adopting FOSS ERP.
6. An ERP system needs to be componentised for easy integration with verticals from
various differentiated industries.
2. http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0000D8
3. http://www.stevemcconnell.com/articles/art04.htm
4. http://analystinfromthecold.wordpress.com/2009/03/06/there%E2%80%99s-a-new-
erp-survey-in-town/
5. http://knowledge.wpcarey.asu.edu/article.cfm?articleid=1378
6. http://searchcio-midmarket.techtarget.com/tip/0,289483,sid183_gci1298568,00.html
7. http://oleg.internetkeep.net/soapiere/SoapiereWhitePapers.html
Learning Objectives
By the end of this chapter, the student shall be able to:
4. Put forward the next idea in business applications for FOSS ERP.
We can see that there are countless facilities, activities, forces and trends that is bringing
open source to the fore. We can also see that even proprietary players such as Microsoft,
Oracle, IBM, Apple, Sun (now bought by Oracle), Netscape (now gone) and Google are
embracing open source without question. It is only the manner they adopt it that is abit
different due to numerous strategies each player is attempting to maneuvour the
playing field to their advantage if possible. However the long term trend is that all such
maneuvouring will not offer an advantage for long. In the end it seems that an
endowed community will benefit the most. It is almost certainly an end-user market.
Information cannot be hidden and someone is bound to reveal the next best thing - free
and open.
Big vendors are putting more computing power and tools and freedom into the hands
of lay users. The tools are getting more easier and faster to use. Today many who
claimed to be hackers are not really hackers. They are just ‘clickers’! They merely are
good at clicking to download ready-made tools to hack or giving them the perception
that they are good at it, when in fact its the marvelous tools that give them such power
and capability. Nevertheless for ERP software, the eco-system is beginning to emerge
where more end-users who otherwise are not capable of contemplating such software
are downloading and configuring it for their specific use. This is particularly true for
small or low end ERP users such as very small enterprise or industry.
This lower the bar of entry for the whole user chain. Higher level lay users are now
more encouraged to experiment with FOSS ERP and this in turn set their expectations to
drive down or reconsider present expensive engagements with proprietary vendors.
The software also experiences a quantum leap in quality when there is true, open and
unabated peer review that hammers it constantly and persistently.
The ADempiere community consists of a right and healthy mix of technical and domain
experts such as accountants, business process managers, consultants, integrators,
testers, end-users, developers and salespeople. Quite a number of them are exposed to
or have implemented other vendor products such as SAP, Oracle Financials, Great
Plains, JD Edwards, Baans and also open source ones such as from our parent project
Compiere and our sister fork Open Bravo. Their chatter and interaction ensures a rich
continous stream of information that is both factual, up-to-date or at least fair enough to
avoid the project of veering to an irrelevant path. Issues or resolutions made by the
community are often on track such as to determine the way forward in scaling up its
growing functional modules. Where there are more lurkers or free riders who did not
contribute anything, there will be a relative fraction of sufficient supporters who
manage to contribute good enough for the project to move on. There are numerous
releases, each of which can boast of tremendous amount of bug fixes, new features and
stablisation effort been put into the release.
Since forking, ADempiere has undergone the following releases (in reverse
chronological order):
Besides the above, there is daily or nightly build release onto a live test site - http://
www.testadempiere.com/webui/ as well as a Hudson compilation and quality
assurance server managed by Metas in Bonn, Germany, that monitors every code
commit done to the trunk to ensure it will compile without error. This makes sure that
the sorucecode is always accesible for a clean release anytime.
There are virtual machine releases too that let users setup ADempiere almost hassle free
and within a matter of minutes rather than days and not uncommon failures by many
newbies.
Far off projects such as OfBiz and the Spring Framework supply ideas on what could be
done in order to scale ADempiere properly. Some interim step done by Trifon was to
introduce interface class for every setter/getter class. A few other senior developers
from Mexico, Malaysia and Romania began to experiment query classes to remove
SQL scripts from the model classes. Such steps move ADempiere closer to better
refactoring. ADempiere is very bulky with alot of ERP functionality and thus migrating
it to any latest platform is very difficult. Ideas such as trying to make it compatible to
Hibernate or Spring in order for it to be more scalable, modular and manageable in its
growth are mind-boggling until the OSGI idea was made feasible by Joerg Viola of
Germany.
The most exciting shoulders to stand on are those of the business intelligence toolsets.
Software such as Drupal, Pentaho, SpagoBI, and Palo are truly amazing and have been
integrated by independant vendors around ADempiere. Even though some of the
scripting or codes have not made into the codebase awaiting readiness from those
vendors, it is no longer a rocket science to make such things happen. Documentation is
abound of such attempts in the project wiki and forums as well as guides from the
respective vendors that any independent developer can follow the footsteps without too
much difficulty. With grander BI capabilities from a growing slew of FOSS applications,
the roadmap for FOSS ERP looks set to head up the value chain as a very sophisticated
and powerful application suite.
Thus it is this twin charge of community and open source shoulder standing feat that
pushes the envelope further and further each day. Even though it is mind-boggling to
imagine how exactly to manage such a geomatrically growing project, the disruptive
but progressive nature of the web and its treasures are making it grow well some way
or the other.
Eclipse like NetBeans has many addons or plugins that create a massive functional
environment to develop and manage software particularly in a global and remotely
connected manner. This is so important for a community open source project such as
ADempiere where many developers and even users can track changes by updating their
source from the project trunk via Eclipse’s Subversion (SVN) toolset. SVN can apply
only the changes since the last update to a local source. A developer can then examine
the exact changes by comparing it chronologically. SVN is not developed by Eclipse but
another 3rd party open source project and so to get that feature you have to go get it
from Subclipse (http://subclipse.tigris.org/).
Figure 2.1 - Eclipse SVN for checking out code from SourceForge project
While the jury is still out on the debate of whether Compiere did the right thing by
closing some parts and alienating the free-rider community, philosophically or
commercially, it has dropped from the SourceForge rankings even to the other fork,
OpenBravo which is based in Spain and is also commercially-run. ADempiere and
OpenBravo (www.openbravo.com) seem to share the top rankings since end 2006 all
thanks to what Compiere has done as an open source project. Even after forking we still
refer to certain improvements in Compiere to bring over to ADempiere. We of course
still maintain most credit and copyright statements as belonging to Compiere. We also
send patches back to Compiere for its own decision to use them and they did make use
of one very important security hole patch we discovered.
Figure 2.3 - Compiere’s website look - very commercially attractive
OpenBravo hires around a hundred developers and even that is insufficient to bring the
project to a speed the world demands of. Paid developers require return on investment
by the funders to the company behind the project. For ADempiere where there is not a
single directly paid developer as there is no company that owns it, there are thus no
debts to repay and no report card to fail. The many developers that worked around
ADempiere are either doing it for their own commercial instances or have an itch to
scratch. This somewhat created a gift economy where like a public place, everyone chips
in a bit to keep it well run without feeling the pinch.
SpagoBI is said to be a middleware that is also open to work with other BI tools such as
the now emerging Palo.
The above build xml is to compile each package of the sourcecode tree and jar them into
a binary structure for deployment. The following build xml is for applying the SQL
scripts that upgrade the database since the last version release. Each SQL will add,
change or delete certain table-field structure in the database so as to work with the latest
revision in the trunk.
Usually each developer or committer as they commit code changes will also commit the
accompanying database changes in the form of those
<target name="init">
<echo
message="============================================================" />
<echo message=" PostgreSQL database update tool for Adempiere ERP" />
<echo message="
Adempiere Licese is GNU GPL License" />
<echo
message="============================================================" />
<echo message="" file="psql.log" append="false" />
<echo append="false" file="build.log" message="#Build log:${line.separator}${line.separator}" />
</target>
<target name="load">
<echo message="Loading file ${file.name}" />
<exec dir="${postgresql.home}/bin" executable="${postgresql.home}/bin/psql"
resultproperty="psql.result" output="psql.log" append="true">
<arg line="-h ${postgresql.host}" />
<arg line="-d ${postgresql.database} -q" />
<arg line="-U ${postgresql.user}" />
<arg line='-f "${file.name}"' />
<env key="PGPASSWORD" value="${postgresql.password}" />
</exec>
<echo message="File ${file.name} status ${psql.result}" />
<echo append="true" file="build.log">File ${file.name} status ${psql.result}</echo>
<echo append="true" file="build.log" message="${line.separator}" />
</target>
</project>
Project developers have access to centralised storage and tools for managing projects. Its
great benefit to FOSS projects is by providing revision control systems such as CVS,
SVN, Git and Mercurial. Major features (amongst others) include project wikis, metrics
and analysis, access to a MySQL database, and unique sub-domain URLs (such as
http://project-name.sourceforge.net).
I sometimes wondered how life would be without SourceForge. Well, we might use one
of its many competitors now, but in those early 2000s, we might not have known
Compiere that easily and came together this nicely into its community fork. Being there
as the largest and most active FOSS project repository in the world has made it a critical
mass and mecca for all travellers and traders in FOSS.
Among the many tools we used on SourceForge, perhaps the most crucial in ensuring
the global visibility of the software is the Tracker for bug fixes and feature requests as
well as the SVN commiting from Eclipse. SVN or SubVersion is another open source
tool in its own right. These two giants allow us to work in concert seamlessly. Eclipse
has an SVN plugin that can be set pointing to the repositoryin SourceForge. Developers
This allows most of us to wait by our mailing boxes to examine each mail from the
trackers. Some senior committers can quickly revert any ill-done code without spending
too much time searching for them through the repository. What they do usually is to
update the changes back into their IDE project. A quick compile and test can be done. If
the logic is not to what they expected, they can trace the last code commit concerned to
the tracker revision number and comment back there and another message is sent back
to the same tracker. The messages are automatically formated as the one below here.
Notice that in this commit by Victor Perez of Mexico, he put a tribute in his comment to
another committer, Low Heng Sin of Malaysia. The minus sign in the message is saying
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 43
that the line after the sign is being deleted and replaced with the line after the plus sign.
Those two signs and the deleted line shown are automatically done for spot-on
reference by the SVN tool in SourceForge. Without them many, many hours resulting in
wasteful effort and unproductive work will have occured and the project will be very
slow and cumbersome to manage.
In this manner, all developers concerned who has their Eclipse ready pointing to the
SourceForge repository will be on par with everyone else. The most up-to-date
committer’s version is just a click away. Everyone truly seem to be in the same room.
SourceForge, Eclipse and the web has made free software engineering into a
phenomenal experience where the smartest people no matter where they are can truly
be working on a single project, seemingly without a project manager or wading through
tiring close door meetings. The morale and spirit is highest when you are working with
such a gifted group of people that comes from many cultures and backgrounds.
The tracker messages will display again all the previous comments to it since inception.
The long one below here is a good recent example. It is shown here in 2 parts.
From this email message you can see the interactive ‘conversation’ from others about
the same matter. There is Paul Bowden from ADAXA, a prominent Compiere/
ADempiere expert implementation consultant company based in Melbourne, Australia,
followed by Ian Chris (Dellph), a DIY programmer from Mindanao, The Philippines.
Finally Carlos Ruiz from Colombia who originated this Feature Request could respond
back and a technical conversation takes shape. Such a system of communication
resolved a few birds with a single stone. Firstly there is documentation with a running
unique reference number which is the holy battle cry of all project owners. Then there is
No closed software team can beat this. Not when all this is absolutely free and done on
a voluntary basis. I as the pathetic temporal leader have no say, have no control and
have no idea in such discussions. They are all technically more superior than me. Yet
there is no mutiny. Not yet, I hope!
Before a production quality version is released, the trunk where the sourcecode is kept
is frozen so that new features are not sent to it which can destabilise the trunk. But we
cannot stop innovation that is equally important in an open source project. Those new
features are allowed to be in their own branch or in a development trunk.
After a period of stabilising where high priority bugs are sieved through and resolved
or worked around them, a peer agreement is made to create a binary release by
compiling the sourcecode in the trunk. The proper process of this is of great importance
as most users are real-life users with real-life businesses to run on. They are highly
sensitive if the software is unstable or unusable. Even though according to the GPL
license, the software is to be used on an ‘as is where is’ basis, its larger meaning is for it
to be really used for business purpose. With this understanding, it puts a dualism onto
the whole project. On one stage, the project is a hobbyist dream, to hack the canvas of
software with strokes of creativity, but on the other hand, is to ensure the paint stays on
the canvas for the audience to make sense of it. This remarkable interplay of opposites
has led to some expected differences of motivations of which ADempiere also cannot
escape from.
It is not uncommon to find code commits reverted the very next instance, with heated
exchanges of opinions. It is like the ‘egg and chicken’ analogy. If you do not commit a
script, how then can we let the world test it? If we are to test it first, we will delay any
release! The ‘Release Early, Release Often’ mantra attributed to Linus Torvalds is not
precise as to what exactly is ‘early’ and what exactly is ‘often’!
There were many arguments or flames in cyber speak, between strong technical opinion
and strong end-user opinion. Fortunately the majority agrees that the project’s end
product is still an ERP software that must work well and satisfy end-users and not
technical developers.
Thus the miracle that the project not only survives, but is able to make release after
release that wins more and more followers, is either an act of unconscious compromise,
or chaotic harmony.
When ADempiere first forked from Compiere, there was already another commercial
open source fork, OpenBravo that resolved the boring and alpha level of its basic
HTML interface, which was built on old servlets with JSPs technology. It was not even
finished and was not really usable for production instances. So for us in ADempiere we
were basically out on our own as we struggle with the massive challenge of first
consolidating our existence that was entirely virtual with no physical central command
centre and no budget to work on. We had a long list of dreams including making
database independence from Oracle and resolving many bugs that riddled the
application as well as moving it along a roadmap that includes Libero Manufacturing
and Business Intelligence integration.
What was and still is amazing is the sudden appearance of Low Heng Sin who happens
to stay 20 km from where I was or a 15 min drive away. I invited him into the
developer’s list in those early days thinking that he was just a young normal newbie
developer that needs some of my encouraging words. Now my assumption is totally
wrong as he turned out to be the most amazing contributor that can rival the speed of
Carlos Ruiz himself. Heng Sin contributed not only better code all round, but helped
bring to production status many items on our long list with vast and ingeniously
crafted improvements to PostgreSQL porting, Java Swing, core modules and this Ajax
interface to replace the old HTML one. Now we can say that the Ajax UI is very
production ready and may have truly save our day as it certainly can rival OpenBravo’s
similar use of Ajax technology and Compiere’s usage of GWT, another flavour of Ajax.
(We even have a GWT implementation lurking in the background and that is been
developed by e-Evolution of Mexico, another great contributing group under Victor
Perez.)
It is also noteworthy that actually ZK Ajax introduction into ADempiere was done by a
small company in Mauritius, called Tamak, but changed its name to POSterita after
meeting me in end 2006. POSterita however abandoned its contributions that include
Webstore and an advanced POS system due to differences in branding strategy with the
rest of us. The ZK Ajax UI contribution from POSterita that time was very rudiment but
a good start and entry point for Heng Sin to pick up and advance on solidly and quite
single-handedly. We still maintain the credit of saying that POSterita is the contributor
After some minutes we can pick out the IP prompted within. Noted below it is
10.37.129.2 with port number 8088.
Then we call up our favourite browser and put in the IP and port into the location. We
will then have the Adempiere HTML admin page appearing, where we then click on the
Adempiere ZK webUI link. When it comes up, login as SuperUser and key in the
password as System. You shall see the amazing ZK Ajax UI in action. Click around the
widgets and icons and even drag around some of them to see how fantastic it is.
It is important to note that Low Heng Sin, like most of us, does not survive without
income. So what he has contributed is what he was paid for and in this case, the Ajax
works are being sponsored by Idalica of USA. This fits very nicely with the 3-line
mantra I promoted in my www.red1.org website and the www.adempiere.org site:
There will be a need for you to package and rebrand your works and that cost more
money (see figure on next page). Then there is marketing to promote at least by word of
mouth. More money. What about time spent reselling? Preselling? Follow up meetings.
More money. In the end you have to ask yourself is it worth it wasting money as a
private enterprise. Not only that. You will not be the only smart ass in the room. There
are countless others already doing what you are thinking of doing. They are all
competing in the little alleys for the main street attention. That they won’t get because
the main project is in the way.
If we in the ADempiere project think about closing up or selling off to a major player,
we will lose value and face almost overnight. Just like what happened to Compiere or
OpenBravo. The millions given to it has to be repaid nevertheless. But the value they
hope to exact from the market is already diluted. Many already know about the other
parent or fork projects. There is no barrier to keep them ignorant. They can just google
and find out the truth.
Linux is free and cannot be stolen. It can be forked and repackaged as Tomix. But who
will pay for it? How to hide the look and feel more convincingly? How to avoid expert
eyes from figuring out what actually is under the fresh coat of paint?
Going private will out you back at the start of the food chain because providing post
installations of mainstream adopted ERP systems can be a major source of income. This
is in accordance to recent analysis conducted which state that many organizations do
not realise that the total cost of ownership of an ERP system is composed largely of
ongoing support[5]. Something that is real but not yet realised is more blue an ocean to
swim in than copycat in a red one.
Glossary
Term Description
Business The ability to analyse data and present in high level but statistical
Intelligence formats usually done with software tools.
SourceForge.net The most popular and largest repository for Open Source projects
to house and operate from.
FOSS Free and Open Source Software, with specific licensing i.e. GPL
6. Tools such as JasperReports allow n-tier freedom to the ERP Application in that it can
now access directly the database for ad-hoc reporting.
8. Private forking of an open project is not necessarily viable from a business sense
unless it is providing something that the open project does not.
2. http://blogs.zdnet.com/Burnette/?p=387
3. http://www.adempiere.com/images/9/96/SpagoBI_&_ADempiere_en_.pdf
4. http://en.wikipedia.org/wiki/SourceForge
Learning Objectives
By the end of this chapter, the student shall be able to:
4. Put forward the next wave in business applications and tools from FOSS.
Since the appearance of Compiere in 2000, the marketplace of shopping for Enterprise
Software began to change. Now users have a choice of going free. After Compiere’s
creators milked the free-riding branding to amass a small fortune, it turned more
commercial and leave it to others to inherit its GPL discarded codebase.
Studying how the Compiere application strategy works can be a reference point for
other business applications. Compiere is a first grade ERP system[1], nothing miniscule
like your daily General Ledger book keeping software. To work or change it requires
not only holistic profound understanding but also pills of patience through a sharp
learning curve. The bright side is that if you come out the other side like I did, you can
be called a guru, like I am.
There are many new application makers out there mushrooming as we speak.
Differentiator is that they have to have enough functional maturity that Compiere and
ADempiere now has. The later has gone through great communal baptism the last 3
years, with many lines of codes and feature snippets scrutinised - understood, modified,
improved, refactored or thrown out. Functionality is king with end-users. All
applications have to remember that.
Searching via any search engine can assist. It is the lots of reading that has to be done.
When doing such a search for “Software Development Strategy” it returns 54 million
hits. In them we will come across the following buzz words:
1. Agile
2. Team based
3. Interoperatibility
4. Documentation Generating
5. Standards Compliance
6. Open Standards
7. Client Server versus Distributed Architecture
8. Supplier Performance & Risk
9. SOA - service oriented architeture
10. Why build? Just uses SaaS - in the Cloud!
11. Or use a Rapid Software Prototyping Tool
Many of these buzz words can be confusing and especially so that the software industry
is very strictly vendor driven. All vendors have their own say on all things. Oracle has
its own version of standards and software strategy. So does Microsoft. Nevertheless we
can find them using the same buzz words. Just watch out for collective stupidity. An
example is SaaS (Software as a Service) which is a repackaging of the failed ASP model
(Application Service Provider). The idea is to tell the customer not to buy software and
set it up inhouse but rent it and have it setup at a data centre. For ERP users, this is
tricky because, like the very first statement I made in this module about how long it
Thus many users are left to pick and choose from the market their own interpretation of
the best buy or build from scratch option. Now, you should strike out the later option
because nobody builds from scratch. You may be surprised but I have come across
many who do! Either they are dreaming of been the next Bill Gates or they felt no one
out there understand or fit their requirements. This is where rapid prototypers may
come in. Do a search for it and again a popular vendor such as Microsoft’s name comes
up. Using Microsoft for instance will lock in the user to a certain vendor’s stack of
software which can be costly and unwieldy to break off from in case of a change of
heart.
There are many building buzz words to speak of and the following often comes to
mind:
As you can see, these are still tools and not the finished buildings or machines. Here I
am giving a strong hint that there is no holy grail of finished friendly dragon that can
take you up into the sky. I have came across some such as JBoss BPM, Groovy
generators, but they are just nice bodyframes with missing parts inside. (There is OfBiz
as an exception that we shall touch on later). There is no business content of business
processes. You will have to build it from scratch. From here we can examine the
Compiere family particularly ADempiere’s due to their inherent body parts and ready
made cushioning. Among their available inbuilt business content features are:
1. Accounting engine to post debits and credits generated in each document transaction;
2. Document Type definition of Sales and Purchases (Orders), Vendor and Customer
Documents (Invoice, Shipments and Payment);
Some of the wishlist of such a new software model will go along the following lines;
The first thing a new application has to do is to trade-off with the ADempiere project.
* It has to offer something in return
* It has to exploit the community open source paradigm
* It has to be useful to the horizontal ERP and other verticals
* It has to be componentised and portable
* It has to earn potential income to the contributor due to its branded domain expertise
Figure 3.3 - EIDA is a sample idea that can be contributed. If not, someone else will
The contributing company should not have over-reliance on own local IT and developer
resource. Java or ERP resource is expensive and even more expensive to keep. Just have
a skeletal 3 man support team per base is sufficient. Rely more on short term and well
paid expatriate team already available in the community. Hire our best brains and
hands to ensure a quick kickoff and exit strategy. Keep lean and beam. Not mean. Go
up your own value chain. Be better in what you are good at and nothing else. High
worth deals only seek for high worth consultancy and services. Seek a niche and not be
everything to everyone. You will soon dry up and no one pays a dime more. There are
many more cups better than yours.
Focus to enjoy more
You won't like a big headache from big office and staff. No one likes you having big
headaches all the time. When you are having fun, you won't mind failing. It is already
paid for.
Today's needs are on the fast-track. Users want an ERP within 6 months instead of 18
months. ERP apps have bloated to become everything to everybody and one size fits
all. Quality large scale implementations can no longer be done by a single expert and
requires open sharing among all parties. Speciliasation by differentiated contributors
lower total cost of ownership for paying users.
Application Modelling
Figure 3.5 - Any vertical application can be incorporated and reuse standard utilities
• Any application design is hard. The bigger it is the harder it is. The more modules to
integrate, the challenge increases exponentially.
• But spend enough time planning it (50%), and enough time designing it (90%), the
coding part is only 10%.
• 2Pack (XML2AD enhanced model by Robert Klein - standard for migrating own apps)
A succesfully introduced or migrated vertical application will enjoy not only the
incumbent multiple rich interfaces and application engine, but also a quantum leap into
the open source services market.
The word 'should' would mean that it is optional but encouraged for maintainability
and scalability of the system.
• SQL scripts for each data model can be executed first in the Database. Then the AD's
Table and Column can bring in those created tables into the Application Dictionary.
• Each table must have the compulsory fields for model persistence and management
within the ADempiere Framework:
• AD_Client_ID - signifies the highest level and distinct identity that owns all the
organisational activity.
• Created - signifies the time-stamp each record in this table at the time of its
creation
Each table should have a 'value' field for search key purposes. In short 'value' is another
reserved name in ADempiere's table modeling.
Entity Relationships between tables can be introduced by having fields that possess the
table ID convention. For example another table 'Cigar Smokers' will have 'Cigar_ID' and
this means that it is a Foreign Key to the 'Cigar' table. This is a loosely stated
relationship.
• Of course you can constraint further within the database constraint setting to say that
if the parent cannot be deleted while having a child still in existence.
• Master Detail table naming should be that the Detail table has suffix 'Line' added to its
name taken from the Master table. For example a 'Cigar' table can be a master table
with a detail table as 'CigarLine'.
Report Modeling
The Reporting Engine in ADempiere (fully inherited from Compiere) is truly on the fly
and hot configurable.
In any window table with records you can click on the Report icon.
• Note the pop up report viewer with your selected single record.
• Click on the Search icon in that viewer.
• You can thus try to do an Advanced Search to get any report cube you want.
• You can reformat the fields and its arrangement easily via the PrintFormat
1. In the same pop up window, select the ToolsBox to zoom into the PrintFormat
window
3. Select those fields you do not want to appear. You can move them around in your
prefered order.
4. Click on the back arrow key to remove them for this report
5. You can then save your new report for later use.
You can put in further functions such as getting the total or running sum of a field with
amount or countable value.
Advanced Search
There is already an on-the-fly Advanced Search engine to filter any results whether it is
in the display window or the reporting format.
• This saves alot of need to create any further engine or tools to produce the right range
of reports.
Process Modeling
Figure 3.8 -A Model goes through various Controller Process that automate work
• The AD Framework allows any Field in Table & Column model to have a Callout
• The Callout will do something when OnChange occurs within the field
• Action can be from reading and calculating a new value for any field in the Tab
• Calculation can be accessing any table or changing its value within the Database
• Metadata Callout allows JSR223 scripting options such as from Python, Beanshell,
Groovy and perhaps Ruby as well as Java.
There is a button field that can spawn a process written in SQL or Java Code
• Accounts Posting
• Workflow Management
• Records Change
At the end of the process, the button may change its state and the Tab record state is
changed.
This table is for route trips or schedule of trips available. It stores the origin
(et_departure) to destinations (et_arrival) mappings.
After these tables are created in the database, you can bring them into the Application
Dictionary through the Table and Column window.
Proof of Concept
We could quickly prototype a POC by building 2 tables :-
• one for Vehicle Schedule containing Bus Registration Numbers for each trip;
• and one for Trip Booking to call-up the Vehicle Schedule and return the right Bus
Registration No.
The Table Reference and Dynamic Validation are used to allow a trip planner pull down
list that shows only available trips.
Suggested Implementation
• To incorporate schedule confirmation and seating selection as 2 extra tabs under the
Sales Order Window.
• As the 3rd tab's schedule is confirmed, the 4th tab shall display the available seating to
choose from.
• As the seat number is/are chosen, all built information is put as Description in the
OrderLine tab.
• The relevant ticket product with correct pricing is extracted from PriceList Version
table.
• Alternatively all this extra work can be put into one single 3rd Tab.
Pull down lists validated against Bus Schedule above. A Java Callout returns the value
of the Bus RegNo and writes it to the Description field, as well as the Departure and
Arrival venues. Refer to next lesson on Reference Table with Dynamic Validation for
details to achieve this effect.
Figure 3.11 Reporting on the fly without a single line of coding needed!
From this E-Ticketing example we can see how the FOSS ERP base we are using can
achieve alot without worrying about the next steps, troubleshooting, and integration.
We can continue focusing on the business model and operational processes more clearly
and build the new modules more surer and faster.
3. They are following a proper design that many developers can recognise;
4. They are reusable;
The last points form the highest motivation on why patterns are so important and need
to be stated here as part of the understanding in application building strategy. Later in
the module we will come across lots of of it. For now we can ponder why they are so
important.
Without patterns, the code no matter how much it uses Java, will be wasting it. Java is
meant to build reusable code. Being object-oriented, we can code objects upon objects.
For example we can have a DocumentType object such as Order.java, Invoice.java and
Payment.java. Each object are made up of smaller objects such as get fields, save fields,
or return transactions of a header document. Such functions are again similar across
documents and therefore can reuse similar patterns of code themselves.
Java also allow inheritance where less code is written to say the same thing. You can just
have one calling line to refer to a block code object to carry out a function in a logical
business sense. Example is Invoice.save(). More of this in later chapter on survival Java.
For now suffice to understand that with Java, building pattern of objects and reusing
them is possible and is heavily used in ADempiere. In fact, Java already has ready-made
This concept is borrowed at a higher level and the most famous pattern often refered to
before is the Application Dictionary or AD for short. The AD is what takes our Table
creation scripts above and generate in the application a brand new window with all the
bells and whistles without a single line of extra hard coding. It uses the approach of
dynamic or active code, where the type of window generated is determined at the data
level and not code level. Such data as taught in earlier modules are refered to as meta-
data, or higher data or data about data. What it means essentially is that it is not static.
It is not hard-coded. If it is hard-coded, then we need to hard code all the time. We take
what changes which is the shape of windows and tables and leave those that are not
which is the generation of the actual windows and features as we see when we open up
the application menu.
This thinking of reusing to avoid repetitive work is a very powerful idea. Many of our
top developers in the community project often apply this whenever they are coding
new stuff or reviewing old ones. It is like building bigger and more powerful machines
to do work. We have to leave the use of old shovels and buckets, and create to use gears
and propellors. From this point onwards you can keep your mind open to observe more
patterns in use. The next topic about ASP is exactly using the same concept but on a
different context.
• Now you can define modules (i.e. Sales / Purchase / CRM / Accounting ...)
• And for each module you can define levels (i.e. Beginner / Full ...)
• Then you can define in a detailed way the functionalities "covered" by each level.
• You can define the supported Windows, Tabs, Fields (optionally you can define to
cover all the fields on a tab), Forms, Tasks, Process, Process Parameters and
Workflows.
WARNING: You must previously define the modules/levels and subscribe the client to
a level - if you don't do that your menu will become empty
There is a another concept phrase floated by ISPs (Internet Service Providers) a long
time ago, which seems to ring well the ASP rhythm, is Apps On Taps that you do not
hear often anymore. Hope you get the idea of what is going ON. So, question is how hot
is in our case, ERP On Demand getting? A simple yahoo check says it is.
Is it Outsourcing?
But as these concepts stem from the disastrous need of throwing out the bathwater
every time a baby is washed, they fall under a broader category called Outsourcing.
We then can have a cursory examination of what can particularly in this area of ERP
happens to pose an even higher risk than in-sourcing.
ERP as we know it is not something you can outsource or give away. It is not non-core
IT activity. It is core business subject matter and that is core.
The expectations of customers of ERP to think they can remove the pain away probably
will give On Demand solutions an intial boost, but as the example of SAP associated
CRM On Demand solution SalesForce.com has shown dramatic flight patterns when its
profits plunge. What more inadvertently giving away its customers' list.
It is a Channel, Stupid
That is what Howard Smith seems to say in his blog. It is still not a service. And service
takes a different drawing board. It takes business concerns, which takes content, which
takes expertise, which takes attention, which takes another business all together.
It is like what I often tell OS pundits that Free doesn't mean Free. So now I have to
introduce anoher phrase, Outsourcing your TCO doesn't mean you do not have another
bigger TCO.
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 88
3.11 Service Oriented Architecture
One of the important and wise software engineering strategy is to have an application
suite ‘loosely coupled’ among its components and functionals. This is to avoid, well
‘tight coupling’ which as the phrase goes can mean cumbersome and unwieldy
structural design. One of the loosely coupled implementation approach is Service
Oriented Architecture or SOA[7]. Such an architecture is more distributed or
distributable where scalability is easy and allows n-tier server arrangement, rather than
just 2 or 3-tier limitations.
Development Guide
You can find instructions about how to add datatypes and/or web services in the repository file
Notes/HowToAddNewWebService.txt
Test Scripts
soapUI
1. Tested the model webservices using soapUI tool. Excellent tool - the tests are working ok.
2. You can find test project for soapui in svn repository AdempiereWebServices-soapui-project.xml
In order to use it you need to change the protocol, hostname and port according to what you want to
test ( search the https://localhost:8443 string and replace it properly with your installation
protocol://host:port )
Eclipse testing
1. I tried testing with Eclipse Ganymede JEE version.
2. Running from Web perspective, you can try Run -> Launch the Web Services Explorer
3. The web services are properly discovered using the WSDL button and entering the URL of the
server wsdl described above.
Unfortunately the web services can't be tested from eclipse. It seems eclipse is not supporting the rpc
style of web services, it's sending the message formatted as document style.
Web Services
Model oriented web services has a different approach to run things on ADempiere. They need login
data on each request, opening a session, executing its operation and closing the session. They are not
intended to replicate the UI functionality, but to allow executing common operations within
ADempiere.
All these web services receive a serviceType parameter. This is configured in the security layer
explained in Adempiere Web Services Security. The parameters are checked (and modified if
necessary) against the definition of the serviceType.
setDocAction
This web service is intended to trigger a change in document action, i.e. complete a material receipt,
prepare a purchase order, void an invoice, etc.
WARNING! - This web service complete documents not via workflow, so it jump over any approval
step considered in document workflow. To complete documents using workflow it's better to use the
runProcess web service.
Parameters:
• serviceType
• tableName
• recordID
• docAction
Returns:
• StandardResponse (Error Message, IsError flag, RecordID)
Process:
• Login and create session (it returns proper message if it can't login)
• Get the record given the tableName and recordID (it must be a document table, it
must have an associated Model class implementing DocAction interface)
runProcess
This web service is intended to run a process, or raise a process that starts a document workflow.
Parameters:
• serviceType
• AD_Process_ID
• AD_Menu_ID - not used
• AD_Record_ID
• DocAction (used if the process is a document workflow)
• ParamValues (optional, set of DataRow)
Returns:
• RunProcessResponse (Error, Summary, LogInfo, Data, IsError, IsReport,
ReportFormat)
Process:
• Login and create session (it returns proper message if it can't login)
• If the process is a document workflow, set DocAction according to the parameter
• Executes the process pointed by AD_Process_ID
• Fill the return message and return accordingly to what the process must return
getList
This web service is intended to get data from a list (reference list or reference table)
Parameters:
• serviceType
• AD_Reference_ID
• Filter - optional
Returns:
• WindowTabData (DataSet -> DataRow array -> DataField array -> pair of Column
and Value)
Process:
• Login and create session (it returns proper message if it can't login)
• Get the list table, columns, where and order by
• Apply the filter
• Fill the return message with values of the allowed output columns
Returns:
• StandardResponse (Error Message, IsError flag, RecordID)
Process:
• Login and create session (it returns proper message if it can't login)
• Create a new record on the desired table
• Set the columns
• Invoke the adempiere persistence engine to save the row (this implies calling
automatically before/after triggers and model validators)
• If successful, fill the RecordID of the response
• Returns any message, and flag the IsError flag accordingly
updateData
This web service is intended to modify one record on a table (accessed by ID). The table and allowed
input columns must be configured in the serviceType.
Parameters:
• serviceType
• TableName
• RecordID - required
• Filter - not used here
• Action - must be Update
• DataRow (DataField array of Column+Value pairs)
Returns:
• StandardResponse (Error Message, IsError flag, RecordID)
deleteData
This web service is intended to delete one record from a table. The table must be configured in the
serviceType.
Parameters:
• serviceType
• TableName
• RecordID - required
• Filter - not used here
• Action - must be Delete
• DataRow - not used here
Returns:
• StandardResponse (Error Message, IsError flag, RecordID)
Process:
• Login and create session (it returns proper message if it can't login)
• Read the record from the desired table using the recordID
• Invoke the adempiere persistence engine to delete the row (this implies calling
automatically before/after triggers and model validators)
• Returns any message, and flag the IsError flag accordingly
readData
This web service is intended to return values from one record on a table (accessed by ID). The table
and allowed output columns must be configured in the serviceType.
Parameters:
• serviceType
• TableName
• RecordID - required
• Filter - not used here
Returns:
• WindowTabData (DataSet -> DataRow array -> DataField array -> pair of Column
and Value) - just one record
Process:
• Login and create session (it returns proper message if it can't login)
• Read the record from the desired table using the recordID
• Fill the return message with values of the allowed output columns
queryData
This web service is intended to query records on a table (accessed by conditions on columns and
filter). The table, allowed input columns (conditions) and allowed output columns must be
configured in the serviceType.
Parameters:
• serviceType
• TableName
• RecordID - not used here
• Filter
• Action - must be Read
• DataRow - to define the conditions of columns
Returns:
• WindowTabData (DataSet -> DataRow array -> DataField array -> pair of Column
and Value) - zero, one or several records
Process:
• Login and create session (it returns proper message if it can't login)
• Query the records from the desired table using the conditions on columns and filter
(and applying the access security defined for role)
• Fill the return message with values of the allowed output columns
WSDL: ADService.wsdl
3E developed lots of UI oriented web services, and they're ready to use and test with their ADClient
tool that you can download here ADClient_0.7.6.zip. In order to test, you will need to activate the
web service ADService (not recommended in production).
According to the instructions on their page you must download ADClient package (2 mb), unzip it in
choosen dir, edit ADClient.ini file and set up service host (or leave it unchanged for localhost) and
run ADClient.exe.
These web services are oriented to UI, this is, they create a session and environment to work as if you
were in Adempiere swing client. You can open windows, navigate data, change, remove, run
processes, etc.
The UI oriented services already included are: login, isLoggedIn, getADMenu, saveLocation,
setDocAction, getLookupData, updateDataRow, getDataRow, ignoreDataRow, addNewDataRow,
getProcessParams, getLocation, runProcess, getLookupSearchData, getVersion, saveDataRow,
deleteDataRow, getDocAction, getADWindow, refreshDataRow, getWindowTabData
Methods
And then you must register each method from the web service. In the 2nd tab, Web Service Method:
Security
Model web services are highly generic - so they need an additional security layer in order to ensure
the server security is not compromised.
Parameters
This web service receives some specific parameters, so we configure here if the parameter can be used
freely (Free), or if the parameter must have a constant value (Constant).
Access
And then you must configure the Access to allow execution from the proper web service role:
Parameters Allowed
You also need to configure the constant and free parameters:
Fields Input
And here you must configure the allowed columns to pass in datarow.
This is a really important step, for example allowing modification of the password on user table it can
compromise seriously the security of the server.
RoadMap
• Implement a webservice that can combine all of the previous within one single login and
transaction (this would need to set values on context variables, to reuse in later messages)
• Reuse login between different calls
• Complete Openbravo POS integration
Cloud computing seems like a major jump in application service, but like Ajax, it is
more of an old technology been exploited to the maximum. It is in a way taking the idea
out of what the JVM did to programming language. It allows higher distributability for
the more global audience to use. Better management of active sessions of the cloud
application will give more users the feel of desktop computing power over the web.
Cloud computing allows or overcome limitations that bulky applications usually face
such as CPU or memory size as such items are scalable and the application portable
from one hardware setup to another. ADempiere also has a virtual machine version
called the AVA[11] and thus can be easily placed in a cloud environment.
The status about this OSGI works is that it is now proven as a POC with a few stubs
created for the ADempiere patterns to now behave as plugins, such as 2Pack,
ModelValidator and Patch. More of these wonderful artifacts by themselves later. For
now, this OSGI plugin mechanism is one big step towards scalability of the whole
application to be like the figure above where verticals can come into the horizontal ERP
system more easily than ever.
Currently, an alpha demo is available. The vision is to integrate it into Adempiere core an have every
further extension be delivered as a plugin.
Technical documentation
The integration consists of four components, implemented each in its own project in an eclipse
environment.
ADempiere patch
This patch currently is very simple. It consists of
• The interface IExtension, a factory for IExtensions called Extension and two implementations:
• Which extension is used, depends on a prefix of e.g. the given classname: osgi://
formClassName would use Equinox whereas formClassName would use the
DefaultExtension and thus provide a clean fallback
• It does so in a seperate thread, because the platform modifies the context classloader
• It fires up an OSGi console on port 1234, so that you may connect to it via telnet and see
whats going on
• It then asks for the so-called "host service", an OSGi-Service gatewaying requests from the
patched adempiere core into equinox
• In fact, I don't like the way, libraries are re-packages during Adempiere install
• Nevertheless, the Equinox OSGI jar must stay intact in order to work, so I switched to only
deploy the patch itself, not the supporting libraries re-packaged
ADempiere Extension
• This is an extension fragment to the system bundle (OSGi slang...)
• ModelValidator
• Form
• Callout
• Process
• It implements and registers the so-called "host-service" that receives requests from the adempiere
core and dispatches them to bundles, typically via extension points.
• It implements and registers the "dictionary service", that uses PackIn to import PackOut.xml.
• It provides a Plugin base class, AbstractAdempierePlugin, that handles install and startup:
• The Method start() of the bundle is called (this substitutes start(BundleContext) from OSGi)
• On stop, The Method stop() of the bundle is called (this substitutes stop(BundleContext) from
OSGi)
• So, if you want a full re-install of the plugin, you must increment the version number or delete the
corresponding entry in "Imported packages"
• Caution: Name and Version in the bundle header and in PackOut.xml must correspond!
• The extension consists of a ModelValidator class (you wouldn't have thought so, would you?)
Basic Setup
This Basics and JBoss Setup will make use of the WebUI layer. Other Setups will target Java Client,
WebStart and so on.
• run Adempiere-patch/build.xml
• It will populate your Adempiere JBoss with the patch, all required equinox library and
configurations
* NOTES
1. The tab "extension points" contains the ModelValidator point.
2. Click on the third icon in the header ("Export deployable...") or in the menu File/Export/Plugin
Development/Deployable plugins and fragments.
Congrats! Your equinox container started, opened a telnet port, started the Host Bundle which in turn
got a ModelValidation engine, found the TestPlugin listening on Table AD_User and registered it on
the Engine.
Test
Now fire up the ZK Web UI, login as SuperUser, Role System Administrator and change any field
value in the Window User.
* You will see:
On the extension tab, you can see why it listens on AD_User: It was declared to the host bundle in the
manifest!
Other Setups
Here we see the deployment on other clients in use such as the Java Swing Client, WebStart client on
LAN and other forms of plugins.
Form extensions
It is now possible to deploy swing forms via a plugin. To do this, create a plugin and specifiy some
dependencies:
(DATEV is a common localisation product specific to German Accounting market and is integrated to
ADempiere by Metas AG of Bonn).
Switch to the extension tab, click add and choose the AdempiereEquinox.Form extension point.
Right-click on the new extension and choose New.../client. Create or select the class (must be of type
FormPanel).
Deploy the plugin. As usual, as SuperUser create a new Form, specifying the class as above and a
new Menu entry. Try it!
WebForm extensions
This works essentially the same as for Form above, extending the point WebForm of course.
Nevertheless, two things are different:
Since plugins essentially are deployed in the EJB layer but must have access to classes in the web
layer (org.adempiere.webui.* and org.zkoss.*), the JBoss WAR classloader has to be turned off. This is
a drawback since we no longer have classpath separation between web- and ejb-tier. You do this by
switching the attribute UseJBossWebLoader to true in $JBOSS/server/adempiere/deploy/jboss-
web.deployer/META-INF/jboss-service.xml.
You have to import several additional packages in your plugin, at least:
org.adempiere.webui.component, org.adempiere.webui.panel,org.zkoss.zk.ui and
org.zkoss.zk.ui.event.
3. ADempiere’s community constantly build a huge knowledge base for easier adoption
learning curve to the open public.
4. Open source allow the standing on the shoulders and reuse previous achievements
without patenting obstructions, but yet maintaining IP credits to the authors.
5. The Compiere parent contribution accounts for many wonderful features that are
unbeatable in the Open Source market.
6. OfBiz is another serious contender for ERP application but it is not its main forte of
focus.
7. Due to the high failure rate of ERP implementations, users out there are looking at
better options.
9. Compiere has offered its application using Cloud Computing but ADempiere opens
up with contributions to make it ASP ready and having its own free virtual machine.
10. SOA and Web Services are also implemented in ADempiere that comes with added
web services security.
11. OpenBravo has bought over a POS from TinyERP which is also being integrated into
ADempiere as a web services component.
12. OSGI allow advanced componentisation of the ERP modules particularly the large
verticals specific to industry.
Glossary
Term Description
Horizontal App An application that is generic fulfilling a broad range of needs such
as an ERP system. Usually configurable to specific needs.
RAD Rapid Application Development is a buzz word for tools that can
help developers program without scafolding or boilerplate work
2. http://ofbiz.apache.org/feature-list.html
3. http://theoserp.blogspot.com/2007/01/finalists.html
4. http://www.technologyevaluation.com/Research/ResearchHighlights/
FreeOpenSource/2004/09/research_notes/VN_FS_JC_09_09_04_1.asp (free
registration)
5. http://java.sun.com/blueprints/patterns/catalog.html
6. http://www.adempiere.com/index.php/ASP
7. http://en.wikipedia.org/wiki/Service-oriented_architecture
9. http://adempiere.svn.sourceforge.net/viewvc/adempiere/branches/
3E_WebServices/migration/
10. http://sourceforge.net/forum/forum.php?thread_id=3162659&forum_id=611158
11. http://www.adempiere.com/index.php/ADempiere_Virtual_Appliance_Install
12. http://www.adempiere.com/index.php/Equinox_Integration
Learning Objectives
By the end of this chapter, the student shall be able to:
In this chapter I hope to gently introduce to the uninitiated what to expect when
handling code and what it means to have open source on your lap. What do you do first
to get the sourcecode? Where is it stored? How is it downloaded? What do we look for
inside the code? What can I start to modify to show my part? That will lead you to
complete the cycle and make you not just a consumer as most people are today, but a
prosumer - producing while consuming.
4. I don’t really know other languages except BASIC and COBOL so I cannot say how
much more suited Python, Ruby or VisualBasic is compared to Java.
So I will rely more on googling to get the answer to the question above. Then we can
provide a more objective analysis rather than relying on hunches and holy faithfulness
to everyone’s own religion.
There are already very common arguments on why Java is best and I will list them
down here so that you can keep them buried somewhere just in case you are
confronted by fanatics from the other side:
1. Java has industry acceptance. You cannot go wrong with Java owned by Sun, bought
over by Oracle and Microsoft having its own Java flavour[2]. No one will hate you
(perhaps envy is more accurate) more than they find it hard to learn it.
2. Java has maturity. It has lots of ready made libraries, tested through time for reusing.
You can use this argument well against newly minted languages as they are bound to
be lacking relatively in common APIs and well, not tested through time. You
wouldn’t want to risk that for sure.
3. Java is more scalable. Now you have to prepare to run or duck as opponents are most
likely to grab a chair and throw at you. Well do not take our word for it, this is what
you have to say to them. Check it out. And understand what we really mean by
scalable. We do not mean the coding but the quantity of people that can really work
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 127
on a single project. Java strongly-typed rules and strict object parametering forces
developers to be more disciplined (besides smarter as it just take a donkey to learn
Php - now you really have to run!) in that another developer working or extending it
will not be stopped by a bunch of spaghetti coding (description used on what will
happen when you are lazy and rely too much on Php).
4. Java has reusability. Perhaps the most powerful idea to address the software crisis.
Java is object-oriented, allows building blocks to grow for reuse by other builders.
Even though other top new languages are staking a claim in the same OO territory
such as Python and Ruby, they also incoperate java adaptors such as Jython and
JRuby respectively, in order to appease the java librarians.
Now let us quickly appease the other side with the suspicions many have against using
Java[3]:
1. It is hard to learn. Actually it is because there are bad teachers. Anyhow the reason for
creating Java was because C++ was very difficult to learn. So hope this set your spirits
higher to take on Java.
2. Java is slow. I do not dare to say ‘slower’ because for that you need more proof and
that is hard to get as well as being very subjective. Benchmark testing has its own
story as it really depends on what you are testing it for[4].
In conclusion I like to urge students to take on Java more so for its vast educational
potential, particularly just by listening to how others debate it out[5]. You get to learn
things seriously and become really smart for having mastered Java one fine day.
Its current layout structure as shown above has not changed since forking from
Compiere with perhaps only new ones such as Posterita, JasperReports and migration
works.
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 129
4.3 Checking Out Source
To get the latest sourcecode into your environment whether it be for scrutinising or
modifying or compiling the latest from the ADempiere project, you have to setup
Eclipse or Netbeans in your PC. Then through the IDE you access the SVN repository of
http://sourceforge.net/projects/adempiere to check it out.
To have the SVN client working you can refer to Figure 2.1 in chapter 2. Once that is
done, you can call up the SVN Respository Exploring perspective. It is here where we
put in the url connection string: https://adempiere.svn.sourceforge.net/svnroot/
adempiere. Once that is validated, we can start a checkout by right clicking on the
repository item, and select checkout command.
You can do this updating whenever you notice there has been new commits done by
others from the SVNLog maillist tracker. In this way your local project instance will be
up-to-date as the trunk’s instance.
Server Installation
First you need to set up two environment variables: ADEMPIERE_HOME and
JAVA_HOME, i.e.:
SET ADEMPIERE_HOME=C:\Adempiere
SET JAVA_HOME=D:\Java\jdk1.5.0_11
Once the prerequisites are installed and tested the installation is straightforward:
1. Uncompress Adempiere
2. Setup the installation
C:\Adempiere\RUN_Setup (.bat or .sh) to setup the adempiere (application-)server.
C:\Adempiere\utils\RUN_ImportAdempiere (.bat or .sh) to import initial adempiere
data into your database (as specified in RUN_Setup).
Hint:If you're reinstalling and have a previous backup ExpDat.dmp you can use
RUN_DBRestore (bat or .sh) instead
RUN_Server2
The most important part of the installation is to fill properly the RUN_Setup
parameters.
RUN_Setup creates Adempiere.properties (server environment) and
AdempiereEnv.properties (Environment info) – these files must be secured, they contain
sensitive information.
Finally, please note the RUN_Server2 leaves a session box opened (command line box).
To avoid this you would need to install adempiere as service:
in windows using the provided tools for %ADEMPIERE_HOME%\utils\windows
in linux using the tools on $ADEMPIERE_HOME/utils/unix.
DB and application server can be installed in one single server. Optionally you can
install DB in one server, and application in other server.
Now that we have got the source out of the way in terms of how to get it and set it up,
we like to examine one important aspect that haunts or brought a lot of interesting
discussions around it - the PO or Persistence Object implementation in the source.
You can have an idea by locating PO.java within the source. Then look for classes that
extends PO by doing a search for ‘extends PO’.
The above search will return about 710 classes most of them X_*.classes. Here we will
focus more on the X_*.classes because together with the M_*.classes is what constitutes
the PO stack or the model’s data calling within the source. This is been debated to be
replaced by a more higher and contemporary technology such as Hibernate or from the
Spring Framework or OfBiz but for now, it is good to grasp its innards and essence of
how Compiere and ADempiere is possessed by it. Later we will see the Query.class
model of abstracting out the unwieldy SQL scripts from the M_*.classes or model
classes. This may not be the ideal way but it can be a good compromise as there are tons
The regime that ADempiere has inherited is exposed in the following sample, whenever
an entity wants to access a field value within the model.
Everytime a model class wants to do something it will go through the above sequence
and build up a context stack within its java call, that so often draws criticism from
present day developers as too monolithic and overweight. But as explained, this can be
efficient in the ERP framework to handle countless model calls. What can be done next
To understand further on what the stack is finally refering to in the abstract PO, as you
can see above, there is reference to ColumnIndex and columnName as well as p_Info
(POInfo.class). These are accessing the Application Dictionary (AD) domain where the
model is defined by information stored in AD_Tables and AD_Fields. Some lessons on
the AD was done in the ERP Setup module. Later we will provide a technical exposition
adapted from Carlos Ruiz’s article in wikiversity.
What we have to appreciate in the Compiere context of handling model and DB access
is that it is wired to the AD from the ground up. Let us think about what happens when
ADempiere is launched. It first calls its AD framework that calls its metadata of what
Menu tree with what Windows and Tabs and Columns to appear in the client. It is
rather like Spring and having its client presentation taken care of dynamically. As it is,
the sourcecode arrangement has sufficient logical separation between the AD and the
business model. Just that since Compiere was first written in the late 1990s, it does not
possess the sophistication of later Java technologies such as Hibernate or other ORM
frameworks. As we can see now, this AD framework is good enough to work on and
improve on.
The way the X_*.classes are pre-generated rather than resolved dynamically may give it
some speed over a dynamic GenericPO approach. You can refer the
GenerateModel.class to see how it is done where the AD table model will have its field
metadata resolved as final setter and getter methods. This GenerateModel.class is
manually run once everytime when deployment from source is needed. But lately it has
been deprecated by dynamic implementation of the set/get calls! So we can say that the
AD is pretty much separated from the developer’s plate. You can now focus more on
business logic development rather than any boiler plate toilings.
There is a deeper raw expose of such technicals compiled by Mario Calderon, from El
Salvador, also an ex-SAP expert with 30 years in Germany after researching it up
directly from Victor Perez[7]. The following is adapted from my wiki article on
Application Dictionary at www.adempiere.com.
Figure 4.6 above gives a visual graph to illustrate the relationship between the
various AD entities and types behind the Menu engine.
Conclusion
• ERP is complex and an ERP Software Application can be even more complex. The role of the AD is
very vital and ingenious in dealing away with as much complexity of the software components as
possible to leave the users a structured modular understanding of the application.
Entity Types
The entity type determines the ownership of Application Dictionary entries. The types "Dictionary"
and "Adempiere" should not be used as they are maintained by ADempiere – this is regarded as the
official ADempiere dictionary.
Last addition in Adempiere (3.3.1) is to define a model package to look for model classes based on
entity types (i.e. Look in org.eevolution.model instead of org.compiere.model)
Element
This is the central repository for field names, description and help/comments. As well as translations.
Define the names, label, description, help for sales and purchase contexts.
• Centralized terminology – if you need an exception disable “centrally maintained” in
field( windows Tabs & Field).
Tables
• Case sensitive
• If the table has an ID it must be exact case with the table name (i.e. CUST_MyTable – the column id
must be named exactly CUST_MyTable_ID)
• View – to define the table definition as view, views are not synchronized in database. You can use it
also to make a table read-only
• Data Access Level – Used for defining the default access for roles
• Maintain Change Log – when selected all changes to this table are logged in AD_ChangeLog table –
it doesn't matter if the role is logged or not
• Window – define the window to enable zoom functionality. Also you can define a different zoom
window for purchase process (PO Window).
• Records deleteable – to allow/disable deletion of records in database
• High Volume - indicates if a search screen will display as opposed to a pick list for selecting records
from this table.
• Create Columns from DB: If you make changes in database (ALTER TABLE ADD/MODIFY
columns) – you can get the changes with this process.
• Copy Columns From Table: This is the quickest process to create a table – you select a similar table
and this process will create all columns with exact columns (the ID will be renamed to match the
Columns
• System Element – the DB Column Name, Name, Description and translation will be inherited from
the element at saving time
• DB Column Name – the exact name of the column in the database
• Column SQL – for virtual columns. Virtual columns can show summary information, or
information from other tables without the need of adding a real column to the database. Is
constructed with a select joined with the main table.
• Reference: Data Type of the column- each reference correspond to a different behavior in GUI.
Please note carefully the difference between Table and Table Direct. Table Direct needs exact match
of the case for the table with the name of the column (excepting the suffix _ID)
• Please note also the difference between Table and Search
• For buttons you can define an associated process
• For Amount, Date, Integer, Number, Quantity you can define a range of min and max value
• Validation: Dynamic change for list and searches
• Reference Key: Static list for tables and lists
• Value Format: For strings you can define a format for the field. Adempiere formatting can enforce
the usage of space, any letter, uppercase, lowercase, letters & digits, only digits, etc. I.e. Formatting
phone numbers
• Default Logic: Context variables – SQL Statements. You can define several defaults separated by “;”
- the first one not-null will be the default
• Key Column: Just one per table (Primary Key – normally ID generated internally, not shown for
users)
• Parent Link Column – Define the child relation with one or more tables – there can be tables
without ID but with one or more parents (like Access tables)
• Mandatory
• Updateable
• Always updateable – make this field always updateable, even if is processed
• Encryption: just for strings – no reversal process – you can loose data, you need to ensure the width
of the column can hold all the current values.
• Read only logic – condition for making the record read-only (by default IsActive and Processed
columns mark the record as readonly without the need of defining the logic here)
• Mandatory logic – condition for making this field mandatory
• Identifier: one or more columns (normally value and/or name) to be shown in lists and for
dereferencing in reports. The identifiers are shown in the order defined in the field Sequence
• Callout – piece of code (customization) for filling other fields or simple validations (not
recommended for validations – you still need to validate on saving) – for string fields callout is
called in keystroke basis
• Selection column – define the column(s) to be shown in the default search window – by default
Value and Name columns are searchable
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 143
• Translated – to define translations for a column – in this case you need to define a table and a tab
with the same name as the original table and the suffix (_Trl), and create the table with the same
key as the parent, language column and the translated columns
Reference
The Reference Window defines field/display types and validations.
Supported Data Types:
Type
Description
Account
Account Element
Amount
Number with 4 decimals
Assignment
Resource Assignment
Binary
Binary Data
Button
Command Button - starts a process
Color
Color element
Costs+Prices
Costs + Prices (minimum currency precision, but if exists more)
Date
Date mm/dd/yyyy
Date+Time
Date with time
FileName
Local File
FilePath
Local File Path
ID
10 Digit Identifier
Image
Binary Image Data
Integer
10 Digit numeric
List
Reference List
Location (Address)
Location/Address
Locator (WH)
Warehouse Locator Data type
Memo
Large Text Editor - Character String up to 2000 characters
Number
Float Number
Printer Name
Product Attribute
Product Attribute
Quantity
Quantity data type
RowID
Row ID Data Type
Search
Search List
String
Character String
Table
Table List (Use Key and Display)
Table Direct
Direct Table Access
NOTE: Table name is taken from the column name except the _ID suffix – CASE SENSITIVE (Use Key
and Identifier)
As promised earlier, I will give some treatment on the effort done by a few of our core
committers such as Teo Sarca (Romania) and Victor Perez (Mexico) to remove SQL
queries from model classes and replace them with refactored query statements. First, we
take a peek at the big picture by showing what is before and after when using the new
query. Below is a diff patch to give a line by line change description:
+ * FR: [ 2214883 ] Remove SQL code and Replace for Query - red1
*/
public MCommissionLine[] getLines()
{
//[ 1867477 ]
-
String sql = "SELECT * FROM C_CommissionLine WHERE IsActive='Y' AND C_Commission_ID=?
ORDER BY Line";
-
ArrayList<MCommissionLine> list = new ArrayList<MCommissionLine>();
-
PreparedStatement pstmt = null;
-
try
-
{
-
pstmt = DB.prepareStatement(sql, get_TrxName());
-
pstmt.setInt(1, getC_Commission_ID());
-
ResultSet rs = pstmt.executeQuery();
-
while (rs.next())
-
list.add(new MCommissionLine(getCtx(), rs, get_TrxName()));
-
rs.close();
-
pstmt.close();
-
pstmt = null;
-
}
-
catch (Exception e)
-
{
-
log.log(Level.SEVERE, sql, e);
-
}
-
try
-
{
-
if (pstmt != null)
-
pstmt.close();
-
pstmt = null;
-
}
-
catch (Exception e)
-
{
-
pstmt = null;
-
}
-
+
//FR: [ 2214883 ] Remove SQL code and Replace for Query - red1
+
String whereClause = "IsActive='Y' AND C_Commission_ID=?";
+
List<MCommissionLine> list = new Query(getCtx(), MCommissionLine.Table_Name, whereClause,
get_TrxName())
+
.setParameters(new Object[]{getC_Commission_ID()})
+
.list();
//
Convert
MCommissionLine[] retValue = new MCommissionLine[list.size()];
list.toArray(retValue);
This refactoring separates the DB access handling from the business logic which is clear
from the above example. Model statements will then be cleaner and more readable as
well as easier to debug and isolate according to type of errors.
Figure 4.7 Query refactoring separates the Model from the Data layer
There are probably many hundreds of such cases all over the application. You can find
that out by doing a search for a sample SQL statement or DB behaviour such as
“DB.prepareStatement” to sniff out their existence. Their replacement in the project
trunk is now underway but due to its high occurence they are done carefully and with
JUnit testings to ensure no mistake or bug creep into the new query replacements.
Once a complete replacement is achieved, the sourcecode will have taken one giant step
forward towards better maintenance and portability. Below we display the new Query
implementation of the above example. You can see that the SQL call is refactored here
under the BuildSQL method.
You can see at the last line above, I have done my very small part in making the code
more debuggable by intoducing a logger prompt to display the table and its fully
qualified SQL statement. This line will only be seen when the debug logger is set to
finest in the Preferences Window.
You can learn up all the new Query implementation methods for all SQL cases such as
FirstOnly(), First(), and setParameters() by looking through http://
www.adempiere.com/index.php/ADempiere_Best_Practices and going to the sub-topic
#How_to_use_Adempiere_Query_class.
2. ADempiere as inherited from Compiere is on Java and uses certain common patterns.
3. ADempiere project sourcecode is always open and available for checkout into a local
IDE such as Eclipse.
5. The Persistence Object is extended by the X_classes which in turn are extended by the
Model classes that handle higher level model and business logic.
6. Query class helps to refactor away SQL scripting from the model classes into a single
place within it.
Glossary
Term Description
Business The ability to analyse data and present in high level but statistical
Intelligence formats usually done with software tools.
SourceForge.net The most popular and largest repository for Open Source projects
to house and operate from.
2. http://stackoverflow.com/questions/631003/microsoft-vs-java-career
3. http://www.jelovic.com/articles/java_good_bad.htm
4. http://www.idiom.com/~zilla/Computer/javaCbenchmark.html
5. http://discuss.joelonsoftware.com/default.asp?joel.3.312232.47
6. http://www.ohloh.net/p/adempiere/analyses/latest
7. h t t p : / / d o w n l o a d s . s o u rc e f o rg e . n e t / a d e m p i e re / D e v e l o p e r G u i d e . p d f ?
use_mirror=osdn
Learning Objectives
By the end of this chapter, the student shall be able to:
Software programming is still an archaic activity, not unlike a row of ladies in a loom
factory stitching a large piece of garment with their bare hands albeit skillful fingers. A
Java developer today still combs through lines of codes, albeit with a great visual tool
such as Eclipse or Netbeans. It is for all intents and purposes a highly manual vocation.
In fact, the garment industry has progressed to full automation where manual labour is
almost gone, but the software industry still need human eyes and brains to literally do it
in manual stitches. No machine can do the work of a software developer as a robotic
Toyota factory can in making cars.
The ADempiere project has brought together some of the marvelous brains from around
the globe in trying out some ideas of resolving the software crisis in ERP application
making. Many of the ideas are grounded on one single concern - to cater to a worldwide
audience, and so not to make the application core specific to any particular locale or
country but alienating another general or specific usage. We learnt how to modify core
without touching it, such as using the ModelValidator to extend it, or 2Pack to house
package metadata instead of binary code patches. We learn also the best way to make
releases without getting creeping bugs. We are using the most open powerful test
engines such as Fitnesse and Hudson. We also looked at good ways to distribute the
application ranging from branch distros to virtual machines.
Perhaps the most important contribution from the ERP software community built
around this project is the tons of documentation in wiki and other formats such as flash
movies, demos and individual blogs. Previously it was a mystical science to think about
learning ERP application development. Today it is a matter of googling for it online.
Extension Tools
We shall go through them in detail. But first, we divide the above into two broad
categories:
1. Micro tools
a. Callouts
b. Customization.jar
c. Model Validators
d. Java Triggers
Import File Loader is more of a migration tool, to bring in model data from a legacy or
3rd party system. There are 2 advanced tools created by the community, the Migration
Log mechanism and the 2Pack that basically record changes done in one ADempiere
instance for transfer to another more effortlessly. Though they are not strictly tools used
for extending, they are important in the maintenance of any extension work.
2Pack and Log Migration Script mostly concern changes in the Application Dictionary.
In the AD is where most configuration changes to the application occurs. You must have
noted in previous modules or lessons that changing ADempiere requires two areas of
focus: Change in code and change in the AD. As the AD is just meta-data, their change
will result in SQL or XML scripts. The former is when you are using Log Migration
Script and the later is when you are using 2Pack. More about these tools later.
DB Field
EXTENDING
> other columns
> other fields
Callout > other Tabs
> other Tables
> other Windows
> apply logic
How It Works
A Callout is a java method which gets executed when the field in an ADempiere window tab
gets focus and onChange activity. A Callout class (extending CalloutEngine) will group such
methods into a single file, usually under a document name i.e. CalloutOrder.java. A Callout is
defined in the Table & Column window, under a column tab, where you may specify a list of
fully qualified methods (separated by ";"). Below we shall create a test case and place it in a
customization jar just to learn another point in our development, which is not touching your
present main sourcecode too much.
Tips
You can have callout functions with 5 parameters (like in the example above) or 6 parameters.
The last parameter is the old value.
I have made a listing of all the Callouts in ADempiere for easy online reference. You can click on
each Callout in the table to lead to the actual Callout coding. (http://www.adempiere.com/
index.php/Callout_Code)
• This Callout can also be called from the Report & Process Window. Just remember to set in the
Rule window from which Event Type are you calling this Rule Script.
Scripting Languages
1. Now standard Adempiere has uploaded jars to work with groovy, jython and beanshell
2. to call a script from a Callout follow these sample syntax:
a. @script:beanshell:ValidateQtyOnHand
b. @script:groovy:ValidateQtyOnHand
c. @script:jython:ValidateQtyOnHand
3. When you create the rule, you have to set in the Search Key such as:
4. Search Key : beanshell:ValidateQtyOnHand
5. Search Key : groovy:ValidateQtyOnHand
a. Search Key : jython:ValidateQtyOnHand
6. Set the Event Type as Callout and Rule Type as JSR 223 Scripting APIs
/* Delete */
String sql = "DELETE FROM " + tableName + " WHERE AD_Client_ID=" +
A_AD_Client_ID;
int no = DB.executeUpdate(sql, A_TrxName);
A_ProcessInfo.addLog (0, null, null, "Deleted "+no+" rows from table "+tableName);
result = "OK";
IMPORTANT: Please take account if your change is fixing a bug, or a contribution worthy to be
integrated in trunk (or patches_321), if this is the case please refer to Adempiere forums in
sourceforge to discuss the specific case for nomination and acceptance via favourable voting.
With this precedence you must take account that you can have problems if your project has a
customized class that is released in the patches project - you must review and apply the changes
to your customized class.
Also note that the content of patches.jar and customization.jar is inserted into Adempiere.jar.
Therefore, if playing around with different versions on your own patches.jar, be aware that
classes you altered with the patch are not automatically changed back to normal after you
installed a new patch without the changed class files.
You can also use arguments to extend the memory assigned for Adempiere, i.e.:
-Xms32m -Xmx512m
With uncommenting one of these lines you'll enable the debugging. The lower (or last) line here
is the option for shared memory debugging which you can use for debugging at the server
itself. The upper line have to be uncommented for external debugging means via network
connection. As you can see the transport type is set to socket and what is named "address" is the
port to be used on this machine.
Be aware that if your server has a firewall installed (should have be so!!!) you'll have to open
this particular port for using it!!
But you can use any other port too - as long as it's not beeing used by another service or
program.
After successfull changing one of these lines you'll have to restart the adempiere process. For
debugging it's recommended to use [Adempiere Home]/utils/RUN_Server2.sh (or .BAT) in
"normal" mode (without sending it to backgroud by " &") so you have better control about
Debugging session
The first thing you can examine is that the stopped session at the server now start and go ahead
to normal operation, last entry is the startup time. At this point you can connect to Adempiere
with a normal client - or to make it difficult using another debugging session with a client from
another desktop session or computer. You can go ahead with normal operations or testing your
applications up to the point where your break points become effective. A typical example for
server operation is the posting of a delivery note or an invoice.
When the debugger stops it will show contents of source code with the maker set to the
corresponding line. Now you can examine the value of variables and resume operations step by
step (F5), line by line (F6) or go ahead to next break point or resume operations (F8).
Document events
Document events occur on the change of the document status. So you have
BEFORE/AFTER CLOSE/REACTIVATE/ REVERSECORRECT/ REVERSEACCRUAL/
COMPLETE/PREPARE/ VOID/ POST
Login Event
It's called when a user log into Adempiere - you can log or restrict users to log in according to
business rules.
FactsValidate Event
It's called when posting a document (accounting). You can change the facts being posted
(similar to calling BEFORE_POST document event.
LoadPreferences Event
It's called after the adempiere preferences are loaded - useful to add context variables or things
after log in.
SaveProperties Event
It's called when a user is saving properties - useful to restrict changes on properties file (Tools ->
Preferences).
/**
*
Get Client to be monitored
*
@return AD_Client_ID client
*/
public int getAD_Client_ID()
{
return m_AD_Client_ID;
}
//
getAD_Client_ID
• Put your code into modelChange() for model change events and into docValidate() for
document events.
• You have to check the parameters po for the table name (po.get_TableName() - if you
registered more than one table/document) and timing/type to react on the right
events.
2. Register your validator in ADempiere. Login as System Administrator and open the
'Client' window. Here you have to enter you validator class (full qualified name) into
the ModelValidationClasses field.
3. Create a jar file with your validator class and rename it to customization.jar. Copy this
customization.jar into the Adempiere/lib folder of your ADempiere installation and
rerun the RUN_setup.bat/sh. Restart the ADempiere server and install the new client
(or restart the client with Java WebStart).
5.7 2Pack
2Pack is the creation of Robert Klein[2] based on the XML2AD work of Marco Lombardo
in which was also improved by Trifon Trifonov with his AD2XML. Carlos Ruiz and
Trifon then housed the improvements in a separate project ComXe. During pre-2Pack
days, I have written about its progress in the XML2AD Tutorial.
2Pack is now migrated into ADempiere. Carlos Ruiz has finished that as to the latest
version and it has been used by several individuals to do Colombian and German
Some Future
I was trying to look at using 2Pack for replication purposes between ADempiere
instances. Initial challenge is to overcome Foreign Key IDs and Unique ID constraints in
Search Value fields. Below I relate my attempt so that newbies can follow a glimpse of
2Pack engineering. The good news is that someone better like Low Heng Sin has better
ideas on resolving it but it is not shown here. You have to search it in the tracker logs.
Some Present
I was proposing an approach to resolve the Foreign Key issue during runtime by
transposing the SearchKeyValue with the given FK_ID. During PackOut we implement
a ReturnValueFromID to store the SearchKeyValue instead of the FK_ID which is not
guaranteed in target Database. During PackIn we implement a ReturnIDFromValue to
replace the SearchKeyValue with the resident FK_ID in the target Database.
This is assuming that the SearchKeyValue is unique. However a failure of this will not
be fatal. Just some inaccuracy in data that can be easily checked after migration of the
tables.
The FK table has to be present first in the target DB. If new records then they have to
migrated over also. This approach is now not sound as not all data tables have
SearchValue fields.
Carlos Ruiz has replied to me in the wiki talk page that he has solved it for PackIn. Its
merely PackOut that needs to create the ValueFromID 'lookupname'. We can try
implement only in tables that have the Value field.
One way is as shown by Carlos Ruiz where FK IDs are replaced with LookUpNames.
* Note that here we even do lookup for SalesRep and C_Order_ID as DocumentNo.
* The test done is basically the transfer of a single Sales Order from one instance to
another instance that has already an extra SO so to prove that the difference in IDs
doesn't break the FK relations integrity.
34 <data clientname="GardenWorld">
35 <dtable name="C_Tax">
36 <drow key1name="" lookupkey1name="" name="ICA 4,14 * 1000" key2name=""
lookupkey2name="">
37 <dcolumn name="AD_Org_ID" class="Table Direct" value="0"/>
38 <dcolumn name="IsActive" class="Yes-No" value="Y"/>
39 <dcolumn name="Name" class="String" value="ICA 4,14 * 1000"/>
40 <dcolumn name="Description" class="String" value="null"/>
41 <dcolumn name="Parent_Tax_ID" class="Table" value="null"/>
42 <dcolumn name="C_Country_ID" class="Table" value="156"/>
43 <dcolumn name="C_Region_ID" class="Table" value="null"/>
44 <dcolumn name="To_Country_ID" class="Table" value="156"/>
45 <dcolumn name="To_Region_ID" class="Table" value="null"/>
46 </drow>
47 </dtable>
48 </data>
This is like the previous example I pasted above where the LookUpKey1Name values are implemented.
This is the resolve the FK issue which are local serial unique integers that may conflict as different
instances are merged.
Creation directory is path to the disk space You want package to be exported to.
Select Tab "Package Details" and fill required fields as on picture:
Previously we would use the 2Pack to export those changes and reimport them back.
2Pack allows better multi-package management, whereas Log Migration Script is used
at a single stage and then the scripts have to be serialised manually. Usually those
scripts are put in the migration folder of the trunk for others to download from and
apply to their instances so as to be up-to-date of the latest changes introduced by any
committer. As such, the changes it logs are meant to be version updates and not private
changes which is better taken care by the 2Pack. Migration scripts are noted
prominently and regarded as the latest version stage when there is a cut-off for the next
release.
Figure 5.11 Preference Window Log Migration Script Checkbox
Development
When you're ready to
develop a trunk
enhancement, bug or
feature request that
requires migration scripts,
you need to open a session
and check the flag "Log
Migration Script" in
Preferences window. Please
note this parameter is not
saved between sessions - so
you need to check it any
time you are going to
develop something new for
the trunk:
This can be combined with
"Dictionary Maintenance"
to generate official
migration scripts, or used
alone to generate
customization migration
scripts.
After this you just continue
creating the needed
C:\Users\Carlos\AppData\Local\Temp\migration_script_postgresql.sql
C:\Users\Carlos\AppData\Local\Temp\migration_script_oracle.sql
in Windows XP
H:\Documents and Settings\user\Local Settings\Temp\migration_script_postgresql.sql
H:\Documents and Settings\user\Local Settings\Temp\migration_script_oracle.sql
IMPORTANT NOTE: POSSIBLE PROBLEM: Even failed SQL statements are being logged.
Developer must review carefully the generated migration script for possible problems before committing.
SELECT
UPDATE AD_PROCESS SET STATISTIC_COUNT=
This feature is part of the Migration Feature in ADempiere to allow complete facilitation
of distributing changes from one user to another easily and efficiently.
Actually, the migration scripts have a small header, that just explains why they were
made, and who created it. Usually, it has this info as SQL comments in the SQL header.
You open up your database manager, and then just apply the migration scripts.
What changes
* The new process here proposed has some differences from the actual process.
* To apply a migration script, you'll do it directly from Adempiere client, using the
System role to fulfill this activity.
o First, all the new migration scripts will have a new file skeleton, that will be like:
File Sample
--BEGINHEADER--
--ENDHEADER--
--BEGINMS--
INSERT INTO test(test_id, ad_client_id, ad_org_id, isactive, created, createdby, updated, updatedby,
name, description, help, t_integer, t_number, t_date, t_datetime, c_uom_id, t_qty, c_currency_id,
t_amount, c_location_id, account_acct, c_payment_id, m_product_id, c_bpartner_id, m_locator_id,
processing, binarydata, processed, characterdata)
VALUES(106, 0, 0, 'Y', '2003-11-26 00:32:53.0', 100, '2000-01-01 00:00:00.0', 0, 'Doh', 'Test record
description', 'Test Comment', 10000002, 10000002, NULL, NULL, 100, 10000002, 195, 10000002, NULL,
INSERT INTO test(test_id, ad_client_id, ad_org_id, isactive, created, createdby, updated, updatedby,
name, description, help, t_integer, t_number, t_date, t_datetime, c_uom_id, t_qty, c_currency_id,
t_amount, c_location_id, account_acct, c_payment_id, m_product_id, c_bpartner_id, m_locator_id,
processing, binarydata, processed, characterdata)
VALUES(107, 0, 0, 'Y', '2003-11-26 00:32:53.0', 100, '2000-01-01 00:00:00.0', 0, 'Doh', 'Test record
description', 'Test Comment', 10000002, 10000002, NULL, NULL, 100, 10000002, 195, 10000002, NULL,
NULL, NULL, NULL, NULL, NULL, 'N', NULL, 'N', '<html></html>');
--ENDMS--
Note that this new file has some new elements that we didn't use with the old approach.
Applying to Database
* Now that we have a new migration script, let's apply it against our database.
* To do that, we have to open Adempiere with the System Role, and then go into the
Application Dictionary folder.
* After it's done, it will show you either a sucess message or error message, containing
the scripts that couldn't be applied.
This feature is used together with the above Log Migration Script. When multiple
developers make changes to the same core Application Dictionary, their useage of
primary key IDs of the system tables and fields has to be synchronised to avoid
redundant occurance and conflicts. This is now solved by having a central server that
keeps track and count of the IDs for each category of AD Model. Each registered
committer will setup their system to access that server to reserve their IDs to assign to
their new table and fields. This again is a contribution by Carlos Ruiz.
DICTIONARY_ID_USER =
Your committer sourceforge ID
and
DICTIONARY_ID_PASSWORD =
Your committer assigned password
Development
Firstly, please configure the comment in the System Configurator window related to the
enhancement, bug or feature request you're solving, example:
When you're ready to develop a trunk enhancement, bug or feature request that
requires official dictionary ID's, you need to open a system session and check the flag
"Dictionary Maintenance" in Preferences window. Please note this parameter is not
saved between sessions - so you need to check it any time you are going to develop
something new for the trunk:
After this you just continue creating the needed dictionary objects and Adempiere will
assign the ID's from the centralized website developer.adempiere.com
The Log
If you want to review the log of used ID's for a table, you can navigate to the site:
http://developer.adempiere.com/cgi-bin/showlog?AD_Reference
Please replace the AD_Reference name with the table you want to see.
If you conduct your own project with distributed developers - with distributed
development databases, then you have the same problem as ADempiere Committers to
synchronize the dictionary ID's.
http://adempiere.svn.sourceforge.net/viewvc/adempiere/contributions/stuff/
POC_Central_System_IDs/linux/
Set up a data directory ../data relative to cgi-bin directory for your project:
http://adempiere.svn.sourceforge.net/viewvc/adempiere/contributions/stuff/
POC_Central_System_IDs/linux/data/Adempiere/
PROJECT_ID_USE_CENTRALIZED_ID = Y (default is N)
This will assign centralized ID's for all tables that have EntityType column, in the seed
those are:
1. I will need to migrate some internal modifications to trunk, more exactly some
columns that have internal allocated IDs (> 1000000). What is the best way to get IDs
from IDs server without creating the columns (because i already have them, i just
need to change the IDs) ?
http://developer.adempiere.com/cgi-bin/get_ID?PROJECT= Adempiere&USER=
your_user&PASSWORD =your_password&TABLE =AD_Column&ALTKEY =
&COMMENT = Comment
Dissected :-)
http://developer.adempiere.com/
The website providing the ID's where cgi shells are installed
cgi-bin/get_ID
?PROJECT=Adempiere
The project Adempiere (centralized ID can be used to manage IDs for other
projects but it needs some setup)
&USER=your_user
&PASSWORD=your_password
&TABLE=AD_Column
The table you want to reserve ID (in this example AD_Column - case sensitive!)
&ALTKEY=
Unused at this moment, to save alternate key for tables like Value
Copyright (C) 2009 Redhuan D. Oon
ERP Software Engineering
P a g e 192
&COMMENT=Comment -- the comments on the reservation
Revision
Here are revision and sound expert advice taken from Carlos Ruiz’s wikiversity
article[1].
Extension architecture
* Callouts
* Model Validator
* Java Triggers
* Processes
* Views and Reports
* Forms
* Print Formats
* Import File Loader
Common code
Context variables
Context variables are like 'global' variables for the whole Adempiere, or for a specific window or tab.
You can see all context variables in Tools -> Preference -> Context
Every field in a window has his own context variable, you can access it programatically.
You can get or create objects from the database using the model classes, for example to read an
invoice from the database:
This is equivalent to issue a 'SELECT * FROM C_Invoice' and load in memory the data.
To create a new record in the database you call the same code with zero as the ID:
You then can make changes to columns using the setter methods of the object, i.e.:
inv.setC_Currency_ID(100);
After you make all the changes you save the record in the database calling the method save():
inv.save();
The method save will execute an INSERT if is a new record or an UPDATE if the record already
exists. If you want to delete an existing record, you can call the method delete(), i.e.
inv.delete(true);
and after deleting you need to call the method save to execute the corresponding DELETE in the
database
To show messages within your programs, please use the i18n facility of Adempiere using the message
table for this purpose, programatically you simply execute, i.e.:
SQL
• Usage of embedded SQL – recommended to use UpperCase in SQL Keywords (for security sql
parser)
• Specially this keywords: SELECT, FROM, WHERE, ON, AS, INNER, JOIN, LEFT, OUTER, FULL
• If you want to issue a simple query returning just one column of the first record, you can use the
DB.getSQLValue functions provided by Adempiere:
• String sql = "SELECT COUNT(*) FROM C_Recurring_Run WHERE C_Recurring_ID=?";
• int current = DB.getSQLValue(get_TrxName(), sql, getC_Recurring_ID());
• To execute a DML operation in the database (INSERT, DELETE or UPDATE) you can use the
DB.executeUpdate method, i.e.:
• String sql = "UPDATE C_CashLine SET Processed='N' WHERE C_Cash_ID=" +
getC_Cash_ID();
• int noLine = DB.executeUpdate (sql, get_TrxName());
• To read several records from the database (cursor) you can execute
String sql = "SELECT C_PaymentAllocate_ID FROM C_PaymentAllocate WHERE
C_Payment_ID = ?";
PreparedStatement pstmt = null;
pstmt = DB.prepareStatement(sql, get_TrxName());
pstmt.setInt(1, payment_ID);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
payment_allocate_ID = rs.getInt(1);
/// ... more code
}
rs.close();
pstmt.close();
Callouts
1. Called after user entered value (for Strings is called every keystroke)
2. It can be used for direct data validation – but you need to validate again before saving
3. Better usage for data consequences: i.e. Filling other fields with lookup values, calculating totals
You must repeat all calculations in persistence layer
4. You can have multiple callouts separated by ;
7. There are also callouts for translation of strings on Import File Loader, these callouts have just one
parameter:
* The value
* 'Returns' the translated value
Exercise: Create a Callout on the Name of Product Category – the name must be passed to the
Description in upper case
• If can't find persistence class then it uses PO to save directly to the database.
• In Adempiere there is a GenericPO that can be used for programatically save tables with no model
class.
• X_ classes are generated automatically – don't change them
Usage of GenerateModel:
arguments:
* Output Directory - C:\srcAdempiere\trunk\base\src\org\compiere\model\
* Package - org.compiere.model
* EntityType - 'D'
* Optional table like - 'U_RoleMenu'
Model validator
Defined at client level
You can have multiple model validators separated by ;
Events:
* User Login – you know the user, role, client and organization – i.e. Useful for veto login
Events on table:
• BEFORE/AFTER
• NEW/ CHANGE/ DELETE
Events on documents:
• BEFORE/AFTER
Exercises:
• Create a ModelValidator that avoid users login twice in Adempiere
• Create a ModelValidator when Order change the business partner – add the previous bp to the
description
• Create a ModelValidator to forbid GardenAdmin to complete an Invoice
• Create a ModelValidator to avoid completely posting from invoices
Processes
• Called from menu or buttons
• prepare method for getting the parameters into variables – Record_ID just work for buttons
• doIt method for execution of the process
• addLog to keep log of the executions / for auditing purposes and showed at the end of the process
• return a message
• for errors must throw exceptions
Forms
Custom swing windows – special cases
Not recommended – not supported for webUI clients
* Extend org.compiere.swing.CPanel
* Swing code – implement listeners
* Use javax.swing and org.compiere.swing components
Exercise:
* Add POReference column to the I_Invoice stage table
* Change the ImportInvoice process to manage the import of this new column
2. When should certain code be part of the core and when should it not be?
Glossary
Term Description
Migration Script SQL scripts that record model changes in the database in between
version releases.
Meta-data Data about data, usually mean configuration details and is stored
as data rather than hard-coded
Patches.jar A jar to add to the application that will override particular core java
classes. It allows easier management of changes without
changing core directly.
5. There are many ways to extend the ERP application but they adhere to strict
discipline to avoid corrupting or breaking its horizontal core structure to be
compatible with the world’s very diverse localisation needs.
6. Localisation needs can be customised into its own jar to override core functions.
7. Model Validators group core changes to the documents’ models in a guarded manner
without impact to other users not needing such changes.
8. Callout is either in its own class or using metadata injection via JSR223 capability.
9. More scripting type metadata rules can be used in the Report and Processes feature.
10. 2Pack allows managing of changes in the form of packages that are transferable to
any other instance.
11. Log migration script is a feature to automatically generate SQL scripts for
application in any other instance that wishes to upgrade accordingly.
12. Centralized ID management is to avoid conflict of IDs when introducing new tables
or columns by other developers in the AD portion of the application.
2. http://www.oslabs.org/index.php?
option=com_remository&Itemid=29&func=select&id=4
3. http://adempiere.svn.sourceforge.net/viewvc/adempiere/contributions/
Localizations/Colombia/packages/LCO_RetencionesBaseData/dict/PackOut.xml?
view=markup
Learning Objectives
By the end of this chapter, the student shall be able to:
This is a sound principle of ‘getting things right the first time’ to avoid the higher cost of
maintaining poorly done code seeping into the whole application. As elaborated before,
a great part that goes towards good coding, is good coding practice and the reusing of
commonly accepted patterns. The ADempiere Best Practice wiki page[1] is vital to act as
a guide for all our developers to follow and learn from. It is a living dynamic document
where as more newer technology in testing emerges to simplify and hasten the tedious
boring testing process, any developer familiarizes with it and introduces it to the
community there. The Compiere sourcecode we inherited from are very well structured
and documented within the java classes. Most of our Java developers could follow and
understand the original intent and content before improving or maintaining them.
At the moment JUnit test classes are included in the project trunk for any developer to
reuse for their QA needs. There is a Hudson compiling testing server contributed and
maintained by Metas GmBH of Bonn, Germany that continously test compile each code
commit sent to the trunk.
However the use of tools is not a fool-proof testing environment. The more important
testing is still conventional practice of asking another user to test a particular change.
Finally when sourcecode is released daily to the open, the open global community of
users that constantly download, install and try out the applicaiton is our best testing
engine. They are an army that never sleeps that constantly provide bug reports and
feedback at every code commit to ensure bug creep is arrested early on. Not only that,
performance issues are included indirectly whenever a feedback points to any hiccup or
telltale signs coming from the many diverse users’ environments.
The Fitnesse Project was first started in February 2009, by Joel Stangeland with Carlos
Ruiz and Joel has documented the progress in the ADempiere wiki[3].
During my visit to Bonn, Mark Ostermann, the CTO of Metas demonstrated to me how
versatile and powerful such test engines are in handling many instances of client
projects individually, to indicate what happened each time a new code commit takes
place. The screen will show graphically and color coded how each instance and module
is impacted in terms of individual code execution performance. The great thing is that
the testing software is open source and free-licensed.
To execute the JUnit, you can simply right click on the test java and select Run As, JUnit
Test.
You have to create each individual test class for each java code you are releasing. Eclipse
is equipped to automaticall help you generate new JUnit classes. But since there are
already numerous samples and test classes done by the ommunity in the trunk, you can
pick out a good example and reuse from there. They are located under the Extend folder
of the trunk.
Each test class has to extend AdempiereTestCase which extends TestCase. The parent
class will resolve the ADempiere context and environment such as its database access
properties for any test to process through and work with the database model.
The above test FunctionalBPartnerTest ran successfully so that it gives a green coloured
banner on the top left panel with 0 errors or failures. It also gives the time clocked
during the test.
Glossary
Term Description
Hudson Server A build server that continously test committed code in the trunk to
ensure they are without syntax and reference errors.
Best Practice An agreed path or conduct to follow by most members due to its
consistent successful or clear guidelines.
Fatal Bug Bug that will corrupt important data and failed the smooth running
of the system. Or return results that are not desired.
Intermittent Bugs Bugs that are not repeatable easily and occur only under different
conditions or operating environment. A bug should be repeatable
under specified conditions to be termed a bug.
2. Many of the testing tools are from open source such as Finnesse and Hudson.
3. JUnit is already incorporated into Eclipse and there are test classes contributed for
reusing during class testing.
2. http://www.adempiere.com/index.php/Fitnesse_use_in_adempiere
3. http://www.adempiere.com/index.php/TestFramework