Apache OFBiz Developer Guide

Administrator 8
apache ofbiz developer guide

Apache OFBiz (Open For Business) is a suite of enterprise applications built on a common architecture using common data, logic and process components. The loosely coupled nature of the applications makes these components easy to understand, extend and customize.

OFBiz is distributed as open source software and it is licensed under the Apache License Version 2.0 (ASL2) which grants you the right to customize, extend, modify, repackage, resell, and many other potential uses of the system.

I would recommend to have basic understanding of OFBiz first, you can read through my earlier post here.

OFBiz’s tools and architecture make it easy to build and manage enterprise applications efficiently. When you have a particular need, it also makes it easy to customize and expand existing features.

The architecture of OFBiz itself makes it easier for you to tailor the applications to your needs,

In this Apache OFBiz Developer guide we will walk you through how to start working with different modules of OFBiz. We will learn how to create an application, entities, services, events, forms, customizing UI and more.

Excited?? So, lets get started then!

Install and Run OFBiz

To install and run OFBiz on windows or linux machine please go through my earlier post.

Please make sure you have OFBiz up and running to continue with next topic.

Create OFBiz Plugin/Component

The OFBiz component is a folder that contains a special xml file called ‘ofbiz-component.xml’ that defines the resources that the component requires to be loaded and requested. OFBiz is a set of components as below:

  • framework components:  These are lower-level components that provide the application components with the technical layer and tools; the features provided by these components are generally those provided by every other development system (data layer, business logic layer, managing transactions, data sources, etc…)
  • application components: These are generic business components needed for extensible/customizable ERP applications (product, order, group, manufacturing, accounting, etc.). Application components have access to the resources and tools provided by the components of the system and to the services published by other components of the application.
  • plugins components: These modules are similar to application components, but intended for applications such as e-commerce, Google base integration, eBay integration, etc., for special purposes.

To create a custom component execute below command

gradlew createPlugin -PpluginId=ofbizDemo
apache ofbiz plugin

  Now, lets update a file just to say “Hello World” and will see how to build and run OFBiz to see our change

Open file /plugins/ofbizDemo/widget/OfbizDemoScreens.xml file from ofbizDemo plugin and just add “Hello World”

<?xml version="1.0" encoding="UTF-8"?>
<screens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-screen.xsd">
    <screen name="main">
        <section>
            <actions>
                <set field="headerItem" value="main"/><!-- this highlights the selected menu-item with name "main" -->
            </actions>
            <widgets>
                <decorator-screen name="OfbizDemoCommonDecorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <label text="Hello World!! :)"/>

                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>
</screens>

Now restart the OFBiz using below command

gradlew loadAll ofbiz

Once OFBiz restarts enter below url in the browser  https://localhost:8443/ofbizDemo

You will be asked to login. Login with user: admin password: ofbiz.

As you login, you will see ofbizdemo application up with the hello world message you have put in screen as shown in below given image. apache ofbiz application

Create OFBiz Database Entity (Table)

OFBiz Entity

To create custom Entities/Tables in database, you need to provide entity definition in  /plugins/ofbizDemo/entitydef/entitymodel.xml file of your ofbizdemo application. You simply need to go in and provide entity definition as shown below. Here we are going to add two new entities for ofbizdemo application.

<?xml version="1.0" encoding="UTF-8"?>
  
<entitymodel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/entitymodel.xsd">
  
    <title>Entity of an Open For Business Project Component</title>
    <description>None</description>
    <version>1.0</version>
  
    <entity entity-name="OfbizDemoType" package-name="org.apache.ofbiz.ofbizdemo" title="OfbizDemo Type Entity">
        <field name="ofbizDemoTypeId" type="id"><description>primary sequenced ID</description></field>
        <field name="description" type="description"></field>
        <prim-key field="ofbizDemoTypeId"/>
    </entity>
  
    <entity entity-name="OfbizDemo" package-name="org.apache.ofbiz.ofbizdemo" title="OfbizDemo Entity">
        <field name="ofbizDemoId" type="id"><description>primary sequenced ID</description></field>
        <field name="ofbizDemoTypeId" type="id"></field>
        <field name="firstName" type="name"></field>
        <field name="lastName" type="name"></field>
        <field name="comments" type="comment"></field>
        <prim-key field="ofbizDemoId"/>
        <relation type="one" fk-name="ODEM_OD_TYPE_ID" rel-entity-name="OfbizDemoType">
            <key-map field-name="ofbizDemoTypeId"/>
        </relation>
    </entity>
  
