Recommendations and Best Practices
Build and Version Info
To be able to have the build date and version of your apps at runtime, it is recommanded to create
a file named build.properties
file in src/main/resources
folder with the following contents.
version=${pom.version}
build.date=${timestamp}
No need to modify the |
Config
-
If you have multiple projects and you don’t want to place the Git repository configuration in each project, you can put the
pre.config.properties
in acommons-lib
project, and create anapp.config.properties
in each project with the app.name key only with a unique name for the containing app. -
To have more flexibility and security, you can replace your
config.properties
orpre.config.properties
during the CICD process to have the right configuration to avoid exposing production and other environments configurations to the wrong people.
Exception Handling
-
If you have checked exception, always have only one catch statement.
-
Never catch Runtime exception
-
In the catch statement just call
JK.throw(e);
the framework will handle the rest. -
If you are handling an exception inside method that should return value, it is safe to return null after
JK.throw(e)
.
Project Structure for Web Apps
As shown in the below figure, below is the preferred project structure for JK-Framework Web applications:
-
Create the following folders in src/main/webapp
-
resources
-
admin
-
login
-
pages
-
public
-
-
Templates: Create three facelet template files in src/main/webapps/WEB-INF/templates:
-
default.xhtml (look below for a proposed template)
-
empty.xhtml (look below for a proposed template)
-
error.xhtml (look below for a proposed template)
-
-
CSS: In the resources create
-
app.css: consists of the high layout of the app, mainly covers the styles in the default.xhtml template.
-
app.js: consists of the main Java script functions and callbacks that are mainly required on the app which most likely called references from default.xhtml template.
-
css/primefaces-fix.css: this file will includes any overridden styles of prime-faces components on the app level, for specific pages changes, you need to override in the page.css of that page.
-
css/root.css: this file shall contains the main theme variables, check the below example for more information.
-
css/components/component1.css: in case of complex pages, it could be good idea to create css file for each component
-
-
Each page in the pages folder should contains page.css and page.js files next to the index.xhtml.
-
In each page, and for consistency, make sure to:
-
Use ${request.contextPath} before any relative URL.
-
use ?reload=#{util.reloadRandom()} next to any static resources url such as javascript or css, to ensure refresh in development time on each request for easier development.
-
-
Pages Structure
-
Create public/home folder for public pages access
-
Create admin folder for admin pages access
-
Create pages folder for protected pages.
-
Each page should be treated as folder, where the folder is the page name, and inside that folder we shall have index.xhtml which will be automatically triggered if we only put the folder name in the URL. For example, if you have employee page, create employee folder in the pages folder, then create index.xhtml page inside that folder, the full path will be _src/main/webapp/pages/employee/index.xhtml*.
-
Create home page at pages/home/index.xhtml to serve as the default page after the user logged in.
-
Create src/main/webapp/index.xhtml that redirects to pages/home/
-

JSF/Faces on Production
JSF may requires important tunings to run smoothly on Production environment with low-overhead.
The needed configuration are discussed in my DZone Article
But mainly, you will need to create a production web.xml
that is placed in the project during the CICD process,
the final web.xml
should looks something like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns = "https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version = "5.0"
metadata-complete = "false">
<context-param>
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>jakarta.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>-1</param-value>
</context-param>
</web-app>
Commons-Lib
It is highly recommended to create a common-lib
project that will include all the common classes, API’s,
components, and utilities that are needed by all the system components.
This library shall be deployed to artifact management software such as Nexus.
Microservices
-
Try to create Microservices clients by extending
JKServiceClient
orJKMatureServiceClient
, this will make it easier for developers to call the other methods transparently. -
Service Clients shall be created by the Microservice developer.
-
Service Clients and Models should be placed in
commons-lib
project to have available to all other developers and projects. -
Microservice component testing should at least include:
-
Launching the API using JKWebApplication.run()
-
Calling all the exposed endpoints using the developed client.
-
Frameworks and libraries such as Mockito could be utilized to provide the needed data during test-automation. |
Logging
It is recommended to use logging as follows:
-
Public method:
logger.info();
at the start of each method. -
Non-public methods:
logger.debug()
-
Most of the time you will not need to use
logger.error()
since it will be used internally by the framework in case of exceptions or failure. -
It could be a good idea to have
logger.info
at the end of each public methods for later performance tuning.