From ADempiere
Jump to: navigation, search
Name This user real name is : Jovansonlee Cesar
Sourceforge logo.png This user has a Sourceforge account.
Facebook_logo This user has a Facebook account.
Blogspot_logo This user has blogs.
Twitter Logo Follow him on twitter
Youtube.gif This user has YouTube

About me

  • Code name: Ivan Ceras
  • Location: Philippines
  • Met ADempiere: February 2008 "just in time"
  • Profession: Computer Engineer, inclined to software development
    • "Also touched hardwares such as programming PIC Chips to instruct the robotics things".
  • Distro: Fedora Core, since FC4
  • CPU:AMD's
  • IDE: Eclipse
  • WebTools: Joomla, Wiki
  • Search Engine: Google
  • Browser: Firefox
Loved about ADempiere
  1. Extreme flexibility - "Configure me your way, and I will behave just as you wanted"
  2. Intuitive, Uniformed and Attractive Design - Dumb users dont have to be instructed over and over again.
  3. Easy to hack-around - Everything is organized disciplinely.

Programming journey:

Almost all of my college projects were made out of C, since C is main subject of programming. I was an extremist programmer of C, but later on, I find it very tiresome to program (even minor) functionalities.

When I had a chance to undergone an OJT to a software establishment. PHP was their main dish, tied-up with MySQL. I quickly learned PHP since I look at it as if it is C(humbly, very easy indeed). Later, together with my teammates, we were able to build our dynamic school website using our spare time during school days and completed the site in a span of 1 month.

When I was hired as an in-house developer of a Manufacturing firm, I was trained with PowerBuilder. I found PowerBuilder to be extremely fast, robust and suitable for (RAD)rapid application development indeed, much more since they tied it up with Oracle 10g. I enjoyed using toad (excellent), but I found PowerBuilder inflexible. You can't just have what you wanted. You have to adjust to the program, and if you won't, you have to go several wasteful time creating your own set controls. Also it lacks inconsistency. Along with the training we are modifying the existing system, SFC(Shop Floor Control). OMG, I find it very badly designed, much more it has a corporate core library with no supplied source code.

How did I encountered ADempiere?
  • Short Answer: "It is just a matter of keyword" - ERP
  • Long Answer:

Back February 2008, I was googling for an application which will be suitable for business application,which has a requirement of a web interface. It is just a matter of keyword really. I used SugarCRM as the basis(I've encountered of SugarCRM on my OJT days, since it was used in the establishment).I tried googling for SFC, CRM... then came related keywords such as SCM, MRP, and "ERP". I tried ERP, Opensource ERP,etc until.... guess what... Compiere appeared to be prominent, with other rivals...Opentaps,OpenBravo,TinyERP,Value-ERP,TinyERP,ERP5, etc. (ADempiere didn't show up.. i dont know) I read on Compiere, was impressed and interested especially on its "Active Application Dictionary" feature.At first I was hesitant since it is programmed with java. (Java was not apart of our curriculum. It was only a report discussion of other group in a group activity). I tried "Opensource ERP in PHP", opentaps then showed, but I gotten almost nothing to read. Maybe it was dead. I've got no choice, but to read and read about compiere. Every additional word I've read make me more curios about it and urge me to look at the source if it is really well-designed(somehow).

I don't know how to download the source yet, since I know nothing about svn. CVS was our dish and "vi" was our knife. I tried again googling "Compiere compressed/zip source code"...etc, luckily ADempiere showed up, with a sourceforge download link. Without any doubt I downloaded both the compiled binary and the source code.I also downloaded the AVA, in case the 2 might not be easy.