</entitymodel>

See the /plugins/ofbizDemo/ofbiz-component.xml file now. You already have a resource entry generated in it to load these entities when loading components from their definitions to the database.As shown below:

<entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel.xml"/>

To verify, simply re-start OFBiz (Ctrl+C followed by “gradlew ofbiz”) and enter below url in the browser to load Entity Data Maintenance Tool  https://localhost:8443/webtools/control/entitymaint and search for entities OfbizDemoType and OfbizDemo. You will see it as shown in below given image. ofbiz-entities

As you have setup your custom entities, now we will see how to prepare some sample data for it. You can do it in data XML files already setup under data directory of your component as  $OFBIZ_HOME/plugins/ofbizDemo/data/OfbizDemoTypeData.xml and  $OFBIZ_HOME/plugins/ofbizDemo/data/OfbizDemoDemoData.xml. Set it up as shown below:

OfbizDemoTypeData.xml

<?xml version="1.0" encoding="UTF-8"?>
<entity-engine-xml>
   <OfbizDemoType ofbizDemoTypeId="INTERNAL" description="Internal Demo - Office" />
   <OfbizDemoType ofbizDemoTypeId="EXTERNAL" description="External Demo - On Site" />
</entity-engine-xml>

OfbizDemoDemoData.xml

<?xml version="1.0" encoding="UTF-8"?>
<entity-engine-xml>
   <OfbizDemo ofbizDemoId="SAMPLE_DEMO_1" ofbizDemoTypeId="INTERNAL" firstName="Sample First 1" lastName="Sample Last 1" comments="This is test comment for first record." />
   <OfbizDemo ofbizDemoId="SAMPLE_DEMO_2" ofbizDemoTypeId="INTERNAL" firstName="Sample First 2" lastName="Sample last 2" comments="This is test comment for second record." />
   <OfbizDemo ofbizDemoId="SAMPLE_DEMO_3" ofbizDemoTypeId="EXTERNAL" firstName="Sample First 3" lastName="Sample last 3" comments="This is test comment for third record." />
   <OfbizDemo ofbizDemoId="SAMPLE_DEMO_4" ofbizDemoTypeId="EXTERNAL" firstName="Sample First 4" lastName="Sample last 4" comments="This is test comment for fourth record." />
</entity-engine-xml>

Now again have a look at $OFBIZ_HOME/plugins/ofbizDemo/ofbiz-component.xml file. You already have resource entry made in it for loading data prepared in these files as:

Entry to be done in ofbiz-component.xml

<entity-resource type="data" reader-name="seed" loader="main" location="data/OfbizDemoTypeData.xml"/><entity-resource type="data" reader-name="demo" loader="main" location="data/OfbizDemoDemoData.xml"/>

Loading data in entity

At this moment to load this sample data into entities/tables defined you can either run ./gradlew loadAll on console or can directly go here in webtools to load entity  https://localhost:8443/webtools/control/EntityImport.

Simply put your xml data in “Complete XML document (root tag: entity-engine-xml):” text area and hit “Import Text”, as shown in below given image ofbiz-import-data

As you will hit Import Text, it will load data and will show the result as shown below ofbiz import data success

That’s it, you have successfully imported the data in the database tables, super easy, right!

Form and Services

In our previous section, we have seen how to create the entities (tables), now it’s time to create a form which will allow you to make entries in that entity.

Create a Service

Before preparing form, let’s write a service to create records in database for OfbizDemo entity in service definition xml file /plugins/ofbizDemo/servicedef/services.xml

services.xml

<?xml version="1.0" encoding="UTF-8"?>
<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/services.xsd">
<description>OfbizDemo Services</description>
<vendor>
</vendor>
<version>1.0</version> <service name="createOfbizDemo" default-entity-name="OfbizDemo" engine="entity-auto" invoke="create" auth="true">
<description>Create an Ofbiz Demo record</description>
<auto-attributes include="pk" mode="OUT" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="false"/>
<override name="comments" optional="true"/>
</service>
</services>

Now again have a look at /plugins/ofbizDemo/ofbiz-component.xml file. You already have resource entry made in it for loading services defined in this file as:

