Compiere survival guide

Neil Gordon


Table of Contents

Last update 2006-05-22
Disclaimer
About this document
Revision history
Cross platform notes
Cheat sheet: Plus and minuses of technologies in the industry
1. Best practices
1. Never modify the source code directly
2. Seperate the business logic from the user interface
3. Extreme programming / test driven development
3.1. Test driven development
4. Working around compiere's weaknesses
2. Getting the compiere source code
1. Todo
3. Running Compiere 2.5.3b
1. Downloading the SDK
4. Running Compiere
1. Getting compiere to run
2. Starting up oracle
3. Setting up a second database (compiere instance)
5. SQL and PL/SQL
1. Adding a new table to compiere
2. Duplicating tables in sql
6. Todo: setting up the source code and dev environment
7. Todo: Writing test cases for compiere
8. Running compiere in eclipse
1. Eclipse settings
9. Setting the classpath in your project
1. Introduction
10. Customizing compiere
1. Adding switch company to compiere
11. Source code analysis
1. DB.java: Undefined term 'mutex' in comment
12. Standard compiere deployment: discovery excercise: creating a set of books for knowledgesuccess (knowledgebook)
1. Installation
2. Starting oracle automatically at boot time (linux)
3. Client setup
4. Excercise in futility - Can't insert Admin Role A
5. No showstoppers allowed
6. Producing an invoice
7. Things look GOOD
8. Things start getting easier and more productive
9. Getting rid of the 'demo' message on the pdf - free pdf replacement
10. Outcome: SUCCESS! Happy customer

Last update 2006-05-22

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

Disclaimer

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.

About this document

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.

Revision history

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

Cross platform notes

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.

Cheat sheet: Plus and minuses of technologies in the industry

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.

Chapter 1. Best practices

1. Never modify the source code directly

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.

2. Seperate the business logic from the user interface

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.

3. Extreme programming / test driven development

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.junit.org

http://www.extremeprogramming.org

3.1. Test driven development

One day all programs will be written this way. Try it out....http://www.junit.org

4. Working around compiere's weaknesses

  • 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.

Chapter 2. Getting the compiere source code

1. Todo

Chapter 3. Running Compiere 2.5.3b

1. Downloading the SDK

You need the SDK 1_5_x download it from Sun before trying anything. Dont try the JRE!

Chapter 4. Running Compiere

1. Getting compiere to run

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.

2. Starting up oracle

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>                                                   

3. Setting up a second database (compiere instance)

Just follow the setup procedure above and in the documentation, however, this time specify a different compiere user. Then re-run RUN_ImportCompiere.sh and the system will import a new compiere under different "user" (schema) name.

Chapter 5. SQL and PL/SQL

1. Adding a new table to compiere

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.

2. Duplicating tables in sql

Hsqldb

SELECT * INTO MYTABLE FROM AD_TABLE

Oracle

CREATE TABLE MYTABLE AS SELECT * FROM AD_TABLE

Chapter 6. Todo: setting up the source code and dev environment

For best practices

Chapter 7. Todo: Writing test cases for compiere

This should be covered in the framework guide since that is one of the goals of that project.

Chapter 8. Running compiere in eclipse

1. Eclipse settings

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

Chapter 9. Setting the classpath in your project

1. Introduction

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.

Chapter 10. Customizing compiere

1. Adding switch company to compiere

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=true

A 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();
	}	//	actionPerformed

dispose() 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
	}	//	dispose

Now 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.

Chapter 11. Source code analysis

This chapter is for discussion of any issues picked up in the source code.

1. DB.java: Undefined term 'mutex' in comment

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.

Chapter 12. Standard compiere deployment: discovery excercise: creating a set of books for knowledgesuccess (knowledgebook)

1. Installation

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.PropertySetter

All 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.

2. Starting oracle automatically at boot time (linux)

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

3. Client setup

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]

4. Excercise in futility - Can't insert Admin Role A

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

5. No showstoppers allowed

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.

6. Producing an invoice

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.

7. Things look GOOD

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.

8. Things start getting easier and more productive

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.

9. Getting rid of the 'demo' message on the pdf - free pdf replacement

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

10. Outcome: SUCCESS! Happy customer

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.