I read about ADempiere(site looks anyway I manage to reach the wiki. Thank God, I feel like home!. I read on it and read. Until then, that I've successfully installed and configured ADempiere and the database, everything follows. Learning after learning, asking after asking, experimenting after experimenting, hacking after hacking(ows..I mean the code!). It was such a very satisfying feeling of enjoyment. So too shall you(newbies)!

  • Conclusion:
    • All in all and for all these,
    • I may be a newbie to Java (but not anymore to programming languages)
    • I may be a newbie to PostgreSQL (but not anymore to databases)
    • I may be a newbie to ADempiere (but not anymore to integrated systems)
    • I may be a newbie to Sourceforge (but not anymore to opensource)
    • I may be a newbie to SVN (but not anymore to version control)
    • I may be a newbie to Eclipse (but not anymore to editors)
    • I may be a newbie to Linux (but not anymore to Operation Systems)
  • You may be a newbie to a thing, but you may not to it in general.

Go newbies! Be scared not as I dont!, Bottom line is, ADempiere hall famers: red1, trifon, carlos, victor, mario, low, teo, colin, karsten(,..etc) were once all newbies(except that they were conceived with keyboard on their hands). Though they got a lot of experience gathered for years, who will take their place when they retire, if not us(newbies). Long live ADempiere!

  • Oops!, newbie ask: How about jj(jorge janke)?. I'm afraid he was not once a newbie!
  • Ans: I don't know!, just believe he was once in his life :-)
  • Seriously, I really adored jj for the wonderful design. I wonder why if he didn't get dizzy designing such, involving closely related objects.

ADempiere Notes

These are the compilation of my personal notes on ADempiere, influence much of

  1. The tuturials I've read(on this wiki, compiere docs, even openbravo's guides)
  2. The answers to my help yells on the sf forums.
  3. The crazy experimentation that I've done towards the software.

There are equivalent tuturials scattered everywhere, but these notes should be useful for impatient starters who wants a short reading and faster learning with regards to ADempiere. Good luck impatient readers!

