Table of Contents
Refer back to for the most recent version of this document.
The PDF version of this document is downloadable here.
HTML Version: Always click REFRESH on your browser to make sure you're reading the most recent version.
The most recent version of this document may be obtained at http://www.knowledgesuccess.com
The information contained in this documentation is based on personal observation only and no authority at all. No warranty as to its correctness is implied.
This document is pragmatic and honest and contains the opinions of only myself.
We (of short memory) often find ourselves looking up the same information again and again. Sometimes this information is stored in different places. The aim of this document is to consolidate everything into one place and perhaps help someone else who is looking for the same information. Also to help novices to intermediate programmers avoid pitfalls we fell into.
We will build this document as we go.... so in the beginning it will be short and will grow....
This document is intended for people who wish to customize compiere - add functionality , extensions, use compiere as a base (e.g. screens)
Please inform us of errors in this document.
2006-03-16 - AD_COLUMN_COPY
Switch company
2006-03-16 14h20 Added some blurb
2006-03-16 15h08 Making a living out of compiere and open source
2006-03-18 13h15 Removed some blurb.
2006-04-26 00h42 Added chapter on doing a standard compiere installation.
2006-05-17 23h37 Various updates
2006-05-18 20h49 Conclusion for the knowledgebook excercise
2006-05-20 14h35 Starting oracle as a service
Screenshots
Screenshots are good practice they help journal your work and retain settings for later. In fedora linux I use ksnapshot. In windows you can use PRINTSCREEN (whole screen) or ALT-PRINTSCREEN (just active window) then the paste buffer can be pasted into (for example) microsoft word.
Examples are based on linux
Many of the examples are based on my linux system however with a bit of reworking they should also apply to win32 platforms. Many complexities arise when using linux and they are highlighted here. You will probably run into slightly different problems in windows. If you email them to me I will include them in this doc.
Todo: Put this section somewhere else...
Compiere is one fantastic package. The only way to truly appreciate it is to put it into production. Use it actively. (This is especially true for consultants). Then some of the apparent weaknesses and quirks turn into strengths.
Compiere is difficult to setup and involves lots of command lines and research
Compiere does not have a good report writer and it is hard to produce good looking reports. (See note above: once you start using it you will get to enjoy it.)
Crystal reports (Business Objects) do not have a way to distribute reports and a whole industry is built up around this
Java does not have a nice easy way to produce GUI's like microsoft does (there are plenty of industries built up around this)
Java is a difficult beast and involves learning lots of technologies
Compiere is a damn nice package
Compiere is free
ln order to write a new report in compiere you will most likely need to setup a new table or view in compiere. (If you're using compiere for what it is meant for then this is unlikely to be an issue).
Compiere's strength is that it runs on oracle. Don't hold your breath for DB independence.
Modifying compiere could cost you more than you think unless you have the right people on your side.
Those of us new to java downloaded the source and modified the version we were working on. This turned out to be a mistake and for live projects caused delays of months in upgrading to new compiere versions. Some people are stuck forever on a specific Compiere version.
The solution was simple: reference the compiere jars as a completed product. When we needed to override (replace) functionality we simply created the same class with the same package name. Our project appears first in the classpath so overrides the functionality that compiere's jars provide.
This same principle should be applied to any active open source project.
We were tought to use for example an OrderManager or a BusinessLogicManager which contained all the functionality. This enables unit tests to be written and the business logic tested.
This is controversial but we believe in following the methodology of extreme programming. See http://www.extremeprogramming.org. This was after being involved in a project and losing a lot of sweat blood and tears which would have been avoided had we studied this methodology. Use test driven development as described on junit.org and in various books.
Test driven development means writing the test first before the code. It also implies that NO UNNECESSARY CODE is written. You write the test specifying the API as you would like to use it. Then you implement only those details necessary to allow the test to pass. You never predict what the customer might want in the future . You only implement what he wants now.
However this is an entire subject and beyond the scope of this document.
References
http://www.extremeprogramming.org
One day all programs will be written this way. Try it out....http://www.junit.org
Maybe new versions have fixed this but the data dictionary structure was limiting and encouraged de-normalized data. Duplication of data in different tables especially in big projects is a killer. Never duplicate data and take whatever steps necessary to avoid it.
Replication of data dictionary between live and production and development servers: We found ourselves making the same changes over and over again and ended up doing our development on the live server. This became painful.
No packaging facility - no way to deliver vertical add ons because of the data dictionary structure
Oracle itself - cumbersome as a dev environment... installing on linux is an excercise... vmware with oracle for windows is a real solution.
After running various scripts and receiving various errors and setting various environment variables we eventually get this cryptic screen.
Being technical people we seem to love technical and cryptic detail.
We really would be tempted to change the keystore password from the default. Then we would be the only ones to know the keystore password.
I wonder if we should bother with the Java VM?
Web port 80 might already be in use but compiere doesn't seem to mind. Same with the other values.
Why do we need a web port anyway? We're just trying to run Compiere.
Why do we need to bother with the mail server? and admin email? and database name? and database search? After trying various settings we eventually get all the tests to pass.
I suppose the database server is necessary but surely some of the other settings could be discovered.
I wonder why we need a system password and a database password?

How to discover the server name.In my case it was under f:\oracle\orahome1\network\admin\listener.ora .
The answer is erp.nglinux. The database search is erp. Both appear to feature in this file.

The following sequence starts up oracle in linuix
lsnrctl start LSNRCTL for Linux: Version 10.1.0.3.0 - Production on 17-MAY-2006 21:49:22 Copyright (c) 1991, 2004, Oracle. All rights reserved. Starting /u01/app/oracle/product/10.1.0/Db_1/bin/tnslsnr: please wait... TNSLSNR for Linux: Version 10.1.0.3.0 - Production System parameter file is /u01/app/oracle/product/10.1.0/Db_1/network/admin/listener.ora Log messages written to /u01/app/oracle/product/10.1.0/Db_1/network/log/listener.log Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC))) Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))) Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 10.1.0.3.0 - Production Start Date 17-MAY-2006 21:49:23 Uptime 0 days 0 hr. 0 min. 0 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/oracle/product/10.1.0/Db_1/network/admin/listener.ora Listener Log File /u01/app/oracle/product/10.1.0/Db_1/network/log/listener.log Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))) Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully [oracle@nglinux knowledgebook]$ sqlplus /nolog SQL*Plus: Release 10.1.0.3.0 - Production on Wed May 17 21:49:37 2006 Copyright (c) 1982, 2004, Oracle. All rights reserved. SQL> connect system/oracle as sysdba Connected to an idle instance. SQL> startup ORACLE instance started. Total System Global Area 276824064 bytes Fixed Size 778736 bytes Variable Size 99622416 bytes Database Buffers 176160768 bytes Redo Buffers 262144 bytes Database mounted. Database opened. SQL>
The following procedure we used in 2.5.1g to copy the AD structure from one table to another. Primitive but better than nothing. The table you are copying from (template) is hard coded in the script (the 346 below). Note: the create columns from db is much improved in recent versions (2.5.3+) so this script should no longer be required.
PROMPT CREATE OR REPLACE PROCEDURE compiere.ad_column_copy3
CREATE OR REPLACE PROCEDURE compiere."AD_COLUMN_COPY3"
(
p_Name in varchar2
)
/*************************************************************************
* The contents of this file are subject to the Compiere License. You may
* obtain a copy of the License at http://www.compiere.org/license.html
* Software is on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implived. See the License for details. Code: Compiere ERP+CRM
* Copyright (C) 1999-2001 Jorg Janke, ComPiere, Inc. All Rights Reserved.
*************************************************************************
* $Id$
***
* Title: Copy One Tab content (i.e. Fields) to another
* Description:
************************************************************************/
AS
-- Logistice
v_ResultStr VARCHAR2(2000);
v_Message VARCHAR2(2000);
v_Record_ID NUMBER;
-- Parameter Variables
v_AD_Tab_ID NUMBER;
v_NoOfFields NUMBER := 0;
v_NextNo NUMBER;
v_EntityType CHAR(1);
-- Copy
CURSOR Cur_Fields IS
SELECT
AD_CLIENT_ID,
AD_ORG_ID,
ISACTIVE,
CREATED,
UPDATED,
CREATEDBY,
UPDATEDBY,
NAME,
DESCRIPTION,
HELP,
VERSION,
ENTITYTYPE,
COLUMNNAME,
AD_REFERENCE_ID,
AD_REFERENCE_VALUE_ID,
AD_VAL_RULE_ID,
FIELDLENGTH,
DEFAULTVALUE,
ISKEY,
ISPARENT,
ISMANDATORY,
ISUPDATEABLE,
READONLYLOGIC,
ISIDENTIFIER,
SEQNO,
ISTRANSLATED,
ISENCRYPTED,
CALLOUT,
VFORMAT,
VALUEMIN,
VALUEMAX,
ISSELECTIONCOLUMN,
AD_ELEMENT_ID,
AD_PROCESS_ID,
ISSYNCDATABASE
FROM AD_Column
WHERE AD_TABLE_ID =
346;
BEGIN
-- Update AD_PInstance
DBMS_OUTPUT.PUT_LINE('Process Started ' );
--select p_AD_Table_ID:=ad_table_id from ad_table where upper(name)=upper(p_Name);
-- Record_ID is the Tab_ID to copy to
v_ResultStr := 'Copying';
FOR f IN Cur_Fields LOOP
-- Get next no
AD_Sequence_Next('AD_Column', f.AD_Client_ID, v_NextNo);
INSERT INTO AD_Column
(AD_COLUMN_ID,
AD_CLIENT_ID,
AD_ORG_ID,
ISACTIVE,
CREATED,
UPDATED,
CREATEDBY,
UPDATEDBY,
NAME,
DESCRIPTION,
HELP,
VERSION,
ENTITYTYPE,
COLUMNNAME,
AD_REFERENCE_ID,
AD_REFERENCE_VALUE_ID,
AD_TABLE_ID,
AD_VAL_RULE_ID,
FIELDLENGTH,
DEFAULTVALUE,
ISKEY,
ISPARENT,
ISMANDATORY,
ISUPDATEABLE,
READONLYLOGIC,
ISIDENTIFIER,
SEQNO,
ISTRANSLATED,
ISENCRYPTED,
CALLOUT,
VFORMAT,
VALUEMIN,
VALUEMAX,
ISSELECTIONCOLUMN,
AD_ELEMENT_ID,
AD_PROCESS_ID,
ISSYNCDATABASE
)
VALUES
( v_NextNo,
f.AD_CLIENT_ID,
f.AD_ORG_ID,
f.ISACTIVE,
f.CREATED,
f.UPDATED,
f.CREATEDBY,
f.UPDATEDBY,
f.NAME,
f.DESCRIPTION,
f.HELP,
f.VERSION,
'U',
f.COLUMNNAME,
f.AD_REFERENCE_ID,
f.AD_REFERENCE_VALUE_ID,
(select ad_table_id from ad_table where upper(tablename) = upper(p_Name)),
f.AD_VAL_RULE_ID,
f.FIELDLENGTH,
f.DEFAULTVALUE,
f.ISKEY,
f.ISPARENT,
f.ISMANDATORY,
f.ISUPDATEABLE,
f.READONLYLOGIC,
f.ISIDENTIFIER,
f.SEQNO,
f.ISTRANSLATED,
f.ISENCRYPTED,
f.CALLOUT,
f.VFORMAT,
f.VALUEMIN,
f.VALUEMAX,
f.ISSELECTIONCOLUMN,
f.AD_ELEMENT_ID,
f.AD_PROCESS_ID,
f.ISSYNCDATABASE
);
v_NoOfFields := v_NoOfFields + 1;
END LOOP;
DELETE FROM AD_COLUMN
WHERE ad_table_id=
(select ad_table_id from ad_table where upper(tablename) = upper(p_Name))
and upper(COLUMNNAME) NOT IN ('CREATED', 'CREATEDBY', 'UPDATED', 'UPDATEDBY', 'ISACTIVE', 'AD_CLIENT_ID', 'AD_ORG_ID');
COMMIT;
RETURN;
END AD_Column_Copy3;
/
First thing to do before running this script is to create your new table in AD_Table. For me this was ZZ_RI_Settings

