Any application dealing with currency should really use the Java class BigDecimal. BigDecimal - java.math.BigDecimal - immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. The value of the number represented by the BigDecimal is therefore (unscaledValue × 10-scale). The BigDecimal class provides operations for arithmetic, scale manipulation, rounding, comparison, hashing, and format conversion.
Request for support of BigDecimal in Service-Builder has been there for around many years. Now it is time to implement. right? Service-builder supports following Java data types and database data types mapping.
- boolean => BOOLEAN
- int, Integer, short => INTEGER
- long => LONG
- float, double => DOUBLE
- String => VARCHAR (<4000), STRING (=4000), TEXT (>4000)
- Date => DATE
Supported primitive types include “boolean”, “int”, “short”, “long”, “float” and “double”; and data types “String” and “Date” got supported , too. The previous blogs post discussed how to apply convert-null element on primitive types. This article will address how to bring data type BigDecimal into Service-Builder.
An example
Consider following service.xml.
<?xml version="1.0"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.1.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd">
<service-builder package-path="com.liferay.sampleservicebuilder">
<namespace>SSB</namespace>
<entity name="Foo" uuid="true" local-service="true" remote-service="true">
<!-- PK fields -->
<column name="fooId" type="long" primary="true" />
<!-- Group instance -->
<column name="groupId" type="long" />
<!-- Audit fields -->
<column name="companyId" type="long" />
<column name="userId" type="long" />
<column name="userName" type="String" />
<column name="createDate" type="Date" />
<column name="modifiedDate" type="Date" />
<!-- Other fields -->
<column name="field1" type="String" />
<column name="field2" type="boolean" />
<column name="field3" type="int" />
<column name="field4" type="Date" />
<column name="field5" type="String" convert-null="false" />
<column name="field6" type="BigDecimal" />
<column name="field7" type="BigDecimal" constraint-precision="8" constraint-scale="3" />
<column name="field8" type="BigDecimal" constraint-precision="10" constraint-scale="4" />
<!-- Order -->
<order by="asc">
<order-column name="field1" />
</order>
<!-- Finder methods -->
<finder name="Field2" return-type="Collection">
<finder-column name="field2" />
</finder>
<!-- References -->
<reference package-path="com.liferay.portlet.asset" entity="AssetEntry" />
<reference package-path="com.liferay.portlet.asset" entity="AssetTag" />
</entity>
</service-builder>
As shown in above code, columns “field6”, “field7”, “field8” have data type “BigDecimal” and columns “field7” and “field8” have constraint precision (8, 10) and scale (3,4).
Solution proposal
The following are proposed steps to support data-type BigDecimal in Service-Builder.
- Add two constraint elements for the data type BigDecimal in Service-Builder DTD.
constraint-precision: M - the maximum number of digits (the precision);
constraint-scale: D - the number of digits to the right of the decimal point (the scale)
The SQL standard requires that the precision of NUMERIC(M,D) be exactly M digits. For DECIMAL(M,D), the standard requires a precision of at least M digits but permits more. In MySQL, DECIMAL(M,D) and NUMERIC(M,D) are the same, and both have a precision of exactly M digits. For example, column salary could be presented in database SQL as follows.
salary NUMERIC(5,2)
As shown in above code, constraint-precision has value 5 (M=5) and constraint-scale has value 2 (D=2).
- Add a data type called BigDecimal in service-builder DTD
For example, column salary could be specified in service.xml as follows.
<column name="salary" type="BigDecimal" constraint-precision=”5” constraint-scale=”2” convert-null="false" />
- Add an object type in Liferay portal core called com.liferay.portal.dao.orm.hibernate.BigDecimalType, where specifies default value;
- Map BigDecimal into NUMERIC(M,D) as part of SQL scripts
- Map BigDecimal into object type com.liferay.portal.dao.orm.hibernate.BigDecimalType if convert-null is set to true; or map BigDecimal into object type org.hibernate.type.BigDecimalType, if convert-null is set to false.
- Map BigDecimal into Java class java.math.BigDecimal when generating models and services.
In above steps, we could make data-type BigDecimal available in Service-Builder.
Results
Solution proposal could be presented as a fix patch. After applying this fix patch, you can generate services, models and SQL scripts with new data type BigDecimal based on above service.xml. The following are generated SQL scripts.
create table SSB_Foo (
uuid_ VARCHAR(75) null,
fooId LONG not null primary key,
groupId LONG,
companyId LONG,
userId LONG,
userName VARCHAR(75) null,
createDate DATE null,
modifiedDate DATE null,
field1 VARCHAR(75) null,
field2 BOOLEAN,
field3 INTEGER,
field4 DATE null,
field5 VARCHAR(75) null,
field6 NUMERIC(5, 2) null,
field7 NUMERIC(8, 3) null,
field8 NUMERIC(10, 4) null
);
Summary
As you can see, data type BigDecimal and two elements constraint-precision and constraint-scale are ready in Service-Builder. And generated services, models and SQL scripts will support data type BigDecimal as well.
What’s next? Check Service-Builder improvement.

