Author: red1 - red1org@gmail.com Heritage: Evolved from org.red1.ninja (2018-2019)
Generate complete iDempiere plugins from simple Excel definitions. No coding required for basic AD models.
Ninja was originally developed as org.red1.ninja featuring:
- Model generation from Excel/CSV definitions
- Kanban board auto-generation
- Print format generation
- Yandex translation integration
- Workflow structure generation
This new version (org.idempiere.ninja) is a modernized rewrite focusing on:
- Silent command-line operation
- Standalone 2Pack generation
- Complete OSGI plugin scaffolding
- Process and Menu sheet support
# Generate everything from Excel
./RUN_Ninja.sh MyModule.xls
# Result: Complete OSGI plugin ready for Eclipse importExcel (MyModule.xls)
│
▼
┌─────────────────────────────────────────────────┐
│ NINJA PROCESSOR │
├─────────────────────────────────────────────────┤
│ │
│ Mode A: Inject AD Models into Database │
│ • Creates AD_Table, AD_Column, AD_Window... │
│ • Synchronizes tables to PostgreSQL/Oracle │
│ │
│ Mode B: Generate 2Pack.zip │
│ • Creates distributable 2Pack file │
│ • Ready for Incremental2PackActivator │
│ │
│ Mode C: Create AD_Package_Exp Records │
│ • Prepares for future changes via PackOut UI │
│ │
│ Mode D: Generate OSGI Plugin Structure │
│ • Complete Eclipse project ready to import │
│ • META-INF/MANIFEST.MF, plugin.xml, etc. │
│ │
└─────────────────────────────────────────────────┘
│
▼
org.idempiere.mymodule/
├── META-INF/
│ ├── MANIFEST.MF
│ └── 2Pack_1.0.0.zip
├── src/
├── plugin.xml
├── .classpath
├── .project
└── README.md
| Property | Value |
|---|---|
| Bundle-Name | org.idempiere.hr |
| Bundle-Version | 1.0.0 |
| Bundle-Vendor | My Company |
| Package-Prefix | org.idempiere.hr |
| Entity-Type | U |
Row 1 = Reference names (creates AD_Reference) Row 2+ = List values (creates AD_Ref_List)
| Status | Priority | DocType |
|---|---|---|
| Draft | High | Standard |
| Active | Medium | Return |
| Closed | Low | Warranty |
┌────────────────┬───────────┬────────────┬───────────────┐
│ A │ B │ C │ D │
├────────────────┼───────────┼────────────┼───────────────┤
│ HumanResources │ │ │ │ <- Row 1: Main menu (A1)
│ │ Employee │ Department │ Employee │ <- Row 2: Tables (B=parent, C=parent, D=child of B)
│ │ L#Status │ Name │ Employee │ <- Row 1 defines master/parent relationships
│ │ Name │ Code │ D#HireDate │ <- Row 3+: Columns
│ │ A#Salary │ T#Desc │ DepartmentRef │
│ │ D#Birth │ │ │
└────────────────┴───────────┴────────────┴───────────────┘
Row 1: Cell A1 = Main menu name. First 2 chars become table prefix (e.g., "HumanResources" → "HR_")
Row 2: Table/Window names. Each non-empty cell creates a Table + Window + Tab
Row 3+: Column definitions for each table (column by column)
| Prefix | Type | Length | Example |
|---|---|---|---|
| (none) | String | 22 | Name |
| S# | String | 22 | S#Description |
| Q# | Quantity | 11 | Q#OrderQty |
| A# | Amount | 11 | A#Salary |
| Y# | Yes/No | 1 | Y#IsManager |
| D# | Date | - | D#HireDate |
| d# | DateTime | - | d#LoginTime |
| T# | Text | 2000 | T#Comments |
| L# | List (Ref) | - | L#Status |
Auto-detection: Columns ending in _ID become TableDir references. Columns named IsXxx become Yes/No.
Define processes with optional table linkage (gear icon):
| ProcessName | Class | Table | Parameters |
|---|---|---|---|
| CheckUpdate | org.idempiere.process.CheckUpdate | UD_History | ForceCheck:YesNo |
| RunReport | org.idempiere.process.RunReport | StartDate:Date, EndDate:Date |
Parameters format: ParamName:Type (comma-separated)
Types: String, YesNo, Integer, Date, DateTime, Amount, Quantity, List, TableDir
Override auto-generated menu hierarchy:
| MenuName | Type | Action | Target | Parent |
|---|---|---|---|---|
| HR System | Summary | |||
| Employees | Window | W | Employee | HR System |
| Run Payroll | Process | P | RunPayroll | HR System |
Sheet name must match table name (e.g., "HR_Department")
| Name | Code |
|---|---|
| Sales | SALES |
| HR | HR |
| IT | IT |
# All modes (default)
./RUN_Ninja.sh MyModule.xls
# Specific modes
./RUN_Ninja.sh MyModule.xls -a # DB inject only
./RUN_Ninja.sh MyModule.xls -b # 2Pack only
./RUN_Ninja.sh MyModule.xls -d # Plugin structure only
./RUN_Ninja.sh MyModule.xls -abd # All except PackExp
# Options
./RUN_Ninja.sh MyModule.xls -v # Verbose logging
./RUN_Ninja.sh MyModule.xls -o /tmp # Custom output directory| Flag | Mode | Description |
|---|---|---|
| -a | DB Inject | Create AD models in database |
| -b | 2Pack Generate | Create 2Pack.zip file |
| -c | PackExp Create | Create AD_Package_Exp for future changes |
| -d | Plugin Generate | Create complete OSGI plugin structure |
| -v | Verbose | Show detailed logging |
| -o | Output Directory | Specify where to generate files |
org.idempiere.mymodule/
├── META-INF/
│ ├── MANIFEST.MF # OSGI bundle configuration
│ └── 2Pack_1.0.0.zip # AD model definitions
├── OSGI-INF/ # Service component XMLs
├── src/
│ └── org/idempiere/mymodule/
│ └── Activator.java # Uses Incremental2PackActivator
├── plugin.xml # Eclipse extension points
├── build.properties
├── .classpath
├── .project
└── README.md # Module documentation
The templates/ directory contains example Excel files:
- VersionMaster.xls.txt - System utility plugin template (version tracking, plugin registry, backup management)
- Create Excel file with your model definitions
- Run:
./RUN_Ninja.sh MyModule.xls - Import generated plugin into Eclipse
- Test and customize
Option A: Re-run Ninja
- Update Excel file
- Re-run Ninja with new version in Config sheet
- New 2Pack will be created
Option B: Use iDempiere UI
- Ninja created AD_Package_Exp records (mode -c)
- Make changes in Application Dictionary
- Use PackOut to create new 2Pack
- Increment version in Excel Config sheet
- Run Ninja
- Copy new
2Pack_x.x.x.zipto plugin's META-INF/ Incremental2PackActivatorauto-imports on restart
Config sheet:
| Bundle-Name | org.idempiere.hr |
| Bundle-Version | 1.0.0 |
Model sheet:
| HumanResources | | |
| | Employee | Department |
| | Name | Name |
| | L#Status | Code |
| | A#Salary | |
| | D#Birth | |
Model sheet:
| SalesOrder | | |
| | Order | Order | <- Row 1: "Order" is parent of col D
| | DocNo | OrderLine | <- Row 2: Tables
| | Date | Q#Qty | <- Row 3+: Columns
| | A#Total | A#Price |
- iDempiere 11+
- Java 17+
- PostgreSQL or Oracle database
- Excel (.xls format - use LibreOffice or Excel)
Provide full path: ./RUN_Ninja.sh /full/path/to/MyModule.xls
Run from iDempiere server directory, or set IDEMPIERE_HOME
Ninja skips existing tables. Change table name or drop existing table.
Ninja provides helpful examples when Excel format is wrong:
[VALIDATOR] ERROR: Model sheet: Cell A1 is empty
┌─────────────────────────────────────────────────────────────┐
│ MODEL SHEET - CELL A1: │
│ │
│ Cell A1 must contain the MAIN MENU name. │
│ Example: │
│ ┌────────────────┬──────────┬────────────┐ │
│ │ HumanResources │ │ │ <- A1 │
│ └────────────────┴──────────┴────────────┘ │
└─────────────────────────────────────────────────────────────┘
Standalone tool for deploying iDempiere AD models and data without requiring iDempiere runtime.
Silent = No iDempiere Runtime Required
Traditional iDempiere development requires running server, OSGi container, full application context.
SilentPiper bypasses all of that:
- Direct JDBC to PostgreSQL
- Pure Java + SQLite for staging
- PIPO-compatible output
Excel → SQLite → 2Pack → PostgreSQL
(silent) (silent) (silent)
| Operation | iDempiere Required? | Database Required? |
|---|---|---|
stage |
No | SQLite only |
packout-model |
No | SQLite only |
packout |
No | SQLite only |
import-silent |
No | PostgreSQL (JDBC) |
apply-data |
No | PostgreSQL (JDBC) |
import |
Yes | PostgreSQL + iDempiere |
apply |
Yes | PostgreSQL + iDempiere |
# 1. Stage Excel model to SQLite (offline)
java -jar SilentPiper.jar ninja.db stage HRMIS.xlsx
# 2. Generate AD model 2Pack (offline)
java -jar SilentPiper.jar ninja.db packout-model HRMIS ./output
# 3. Import to PostgreSQL (no iDempiere runtime needed!)
java -jar SilentPiper.jar ninja.db import-silent ./output/HRMIS_Model_1_0_0.zip| Command | Description |
|---|---|
stage <excel.xlsx> |
Parse Excel intent model to SQLite |
show [bundle] |
Display staged models |
| Command | Description |
|---|---|
packout-model <bundle> [dir] |
Generate AD 2Pack from SQLite (OFFLINE) |
packout <pack> [dir] [client] |
Export staged data to 2Pack |
packout-ad <prefix> [dir] |
Export AD model from PostgreSQL |
packout-model generates PIPO-compatible 2Pack containing:
- AD_Element, AD_Table, AD_Column
- AD_Window, AD_Tab, AD_Field
- AD_Menu
| Command | Description |
|---|---|
import-silent <2pack.zip> |
Import 2Pack directly via JDBC |
apply-data <pack> |
Insert staged data directly |
import-silent workflow:
2Pack.zip → SAX Parser → SQL INSERT/UPDATE → PostgreSQL
(no iDempiere classes needed)
Supported: All AD_*, MP_*, A_ASSET* tables
| Command | Description |
|---|---|
sql2pack <data.sql> |
Parse SQL INSERT statements to SQLite |
packs [name] |
Show staged data packs |
applied <pack> |
Show applied records |
clean-data <pack> |
Delete applied records |
| Command | Description |
|---|---|
sync-ad |
Pull AD model from PostgreSQL to SQLite |
info |
Show AD model statistics |
history [limit] |
Show operation history |
# Stage, generate, deploy - all without iDempiere running
java -jar SilentPiper.jar ninja.db stage ./models/HRMIS.xlsx
java -jar SilentPiper.jar ninja.db packout-model HRMIS ./output
java -jar SilentPiper.jar ninja.db import-silent ./output/HRMIS_Model_1_0_0.zipjava -jar SilentPiper.jar ninja.db sql2pack ./data/sample.sql
java -jar SilentPiper.jar ninja.db packout GW_Sample ./output 11
java -jar SilentPiper.jar ninja.db apply-data GW_SampleBuilt-in commands for modifying existing PackOut.xml files.
Apply SQL UPDATE statements to PackOut.xml directly without database connection.
# Apply single SQL file
SilentPiper ninja.db xml-update PackOut.xml updates.sql
# Apply all SQL files from directory
SilentPiper ninja.db xml-update PackOut.xml ./sql_updates/
# Output to different file
SilentPiper ninja.db xml-update PackOut.xml updates.sql PackOut_fixed.xmlSQL Format Supported:
-- Update by ColumnName (AD_Element)
UPDATE AD_Element SET Name='New Name', Help='New help' WHERE ColumnName='MyColumn';
-- Update by ID (AD_Window, AD_Tab, AD_Field, etc.)
UPDATE AD_Window SET Name='Employee Window' WHERE AD_Window_ID=123;
-- Update by Name (AD_Menu)
UPDATE AD_Menu SET Name='HR Menu' WHERE Name='Old Menu Name';Features:
- NO database connection needed (pure XML transformation)
- Preserves original XML formatting
- Handles large AD_Window elements (5000+ lines)
- Skips EntityType='D' (core dictionary)
- Applies ALL matching rules per element
Use Case: Update Help text, Names, translations in existing 2Pack without re-exporting.
Sync PackOut.xml with current database values.
# Sync and overwrite
SilentPiper ninja.db xml-sync PackOut.xml
# Sync to new file
SilentPiper ninja.db xml-sync PackOut.xml PackOut_synced.xmlFeatures:
- Updates Name, Help, Description from database
- Only updates EntityType='U' (user/module elements)
- Skips core dictionary (EntityType='D')
- Supports: AD_Element, AD_Window, AD_Tab, AD_Field, AD_Process, AD_Form, AD_Menu
Use Case: Pull latest Help text from database into existing 2Pack.
- PIPO Insight - Deep-dive into iDempiere's 2Pack architecture
GPL v2 - Free for commercial and non-commercial use.
Report issues and contribute at: https://github.com/red1oon/org.idempiere.ninja
Ninja - Making iDempiere plugin development accessible to everyone