Now we run the following within pl/sql enabled tool such as datastudio:
begin
AD_COLUMN_COPY3('ZZ_RI_Settings');
end;This copies the common fields from another table.:

Now you should define the additional columns for the table if not defined already.
Version update: as at 2.5.3c, the 'Create columns from db' is greatly improved so the script above should not be required. In earlier versions the columns were created with the incorrect case and without the system element references. The new script also creates the system elements which is a great improvement.
You should use as a template script one of the tables which has already been created in compiere, e.g. AD_Column. This will ensure you get the constraints and keys as part of the table.
Once you've created the table you should complete the definition in compiere under the table window. Once this is done you must generate the model class for the table. This model class is used for accessing the data and for O/R mapping.
The easiest way to do so is using run configuration in eclipse as follows:

Under the 'arguments tab' set your appropriate arguments as follows

The first arguments above refer to where the model classes will be generated. You should create this folder in your project. Note the trailing '/'. The second argument is the package name used in the source header. The third argument refers to entity type - 'U' = 'User'
Program arguments (for easy copy/paste)
src/org/compiere/model/ org.compiere.model 'U'
VM Arguments
-Dlog4j.ignoreTCL=true -DPropertyFile=/home/oracle/Compiere.properties -DCOMPIERE_HOME=/home/oracle
When you run the GenerateModel you should get the following output:
*** 2006-05-11 23:07:32.13 Compiere Log (CLogConsole) ***
23:07:32.129 Compiere.startup: Compiere(r) Release 2.5.3c_2006-02-22 - Smart ERP & CRM - (c) 1999-2006 Compiere (r); Implementation: 2.5.3c 20060307-2201 - ComPiere Inc. (C) 1999-2006 Jorg Janke
23:07:32.131 Compiere.startup: /home/oracle - Java HotSpot(TM) Client VM 1.5.0_06-b05 - Linux 2.6.11-1.1369_FC4 unknown
23:07:48.127 Ini.loadProperties: /home/oracle/Compiere.properties #31
23:07:50.343 CLogMgt.setLevel: FINE
23:07:50.343 GenerateModel.main: Generate Model $Revision: 1.52 $
23:07:50.344 GenerateModel.main: ----------------------------------
23:07:50.344 GenerateModel.main: Directory: src/org/compiere/model/
23:07:50.344 GenerateModel.main: Package: org.compiere.model
23:07:50.344 GenerateModel.main: EntityType IN ('U')
23:07:50.345 GenerateModel.main: ----------------------------------
23:07:50.415 GenerateModel.writeToFile: /mnt/hda3/A/workspaces/dev/ReportIntegration/src/org/compiere/model/X_ZZ_RI_Settings.java - 3.5 kB
23:07:50.415 GenerateModel.main: Generated = 1
*** 2006-05-11 23:07:50.418 Compiere Log (CLogConsole) ***
You will notice a new class appears in the org/compiere/model folder. Note that this method becomes inefficient when you've got lots of 'USER' tables and using CVS you will need to modify the GenerateModel class.
NB: Remember to refresh your project after running this otherwise it will appear nothing has happened.
This should be covered in the framework guide since that is one of the goals of that project.
You should duplicate the behaviour of RUN_Compiere2.sh in an Eclipse launch profile. All environment variables and JRE parameters can be set from Eclipse.
You should be working in the 'Java Perspective' not the 'Resource Perspective'. Reading up on Eclipse is a must.
Here are screenshots showing examples. This topic will not be covered here in detail yet.
Important: If you're working with the framework (hsqldb) version refer to that guide on how to start compiere.
Main Tab