<!-- service resources: model(s), eca(s) and group definitions --><service-resource type="model" loader="main" location="servicedef/services.xml"/>

For this service definition to load you will need to restart OFBiz.

To test this service you directly go to webtools -> Run Service option here: https://localhost:8443/webtools/control/runService

Running service via Web Tools: This is a smart utility provided by framework to run your service.

On submission of the form above, you will presented a form to enter IN parameters of the service.

Create a Form

Let’s create our first form for this service and for that let’s edit the existing file at location /plugins/ofbizDemo/widget/OfbizDemoForms.xml and add Create Form for OfbizDemo as shown below: OfbizDemoForms.xml

<form name="FindOfbizDemo" type="single" target="FindOfbizDemo" default-entity-name="OfbizDemo">
<field name="noConditionFind">
<hidden value="Y"/> <!-- if this isn't there then with all fields empty no query will be done -->
</field>
<field name="ofbizDemoId" title="${uiLabelMap.OfbizDemoId}">
<text-find/>
</field>
<field name="firstName" title="${uiLabelMap.OfbizDemoFirstName}">
<text-find/>
</field>
<field name="lastName" title="${uiLabelMap.OfbizDemoLastName}">
<text-find/>
</field>
<field name="ofbizDemoTypeId" title="${uiLabelMap.OfbizDemoType}">
<drop-down allow-empty="true" current-description="">
<entity-options description="${description}" key-field-name="ofbizDemoTypeId" entity-name="OfbizDemoType">
<entity-order-by field-name="description"/>
</entity-options>
</drop-down>
</field>
<field name="searchButton" title="${uiLabelMap.CommonFind}" widget-style="smallSubmit">
<submit button-type="button" image-location="/images/icons/magnifier.png"/>
</field>
</form> <form name="ListOfbizDemo" type="list" list-name="listIt" paginate-target="FindOfbizDemo" default-entity-name="OfbizDemo" separate-columns="true"odd-row-style="alternate-row" header-row-style="header-row-2" default-table-style="basic-table hover-bar">
<actions>
<!-- Preparing search results for user query by using OFBiz stock service to perform find operations on a single entity or view entity -->
<service service-name="performFind" result-map="result" result-map-list="listIt">
<field-map field-name="inputFields" from-field="ofbizDemoCtx"/>
<field-map field-name="entityName" value="OfbizDemo"/>
<field-map field-name="orderBy" from-field="parameters.sortField"/>
<field-map field-name="viewIndex" from-field="viewIndex"/>
<field-map field-name="viewSize" from-field="viewSize"/>
</service>
</actions>
<field name="ofbizDemoId" title="${uiLabelMap.OfbizDemoId}">
<display/>
</field>
<field name="ofbizDemoTypeId" title="${uiLabelMap.OfbizDemoType}">
<display-entity entity-name="OfbizDemoType"/>
</field>
<field name="firstName" title="${uiLabelMap.OfbizDemoFirstName}" sort-field="true">
<display/>
</field>
<field name="lastName" title="${uiLabelMap.OfbizDemoLastName}" sort-field="true">
<display/>
</field>
<field name="comments" title="${uiLabelMap.OfbizDemoComment}">
<display/>
</field>
</form>

Here you can notice we have used auto-fields-service to auto generate the form based on service definition IN/OUT attributes.

Go to Screens xml file(OfbizDemoScreens.xml) add this form location in decorator body to your screen that you used to show the “Hello World” text. As shown belowAdding Form Location to the Main Screen

<?xml version="1.0" encoding="UTF-8"?>
<screens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-screen.xsd"> <screen name="main">
<section>
<actions>
<set field="headerItem" value="main"/> <!-- this highlights the selected menu-item with name "main" -->
</actions>
<widgets>
<decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
<decorator-section name="body">
<screenlet title="Add Ofbiz Demo">
<include-form name="AddOfbizDemo" location="component://ofbizDemo/widget/OfbizDemoForms.xml"/>
</screenlet>
</decorator-section>
</decorator-screen>
</widgets>
</section>
</screen>
</screens>

Controller Entry for Form

