App Sample

Version: 1.0 | Release Date: 30/6/2018

Things to know

Our app example is a simple book borrowing program that contains two main objects: Book and Member

  1. The member's profile stores his borrowing history
  2. The Available Property of Book decided whether it can be borrowed or not
  3. Each book has an ISBN number that checks its validity each time it is saved.
  4. Users can also manually check the ISBN before saving.
  5. Add a Printing Report to the Member
  6. Add a EBI Report to the Member

You can download the runable code of the entire app from github

Define App in App.xml

p-share\src\main\resources\META-INF\app.xml

<?xml version="1.0"?>
<app xmlns="http://www.multiable.com/app">
	<name>opcq</name>
	<version>1.0</version>
	<description>Opcq App</description>
	<dependences>
		<dependence id="caw" versions="1.0" />
	</dependences>	
	<ear>caw_ear</ear>
	<ejb>p-ejb</ejb>	
</app>

See App.xml for other available setting parameters.

Define Table Structure in datadict.xml

p-share\src\main\resources\META-INF\datadict.xml

<?xml version="1.0"?>
<dd xmlns="http://www.multiable.com/datadict">
	
	<table name="opcqbookcat" mess="opcq.bookCat" pk="id">
		<inherit name="module_fm" />
		<column name="code" type="varchar" mess="core.code" length="20" defPattern="fmCode" required="true" batchUpdate="false"/>
		<column name="desc" type="varchar" mess="core.description" length="100" defPattern="charDesc" i18nField="true" batchUpdate="true"/>
		
		<index name="module_code" columns="code" />
	</table>
	
	<table name="opcqbook" mess="opcq.book" pk="id" >
		<inherit name="module_fm" />
		<column name="code" type="varchar" mess="opcq.bookCode" length="40" defPattern="fmCode" required="true" batchUpdate="false"/>
		<column name="isbn" type="varchar" mess="opcq.isbn" length="40" defPattern="char20" required="true" batchUpdate="false"/>
		<column name="desc" type="varchar" mess="opcq.title" length="200" defPattern="charDesc" i18nField="true" batchUpdate="true"/>
		<column name="author" type="varchar" mess="opcq.author" length="100" defPattern="char60" i18nField="true" batchUpdate="true"/>
		<column name="publisher" type="varchar" mess="opcq.publisher" length="100" defPattern="char100" i18nField="true" batchUpdate="true"/>
		<column name="pDate" type="datetime" mess="opcq.pDate" defValue="NOW()" defPattern="date"/>
		<column name="photoCode" type="varchar" mess="opcq.coverImg" length="60" defPattern="imgCode" />
		<column name="bookCatId" type="int_unsigned" mess="opcq.bookCat" defValue="0" defPattern="opcqBookCat" batchUpdate="false"/>
		<column name="avail" type="bit" mess="opcq.avail" defValue="0" defPattern="check"/>
		
		<index name="module_isbn" columns="isbn" unique="true"/>
	</table>
	
	<table name="opcqmem" mess="opcq.mem" pk="id" >
		<inherit name="module_fm" />
		<column name="code" type="varchar" mess="opcq.memNo" length="60" defPattern="fmCode" required="true" batchUpdate="false"/>
		<column name="desc" type="varchar" mess="opcq.name" length="200" defPattern="char50" i18nField="true" required="true" batchUpdate="true"/>
		<column name="card" type="varchar" mess="opcq.cardNum" length="60" defPattern="char30" required="true" batchUpdate="false"/>
		<column name="email" type="varchar" mess="opcq.email" length="200" defPattern="char100" batchUpdate="true"/>
		<column name="addr" type="varchar" mess="opcq.address" length="-1" defPattern="char2000" i18nField="true"/>
		
		<index name="module_code" columns="code"/>
	</table>
	
	<table name="opcqmemt" mess="opcq.memt" pk="id">
		<inherit name="id_irev" />
		<column name="hId" type="int_unsigned" mess="opcq.mem" defValue="0" defPattern="opcqMem" dataImport="false" dataExport="false" buildin="true"/>
		<column name="itemNo" type="varchar" mess="core.itemNo" length="12" defPattern="char6" dataEasy="true" dataImport="false" dataExport="false"/>
		<column name="bookId" type="int_unsigned" mess="opcq.bookCode" defValue="0" defPattern="opcqBook" required="true"/>
		<column name="bDate" type="datetime" mess="opcq.bDate" defValue="NOW()" defPattern="date"/>
		<column name="rDate" type="datetime" mess="opcq.rDate" defValue="NOW()" defPattern="date"/>
		
		<fk name="book" columns="bookId" refTable="opcqbook" refColumns="id" />		
	</table>