Copy and paste VM arguments from here
-Dlog4j.ignoreTCL=true -DPropertyFile=config/properties/oracle/Compiere.properties -DCOMPIERE_HOME=config/properties/oracle
This is one of the most important topics. Once you get this many things become clear in the world of java.
Here is the framework project's classpath. You can access it by right-clicking at the top of your project on the navigator or the package explorer and selecting properies.
You will see in this screenshot I've included two other projects in my workspace. The compiere253b source code and the hsqldb source code. I've only done this for debugging purposes so that my breakpoints land on valid code. When the source code is published these references must be removed.

To take a step backwards notice the 'Source' tab.

The source tab specifies which folders will be treated as source code and compiled. It is also removed from the package name so your class CompiereFramework_Dev/src/com/mycom/net/MyClass.java will require the package name com/mycom/net/MyClass.java. Make sure'Allow output folders for source folders' is unticked. If you don't then your classes get compiled in the same location as your source code.
The 'Libraries' tab is the place where you specify which 3rd party or external jars you will be using. However the order (precedence) is not specified here. It is specified in the Order and Export tab.
The next most important setting is the Order and Export tab shown below.

You will notice the compiere source code is referenced first after my project. This means that any source code in my project which has the same package and classname will override the source code in the reference project.
Now since I'm working with hsqldb a lot I need to see the source code. Notice I've pushed the hsqldb project just above the hsqldb.jar . Once again overriding takes place. Basically hsqldb.jar will be ignored but I've left in the list so that I don't forget about it when I remove the reference to compierereference253b.
This documents how to go about adding a patch to compier and at the same time adding useful functionality - the ability to switch companies (that is, login again without exiting compiere).
Here is how the final product looks.

