Create New Subapplication
Overview
This tutorial provides a step-by-step guide to creating a new subapplication within Etendo Mobile. By following these instructions, you will learn how to fully utilize the capabilities of Etendo RX and leverage the visual components available in the Etendo UI Library to build a functional subapplication.
The tutorial will guide you through the creation of the Product Subapp, a simple application that enables the addition, deletion, and modification of products, as well as their visualization in a grid. Upon completion, you will have the skills to create and distribute subapplications as modules, thereby extending the mobile functionality of Etendo.
Info
Before beginning, ensure that your local environment meets all necessary requirements by reviewing the Etendo Mobile Getting Started section.
Module Setup
Create New Etendo Classic Module
Application
> Application Dictionary
> Module
-
As a System Administrator role, open the Module window and create a new register. This module will be used to develop and distribute the application.
Tip
- Notice that the name can be anything you want, but the type has to be set as Module.
- The description field is free and also required.
- The Is Rx checkbox indicates that this module will include RX service configurations, the RX service Javapackage must be specified.
- The Is React checkbox indicates that this module includes a subapplication and React Native code is generated.
- In this case, start from
1.0.0
module version and set the DB Prefix asETSAPPP
.
Dynamic App configuration
Application
> General Setup
> Application
> Dynamic App
Configure and export dynamic applications in Etendo Classic, which are displayed dynamically in Etendo Mobile.
In the Dynamic App window, specify the subapplication path and version.
For the example we are following, the Dynamic App in Etendo must be configured with the following form fields and corresponding values:
Fields to note:
- Module: The module that can export the window configuration. In our example case, set
Product SubApp
. - Name: Name with the application will be shown. In our example case, set
Product Subapp
- Directory Location: The path where the compiled application bundle is located. In development, the path is empty
/
, but in production, the path is/<javapackage>/web/
. In our example case, set/
- Active: To select if this application is active or not. In our example case, set
true
The Dynamic App Version tab allows the application to be versioned, enabling both development and production versions.
Fields to note:
- Name: Name of the application version E.g.
dev
or1.0.0
. In our example case, setdev
- File Name: The bundle name of the compiled application, by default
dist.js
. - Default: This check defines that this version is productive. In our example case, set
false
- Is Development: This check defines that this version is in development and can be deployed locally. In our example case, set in
true
- Active: To select if this application version is active or not. In our example case, set
true
Info
For more information visit the Dynamic App developer guide.
Role configuration
Application
> General Setup
> Security
> Role
Logged in as the Group Admin role (which is the default role for accessing Etendo Mobile), the settings are applied as specified below.
Important
Keep this dynamic app as active.
Export the Module
-
After saving all the configuration, you have to export the changes. Open a terminal in the root of your Etendo Classic project and execute the following command:
Important
The output must be a "BUILD SUCCESSFUL" message.
-
A new module is created in the
/modules
folder, with the following structure
Dockerized Services
Before proceeding, it is necessary to start the Etendo RX services. These services provide a security layer (Auth Service), a data access layer (Das Service), which are essential for consuming or writing data in Etendo and Edge Service . Additionally, by selecting the isReact checkbox in the previously defined module, React code will be automatically generated, allowing for easier data access.
To launch all the services, it is necessary to define the following configuration variables in the gradle.properties
file:
Info
For more information about how to handle Etendo Dockerizations, visit Docker Management.
Tomcat and PostgresSQL Dockerized (Optional)
It is also possible to run the dockerized PostgreSQL service and Tomcat service, optionally adding the Platform Extensions Bundle and the following configuration variables:
Then, to effectively run the services, it is necessary to execute the command in the terminal:
Here, all the services and their respective logs can be seen running using Docker Desktop tool.
RX Config window
Application
> Etendo RX
> RX Config
This configuration window stores the access data for Etendo RX services, which are crucial for the interaction between different services. In this case, two records need to be created: one for the RX Config service, responsible for distributing the dynamic configurations of other available services, and another for the Auth service, which provides security utilities. The Auth service must be accessible by the subapplication to obtain the authentication token for requests.
As System Administrator
role, in this window, it is necessary to add two entries, one for each service to be used. The following fields should be included:
- Service Name: The name of each service.
- Service URL: The internal URL of the Docker service.
- Updatable Configs: Check this checkbox.
- Public URL: Configure the publicly accessible URL for the service.
See the configuration examples bellow and replicate them.
Info
The Public URL field only needs to be configured when the subapplication is set to production.
Info
If using Dockerized Tomcat, the URLs within the container's network are http://config:8888
and http://auth:8096
.
Projections and Search
This section covers the creation of projections, mappings, and searches, which enable the generation of a dynamic REST API in the RX DAS service. These configurations allow for reading, writing, and filtering data. Projections are applied to Etendo Classic tables, creating a subset of data that can be interacted with through the API.
Create a Projection
Application
> Etendo RX
> Projections and Mappings
-
As a
System Administrator
role, it is required to create a projection that reflect partial views of the Product class and contain only the necessary properties. -
To do this, we will go to the
Projections and Mappings
window and create a new projection, select the module under developmentProduct SubApplication - 1.0.0 - English (USA)
, where these configurations will be exported and in the name field we defineProdSubApp
. -
Now, with the selected projection we add in the tab
Projected Entities
two projections, one for reading data, selecting the tableM_Product
and in the Mapping Type field we selectEtendo to external system
and another projection for writing data, selecting again the tableM_Product
and in the Mapping Type fieldExternal system to Etendo
. The other fields are auto-completed with respect to these values.
Creating Entity Fields
-
Now, we define which fields we want to retrieve. To do this, we start by selecting the data reading projection
PRODSUBAPP - Product - Read
and run theCreate Projection Fields
process, in the pop-up we will select the fields to project. In our example case:- active
- id
- name
- productCategory
- searchkey
- taxCategory
- UOM
- UPCEAN
Note
While not all of these fields will be displayed in the application, as record editing is allowed, we are also selecting all the mandatory fields to create a product.
-
Now we define which fields should be saved when creating or editing a record, in this case we select the write projection
PRODSUBAPP - Product - Write
and run the processCreate Projection Fields
selecting the same fields as for the read one- active
- id
- name
- productCategory
- searchkey
- taxCategory
- UOM
- UPCEAN
-
In the case of the
productCategory
,taxCategory
andUOM
fields in the application they will not be editable, but they must be autocompleted with a default value, for this we can use constant mappings. If new Products are created, these default values will be used.To do this, we go to the
application
>Etendo RX
>Constant Values
window and define constant IDs of default values. Here are some example IDs:Name Default Value ProductCategory
DC7F246D248B4C54BFC5744D5C27704F
taxCategory
43A120C9377B4537B5D1976D9B1233D7
uOM
100
-
Finally selecting the
PRODSUBAPP - Product - Write
write projection, edit theproductCategory
,taxCategory
andUOM
records, modify theField Mapping
field toConstant Mapping
, delete theJsonpath
and select the corresponding value in theConstant Value
drop-down list, defined in the previous step.
Create a Search in Projected Data
Now, when reading data, it is possible to create filters, for this we have to associate these filters to a table and it is possible to export this filter in the module under development.
To do this, we open the Tables and Columns
window, in our example select the M_Product
table, go to the Repository
tab and create a new record with the development module. Then we create a new record in the Search
tab
Create a New Search and Search Parameter
Next, we will define a search method to be used when we want to consume the products. To create this new filter/search method, in the Repository tab of the M_Product
table, create a new record with the method name getFilteredProducts
and the hql query filter.
SELECT e FROM Product e WHERE (e.active = true) AND (lower(e.name) LIKE lower('%' || :name || '%') OR lower(e.uPCEAN) LIKE lower('%' || :name || '%')) order by e.updated desc
As we can see in the query, it receives the:name
parameter of String type that we define in the Search Parameter
tab.
Restart the Etendo RX Service
Restart the Das RX service to recognize the projections and mappings.
Info
By accessing http://localhost:8092/swagger-ui/index.html, the RX DAS Service Swagger can be visualized. This interface allows for consultation of the endpoints generated based on the previously made configurations.
Creating the Subapplication
-
Now, create the subapplication based on a template published in NPM, Etendo Subapp Data Template Typescript . Execute the Gradle command to automatically create the subapplication within the module under development.
In the example we are working on, use the following command:A new subapplication will be created within the module, with the following structure:
Product Subapp Example
This section covers an overview about the product subapplication example screens and principal parts of the subapplication.
Consideration
The applications must be developed for both platforms: phone and tablet.
Home Screen
- This is the main screen of the subapplication. It will show a list of products. Also, it will allow us to edit and remove a product, find a product by name and navigate to the detail of a product.
Phone View
- The route to this screen is
src/screens/home/index.tsx
and the content:
import React from 'react';
import TableList from '../../components/table/list';
import { NavigationProp } from '@react-navigation/native';
import { INavigationContainerProps } from '../../interfaces';
import locale from '../../localization/locale';
import useProduct from '../../lib/data_gen/useProduct';
import { Product } from '../../lib/data_gen/product.types';
interface TableListProps {
navigation: NavigationProp<any>;
route: any;
navigationContainer: INavigationContainerProps;
}
const Home = (props: TableListProps) => {
const { getFilteredProducts, updateProduct } = useProduct();
return (
<TableList
deleteDataItem={async (item: Product) => {
item.active = false;
await updateProduct(item);
}}
{...props}
columns={[
{
key: 'id',
primary: true,
visible: false,
},
{
key: 'name',
label: locale.t('Table.products'),
visible: true,
width: '50%',
},
{
key: 'uPCEAN',
label: locale.t('Table.barcode'),
visible: true,
width: '30%',
},
]}
getData={getFilteredProducts}
labels={{
dataName: 'Product',
navbarTitle: locale.t('Home.welcome'),
containerTitle: locale.t('Home.productList'),
buttonNew: locale.t('Home.newProduct'),
searchPlaceholder: locale.t('Home.typeProduct'),
successfulDelete: locale.t('Success.deleteProduct'),
errorDelete: locale.t('Error.deleteProduct'),
}}
/>
);
};
export default Home;
Product Detail
- This screen will show the detail of a product. Also, it will allow us to edit the product.
- It is the same screen used to create a new product, if the prop does not have ID.
- The route to this screen is
src/screens/productDetail/index.tsx
, add the content:
import React, { useState } from 'react';
import TableDetail from '../../components/table/detail';
import { NavigationProp } from '@react-navigation/native';
import locale from '../../localization/locale';
import useProduct from '../../lib/data_gen/useProduct';
interface TableDetailProps {
navigation: NavigationProp<any>;
route: any;
}
const ProductDetail = (props: TableDetailProps) => {
const { createProduct, updateProduct } = useProduct();
const [id, setId] = useState<string>('');
const [searchKey, setSearchKey] = useState<string>('');
const [name, setName] = useState<string>('');
const [uPCEAN, setUPCEAN] = useState<string>('');
return (
<TableDetail
{...props}
createData={async () => {
await createProduct({ searchKey, name, uPCEAN });
}}
updateData={async () => {
await updateProduct({ id, searchKey, name, uPCEAN });
}}
fields={[
{
key: 'id',
visible: false,
setValue: setId,
getValue: id,
labels: {
title: '',
placeholder: '',
},
},
{
key: 'searchKey',
setValue: setSearchKey,
getValue: searchKey,
labels: {
title: locale.t('ProductDetail.searchKey'),
placeholder: locale.t('ProductDetail.searchKeyExample'),
},
},
{
key: 'name',
setValue: setName,
getValue: name,
labels: {
title: locale.t('ProductDetail.products'),
placeholder: locale.t('ProductDetail.nameExample'),
},
},
{
key: 'barcode',
setValue: setUPCEAN,
getValue: uPCEAN,
labels: {
title: locale.t('ProductDetail.barcode'),
placeholder: locale.t('ProductDetail.barcodePlaceholder'),
},
},
]}
labels={{
editTitle: locale.t('ProductDetail.editProduct'),
newTitle: locale.t('ProductDetail.newProduct'),
errorTitle: locale.t('Error.product'),
successUpdateTitle: locale.t('Success.updateProduct'),
successCreateTitle: locale.t('Success.saveProduct'),
connectionError: locale.t('Error.connection'),
navbarTitle: locale.t('Home.welcome'),
cancel: locale.t('Common.cancel'),
save: locale.t('Common.save'),
successTitle: id
? locale.t('Success.updateProduct')
: locale.t('Success.createProduct'),
}}
/>
);
};
export default ProductDetail;
Navegation
In addition, it is necessary to add the navigation configuration in the app.tsx
file, in the return statement. This configuration provides the infrastructure to navigate between the different screens of the application.
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
options={{ headerShown: false }}
name="Home"
initialParams={{ dataUser }}>
{props => <Home {...props} navigationContainer={navigationContainer} />}
</Stack.Screen>
<Stack.Screen
options={{ headerShown: false }}
name="ProductDetail"
initialParams={{ dataUser }}>
{props => <ProductDetail {...props} />}
</Stack.Screen>
</Stack.Navigator>
Info
For more information, visit Navegation Stack concept in Subapplication Structure Page.
Info
For more information about the language management and translations, visit Languague concept.
Info
For more information about Subapplication Params, visit Params from Etendo Mobile concept.
Running the Sub-application
-
Once the subapplication is created, the react-native code must be generated, with types and functions that interact with the RX DAS Service, for this we execute the command Gradle :
Info
Make sure that the Etendo RX services are running and without errors before executing this command.
In our example case
As we can see, it will be generated in the/subapp/src/libs/
folder the functions and types that will be used for reading and writingGET
andPOST
data. -
In a terminal on path
modules/<javapackage>/subapp
, install the depedencies declared in thepackage.json
, following the command: -
Then, to run the subapplication in development mode execute:
Note
By default, the application run in development mode on
localhost
at port3000
. Additionally, changes in the/src
directory are automatically scanned, enabling dynamic updates to the application during development. This ensures that any modifications are reflected in real-time without restarting the application.
Visualizing the subapplications
-
Open the Etendo Mobile application on a mobile device. You can use either an emulator or a physical device.
-
In Etendo Mobile setting up the Edge service URL (Edge is an Etendo RX service, which implements a Spring cloud-driven gateway), by default the environment URL should be
http://<local-network-ip>:8096/
and the context path by default/etendo
.Info
To find out your IP address on the local network, you can run the command
ifconfig
in a Mac or Linux terminal oripconfig
in Windows CMD. -
Login Etendo Mobile and you will see the list of subapps. Clicking on
Product Subapp
will access to development mode app. -
Now you can view, filter, create, edit and delete products.