Code Generator Tutorial
A Customer Relationship Management System Example
JRapid produces flexible, full-featured applications in a fraction of the time and with much less code than would normally be required. In fact, the entire source for the example we have below in AML, JRapid Application Modeling Language, is only a little over 400 lines. This application is a fully-featured customer relations management (CRM) system with every type of UI interface you could possibly need including forms, listings, charts, maps, crosstabs and many more.
Download full source here. In order for this app definition to work, you will need to import the following views and widgets using the Add-ons menu. Widgets: * Date and Time Picker Views: * Google Charts * Full Calendar * Google Map 3
With very few lines of code, the JRapid generator creates entities and all the necessary user interface pieces to view, manage and report on the business objects. A professional, fully-featured system is possible without committing hundreds of hours. Also, look and feel and functionality is consistent across the system, and you are free to extend the back end code to specialize the application to your particular needs.
In the following tutorial, I am going to show you how creating a system like the one above is both quick and easy. Once you get a hang of the basics and set up your environment as detailed above, you will see that flexibility of the JRapid architecture makes nearly any specialized use possible and much easier than with conventional tools.
JRapid follows the specifics of Model-Driven Design which emphasizes the importance of the entities or business objects and their relationships. First, we will start by modeling the necessary entities and their properties. Entities can be thought of as your business objects, or more simply as nouns and the properties are the attributes that define each instance of the entity.
Lists are interfaces that allow you to view all or a subset of your existing instances of a particular entity.
Properties are available in many different types. They can be any basic type like an integer, double or string or more complicated objects like phone numbers or email addresses. Properties can also be instances of other entities creating relationships. Our customer entity has a property that is a reference to the country entity. This creates a one to one (or one to none if null) linking between the two entities.
<entity label="Customer" menu="Customers" name="Customer"> <property display="primary" label="Name" name="name"/> <property label="Contact" name="contact"/> <property label="Phone" name="phone" type="phone"/> <property label="Email" name="email" type="email"/> <property display="secondary" label="Address" name="address"/> <property autosuggest="autosuggest" display="secondary" label="City" name="city"/> <property display="secondary" entity="Country" label="Country" name="country"/> <property display="secondary" entity="State" label="State" name="state" subset="forCountry" subsetparams="country"/> <property entity="Industry" label="Industry" name="industry"/> … </entity>
The basic view of the customer contains 9 properties modeling each customer in the system. There are simple types like string, and more complicated built-in ones like phone and email. There are also references to Country, State and Industry entities creating relationships with those other tables.
Properties are also flexible and configurable. For example, a default value can be set for values when a new entity is being created.
<entity name="Sale" label="Sale" menu="Sales" > ... <property name="shipped" label="Shipped" type="boolean" default="false" /> ... </entity>
This will create a default value of false for shipped in the user interface when adding a sale.
Embedding allows one entity to be placed inside of another for use as a child of the outside entity.
<property childproperty="sale" collection="list" embedded="inline" entity="SaleLine" extendable="extendable" labelposition="top" listindex="line" name="detail"/>
The entity SaleLine, defined as shown below is being referenced here as a one to many property of a sale. Extendable means that the user will be able to add new rows. The application now has a sale with an interface for adding as many sale lines as the user deems necessary for a particular sale.
<entity label="SaleLine" name="SaleLine"> <property display="primary" entity="Sale" label="Sale" name="sale"/> <property display="primary" label="Quantity" name="quantity" type="integer"/> <property display="primary" entity="Product" label="Product" name="product" subset="forCombo" widget="combo"/> <property display="primary" label="Price" name="price" type="double"> <dynamicvalue expr="product.price"> <param entity="Product" name="product" value="product"/> </dynamicvalue> </property> <property calculated="price * quantity" label="Total" name="total" type="double"/> <property hidden="hidden" label="N" name="n" type="short"/> </entity>
Formula, calculated and dynamicvalue are other possible attributes for a property. Formula will allow you to set a property value based on an SQL statement. To add a property displaying the average sales for a salesperson one could add the following line to the seller entity:
<property name="avgSales" label="Avg sales" display="secondary" formula="(SELECT SUM(sale.total)/COUNT(DISTINCT MONTH(sale.date)) FROM sale WHERE sale.seller = id)" />
The above SaleLine example also includes a calculated value for the total. When a price and quantity is entered, the total field is automatically populated.
The property can also dynamically pull the value of a particular field of an entity from the underlying database. For example, the product entity has a price. The SaleLine entity uses the combo widget to automatically suggest products matching what the user begins to type. Once a product is selected there is a dynamic call that populates the price by going to the product table in the database. If the user has typed a quantity for the product, the entire line is calculated at the point when the product is selected.
Filters are ways to limit the number of visible rows for a particular list. The above customer example creates two filters allowing the user to search for customers with a particular name or search by their state. With only the following two lines, both the front end interface and the back end services are provided for you.
<filter display="primary" label="Name" name="name" property="name"/> <filter display="primary" label="State" name="state" property="state"/>
The display attribute being primary causes the filter to show up in the primary list for the entity. The property value for the filter must match the name of a property for the entity.
Subsets are another way to limit the number of entities in a list. Whereas filters work by giving the user a way to search and limit on their own, subsets are created to restrict a data set when all the records do not make sense for a particular use. The most common usage is to create a subset with one or more parameters that limits the number of records. For example, we have state and country entities with each state having a country as one of its properties. To create a subset which returns all states for a country is trivial:
<entity label="State" menu="Config" name="State"> <subset name="forCountry"> <param entity="Country" name="country"/> <condition field="country" value="country"/> </subset> ... </entity>
In the example this subset is used when entering addresses to restrict the states only to those in the country previously selected.
The default listings are not the only options you have for displaying entities' lists to users. The default listing can be easily set to any list:
<entity defaultlisting="pictures" label="Seller" menu="Config" name="Seller"> <listing displayproperties="photo,name,email,phone,avgSales" name="pictures"/> </entity>
This list will display the photo of the seller along with their name, contact information and average sales as the default for the entity as defaultlisting is set to the custom pictures listing.
JRapid even supports Google map listings, so if you want to display a map with points showing the address of your customers you can easily do so. This will require you to install a view add-on from the JRapid community to have access to the map functionality.
<entity label="Customer" menu="Customers" name="Customer"> <listing name="map" view="googlemap3,table"/> ... </entity>
Widgets are attributes you can specify to customize how certain properties appear. There are built-in widgets from the JRapid core library, and user generated widgets from the JRapid community that you can add through the web designer.
<property label="Payment method" name="paymentMethod" type="enum" widget="radio"> <enum>Check</enum> <enum>Credit card</enum> <enum>Cash</enum> </property>
The above example creates a radio box for the enumerated types.
Some common core widgets are select, combo, radio, selectmultiple and checkbox. The latter two are used when the user can select more than one value, or a collection of values.
There is a wide selection of widgets available in the JRapid community including ways to select points on a map, choose a color, or even handle documents in Google documents. You can find a more information here.
In addition to the ability to display your properties with different widgets, there is also the ability to add CSS directives so your application can be customized to the look and feel you want. Properties accept a style attribute allowing you to format a single property as is used in the product entity.
<property display="primary" label="Title" name="title" style="width: 300px;"/>
Pure HTML can also be added to an entity to display a title or provide a description of properties.
<entity label="Customer" menu="Customers" name="Customer"> ... <html name="title">Please select the closest industry for the customer</html> <property entity="Industry" label="Industry" name="industry"/> ... </entity>
It is simple to include a listing of other entities inside one entity. This can be done with a relationship between two entities such as a one to many parent child relationship, or with all or a subset of another entity where there is no relationship. The following example shows how to embed a listing of the sales for a customer into the customer entity. Failing to specify a subset would yield all the records for a particular entity.
<entity label="Customer" menu="Customers" name="Customer"> ... <embeddedlisting entity="Sale" name="sales" subset="forCustomer" subsetparams="."/> ... </entity>
- Related entity allows you to open the entity form for an entity contained as a property. To view the industry for a customer, this could be used to get to the industry form.
- Related listings will open a list when the related property is a collection or can be used with a subset.
- Open entity is the default functionality for lists when a row is double clicked on. This will open the form for an entity.
One can easily create an action that opens a company selected for a sale with the following lines:
<entity label="Sale" menu="Sales" name="Sale"> ... <property dimension="row" display="primary" entity="Customer" label="Customer" name="customer"> <action label="View" location="form" name="openCustomer" type="openentity"/> </property> ... </entity>
Panels provide you with the ability to group and organize the various components of your application. They can contain their own menus. To organize a panel, you can use columns and specify their width. Inside of each column there is an accordion layout for placing items.
<panel menu="Panels" name="Index" title="Sales Manager 1.0 (powered by JRapid)"> <menu/> <column width="70%"> <accordeon> ... </panel>
Business Intelligence Reporting
JRapid also provides you with an additional BI reporting module that runs against the supporting database. This module provides summarized information representing the objects in the system. In this case it is used to show sales per month by reporting on the quantity of sales with a date in each month for each particular user.
Business Intelligence also provides you with “dimensions” that allow you to filter and group your results In the above example, the dimensions are seller for the rows, and date_year and date_month for the columns. “Configure” will allow the user to modify the groupings dynamically while the web application is executing. Also, charts can be obtained by running a BI report.