</dd>

See Datadict.xml for other available setting parameters.

For reuse purposes, the properties of the field can be defined by Pattern.xml

<?xml version="1.0"?>
<pattern xmlns="http://www.multiable.com/pattern">

	<record code="opcqBookCat" type="lookup">
		<lookup searchType="opcqBookCat"/>
	</record>
	
	<record code="opcqBook" type="lookup">
		<lookup searchType="opcqBook"/>
	</record>			
	
	<record code="opcqMem" type="lookup">
		<lookup searchType="opcqMem"/>
	</record>
</pattern>

Define Module in module.xml

This app has a total of three modules, they are:

  1. Book Category
  2. Book
  3. Member

p-share\src\main\resources\META-INF\module.xml

<?xml version="1.0"?>
<md xmlns="http://www.multiable.com/module" app="opcq">

	<module name="opcqBookCat" mess="opcq.bookCat" extend="false" mainTable="opcqbookcat" recType="" useAccess="true" useAttach="true" useBeShare="true" useApv="true" useChangenote="true" fmShare="Y" genCode_Type="BC">
		<table name="opcqbookcat" key="id" c="true" r="true" d="true" u="true" initRow="1" hpk="" fKey="" order=""/>
	</module>		
	
	<module name="opcqBook" mess="opcq.book" extend="false" mainTable="opcqbook" recType="" useAccess="true" useAttach="true" useBeShare="true" useApv="true" useChangenote="true" fmShare="Y" genCode_Type="BK">
		<table name="opcqbook" key="id" c="true" r="true" d="true" u="true" initRow="1" hpk="" fKey="" order=""/>
		
		<checker class="com.multiable.opcq.ejb.checker.OpcqBookChecker"/>
	</module>
	
	<module name="opcqMem" mess="opcq.mem" extend="false" mainTable="opcqmem" recType="" useAccess="true" useAttach="true" useBeShare="true" useApv="true" useChangenote="true" fmShare="Y" importThreadMode="false" genCode_Type="MEM">
		<table name="opcqmem" key="id" c="true" r="true" d="true" u="true" initRow="1" hpk="" fKey="" order=""/>
		<table name="opcqmemt" key="id" c="true" r="true" d="true" u="true" initRow="0" hpk="hId" fKey="" order="" cpnType="table"/>
	</module>
</md>

See Module.xml for other available setting parameters.

Define Menu in navmenu.xml

This app has a total of four menus, they are:

  1. Book Category
  2. Book
  3. Member
  4. EBI for Member

p-share\src\main\resources\META-INF\navmenu.xml

<?xml version="1.0"?>
<nm xmlns="http://www.multiable.com/navmenu" app="opcq">
	
	<folder code="m18Opcq" messCode="opcq.opcqApp">
		<menu code="opcqBookCat" messCode="opcq.bookCat" src="view/opcq/module/opcqBookCat" module="opcqBookCat" mType="FM" order="1000">			
			<inherit name ="module_fc" />
		</menu>	
		<menu code="opcqBook" messCode="opcq.book" src="view/opcq/module/opcqBook" module="opcqBook" mType="FM" order="2000">			
			<inherit name ="module_fc" />
		</menu>	
		<menu code="opcqMem" messCode="opcq.mem" src="view/opcq/module/opcqMem" module="opcqMem" mType="FM" order="3000">			
			<inherit name ="module_fc" />
		</menu>		
		<folder code="biOpcq" messCode="opcq.ebi" order="4000">
			<icon name="cicon-ebi" library="font/cawIcon"/>
			<menu code="M18_EBI_OPCQMEM" messCode="opcq.memRep" src="view/module/ebi/ebi" mType="EBI" order="1000">
				<icon name="cicon-ebi-report" library="font/cawIcon"/>
				<inherit name="module_ebi"/>
			</menu>
		</folder>
	</folder>	
</nm>

See NavMenu.xml for other available setting parameters.

i18N Support

In order to avoid conflicts with other apps, the Key of each translation item is prefixed with Appname.

p-share\src\main\resources\META-INF\lang\Message_en.properties

p-share\src\main\resources\META-INF\lang\Message_zh-CN.properties

p-share\src\main\resources\META-INF\lang\Message_zh-TW.properties

c6

App Screenshot

Book Category

c2

Book

c3

Add books to Member

c4

c5