App Studio is a cloud-based IDE to quickly create and deploy applications. Use cases range from simple or medium complexity applications for personal use, to large scale business enabling and missing-critical applications structured as a micro-service architecture.
In this tutorial, we provide a practical guide on how to get started developing application with EInnovator App Studio, using as example a application to manage a database of Superheros. We will start be showing how to create a project, and define the data-model for the application. Following that we will use the built-in templates to automatically generate a Web Controller Component and Views for listing, displaying, creating and editing Superheros. We will test the application from within the App Studio followed by actual deployment in a Cloud Environment, by generation and building a Spring Boot application automatically from the application model. In later section we will also show how to add role-based based security checks, and to notify users of relevant events in the application.
A complete implementation of this tutorial, is available as a free solution in the App Studio marketplace. Thus, in addition to follow this tutorial by starting from an empty project, you may also import the Supeheros marketplace project and review the complete solution with the aid of this tutorial.
EInnovator Studio provides an high-level rapid application development (RAD) environment, combining the simplicity of visual programming and the power of traditional programming and IDE. It provides a well-defined programming model based on the Model-View-Component paradigm, with an integrated security and user notification model. Built-in abstractions include: Data-Model Entities, Views, Components, Roles, Notifications, test Datasets and test users.
Several View and Component generation templates are available allow quickly bootstrap new application and business solution in minutes. The view and component generation is informed by the data model which provides information to what makes most sense to generate in a particular application. An extensive Widget component library is available (e.g. for content, forms, charts, and other use-cases) to allow full customization of look-and-feel of UIs.
Code generation is multi-Target, and a single project can have multiple Targets. Supported targets include server and client sides with different runtimes and stacks (e.g. Java with Spring Boot), pure front-end PWA, mobile native, and hybrid frameworks. Additionally, a built-in application execution emulator allow to preview, test and demo applications from the cloud IDE without having to deploy to the cloud. This is considered extremely useful as it accelerates considerable the development and experimentation process. Generate target code is pushed to Git repositories (one for each Target), thus allowing developers and business to retain full control and ownership of the code-base. Including following mixed programming methodologies where some of the artifacts are generated by the App Studio and target-specific fine-grained customization can be done using the underlying runtime and stack APIs, practices, and mechanisms. App Studio also support partial run-trip code generation, allowing existing code-based based to be partially mapped back to Studio style data-model and abstractions, thus effectively working as a cross-target code converter.
Cloud building and deployment is done with integration with EInnovator Cloud Manager and EInnovator Cloud — a Kubernetes based cloud environment. This allows to setup a fully integrated continuous delivery practice where the development cycle is interwoven with devops operations.
Optional integration with EInnovator Micro-Sertice Suite — a set of out-of-the-box services solutions for common functionally, from SSO Authentication, to user notifications, file persistence, and social interaction — further simplifies development as it allows individual applications develop with the App Studio to focus on the specific functionality of their business domain. This further speeds up the app development-to-production life-cycle, the real-world inception of the new solutions, and continuous exploration of new features and business ideas.
First step to implement the Superheros application is to create a Project in the App Studio for the application. You will need first to register an account into EInnovator website, if you have not done so. Assuming you are already registered, navigate to https://studio.einnovator.org, and create a new project with name Superheros.
Select target type Service. with default settings, namely the default runtime Java, default stack Spring Boot, and default VDL Thymeleaf. This is not too important at this point, as you can later add additional Targets or change the Target type and settings. It is possible to preview, test, and demo the application from within the App Studio without performing a cloud build and deploy, so selecting a Target becomes important only when you want to build the app and deploy the app to the cloud for your users, or you want to push the target generated artifacts to a Git repository.
Image below shows the Project creation page, and the project dashboard page. Notice that the project dashboard has tabs to list and manage the key abstractions used to implement the project. Namely, the tabs Data-Model, Views, Components, Integration, Targets, and Settings.
First step into creating an application is to define its data model. That is, the set of entities, associations, and support types together with their properties, that captures and represents the domain. For the Superhero project, we will use only one Entity named Superhero and one support Enum type named Squad.
Create entity of category Entity with name Superhero. Select as parent entity the built-in library entity EntityBase3*. This provides some basic fields to the Entity, like a unique id, a unique uuid, and creationDate.
Create another entity of category Enum with name Squad.
Open the dashboard for entity Superhero and add the properties below:
name
of type String
variant Text
. Set as editor widget Input:Text
. Enable filtering, and set as filtering property q
with operator contains. Enable also the Table Column
option. While these setting are not strictly necessary, they inform view and component generation with makes it easier and faster to get the app to prototype stage.
img
of type String
varient Image:URL
. Set as editor widget Upload:Media
.
description
of type String
variant Text
. Se as editor widget Textarea
. Enable filtering, and set as filtering property q
with operator contains
(same as for property name).squad
of type Squad
(the enum you created earlier). Set as editor widget Select
. Enable filtering for this property.
villian
of type Boolean
. Set as editor widget Checkbox
.We already already created enumerated Squad
but did not specify which values are possible. Open the dashboard for enum Squad
, and navigate to the tab Dataset
. Each enumerated can have a set of static values, each with two (and possibly other) properties, namely value
and displayValue
. Add two values to Squad
:
MARVEL
value, with displayValue = Marvel
DC
value, with displayValue = DC
So far the data-model in very simply in the sense that there is no association between entities. To make it more realistic and interesting let’s define an additional property named friends
as a One-To-Many association between each Superhero and a set of other Superheros. Set the type of this property to List
with element type Superhero
.
Review the defined data-model in the the tab Data-Model > Data-Graph.
Something useful to do before moving forward is to generate a dummy dataset of instances of Entity for the purpose of later testing the app. In the dashboard of entity Supehero, tab Dataset click Generate Values. Select a instance count of 100. Confirm that 100 instance of dummy Supeheros have been created, using automatically generated value for the different properties, including name and description, and an identicon for the image.
Now that we have a data model we should create a set of Views that can be used to list, display, create, edit, and manage the instance of type Superhero.
On project tab View, click Add View. Select as view type, Fragment and view category Entity List. Select entity Superhero. Leave the other settings with default values.
Once the view is generate you should see the dashboard of the View the generated widget tree as shown below.
You can preview the View in tab Preview. Notice that data in the dummy dataset is being used for provide the data for the listing.
We also want that the project View have a user-friendly and consistent layout, so we will create a page with a layout that include the Entity List Panel. On project tab View, click Add View, and select as view type, Page. Select one of the provide layout — e.g. a two-column layout. Select the previous created fragment Entity List Panel as imported sub-view. This is shown in screenshot below.
Once the page view is created, preview it. Confirm that the page has the selected layout, and import the listing panel showing the details of the dummy Superheros.
You many not fully be happy about the ordering of the fields as they show in the table. Fortunately, the App Studio View editor makes it very easy to customize the generate views, or even create completely new View from scratch, using drag&drop and widget configuration panel. Try drag&drop the TH and TD columns widget, so that the columns are shown in the following order: img
, name
, squad
, vilian
, and friends
. Use preview as much as need to help you guide trough the process.
You many also want to change the look&fell of the page. Click on the widget created and edit some style properties in the widget property editor panel on the right side. Experiment with color, background, fonts, borders, margin and padding, etc.
We can repeat similar steps as above for the Supehero details view. On project tab View, click Add View. Select view type Fragment and view category Entity Details Panel. Select entity Superhero. Leave the other settings with default values. Preview the generate view. Use drag& drop to move the Image to top of the panel, and the widgets for the description and friends to the bottom.
Next, create another view of type Page. Select same layout as before. Select the previous created fragment Entity Details Panel as imported content sub-view.
Finally, let create a editor panel to create new instances or edit existing instance of Superheros. On project tab View, click Add View. Select view type Fragment and view category Entity Editor Panel. Select entity Superhero. Leave the other settings with default values. Preview the generate view. Use drag& drop to MediaUpload* widget to the top of the panel, and the widgets for the description and friends to the bottom.
Next, create another view of type Page. Select same layout as before. Select the previous created fragment Entity Editor Panel as imported content sub-view.
Once we have generate and customize the Views, we can move forward to generate the components needed to drive the application. The most important component is a Web Controller to control the rendering of the Superhero pages and data. This is the only component that we will strictly need run and test the app from within the App Studio with the built-in emulator. Other components if needed, are implicitly created by the emulator.
On project tab Components, click Add Component. Select component type Web Controller, and component template Entity CRUD. Select entity Superhero. Leave the other settings with default values. This will create a component named SuperheroController.
Confirm that the SuperheroController is create with success, with several methods each with a body of instructions. This methods implements the basic CRUD workflow to list, create, and edit instances of Superhero. The generated methods and instructions body are usually enough to get started with the project, and rendering the generated view. However, it is always possible to extend and modify the existing methods and add new methods to the component. App Studio offers an intuitive mixed visual-imperative programming model, that should be easily understandable by starting developer but powerful enough to support complex use cases and the sophistication of experienced developer.
Most methods in this generated component have an associate endpoint mapping, with an HTTP method and an associate URL path. The component SuperheroController defines also a based endpoint path prefix /superhero
. So the actual endpoints concat this prefix with the path specified in each endpoint method. The generated endpoints are summarized and explained below:
GET /supeheros list()
‐ Render the lists of SupeherosGET /supeheros/{id} show()
‐ Renders the details page of a particular Supehero uniquely identified by the id
in the path.GET /supeheros/create create()
‐ Renders the Supehero creation form pagePOST /supeheros createPost()
‐ Processes a submitted editor data (form in a web app) and create a new instance of Superhero. Redirect to the details page if the creation is successful.GET /supeheros/{id}/edit edit()
‐ Edits the details of an existing SuperheroPUT /supeheros/{id}/edit editPut()
‐ Processes a submitted editor data (form in a web app) and updates the instance of Superhero. Redirect to the details page if the creation is successful.DELETE /supeheros/{id} delete()
‐ Deletes the instance of Superhero with specified id
. Redirect to the listing page after deletion.An additional method of category ExceptionHandler
is also generated. This is method captures and processes any error Exception
sent by other methods.
Looking at the body of the generated method, you should notice that the ones that render a view complete the processing with instruction RENDER. This is the instruction used to select the view to render. The parameter of the RENDER is the name of the view. Confirm that those view name match and are bound to the View pages create earlier. If this is not the case (e.g. if you changed the default view names), select the view as appropriate.
Similarly, the methods that perform a redirect do this with instruction REDIRECT. The parameter of this instruction specifies which other HTTP endpoint should be rendered next. Confirm that the endpoint path match and are bound to other endpoints in this component. If you change the path of some the method endpoints, you should update the path as well in the REDIRECT instructions that should reference that endpoint.
Next we want to test the application, using the built-in emulator and interacting with the app. Select the Test tab in the SuperheroController dashboard. Select an endpoint method to test, starting with the method list()
mapped to endpoint /superhero
. Press Submit.
Confirm that the page with the list of Superheros is rendered. Do a a quick search on the list of Superhero by typing some query on the filter widgets.
Next, click on the hyper-link with the name of any of the Superhero, and confirm that the details page is rendered. Press the Back
button, and do this for other instances as well. Press also Edit and change the details of some of the instances.
For all pages, listing, details, and editor, you should confirm that the pages rendered are exactly the ones that you had previewed already. Previewing the page allow to do guide the creation of the look&feel. However, experimenting with and testing a Web Controller component allows to fully experience the app and UI/UX workflow as the a real final user will experience. Thus, going beyond what can be done only by previewing a View. Moreover, the data model variables used in rendering each view are fully determined by workflow, rather than being “mocked” and statically selected.
In the details page, press Delete and confirm that a delete confirmation modal show up. Choose to delete the Superhero and confirm that you are redirect again to the listings page. In other tab, open the entity dashboard for the Superhero entity, and confirm that delete entity is not longer present in the dummy dataset.
The Views and controller code generated automatically provides a good starting point to build the Superhero application. More often than not, we want to go further than the vanilla solution produced mostly automatically by the App Studio templates. To demonstrate how one goes about extending a basic application, we introduce the requirement of rendering a donut chart showing the relative proportion of Supeheros of each Squad (i.e. Marvel vs. DC). This involves three steps:
group by
query.SuperheroController.list()
method.In addition to Web Controller components as the one we created earlier, App Studio supports additional categories of components. Such as Rest Controllers, Managers, Repositories, and Event Listeners. A common pattern is for each Entity in a project to have one of each of these components, namely Repositories to define custom queries, and Managers to perform business functionality beyond pure DB quering. Managers and Respositories are implicit created by the App Studio to cover basic operations, while the other types of components which implements different kinds of presentation layers should be created explicity – often using the built-in templates as starting point.
For the Superhero app we want to create a custom Repository to add a custom query to group and count the number of Supeheros in each Squad. On project tab Components, click Add Component. Select component type Repository, and component template Entity CRUD. Select entity Superhero. Leave the other settings with default values. This will create a component named SuperheroRepository.
Confirm that the component SuperheroRepository is create with success, with several query methods created. These repository methods don’t have body made of instructions, rather they represent queries whose semantic is inferred form the name of the method or for more advanced use case from explicit query clauses. The methods already created implement basic CRUD functionality – i.e. create, retrieve one or many, update, and delete, for instances of Superhero. We now want to add one additional method name countGroupBySquad()
.
In the dashboard of component Superhero controller, click Add Method to open the method creation modal. Enter method name countGroupBySquad()
, without any parameters. Confirm that the method is created and shows up below the other pre-generated methods. This method will return a list of maps (key-value pairs) of the form {count=N, squad=Squad}
.
Next step is to invoke the method SuperheroRepository.countGroupBySquad()
from the method SuperheroController.list()
. Navigate to the dashboard of the SuperheroController component, and notice the instructions toolbar on the top. Drag the instruction EXPORT and drop in the method list()
before the RENDER instruction. The EXPORT instruction is used to make data available during a view rendering. It takes two parameters, one for the name to give to the exported variable and another for the expression to assign to the variable. Enter squadCounts
as variable name and superheroRepository.countGroupBySquad
. This is shown in the image below.
Finally, we want to modify the Superhero Table view to render in addition to the filter, and table, a donut chart to display the relative counts of Superhero per Squad. Navigate to the dashboard of the view Superhero Table. Notice the widget toolbar on the top. Click on the Graph widget category button, and drag a Chart widget to the view above the table and below the filter subview. Click on the Chart widget to edit the properties. Sel the type of the chart as Donut. Next, click on Add Dataset. Enter in the Expression attribute the value ${squadCounts.count}
and in the X Expression attribute the value ${squadCounts.squad}
.
To test the chart rendering, go back to the SuperheroController dashboard Test tab. Select the again the endpoint method list()
mapped to endpoint /superhero
, and press Submit. Confirm the donut chart is rendered, as show in the the image below.
After some tinkering, iteration, and interactive testing of the app, one might want to make a first deployment to the cloud. For this, we need to select a Target to generate code to and a cloud platform to deploy. In the Superhero Project dashboard, go to tab Targets. If you had selected the target Service at project creation time, there should be a tab for it already. In the Java Service > Settings tab, confirm that the runtime Spring Boot and VDL Thyemeleaf is selected.
To generate code for a Target we need first to configure a Git repository where the artifacts will be pushed. Click on Add Repository and select a GIT
In the Generate tab, press Generate. Confirm that a list of artifacts
With the Docker image in place, we are now fully ready to deploy the app to the cloud. We just need to make sure that the DB connection is configured appropriately also in the cloud environment. Fortunately, this is done automatically by EInnovator Cloud Manager if you specify a suitable Stack setting for the app.
TODO 3-4: Deploy the App in the Cloud with a MySQL binding
Suite / Boot
to tell the Cloud Manager, that the app is built using a Spring Boot stack, and additionally makes use of several services in EInnovator Micro-Service suite.spring.datasource.*
is set with values picked-up from the MySQL connector named superheros/root
. Make sure that the unique name of the app (superheros
) matches the name of the database.server.port
is to port mapped in the container (80 by default).http://superheros.myusername.nativex.cloud
.The default setting for the SSO Gateway server out of the blueprint https://sso.samples.sandbox.nativex.cloud
, uses a pre-deployed shared virtual server with name samples
running in Sandbox plan/mode. You want to change this, so you can have your own set of users, configure and administer the server, or even customize the look&fell of the server UI as seen by your users. There is can be done in two broad variations: your own sandbox like the samples
on, but with your owns database and a different name, or a dedicated server paid plan. With the Sandbox you are limited to a user pool of 100 users and limited request rate of 100 requests/hour, which is makes it mostly useful for early learning and exploration like following this tutorial. For real world development, you will want to upgrade to a dedicated server. The steps to follow to deploy a Sandbox or dedicated server are almost the same, but with the dedicated deployment you can obviously customize resources size like memory, number of instances, unlimited request rates, have enhanced security, and so forth.
TODO 4-1: Deploy a SSO Gateway
MyApps - dev
click on the Manage tab in the MySQL deployment, and the Database sub-tab. Create a Database named sso
by clicking on button Add Databasesso
and user root
, which should get the automatic name of sso/root
.sso
and your previouslly created domain. Keep the auto-deploy checkbox checked.Some of the great features of the SSO Gateway in EInnovator micro-service suite include the ability for different kinds customization. In other tutorial, we discuss in detail how to customize the UI, create custom UI themes, custom signup and registrations pages, branding and customization of notification templates, among other aspects — Custom Themes. In this tutorial, we focus on how to perform role based access control with custom roles.
When an application starts it registers in the SSO Gateway. Exactly what is registered can be configured in the property sso.registration
in application.yml
. In particular, we can register custom roles used to role based access control in out Superheros app, while benefinting from the role assignment and security management available in the admin UI of the SSO Gateway. Roles can be of two types Global Roles and Group Roles. In the Superheros app, we will use only Global roles. In particular, we want to define a global role Superhero Manager which is required to delete Superheros created by other users.
To improve user engagement we want the Superheros app to send notifications to users when certain events occur. In particular, we want notifications when a Superhero is updated to the user that first created the Superhero or last modified it, and to users with role SUPERHERO_MANAGER when a new Superhero is created or updated. Additionally, we want uses to receive notification via multiple channels, including email, SMS, and in app, and be able to customize their notification preferences. For this purpose, we will deploy the Notifications Hub of the EInnovator microservices suite and refactor the app to register new three new kinds of notifications on startup. A bonus point of using the Notifications Hub is that as app admins we can send newsletters and other email communications to our users (e.g. about Superheros* inside stories and news about app updates), or even perform SMS based campaigns.
TODO 7-2: Deploy the Notification Hub marketplace service.
notifications
and use (one of) your previously created domain. Keep the auto-deploy checkbox checked. Deploy the service.Superheros are usually popular and have lots of fans (and some detractors). We would like fans and detractors to be able to post comments and have discussions related to Superheros. Rather than reinventing the wheel and develop a commenting and social discussion functionality from the ground-up for specifically for the Superheros, will the more convenient approach of integrating the app with the Social Hub service from EInnovator micro-service suite. Specifically, we want to have a general Superhero discussion forum, and will want each Superhero details page to have its own dedicate discussion channel. Social Hub also support additional features like social impressions (e.g. likes and star ratings) case we decide to integrate that later.
TODO 8-1: Deploy the Social Hub marketplace service.
social
and use (one of) your previously created domains. Keep the auto-deploy checkbox checked. Deploy the service.TODO 8-2: Configure the Superhero app to use Social Hub.
Full access to generated source-code in own provided Git/VCS repositories. Round-Trip Code Generation with cross-model and language mappings. Integrated cloud builds and deployment with Integration with EInnovator Micro-Service Suite for modularity, scalable and robust distributed architectures. Integrated issue tracking for easy of coordination between developers, teach-leads, managers, and clients. Opt-in Project Ticket support. Marketplace of Solutions, Themes, Components and Widgets
In this getting started tutorial, we learn how to build microservice-enabled application for management of Supeheros using EInnovator micro-services. We build a docker image for the app and deployed to the cloud using the Cloud Manager. We installed different marketplace solutions. The SSO Gateway for authentication and role-based access control. The Document Store for file upload persistence. The Notification Hub for sending notification to users about Superheros updates. And Social Hub to setup a discussion forum and post comments about the Superheros.
Some suggested exercise extending the Superheros app:
Superhero.locked
, and update the access control rules so that Superheros with property locked=true
can only be updated by users with role SUPERHERO_MANAGER
"#superheros"
in method SuperheroManagerImpl.getTargetsCreate()
.
Comments and Discussion