Before you go to the form and start creating OfbizDemo records from add form, you will need to make an entry in /plugins/ofbizDemo/webapp/ofbizDemo/WEB-INF/controller.xml file for the target service which will called when form is submitted. You can do it as shown below under Request Mappings in your ofbizdemo apps controller file:

<request-map uri="createOfbizDemo">
<security https="true" auth="true"/>
<event type="service" invoke="createOfbizDemo"/>
<response name="success" type="view" value="main"/>
</request-map>

Everything set, let’s have a look into to our recently create form https://localhost:8443/ofbizDemo ofbiz-createForm Primary key (ofbizDemoId) is not needed to be send in with the form, it will be auto sequenced by OFBiz in db records.

Services using other engines

Whenever you have to build a business logic you should prefer to write services to leverage features from its built in Service Engine.

The service “createOfbizDemo” that we created earlier was using engine=”entity-auto” and hence we didn’t need to provide its implementation and OFBiz took care of create operation.  When we need to work on complex operations in service involving multiple entities from database and custom logics to be built, you need to provide custom implementation to your service.

In this section we will focus on this.

Service in Java

You can implement a service in Java as directed here in below given steps:

1. Define your service, here again we will be operating on the same entity (OfbizDemo) of our custom Ofbiz Demo application. Open your service definition file

/plugins/ofbizDemo/servicedef/services.xml and add a new definition as: services.xml

<service name="createOfbizDemoByJavaService" default-entity-name="OfbizDemo" engine="java" location="com.companyname.ofbizdemo.services.OfbizDemoServices" invoke="createOfbizDemo" auth="true">
<description>Create an Ofbiz Demo record using a service in Java</description>
<auto-attributes include="pk" mode="OUT" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="false"/>
<override name="comments" optional="true"/>
</service>

Notice we have this time used engine=”java”.

2. Create package “com.companyname.ofbizdemo.services” in your ofbizDemo components src/main/java directory

Example: src/main/java/com/companyname/ofbizdemo/services. Services for your application which have to be implemented in Java can be placed in this java directory.

3. Define new Java Class in file OfbizDemoServices.java here in services directory and implement method, which is going to be invoked by your service definition, as shown below:

OfbizDemoServices.java

package com.companyname.ofbizdemo.services;
import java.util.Map;
  
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.service.DispatchContext;
import org.apache.ofbiz.service.ServiceUtil;
  
public class OfbizDemoServices {
  
    public static final String module = OfbizDemoServices.class.getName();
  
    public static Map<String, Object> createOfbizDemo(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> result = ServiceUtil.returnSuccess();
        Delegator delegator = dctx.getDelegator();
        try {
            GenericValue ofbizDemo = delegator.makeValue("OfbizDemo");
            // Auto generating next sequence of ofbizDemoId primary key
            ofbizDemo.setNextSeqId();
            // Setting up all non primary key field values from context map
            ofbizDemo.setNonPKFields(context);
            // Creating record in database for OfbizDemo entity for prepared value
            ofbizDemo = delegator.create(ofbizDemo);
            result.put("ofbizDemoId", ofbizDemo.getString("ofbizDemoId"));
            Debug.log("==========This is my first Java Service implementation in Apache OFBiz. OfbizDemo record created successfully with ofbizDemoId:"+ofbizDemo.getString("ofbizDemoId"));
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError("Error in creating record in OfbizDemo entity ........" +module);
        }
        return result;
    }
}

4.) Stop server and re-start using “gradlew ofbiz”, it will compile your class and will make it available when ofbiz restarts which updated jar file.