xlib_lock failure in Linux

  • Behaviour:
    • the java virtual machine dont work
    • this is caused by library conflicts between java and xinerma, I think.
  • Solution/Workaround:
    • use the sed workaround(as suggested in sun's forum.)
      1. Locate the file (ie, /opt/jdk1.5.0_15/jre/lib/amd/xawt/
      2. Be root, then issue the command:
 sed -i 's/XINERMA/FAKEEXTN/g' /opt/jdk1.5.0_15/jre/lib/amd/xawt/ 
  • I've tested it both on WereWolf(Fedora Core 8) and Hardy Heron(Ubuntu 8.04), and it works.
  • Note: more or less, in jdk1.6.0 or above, this issue has already been eliminated

The AD in ADempiere

  • AD ( Application Dictionary ) "The application is configured by a module of the application itself".
  • In order to appreciate ADempiere, you should be able to understand how the AD works, and at least have a hands on "know how" on how to do it.
  • I refer a window in ADempiere as "AD Window" so as not to confuse from an ordinay windows in every application

Master/Detail Tabs

"I really had a hard time on how to set that up , thanks to Karsten for the guidance" Master/Detail tab relationship is the basic of ADempiere know how, that every newbie should be able to have.

  • Terminologies/Notes:
  1. Master/Detail - a list of master records, each has its own set of records(detail) that pertains to it.
  2. Master Records is also known as Header.
    • Header is much more applicable when we are talking of tables
    • Master is more appropriate when we are talking about records
  3. Tabs are tables that are used in an AD Window construct.
  4. When a certain tab is a detail of the Master tab, assuming that the tab level of the Master tab is 0,then the Detail tab must have a tab level set to 1.
  5. In my presumption, this is the step which often neglected by newbies and alike.
  • Requirement:
  1. In order to create a Master-Detail tab, you should have the 2 table that relates as Master and detail.
  2. The Detail table must have the key column of the Master table -- (General Knowldege, of course)and must be have a reference of "Table Direct" and marked as "Parent Link Column"
  • Example/Scenario:

In a certain Product Manufactured. Every Model has its own set of R numbers.

  1. Master Table: "Model" - can have it as "tt_Model" (test table Model)
  2. Detail Table: "R number" - can have it as "tt_Rno" (test table R Number)
  3. "tt_Rno" must have a column "tt_Model_ID" as "Table Direct" and marked as "Parent Link Column"
    • "Table Direct" Reference could still be used from other window, this field is read-only, it will be set in the underlying scripts that handles the window
  4. To Refect this to your AD Window (ie, Model)
  5. Have the two table as tabs of the window.
  6. Set the tab level of R number to 1. No need to set tab level of Model to 0, since it is 0 by default.
  • Refer to NewWindow for a detail tuturial on this.

Collapsable Detail Tab displayed in the Master Tab

  • The Detail tab could be displayed in the Master tab of you AD Window.
  • This feature has been implemented in Release 331t on January 2008 (I was not involved to Adempiere at this time),with prominent faces of the legendary Victor Carlos Perez(saludo!)
  • Steps to do this:
  1. You must have successfully set the Master/Detail tab in my previous note.
  2. Select a Field(column) in your Master Tab which will be used as "Marker"(entity replacement) to be replaced by the Detail tab when organizing the AD Window. I usually use "Searh Key", since most likely the user needs not to fill them.
  3. In "Search Key" record, Set the "Included Tab" to Detail Tab
  • You should now see that the detail tab of your AD Window is being displayed in the Master Tab.

Synchronize Column

Synchronize Column - creates the physical table into the database.Take note that a table you create using AD in "Table & Columns" is not created yet in the database, even if you are using "Copy Column from Table" button. If you are using "Create columns from DB", of course you should already have a physical table in the database, and this is a reverse process of "Synchronize Column".

Synchronize Column - reacts differently on two situation.

  • Condition 1:If you had just constructed your table using AD this goes that you don't have the physical table yet.You may look at it using Database Admin Software(ie. Toad, PgAdmin) if you are skeptic( as I do).
  • Reaction: Synchronize column will create the table, and the columns associated with it. Look at your Toad to prove.
  • Condition 2:If the physical table has been created (perhaps via Condition1)
  • Reaction: Each column is updated if something has been change(ie. its datatype/referece).If the column is new, it is added to the physical table.
  • Note: Each time you delete a column in AD table definition, make sure you also delete the equivalent column in the DB physical table, especially for columns that were defined as Mandatory. This is to prevent errors such as "Mandatory error constraint". You may also stupidily choose not to delete the columns, provided that you set them as "inactive" or "non-mandatory" in the AD Table definition. It's up to you. But I suggest, you delete those equivalent columns in the database for "seiri"(cleanliness?) sake!

Copy Columns from Table

  • "Copy Columns from Table" has an attached process which will copy the columns of an AD Table specified. All columns will be copied except for the key column(<specified_table_name>_ID) of the specified AD Table. Instead, along with the copied columns it will also create a key column for your own table(<your_table_name>_ID). Wow, isn't that easy!(Thanks to the developers!, wonderful).
  • This will function only if and only if the AD Table definition has no physical table in the database yet. Also this don't create the actual database columns in a physical table (Again, the changes/creation of the physical table is done via "Synchronize Column").
  • Tip:If you want to create a basic table structure(which you would likely modify later) use the "M_FreightCategory" table, since this contains the most basic columns required for you to be able to include/create the table for your AD Window.

You can also create the columns of you table one by one(Creating/Reusing a system element, Inserting them one by one to your AD Table as Columns, etc...tiresome..) without using "Copy Columns from Table" functionality.

Create Columns from DB

  • "Create Columns from DB" this also has an attached processed that does the exactly the opposite of "Synchronize Column".

"Create Columns from DB" creates an "AD Table Column definition" based on the physical table on the Database.

  • Note: I used physical table when I refer to the actual table in the database, so as not to confuse reader from the table in AD Table, which are table definition only, stored in AD.
  • This functionality is not very useful to everyone, but for others it may. Just to point out, Create Columns from DB is applicable when you had designed your database structure before you had encountered ADempiere, and you dont want to redundantly recreate them again using the AD(especially if it involves lots of tables).
  • Important: If you prefer using this option, you must have to review your database structure, so as it conforms the ADempiere standards, to avoid problems later on. Standards such as <table_name>_ID naming instead of <table_name>_key as most database designs are. You should also consider data types uniformity such as Numeric instead of Integer(in PostgreSQL).
  • Oops, using this option still gets your way still complicated! So, I suggest you re-create your database structure definition using the AD.
  • This offers ample advantages:
    1. You can refresh your mind regarding on the database structure that you have designed(especially when it was designed wayback around 19... you don't remember anymore!)
    2. It gives you a solid hands-on experience on using ADempiere not just on developing it but also as a whole(yes!, as a whole) since ADempiere is designed to be consistent in all aspect, whether you are designing its functionality or you are using it in your business scenario. Same familiar steps/processes are repeated over and over again, what that differ is the data you are handling.
  • If you have to build the your system or extensions from scratch(I mean the database, from scratch) and will be based on ADempiere, Well you dont have to use this functionality. You should enjoy using the comfortable "Copy Columns from Table" functionality instead.

Display Logic

  • Display Logic allows you to dynamically control the display of controls/fields just as they are needed, so as not to confused/distract the user.

This allows you to configure the display behavior(show/hide) of fields of a certain AD Window. This is very useful when you wanted to have a user friendly User Interface Window. This also applies to Show/hide of tabs for each corresponding window.

Syntax: @<db_column_name>@=<validation_search_key> @<context_variable>@=<value>

Default Logic

When a field is a look-up to a table list validation and you intend to have a default value, the default logic must be the Record_ID of the look-up table (ie. 100000) or you could have a SQL statement. The SQL statement will return the Record_ID from the DWS_Barangay Table where that Barangay name is 'Mayakabac'

  • @SQL=SELECT DWS_Barangay.DWS_Barangay_ID FROM DWS_Barangay WHERE DWS_Barangay.DWS_Barangay='Mayakabac'

Note: Barangay(ph) = District(en) The field is filled up only when the save button is pressed. The value of the

Dynamic Validation

  • Dynamic Validation behaves likely as References in Table and Columns, it only differs that the set of values referred to other table can change depending on how you use it.

This is very much useful when you wanted to have a suppressed list of values that is applicable according to the set of inputs created by the user. Likely the Dynamic Validation has a where statement that related to the set of user inputs. Dynamic Validation is invoked when a other fields/own fields changes.

Column SQL

  • Column SQL (Also known as Virtual Columns) - useful for read-only/computed fields.

This could be used to return a value that is looked up from other table. You can take Column SQL as a sub-query of your ordinary SQL statements.

  • Remember: Sub-query must return only 1 record!(You should probably have where statement here).
  • Useful SQL keywords:
    • "coalesce" - could be used as a replacement of "decode" in Oracle. 'coalesce provides a way to return the second argument if the first argument is null
    • "case-when-then-else-end" - acts like a if-then-else in programming(I have just learned this too, maybe we are indulge too much with "decode"). It is also applicable for both Oracle and PostgreSQL. I find "case-when-then-else-end" more handy and comprehensive than "decode".
  • Sample for Column SQL
(SELECT "dws_customer_information"."dws_cust_info_first_name"||'  '||coalesce("dws_customer_information"."dws_cust_info_middle_initial",' ')||'  '||"dws_customer_information"."dws_cust_info_last_name"||'  '||coalesce("dws_customer_information"."dws_cust_info_name_ext",' ') FROM "dws_customer_information" WHERE "dws_customer_information_id"="dws_reading"."dws_customer_information_id")
  • Important: You need to wrap the Column SQL with parenthesis, since that Column SQL will be merge into the Main SQL statement as a sub-query. Note also that a sub-query must return only one record, so you must design it to return only one record.

Process vs Callouts

  • A Process assigned to a button(mostly and appropriate) is applicable for server process and appropriate when you need an extra parameter for processing.
  • Callout is applicable of processing and accessing the values on the fields (which are created on the client side and not on the server side).
  • Callout is appropriate when you want a precalculation of values for other fields in an AD Window before it is saved into the database.
  • Callouts can be assigned to any fields/controls (ie, Button, combobox,checkboxes,textboxes, etc.)


  • Identifier mark a column to be a part of the unique
  • When columns are marked as identifier(this goes that they belong to be a member of unique), the values of the column are concateneted with "-" with respect to the sequence order, when the table is referred in other table when displayed in the AD Window.

Create Fields

  • Create Fields - this automatically create the fields of your AD Window based on the column definition you have created in the AD Table. This fills up the fields tab in the "Window Tab & Fields" Window. You could use this functionality even you haven't created the physical table yet, in fact, the AD Window is already ready to be shown. The error arise when you start to input a new record, of course error spits out since there's no appropriate table for the AD to save that record.

Image Reference

Image Reference is a field in which the actual image is stored in AD_Image with its either binary data or image url. When your table needs an image, Make sure your Column ends with "_ID"(prefer to use the predefined column "Logo_ID" as of version 354 ) in a way this would be treated as numeric when created into the database. Failure to do so will see a cast error of String != Integer.

Java Version

  • Using ADempiere 342 ( stable ) for production deployment which is using the jdk1.5.0 jvm, there's seems not a problem, but when trying to see the ZSS ( zk spreadsheet application demo ) which would not run in jdk1.5.0, I installed jdk1.6.0 to make it work. After a few days to be back in using ADempiere, i see that something is wrong, such as: using the "Copy Columns from Table" in "Table and Column" AD_window, the dialog box, don't display anything. So with when using other windows such as "Pack Out" dialog boxes is empty. I first thought it was a postgresql error, until i tap on the command line
$java -version
java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) 64-Bit Server VM (build 11.3-b02, mixed mode)

It was the cause, so the solution is obvious, set the JAVA_HOME and PATH back to jdk1.5.0 here is my configutarion:

#file: /etc/profile.d/
#for jdk1.5.0
export JAVA_HOME=/usr/java/jdk1.5.0_18
export PATH=$JAVA_HOME/bin::$PATH

#for jdk1.6.0  commented, since not in used
#export JAVA_HOME=/usr/java/jdk1.6.0_13
#export PATH=$JAVA_HOME/bin::$PATH

do a bash once again to take the changes

$java -version
java version "1.5.0_18"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_18-b02)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_18-b02, mixed mode)