We can use the classpath to override the Compiere classes and as mentioned before do not modify the reference code if working in a production proejct.
We need to identify which class is controlling the main menu. We run Compiere from Eclipse and watch the trace output carefully. Either we can do this or search for a keyword in the source code. Often watching the trace code is overlooked and is actually easier. You can save a great deal of time this way. Some people advocate not using debugging at all just tracing. However debugging is practical at times.
We see a little down in the trace code the following in the Console window.
[Server@1ef8cf3]: Startup sequence completed in 12559 ms.
[Server@1ef8cf3]: 2006-03-16 06:21:37.407 HSQLDB server 1.8.0 is online
[Server@1ef8cf3]: To close normally, connect and execute SHUTDOWN SQL
[Server@1ef8cf3]: From command line, use [Ctrl]+[C] to abort abruptly
06:21:37.639 AMenu.<init>: CodeBase=null
-----------> CConnection.queryAppsServerInfo: jnp://MyAppsServer:1099
- javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out]
- {java.naming.provider.url=jnp://MyAppsServer:1099, java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, jnp.discoveryTimeout=5000, jnp.timeout=5000, java.naming.factory.url.pkgs=org.jboss.naming.client, jnp.sotimeout=5000}
06:23:23.539 ALogin.connectionOK: [11]
06:23:23.564 Login.getRoles: User=SuperUser [11]
06:23:23.781 Login.getWarehouses: No Warehouses for Org: 0=* [11]
06:23:23.864 Msg.initMsg: Records=762 - en_US [11]
06:23:27.466 Login.getWarehouses: No Warehouses for Org: 0=* [11]
06:23:28.553 ALogin.defaultsOK: [11]
06:23:28.604 MyValidator.initialize: MClient[11-GardenWorld] [11]
06:23:28.608 Login.loadPreferences: Org: 0=* [11]
06:23:28.626 MRole.get: AD_Role_ID=0, AD_User_ID=100, reload=true [11]
06:23:28.799 MRole.get: MRole[0,System Administrator,UserLevel=S ,AD_Client_ID=0,AD_Org_ID=0] [11]
06:23:28.811 Login.loadPreferences: Default Values ... [11]
06:23:40.493 DB.isDatabaseOK: DB_Version=2006-01-20
06:23:41.772 WFPanel.<init>: RW=false
06:23:42.480 MTree.<init>: AD_Tree_ID=10, AD_User_ID=100, Editable=false, OnClient=trueA good guess is AMenu is controlling the menu. In order to locate the class in Eclipse we open the Java perspective then press CTRL-SHIFT-T. Then type in AMenu and you will see all the choices for AMenu.

Notice your compiere source code should be in a different project which is not modified it is used for reference purposes only.
Copy the java class AMenu into your project using the identical package name. Here it is illustrated in the framework project.

Note the advantages of having not modified this class directly. They are numerous. The first obvious one is that you can see quickly which classes you have customized. The projects I worked on where we modified source code directly - upgrades to new version of Compiere could take months.
Summary of classes patched for this demo
org.compiere.apps.AMenu
org.compiere.Compiere
Lets add a switch company menu option. We won't worry about translations at this point. Translation support should be fairly easy to add as you will see from the source code.
In private void createMenu() just below mFile.addSeperator() or wherever you prefer add the following code.
Eclipse tip: When your cursor is inside the AMenu class press CTRL-O to quickly locate the method.
Copy the class AMenu.java from your reference set of code and modify as follows.
AMenu.createMenu()
// File
JMenu mFile = AEnv.getMenu("File");
menuBar.add(mFile);
AEnv.addMenuItem("PrintScreen", null, KeyStroke.getKeyStroke(KeyEvent.VK_PRINTSCREEN, 0), mFile, this);
AEnv.addMenuItem("ScreenShot", null, KeyStroke.getKeyStroke(KeyEvent.VK_PRINTSCREEN, KeyEvent.SHIFT_MASK), mFile, this);
mFile.addSeparator();
miSwitch = AEnv.addMenuItem("Switch company", null, null, mFile, this);
mFile.addSeparator();
AEnv.addMenuItem("Exit", null, KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.SHIFT_MASK+Event.ALT_MASK), mFile, this);Add this somewhere in the declarations near the beginning.
private JMenuItem miSwitch = new JMenuItem(); //framework
A word of caution: If working with a reference version of the source code it is easy to accidentally modify the reference class instead of your copy.
Add a patch to handle the mouseclick on the menu item.
public void actionPerformed(ActionEvent e)
{
// Buttons
if (e.getSource() == bNotes)
gotoNotes();
else if (e.getSource() == bRequests)
gotoRequests();
else if (e.getSource() == miSwitch) { //framework
dispose();
Compiere.doSwitch();
}
else if (!AEnv.actionPerformed(e.getActionCommand(), m_WindowNo, this))
log.log(Level.SEVERE, "unknown action=" + e.getActionCommand());
updateInfo();
} // actionPerformeddispose() needs to be modifed so that java doesn't exit when we switch companies
/**
* Dispose - end system
*/
public void dispose()
{
// clean up - close windows
Ini.setWindowDimension(0, getSize());
Ini.setDividerLocation(treePanel.getDividerLocation());
Ini.setWindowLocation(0, getLocation());
Ini.saveProperties(true);
setVisible(false); //framework
super.dispose();
// AEnv.exit(0); framework removed
} // disposeNow we need to patch org.compiere.Compiere. Add one function
org.compiere.Compiere
public static void doSwitch() { //framework
new org.compiere.apps.AMenu();
}Now we can run compiere and see what happens.
We get two errors (warnings) in red as follows
-----------> Msg.getMsg: NOT found: Switch company ===========> Env.getImageIcon: Not found: Switch company16.gif
Safe to ignore them.
This chapter is for discussion of any issues picked up in the source code.
This might seem to be a petty point. However it is raised because of the confusion caused when reading the code. Consider the code
synchronized (s_cc) // use as mutex
{
s_cc = cc;
s_connections = null;
s_connectionRW = null;
}The problem here is the comment [use as mutex]. Defining the term mutex in dictionary.com shows that the comment is redundant as synchronized is actually a synonym (if understood correctly).Here is the definition for mutex.
“<parallel> A mutual exclusion object that allows multiple threads to synchronise access to a shared resource. A mutex has two states: locked and unlocked. Once a mutex has been locked by a thread, other threads attempting to lock it will block. When the locking thread unlocks (releases) the mutex, one of the blocked threads will acquire (lock) it and proceed. If multiple threads or tasks are blocked on a locked mutex object, the one to take it and proceed when it becomes available is determined by some type of scheduling algorithm. For example, in a priority based system, the highest priority blocked task will acquire the mutex and proceed. Another common set-up is put blocked tasks on a first-in-first-out queue.”
The principle in XP is not to add comments at all unless it adds value; code should be self-documenting.
This chapter is written for those of us who don't install compiere every day so we often land up re-learning the process.
Compiere version: 2.5.3b. Java 1.5. Oracle 10g.
First port of call is here http://www.compiere.com/support/install/index.html . You will find here the official compiere install instructions.These should be followed in conjunction with this guide (if you run into similiar problems as I did.)
Extremely handy and mostly complete guide for installing oracle 10g on linux is available on Puschitz's site.
Any oracle related comments here refer to the installation as done per his instructions.
Download distribution file (latest compiere files) from sourceforge.
Create folder to house your distribution files.
This guide details how to get compiere to run under the user created for oracle 'oracle'.
Extract files. For this example we use /A/local/knowledgebook. My environment looks like this
[neil@nglinux knowledgebook]$ pwd /A/local/knowledgebook [neil@nglinux knowledgebook]$ ls build.xml install.html lib rel252.html RUN_setup.bat data InstallSteps.gif license.html RUN_Compiere2.bat RUN_setup.sh index.html jboss rel251.html RUN_Compiere2.sh utils [neil@nglinux knowledgebook]$
Next logical steps
[neil@nglinux knowledgebook]$ ./RUN_setup.sh bash: ./RUN_setup.sh: Permission denied [neil@nglinux knowledgebook]$ chmod 777 *.sh [neil@nglinux knowledgebook]$
We RUN_setup again.
Change some values to avoid port conflicts. Then click test. We get an error as shown

We have oracle running yet we get this error