5.) Test service implemented using webtools -> Run Service option(https://localhost:8443/webtools/control/runService) or simply update the service name being called by your controller request to use this service instead and use add form in your app that you prepared earlier. By doing this your Add OfbizDemo form will call this java service.

<request-map uri="createOfbizDemo">
<security https="true" auth="true"/>
<event type="service" invoke="createOfbizDemoByJavaService"/><response name="success" type="view" value="main"/>
</request-map>

To make sure this new service implementation is being executed, you can check this line in console log that you have put in your code using Debug.log(….). For logging in OFBiz you must always use Debug class methods in Java classes.

Console Log

[java] 2014-06-24 12:11:37,282 (http-bio-0.0.0.0-8443-exec-2) [  OfbizDemoServices.java:28 :INFO] ==========This ismy first Java Service implementation in Apache OFBiz. OfbizDemo record created successfully with ofbizDemoId: ......

Service in Groovy

To utilize feature of on the fly compilation and less line of code you can implement services for building business logics in OFBiz using Groovy DSL.

To implement a service using Groovy you can follow below given steps:

1. Add new service definition to services/services.xml file as: services.xml

<service name="createOfbizDemoByGroovyService" default-entity-name="OfbizDemo" engine="groovy"location="component://ofbizDemo/groovyScripts/ofbizdemo/OfbizDemoServices.groovy" invoke="createOfbizDemo" auth="true">
<description>Create an Ofbiz Demo record using a service in Groovy</description>
<auto-attributes include="pk" mode="OUT" optional="false"/>
<auto-attributes include="nonpk" mode="IN" optional="false"/>
<override name="comments" optional="true"/>
</service>

2. Add new groovy services file here  component://ofbizDemo/groovyScripts/ofbizdemo/OfbizDemoServices.groovy

3. Add service implementation to the file OfbizDemoServices.groovy

OfbizDemoServices.groovy

import org.apache.ofbiz.entity.GenericEntityException;
 
def createOfbizDemo() {
    result = [:];
    try {
        ofbizDemo = delegator.makeValue("OfbizDemo");
        // Auto generating next sequence of ofbizDemoId primary key
        ofbizDemo.setNextSeqId();
        // Setting up all non primary key field values from context map
        ofbizDemo.setNonPKFields(context);
        // Creating record in database for OfbizDemo entity for prepared value
        ofbizDemo = delegator.create(ofbizDemo);
        result.ofbizDemoId = ofbizDemo.ofbizDemoId;
        logInfo("==========This is my first Groovy Service implementation in Apache OFBiz. OfbizDemo record "
                  +"created successfully with ofbizDemoId: "+ofbizDemo.getString("ofbizDemoId"));
      } catch (GenericEntityException e) {
          logError(e.getMessage());
          return error("Error in creating record in OfbizDemo entity ........");
      }
      return result;
}

4. Stop server and re-start using “gradlew ofbiz”, this time we just need to load the new service definition, no explicit compilation is required as its a service implementation in Groovy.

5.) Test service implemented using webtools –> Run Service option (https://localhost:8443/webtools/control/runService) or simply update the service name being called by your controller request to use this service instead and use add form in your app that you prepared earlier for testing. By doing this your Add OfbizDemo form will call this groovy service.

controller.xml

<request-map uri="createOfbizDemo"><security https="true" auth="true"/><event type="service" invoke="createOfbizDemoByGroovyService"/><response name="success" type="view" value="main"/>
</request-map>

To make sure this new service implementation is being executed, you can check this line in console log that you have put in your code using Debug.log(….). For logging in OFBiz you must always use Debug class methods in Java classes.

Console Log

[java] 2014-06-24 12:11:37,282 (http-bio-0.0.0.0-8443-exec-2) [  OfbizDemoServices.java:28 :INFO] ==========This is myfirst Groovy Service implementation in Apache OFBiz. OfbizDemo record created successfully with ofbizDemoId: .....

Events

Events demonstration

Events in Apache OFBiz are simply methods used to work with HttpServletRequest and HttpServletResponse objects. You don’t need to provide definitions of these as you did with services. These are directly called from controller. Events are also useful when you want to add custom server side validations to input parameters.

To write an event in OFBiz follow these steps:

1.) Add a new events directory to package and a new Events class file as mentioned here:

OfbizDemoEvents.java

package com.companyname.ofbizdemo.events;
  
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
  
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
  
public class OfbizDemoEvents {
  
 public static final String module = OfbizDemoEvents.class.getName();
  