ReRun Adempiere

Some of my contributions

Some nice words about me

Some thoughts

Full Web App

  • You could have a web application act as a full desktop application. The thing that web app can not do, is to access the your local file system and peripheral devices. But this could be patch up using AIR (Adobe Integrated Runtime)
    • Using AIR as a substitute of a browser,


    • Create a swf file, as part of your web-app, then interact with it using FA_bridge.js
    • Create an AIR application which will be installed in the local computer of the user. This will be the agent for your web-app request
    • Let your web-app communicate the swf of your web-app, and let the swf part of your web-app communicate with AIR using local-connection.
    • I will try to elaborate this later-on.

Simplest way to network two computers

  • You could network your two computer using an ordinary LAN cable only.
    • I heard about this long ago, but I am very skeptic to believe them, until I've tried it last week(just last week, and it worked)

Simple, Reliable ADempiere PITR back-up

  • PITR - Point in time recovery, means you have the ability to restore your database status as it was in a certain point in time that you had made a back-up
  • This is very useful for the prevention of risk!, especially when in time of disaster, or your system is hacked!
  • Applicable for daily back-up only
  • Utilizes two reliable simple and reliable technoloy
  1. Use of version control (ie, subversion)
  2. Use of dump (ie pg_dump) in PostgreSQL


  • You should already had a working SVN version control