If running on linux the following command should come in handy to see if something is listening on that port
nmap -sT 127.0.0.1 -p1521
(There should be a version of nmap or equivalent tool available for win32.) Here is the result
[root@nglinux neil]# nmap -sT 127.0.0.1 -p1521 Starting nmap 3.81 ( http://www.insecure.org/nmap/ ) at 2006-04-25 23:24 SAST Interesting ports on localhost (127.0.0.1): PORT STATE SERVICE 1521/tcp closed oracle Nmap finished: 1 IP address (1 host up) scanned in 0.167 seconds [root@nglinux neil]#
Clearly showing that nothing is listening on the port specified.
When we installed oracle we were given this information at the end:
The following J2EE Applications have been deployed and are accessible at the URLs listed below. Ultra Search URL: http://localhost:5620/ultrasearch Ultra Search Administration Tool URL: http://localhost:5620/ultrasearch/admin iSQL*Plus URL: http://localhost:5560/isqlplus iSQL*Plus DBA URL: http://localhost:5560/isqlplus/dba Enteprise Manager 10g Database Control URL: http://localhost:5500/em
The following step is optional and is only needed to view the database via a web browser. We need to issue this to start the web based interface
# su - oracle $ emctl start dbconsole TZ set to America/New York Oracle Enterprise Manager 10g Database Control Release 10.1.0.3.0 Copyright (c) 1996, 2004 Oracle Corporation. All rights reserved. http://localhost:5500/em/console/aboutApplication Starting Oracle Enterprise Manager 10g Database Control ......................... started. ------------------------------------------------------------------ Logs are generated in directory /u01/app/oracle/product/10.1.0/Db_1/localhost_orcl/sysman/log [oracle@nglinux admin]$
Here is the root of the problem. However I suspect it is the oracle listener that isn't running. This would all have worked if I'd done the install immediately after oracle without a reboot.
The following command starts the listener and should be coded into one of the startup files
[oracle@nglinux admin]$ lsnrctl start LSNRCTL for Linux: Version 10.1.0.3.0 - Production on 25-APR-2006 23:55:38 Copyright (c) 1991, 2004, Oracle. All rights reserved. Starting /u01/app/oracle/product/10.1.0/Db_1/bin/tnslsnr: please wait... TNSLSNR for Linux: Version 10.1.0.3.0 - Production System parameter file is /u01/app/oracle/product/10.1.0/Db_1/network/admin/listener.ora Log messages written to /u01/app/oracle/product/10.1.0/Db_1/network/log/listener.log Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC))) Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))) Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 10.1.0.3.0 - Production Start Date 25-APR-2006 23:55:38 Uptime 0 days 0 hr. 0 min. 0 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/oracle/product/10.1.0/Db_1/network/admin/listener.ora Listener Log File /u01/app/oracle/product/10.1.0/Db_1/network/log/listener.log Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))) Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully [oracle@nglinux admin]$
Even though there is a red mark after the database name system seems to have accepted the settings.

We click save and it appears to be working. It is good practice to record these settings or take a screenshot in case
they get corrupted at some point. Then we don't have to remember the settings.
We then tried RUN_ImportCompiere under the utils folder, logged in as the usual user. This is the result
[neil@nglinux utils]$ ./RUN_ImportCompiere.sh Setting myEnvironment .... Import Compiere - /mnt/hda3/A/local/knowledgebook (orcl) Re-Create Compiere User and import /mnt/hda3/A/local/knowledgebook/data/Compiere.dmp - (orcl) == The import will show warnings. This is OK == 14996 -rw-r--r-- 1 neil neil 15335424 Feb 12 04:18 /mnt/hda3/A/local/knowledgebook/data/Compiere.dmp Press enter to continue ... Compiere Database Import : 1.10 $ Importing Compiere DB from /mnt/hda3/A/local/knowledgebook/data/Compiere.dmp ------------------------------------- Re-Create DB user ------------------------------------- sqlplus system/oracle@orcl @/mnt/hda3/A/local/knowledgebook/utils/oracle/CreateUser.sql compiere oracle oracle/ImportCompiere.sh: line 25: sqlplus: command not found ------------------------------------- Import Compiere.dmp ------------------------------------- imp system/oracle@orcl FILE=/mnt/hda3/A/local/knowledgebook/data/Compiere.dmp FROMUSER=\(reference\) TOUSER=compiere oracle/ImportCompiere.sh: line 31: imp: command not found ------------------------------------- Create SQLJ ------------------------------------- . Load Oracle SQLJ ... /mnt/hda3/A/local/knowledgebook/utils/oracle/create.sh: line 11: loadjava: command not found . Create Oracle Functions ... /mnt/hda3/A/local/knowledgebook/utils/oracle/create.sh: line 15: sqlplus: command not found ------------------------------------- Check System Import may show some warnings. This is OK as long as the following does not show errors ------------------------------------- sqlplus compiere/oracle@orcl @/mnt/hda3/A/local/knowledgebook/utils/oracle/AfterImport.sql oracle/ImportCompiere.sh: line 43: sqlplus: command not found [neil@nglinux utils]$
This is one way to fix the problem above:
[neil@nglinux local]$ su Password: [root@nglinux local]# chgrp -R oinstall knowledgebook [root@nglinux local]# chmod -R g+rwx knowledgebook [root@nglinux local]# su - oracle [oracle@nglinux ~]$ [oracle@nglinux ~]$ pwd /home/oracle [oracle@nglinux ~]$ cd /A/local/knowledgebook/ [oracle@nglinux knowledgebook]$ cd utils [oracle@nglinux utils]$
Fixes the permissions. Unsure if we will have to work in Compiere as the oracle user. (oracle=dba account, oinstall=group used when installing oracle; oracle is member of oinstall). Otherwise we can try add 'neil' to the group oinstall.
Importing now proceeds as documented.
After the import we attempt to run Compiere as follows
[oracle@nglinux knowledgebook]$ ./RUN_Compiere2.sh Compiere Client JAVA_HOME is not set. You may not be able to start Compiere Set JAVA_HOME to the directory of your local JDK. COMPIERE_HOME is not set You may not be able to start Compiere Set COMPIERE_HOME to the directory of Compiere2.
If your system hangs at this point:
Troubleshoot: Change the last command in RUN_Compiere2.sh from
$JAVA -Xms32m -Xmx512m -DCOMPIERE_HOME=$COMPIERE_HOME $PROP $SECURE -classpath $CLASSPATH org.compiere.Compiere
to
echo $JAVA -Xms32m -Xmx512m -DCOMPIERE_HOME=$COMPIERE_HOME $PROP $SECURE -classpath $CLASSPATH org.compiere.Compiere
Turns out there was a symbolic link in /usr/bin to java (probably the wrong version). Also you need to take care when installing fedora 4 out the box it installs a non-sun JDK. (Reboot required to resolve this after removing the JVM link). Need to remove the symbolic link. This was resolved by typing in the following
[oracle@nglinux knowledgebook]$ which java /usr/bin/java [oracle@nglinux knowledgebook]$ su Password: [root@nglinux knowledgebook]# rm /usr/bin/java rm: remove symbolic link `/usr/bin/java'? y [root@nglinux knowledgebook]# exit
You also need to su to oracle and edit your .bash_profile. The completed modified one , created initially by the oracle install process, looks as follows. Edit the file first.
su - oracle kate ~/.bash_profile
# .bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environment and startup programs PATH=$PATH:$HOME/bin export PATH unset USERNAME ulimit -n 63536 ulimit -u 16384 export ORACLE_BASE=/u01/app/oracle export ORACLE_SID=orcl export ORACLE_HOME=$ORACLE_BASE/product/10.1.0/Db_1 export JAVA_HOME=/usr/local/java1_5 export PATH=$PATH:$JAVA_HOME/bin:$ORACLE_HOME/bin export LD_LIBRARY_PATH=$ORACLE_HOME/lib export COMPIERE_HOME=/A/local/knowledgebook
You will need to substitute your folders where relevant.
Then do the following to get things running
[root@nglinux local]$ exit [root@nglinux local]# xhost +[1] [root@nglinux local]# su - oracle [oracle@nglinux ~]$ cd /A/local/knowledgebook [oracle@nglinux knowledgebook]$ ./RUN_Compiere2.sh
There are no more complaints about environment variables being missing.
The compiere dialog starts up. Then the database dialog. (These settings will be saved to a file Compiere.properties. The exact location is based on a formula in compiere. Should be saved to COMPIERE_HOME if that environment is set. If you have multiple copies of these files lying around best to delete them to avoid confusion.)