    public static String createOfbizDemoEvent(HttpServletRequest request, HttpServletResponse response) {
        Delegator delegator = (Delegator) request.getAttribute("delegator");
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
        GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
  
        String ofbizDemoTypeId = request.getParameter("ofbizDemoTypeId");
        String firstName = request.getParameter("firstName");
        String lastName = request.getParameter("lastName");
  
        if (UtilValidate.isEmpty(firstName) || UtilValidate.isEmpty(lastName)) {
            String errMsg = "First Name and Last Name are required fields on the form and can't be empty.";
            request.setAttribute("_ERROR_MESSAGE_", errMsg);
            return "error";
        }
        String comments = request.getParameter("comments");
  
        try {
            Debug.logInfo("=======Creating OfbizDemo record in event using service createOfbizDemoByGroovyService=========", module);
            dispatcher.runSync("createOfbizDemoByGroovyService", UtilMisc.toMap("ofbizDemoTypeId", ofbizDemoTypeId,
                    "firstName", firstName, "lastName", lastName, "comments", comments, "userLogin", userLogin));
        } catch (GenericServiceException e) {
            String errMsg = "Unable to create new records in OfbizDemo entity: " + e.toString();
            request.setAttribute("_ERROR_MESSAGE_", errMsg);
            return "error";
        }
        request.setAttribute("_EVENT_MESSAGE_", "OFBiz Demo created succesfully.");
        return "success";
    }
}

2.) Add controller request of calling this event as:

controller.xml

<request-map uri="createOfbizDemoEvent"><security https="true" auth="true"/>
<event type="java" path="com.companyname.ofbizdemo.events.OfbizDemoEvents" invoke="createOfbizDemoEvent"/>
<response name="success" type="view" value="main"/><response name="error" type="view" value="main"/>
</request-map>

3. Stop and start server by rebuilding it as we need to compile Java event class that we have added in #1.

4.) Now to test the event you can simply change the AddOfbizDemo form target to read “createOfbizDemoEvent” and as its submitted now it will call your event.

Difference between service and event

Here are some difference between services and events,

  • Events are used for validations and conversions using map processor, while services are used for business logics like CRUD operations.
  • Service returns Map.
  • Event returns String.
  • Services are loaded with the server, any changes in definition (not implementation if in MiniLang) needs a reload.
  • We can call service inside event. But we cannot call event inside service.
  • An event is specific local piece functionality normally used in one place for one purpose and called from its location.
  • A service is a piece of functionality which can be located anywhere on the network, is most of time used in several different places and is called by its ‘name’.
  • In case of events you have access to HttpServletRequest and HttpServletResponse objects and you can read/write whatever you want. In case of services, you have access only to service parameters.

Customizing User Interface

Using FreeMarker Template and Groovy Script

Okay so we are here in the last part of OFBiz tutorial. In this part we will focus on customizing UI layer of Apache OFBiz for business management apps i.e. backend apps and esp. Most of the time you will find the OFBiz Widgets are enough. But sometimes the important thing is to develop applications as users exactly want it.

So to customize UI part of your application first of all to make it easy we will be using Freemarker Templates instead of inbuilt Form Widgets. First of all we will see how to use Freemarker and Groovy scripts with Apache OFBiz and then we’ll see how to put on custom styling on it by defining your own decorators. Initially we will be using OFBiz default decorators.

Please follow below steps:

1. Add two Freemarker files at location $ /plugins/ofbizDemo/webapp/ofbizDemo/crud/AddOfbizDemo.ftl and ListOfbizDemo.ftl, as shown below:

AddOfbizDemo.ftl

<div class="screenlet-body">
  <form id="createOfbizDemoEvent" method="post" action="<@ofbizUrl>createOfbizDemoEvent</@ofbizUrl>">
    <input type="hidden" name="addOfbizDemoFromFtl" value="Y"/>
    <fieldset>
      <div>
        <span class="label">${uiLabelMap.OfbizDemoType}</span>
        <select name="ofbizDemoTypeId" class='required'>
          <#list ofbizDemoTypes as demoType>
            <option value='${demoType.ofbizDemoTypeId}'>${demoType.description}</option>
          </#list>
        </select>*
      </div>
      <div>
        <span class="label">${uiLabelMap.OfbizDemoFirstName}</span>
        <input type="text" name="firstName" id="firstName" class='required' maxlength="20" />*
      </div>
      <div>
        <span class="label">${uiLabelMap.OfbizDemoLastName}</span>
        <input type="text" name="lastName" id="lastName" class='required' maxlength="20" />*
      </div>
      <div>
        <span class="label">${uiLabelMap.OfbizDemoComment}</span>
        <input type="text" name="comments" id="comments" class='inputBox' size="60" maxlength="255" />
      </div>
    </fieldset>
    <input type="submit" value="${uiLabelMap.CommonAdd}" />
  </form>
</div>

ListOfbizDemo.ftl