Steps to follow

  • Set- up a new repository in your SVN
  • Name it at your preference(i.e, repos/ADempiere_PITR )
  • Set up a directory (like a development directory) which will contain the dump file
  • Dump your database to you ADempiere PITR working directory
     pg_dump > Adempiere_pitr.dmp
     sample pg_dump command
     pg_dump -U adempiere adempiere354 > Adempiere033110.dmp
  • SVN add ADempiere_pitr.dmp
  • SVN commit ADempiere_pitr.dmp
    • This should put your file into the SVN repository as revision 1 (you need to take note of the date)
    • The next time you wanted to make a backup follow the same process as a version control
    • pg_dump > Adempiere_pitr.dmp again, (This will overwite the file ADempiere_pitr.dmp)
    • Commit it again to the SVN Repository

Recovery Steps

  • ( Optional )Back-up your last database status, this might be useful for future resource and documentation.
  • Shutdown your application server and any other application that might be accessing the database(This is to stop service momentarily, to avoid user access to the database)
  • Drop your database schema
   psql -U adempiere -d adempiere -c "drop schema adempiere cascade"
   psql -U adempiere -d adempiere -c "drop schema sqlj cascade"
  • svn update your Adempiere_pitr.dmp to any revision you intend to (based the revision to the date of the commit)
  • restore the database
   psql -U adempiere -d adempiere -f Adempiere_pitr.dmp


  • No needed downtime
  • Simple and reliable
  • Save disk space, since SVN stored them in a logical way that it saves disk (only changes from the previous file is actualy saved)
  • No new technologies involved, use svn as you are used to using it :-)


  • Everytime you create you back-up, the whole database is read, since we are using dump
  • Can't be used to have a per minute hot back-up. If ever you do,then your server performance will be affected