These were the settings that worked for me. It is good practice to record these settings or take a screenshot in case they get corrupted at some point. (Do this after the app server is working.)
Don't worry about the app server for now.Click OK.
Unfortunately my guess about where the Compiere.properties file was turned out to be incorrect . For some reason mine was being stored under the home dir as evidenced by this log entry when starting compiere.
02:13:33.361 Ini.loadProperties: /home/oracle/Compiere.properties #24
This is not good because we have the properties file in a different location to the application (probably useful for other scenarios). So I removed this Compiere.properties and edited RUN_Compiere2.sh as follows:
# To switch between multiple installs, copy the created Compiere.properties file # Select the configuration by setting the PROP variable #PROP= PROP=-DPropertyFile=$COMPIERE_HOME/Compiere.properties
Now we can see from the logging output of compiere that the file is centralized where we expect it. Best thing to do is to delete all other unneeded copies of the properties file to avoid confusion.
User names passwords and other settings are stored in the Compiere.properties file and on a rich client it is encrypted. Due to web server security the file is not encrypted on jboss according to my last knowledge.
Here is the logging
-----------> Ini.loadProperties: /A/local/knowledgebook/Compiere.properties not found
Since it is not found we have to re-enter the settings.
Success. The welcome screen is displayed

Password System.
We exit and tackle the application server (no GL postings can occur without the app server running).
Running the app server..
cd utils
[oracle@nglinux utils]$ ./RUN_Server2.sh
Setting myEnvironment ....
: command not foundnowledgebook/jboss/bin/run.conf: line 6:
: command not foundnowledgebook/jboss/bin/run.conf: line 8:
: command not foundnowledgebook/jboss/bin/run.conf: line 12:
: command not foundnowledgebook/jboss/bin/run.conf: line 20:
: command not foundnowledgebook/jboss/bin/run.conf: line 27:
: command not foundnowledgebook/jboss/bin/run.conf: line 33:
: command not foundnowledgebook/jboss/bin/run.conf: line 38:
/mnt/hda3/A/local/knowledgebook/jboss/bin/run.conf: line 52: syntax error: unexpected end of file
=========================================================================
JBoss Bootstrap Environment
JBOSS_HOME: /mnt/hda3/A/local/knowledgebook/jboss
JAVA: /usr/local/jdk1.5.0_06/bin/java
JAVA_OPTS: -server -Xms64M -Xmx512M -DCOMPIERE_HOME=/mnt/hda3/A/local/knowledgebook -Djava.awt.headless=true -Dprogram.name=run.sh
CLASSPATH: /mnt/hda3/A/local/knowledgebook/jboss/bin/run.jar:/usr/local/jdk1.5.0_06/lib/tools.jar
=========================================================================
log4j:ERROR Failed to create directory structure: /mnt/hda3/A/local/knowledgebook/jboss/server/compiere/log
log4j:ERROR setFile(null,false) call failed.
java.io.FileNotFoundException: /mnt/hda3/A/local/knowledgebook/jboss/server/compiere/log/boot.log (No such file or directory)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
at java.io.FileOutputStream.<init>(FileOutputStream.java:102)
at org.apache.log4j.FileAppender.setFile(FileAppender.java:272)
at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:151)
at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:247)
at org.apache.log4j.config.PropertySetterAll look like permissions related problems. For some reason our user can't create folders. We rerun the permissions command as follows
cd .. chmod -R g+rwx knowledgebook chmod: changing permissions of `knowledgebook': Operation not permitted [oracle@nglinux local]$ su Password: [root@nglinux local]# chmod g+rwx knowledgebook [root@nglinux local]#
Looks like I initially left of the -R (recurse into subdirectories. Fixed in the doc above).
While we are here there are some useful symbolic links which can be created to make life easier as follows
[oracle@nglinux knowledgebook]$ ln -s ./utils/RUN_Server2.sh start.sh [oracle@nglinux knowledgebook]$ ln -s ./utils/RUN_Server2Stop.sh stop.sh [oracle@nglinux knowledgebook]$ ln -s RUN_Compiere2.sh run.sh [oracle@nglinux knowledgebook]$
Then just type ./start.sh to start the server. ./stop will stop the server. ./run.sh will start compiere.
Things are running better with the jboss server now. I need to open a new console because this one won't release the display (could've run it will & at the end though to run into background). You can stop the server with CTRL-C or by typing stop.sh in another terminal window.
When running compiere go into the connection settings (expansion button next to the server on the welcome screen). Set your application server only the rest should be filled in automatically

Thus it would've been easier to get the server working first and this is recommended.
Note: great care must be taken when choosing hostnames when working over a network. Remember you will need a dns server or you will need to hard code an ip address. These settings are taken from the server setup dialog. Any names you use must be accessible from anywhere on the network. With servers without DNS it is probably easier just to use the server's ip address although if it changes you will need to change each client.
Also good to mention here is that your hosts file must be setup correctly. Edit /etc/hosts from the root prompt. Here is mine.
127.0.0.1 localhost localhost.localdomain nglinux 192.168.219.128 vmware compierelocal nglinux
nglinux is my local machine name. You will need a static IP address for a server with clients.
The localhost entry is very important and is sometimes missing for some reason on some workstations.
If necessary go back now and correct your hostnames (especially on the server setup), if you're running compiere on a network. This will be a showstopper if it isn't right. Compiere seems to get the host name based on what you've setup on the server. I think compiere might also do a reverse lookup on the ip address to get the host name which makes it more complicated (can't just workaround with IP addresses).
Now you can click the OK button and login to Compiere.
If you ever need to start fresh again just re-import the dump of compiere.
Added a shortcut to my desktop. Told it to start as a different user 'oracle'. Ran into problems so switching back to commandline.
Create /etc/init.d/oracle:
#!/bin/bash
#
# Init file for oracle Vesion 1.01 by Neil Gordon http://www.knowledgesuccess.com
#
# chkconfig: 5 90 50
# description: Oracle 10g server demon
#
# processname: oracle
# source function library
. /etc/rc.d/init.d/functions
# pull in sysconfig settings
[ -f /etc/sysconfig/oracle ] && . /etc/sysconfig/oracle
RETVAL=0
prog="oracle"
ORACLE_SYSTEM_USER="system"
ORACLE_SYSTEM_PASSWORD="oracle"
# Some functions to make the below more readable
do_start_listener() {
su - --command="lsnrctl start" oracle
}
do_stop_listener() {
su - --command="lsnrctl stop" oracle
}
do_start_db() {
su - --command="sqlplus /nolog << EOF
connect $ORACLE_SYSTEM_USER/$ORACLE_SYSTEM_PASSWORD as sysdba
startup
quit
EOF" oracle
}
do_stop_db() {
su - --command="sqlplus /nolog << EOF
connect $ORACLE_SYSTEM_USER/$ORACLE_SYSTEM_PASSWORD as sysdba
shutdown immediate
quit
EOF" oracle
}
start()
{
echo -n $"Starting $prog: "
do_start_listener
do_start_db
RETVAL=$?
echo
}
stop()
{
echo -n $"Stopping $prog: "
do_stop_db
do_stop_listener
RETVAL=$?
echo
}
status()
{
su - --command "lsnrctl status" oracle >/dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ] ; then
echo "listener is running"
else
echo "listener is NOT running"
fi
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
RETVAL=1
esac
exit $RETVAL
The common mistake is to forget to make the script executable. Of you do this you will get errors about the 'service not recognized' or some such. Use
chmod +x /etc/init.d oracle
Method 1: Manual: Create symbolic links for runlevel 5. The S is used when starting the process and the K is used when stopping the process. The 98 specifies the sequence in which the process starts and is almost at the end.
cd /etc/rc.d [root@localhost rc.d]# ls init.d rc0.d rc2.d rc4.d rc6.d rc.sysinit rc rc1.d rc3.d rc5.d rc.local [root@localhost rc.d]# cd rc5.d [root@localhost rc5.d]# ln -s /etc/init.d/oracle S98oracle [root@localhost rc5.d]# ln -s /etc/init.d/oracle K98oracle
Method 2: Use chkconfig (recommended): 'ckkconfig' will create the symbolic links for you and can be used to manipulate the links in rc.d folder. Use it instead of creating the symbolic links manually as shown above. The comment under 'chkconfig' 5 90 50 - if you examine the manpage for chkconfig - you will see the meanings. 5 = runlevel, 90 = start priority , 50 = stop priority. So you will get symlinks created with S90oracle, K50oracle. 5 is the standard runlevel where the GUI is running. You can have more than one service with the same priority level as long as the name is not the same, which wouldn't be possible anyway because the scripts are all stored in /etc/init.d.
If you wish to change the priorities and consequently the symlinks use the '--del' option of the chkconfig to delete the symlinks then use '--add' to add the service.
cd rc5.d [root@localhost rc5.d]# /sbin/chkconfig --add oracle [root@localhost rc5.d]# /sbin/chkconfig --list oracle oracle 0:off 1:off 2:off 3:off 4:off 5:off 6:off [root@localhost rc5.d]# /sbin/service oracle start oracle: unrecognized service [root@localhost rc5.d]# /sbin/chkconfig --level 5 oracle on [root@localhost rc5.d]# /sbin/chkconfig --list oracle oracle 0:off 1:off 2:off 3:off 4:off 5:on 6:off [root@localhost rc5.d]# /sbin/service oracle start oracle: unrecognized service [root@localhost rc5.d]# chmod 755 /etc/init.d/oracle [root@localhost rc5.d]# /sbin/service oracle start Starting oracle: LSNRCTL for Linux: Version 10.1.0.3.0 - Production on 20-MAY-2006 14:25:12
When all is done well will appear in the GUI as a service. Here you can also start and stop the service and control whether the service starts automatically at boot time. Also use the command line
/sbin/service oracle start

I used this URL as a partial guide to figure out what was happening behind the scenes http://farley.no-ip.org/linux/daemon-boot.php
Go to client setup on the system menu.
This is how I setup my client

For some reason the currencies aren't sorted alphabetically. Maybe someone can submit a patch for yorg. You can type in the first letter of the currency until yours comes up.
Not being an accounting guru I decided to stick with the US standard set of accounts. Apparently you can restructure later anyway.
I loaded the values. This gave an error and didn't seem to have created a new client.
So I tried again with a shorter client name 'kn'. This is the error:

This was the traceback in the console:
04:00:44.209 Ini.loadProperties: /A/local/knowledgebook/Compiere.properties #28
===========> MRole.saveError: AccessTableNoView - Required=2(Client Data) != UserLevel=S [11]
===========> MRole.saveError: AccessTableNoView - Required=2(Client Data) != UserLevel=S [12]
===========> MRole.saveFinish: afterSave [13]
java.lang.IllegalArgumentException: AD_User_ID is mandatory.
at org.compiere.model.X_AD_User_Roles.setAD_User_ID(X_AD_User_Roles.java:72)
at org.compiere.model.MUserRoles.<init>(MUserRoles.java:147)
at org.compiere.model.MRole.afterSave(MRole.java:318)
at org.compiere.model.PO.saveFinish(PO.java:1738)
at org.compiere.model.PO.saveNew(PO.java:2201)
at org.compiere.model.PO.save(PO.java:1714)
at org.compiere.model.MSetup.createClient(MSetup.java:186)
at org.compiere.apps.form.VSetup.run(VSetup.java:414)
at org.compiere.apps.form.FormFrame$2.run(FormFrame.java:333)
===========> MSetup.createClient: Admin Role A NOT inserted [13]
Well here we get in touch with compiere's user friendly support.
Please refer support request [ 1445591 ] cannot setup new client in 253b, from which I quote:
Customer:
“ cannot setup new client in 253b After installation of 253b cannot setup new client. Error message: "Admin Role A NOT inserted" See attached file for trace.”
Kathy response
“if you have a support contract you can download the latest code from your assets and migrate the database. There is no patch available”
Customer:
“As far as i know there is no release 253c available for download and thus you are suggesting to download current version from cvs. I cannot do that, since i need a stable version i can use in production. What's your suggestion? Is it possible to patch version 253b? I am currently working with 253a but i need some fixes from 253b...”
Kathy:
.
Well there is no reason in reproducing any more of this garble. The answer in the end is NO. I'm certainly a bit peeved having spent so much time and now run into a stupid bug (right in the beginning) which is in the only code which is publicly downloadable from sourceforge.
A SHOWSTOPPER FOR ME
Ok, well there was no coming right with the version 253b even after submitting a new support request. (Understandably they needed a support contract in order to look into the issue further). Someone kindly supplied me with a a 253c version of the client so here I am continuing with the excercise. :)

The above far more friendly view greets us after creating the new client. I've created a completely seperate database - called knowledge - so I can keep my books in a seperate file from development work. (See the short section on setting up a second compiere database). Also in a seperate window started up the application server - then in the server expansion window selected my local host as the app server - actually works quite well, automatically figured out the database, passwords, etc.
I don't know much about accounting so I just imported the standard US chart of accounts, hoping to work it out later.
The top priority for me is producing an invoice. If I can actually achieve this in Compiere then there will be far more practical use for me and will start appreciating the functionality more.
Wonder who decided my password? I'm just going to work as knowledgeAdmin for now. Oh yes now I remember, Compiere works on roles. So log out, restart Compiere, login as SuperUser this time. Gives a selection of roles, can't remember off hand why superuser has access to my new role or where this is specified.

My first product

Set my cheap price:

(It presented me something about 'price list version' ; whatever that is I just chose the one presented to me on the list)
Now lets try an invoice....
Oops need a customer first.
Setup a business partner, ticked the 'customer' checkbox on the second tab.
I can start seeing the benefit of doing things this way. My usual way of producing invoices is in open office. Now that I've got this far, setting up products and prices is easy. Business partner was easy. Entering the invoice was easy.
The invoice produced by compiere doesn't look at all nice though.In order to see it on the screen you need to 'always preview print' on the preferences window.
With the reputation of compiere's report writer though I'm now faced with how to produce a good looking invoice. Not at all keen on modifying using the tried and tested compiere report writer. I want something I can send to my customers.
I would use crystal reports but not worth it for my size operation. Also crystal reports seemed to have ignored the basic fact that people actually would want to run reports on their workstations as opposed to just designing them :) (Report distribution , dig, dig - :) )
(Whole industries based around missing segments which people wouldn't believe you would actually leave off from a reputable product. Why doesn't it say on the business objects/crystal reports front page that you will need to be an IT expert in order to distribute your reports? Guess thats why microsoft is so popular.)
Well, I've got an invoice but long way to go before sending it off to no.1 customer. Here is how it looks out the box.

At this point the excercise started flowing a lot easier. Setting up business partners was a breeze. I decided to stick with the compiere report after all. Clicking on the customize report button on the report showed me how easy it is to modify the layout. Not , unfortunately, in the same way as a GUI report designer. However adding and removing fields, adding headings, extra lines is not at all difficult.
One of the first priorities was to email the invoice to the customer. However when exporting the report it comes stamped with 'Demo Version' across the PDF. This was solved by the following workaround, which was discovered on http://www.red1.org forums. I editted the PDF's that were being generated with a text editor (in my case good old VI) and simply removed the entire line which read demo version. Reopening in acrobat reader proved that the workaround was ok. Will have to find a way around this later (such as incorporating an open source pdf library) however the workaround is acceptable for now.
My only gripe was that when capturing my invoice and having completed the invoice, I then discovered that I'd made an error on the invoice, so I reversed/corrected it using the button provided. (I'm using Customer (Invoice) option). This generated an identical transaction (AR Invoice) with a negative sign, thus using up yet another one of my sequences. I would've thought a credit note would've been more appropriate. I would say that if this is an issue then issue a credit note manually and allocate it against the invoice. However, I haven't tried it yet, since the point is more of an irritation than anything.
Also I had to post each of the invoices manually. The reversals refused to post giving an error message about something being locked. Will have to investigate this further.
One of the things I enjoyed about the new version of Compiere is the ability to create customers 'on the fly' with the shortcut on the right-click.
Thanks to 'bjornw' for pointing me in the following direction.
There is a freepdf replacement available at http://www.iku-ag.de/compiere/freepdf-eng.jsp
If you follow the instructions it works as advertised and the 'demo' is gone from the PDF. I incorporated the library in a slightly different way by incorporating it into my build.xml (compiere client folder)as follows
.
.
<!-- ==================================================== -->
<!-- Compiere Client Lib -->
<!-- ==================================================== -->
<target name="setupCLib" depends="setupInit" unless="isAppsTomcat"
description="Setup Compiere Client Lib">
<!-- Delete Old -->
<delete file="lib/CompiereCLib.jar" failonerror="no" />
<delete file="lib/CClient.jar" failonerror="no" />
<delete file="lib/CTools.jar" failonerror="no" />
<delete file="lib/jPDFPrinter.jar" failonerror="no" />
<mkdir dir="buildCLib" />
<unjar src="lib/CCTools.jar" dest="buildCLib" />
<unjar src="lib/jPDF.jar" dest="buildCLib" />
<unjar src="lib/jPDFPrinterProd.jar" dest="buildCLib" />
<unjar src="lib/${COMPIERE_DB_TYPE}.jar" dest="buildCLib" />
<unjar src="lib/${COMPIERE_APPS_TYPE}.jar" dest="buildCLib" />
<unjar src="lib/freepdf.jar" dest="buildCLib" />
.
.After this RUN_setup.sh must be run to rebuild the CompiereCLib library
Well worth the effort that was invested. Should've done this excercise a LONG time ago.
[1] This is required on linux. You can also use xhost + 127.0.0.1. It controls who can access the X windows on your PC so it is important to be careful with this when connected to the internet.