<div class="screenlet-body">
  <#if ofbizDemoList?has_content>
    <table cellspacing=0 cellpadding=2 border=0 class="basic-table">
      <thead><tr>
        <th>${uiLabelMap.OfbizDemoId}</th>
        <th>${uiLabelMap.OfbizDemoType}</th>
        <th>${uiLabelMap.OfbizDemoFirstName}</th>
        <th>${uiLabelMap.OfbizDemoLastName}</th>
        <th>${uiLabelMap.OfbizDemoComment}</th>
      </tr></thead>
      <tbody>
        <#list ofbizDemoList as ofbizDemo>
          <tr>
            <td>${ofbizDemo.ofbizDemoId}</td>
            <td>${ofbizDemo.getRelatedOne("OfbizDemoType").get("description", locale)}</td>
            <td>${ofbizDemo.firstName?default("NA")}</td>
            <td>${ofbizDemo.lastName?default("NA")}</td>
            <td>${ofbizDemo.comments!}</td>
          </tr>
        </#list>
       </tbody>
    </table>
  </#if>
</div>

2. Add new Groovy file for data fetching logic at location /plugins/ofbizDemo/groovyScripts/crud/ListOfbizDemo.groovy and add code as shown to list out OfbizDemo records:

ofbizDemoTypes = delegator.findList("OfbizDemoType", null, null, null, null, false);
context.ofbizDemoTypes = ofbizDemoTypes;
ofbizDemoList = delegator.findList("OfbizDemo", null, null, null, null, false);
context.ofbizDemoList = ofbizDemoList;

3. Add new screen file with Ofbiz default decorator to OfbizDemoScreens.xml with newly added freemarker and groovy files as:

OfbizDemoScreens.xml

<screen name="AddOfbizDemoFtl">
    <section>
        <actions>
            <set field="titleProperty" value="PageTitleAddOfbizDemos"/>
            <set field="headerItem" value="addOfbizDemoFtl"/>
            <script location="component://ofbizDemo/groovyScripts/crud/ListOfbizDemo.groovy"/>
        </actions>
        <widgets>
            <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
                <decorator-section name="body">
                    <screenlet title="${uiLabelMap.OfbizDemoListOfbizDemos}">
                        <platform-specific>
                            <html><html-template location="component://ofbizDemo/webapp/ofbizDemo/crud/ListOfbizDemo.ftl"/></html>
                         </platform-specific>
                    </screenlet>
                    <screenlet title="${uiLabelMap.OfbizDemoAddOfbizDemoServiceByFtl}">
                        <platform-specific>
                            <html><html-template location="component://ofbizDemo/webapp/ofbizDemo/crud/AddOfbizDemo.ftl"/></html>
                        </platform-specific>
                    </screenlet>
                </decorator-section>
            </decorator-screen>
        </widgets>
    </section>
</screen>

4. Add new controller request and a new item for OfbizDemo menu as:

controller.xml

<!--Request Mapping-->
<request-map uri="AddOfbizDemoFtl"><security https="true" auth="true"/>
<response name="success" type="view" value="AddOfbizDemoFtl"/></request-map>
<!--View Mapping-->
<view-map name="AddOfbizDemoFtl" type="screen" page="component://ofbizDemo/widget/OfbizDemoScreens.xml#AddOfbizDemoFtl"/>

OfbizDemoMenus.xml

<menu-item name="addOfbizDemoFtl" title="${uiLabelMap.OfbizDemoAddFtl}"><link target="AddOfbizDemoFtl"/>
</menu-item>

5. Add new UI Labels as used by your app.

6. Run your ofbiz demo application and go to the new tab you just added. You should have view as: ofbiz-customUI

Recommendation

If you want to go in depth and learn more about OFBiz, I would recommend below books.

Conclusion

So, if you have followed all the steps and developed practice application from this tutorial then this will help you in understanding other implementation in OFBiz. These things are basic foundation of working in OFBiz. Now you know, how you can start development in OFBiz.

Now you are ready to dive in. Welcome to OFBiz world.

References

ofbiz.org

Tags:

8 Replies to “Apache OFBiz Developer Guide”

  1. After checking out a few of the articles on your web site,
    I seriously appreciate your technique of blogging. I bookmarked
    it to my bookmark website list and will be checking back in the near future.
    Please check out my website too and let me know your opinion.

Leave a Reply