Hacker for hire!!!

  • I am planning to quit my job, as I see the light in ADempiere!
  • I got potential clients, not served yet!
  • I can't do this alone! There are still areas on the deployment process, which I can't really have confidence, such as security, hot back-up, etc!.
  • I'm looking for ADempiere oppurtunities, employer, partnership, etc..
  • Any interest? email me: ivanceras at google's mail server .com

Short Notes

  • No space should be used in a DB column when defining in AD.
  • getting Adempiere home directory is in: org.compiere.util.Ini.findAdempiereHome
  • Hiding the Performance Analysis Panel(the charts displays as a dashboard) is configured by setting all the Performance Goals records inactive in "Performance Goal" AD Window.
  • Changing the generated report output format is done in "zkwebui/WEB-INF/src/org/adempiere/webui/window/". This applicable for the web interface, of course. You can alter the default output format(pdf) to html, you need a temporary file for this.To impress the user, you could also changed the format to "xls"(temp file), then have it be viewed using the ZSS spreadsheet(ZK spreadsheet) component. The user could view the report as a spreadsheet in the browser, as if he/she is used to view a spreadsheet in a desktop.

Useful Links

Finally I have convinced myself to start blogging

I have created a blog which talks about my interest. and one of them is this open source software ( ADempiere )

ADempiere Wishlist

These are my wish list for ADempiere. These are minor "nice to have" features and functionality(mostly focused on UI and user friendly experience), which perhaps I would like to implement in the future, when Im ready for the code battle.

  1. There must be a more intuitive way to delete multiple records.(ie. Multiple selection of Records and then pressing the delete button)
  2. There must be an easy way to configure the toolbars
    • There must be an easy way to override, hook-up, extend functionality of standard toolbar buttons (ie. the report button could be configured to execute a different report(ie. jasper reports/process) other than the "not so flexible" generated default report by the report engine.
      • (This is already possible, I just haven't dig it deeper :) )
    • There must be a way to stripped off the toolbars in an included tab, such as the "Save button" functionality in the included tab will be carried by the its Parent Tab, report button, archive and history. These menu are most likely will not be useful in the included tab, since these records will mostly be included in the parent tabs (ie when creating a report).
    • There must be an easy way to add custom menu on the toolbar for processes that are not covered by the standard menu on the toolbar, example of which are custom functions to direct users to their recommended/next move.
  3. Image presentation needs to be improved, display in both the swing and the zkwebUI client. The image could span more than 1 colum, or 1 row if needed, depends on the size/aspect ratio of the image.
  4. A need to have new field type: HTML. There is a partial implementation on this on text and could still be viewed in Html, swing has no way we could edit the HTML. In zkwebUI it is editable and working great uing the FCKeditor.
    • The HTML field type must be displayed in Html by default to allow the user to see the data at once.
    • When the user clicks on the field, that's the time the FCKEditor, will be attached to the field in edit mode.
    • Even when the the record is viewed in Multiview, the HTML must remain intact in its HTML display.
  5. Combine the Single Row View and Multi-Record view
    • By default, windows will be viewed in Multi-Record, when the user clicks on a Record, that record will be put up in the Single Row view, while all the others will are still displayed in Multi-Row at the same Panel(scrollable), at the bottom or at the top of the Viewed record whichever they are arranged. When the user clicks on another record, the Singe-Row view switches to the selected record.


The notes, that I am writing here may not be accurate since I'm still a newbie. The reader should not take it seriously as a reference, rather as a hint only. If you discover that the idea/"know how" I presented here is wrong or inappropriate, feel free to modify it. Other notes here are just rewriting to short notes I've gathered (don't remember where have I gotten those). One reason why I'm writing this notes is for others(new newbies alike) to accelerate their learning towards ADempiere by giving hint in such a way they will suffer lesser pain than those who have dived prior to them.

Where is ivanceras now?

As you have notice, I am not active for the past months, it is because im currently working in commercial IT firm as a programmer. I may come back from time to time to see what's new and continue my pending improvements during my little free times.

Im back

After a long while im back into a project which uses Adempiere. Wow, a lot of changes has been here.

I guess I have to continue pending features and improvements.

Looking forward to contribute patches and codes.

Projects Im working on

Recently I have been working with some experiments with ADempiere Application Dictionary Data to have it work in Google App Engine.

Here is the link to the blog