Skip to the content.

Welcome to the cdi-training Wiki!

The intention of this repository is to provide a training for the JakartaEE CDI 2.x specification. This project will be developed under the umbrella of a Gepardec Learning Friday Project.

Developer Guide

This page represents the guide which will help you to setup the project on your local machine and tells you how to contribute to the project.

The project is based on the following listed specifications.

The project uses the following client side libraries in form os webjars.

System Requirements

This project depends on the following software:

  1. OpenJDK-17
  2. Wildfly-26.1.0.Final
  3. Maven-3.x.x

How to set up your environment

Install the depending software, check out the github repository and setup the IDE of your choice. See the repository root README for further details.

How to provide documentation

All of our documentation is available as Github Pages, which relates to the projects repository.

How to use Git Branching

We use the simple Github-Flow because we need no special version handling. We name our feature branches feature/<ticket_id_or_expresive_name> and merge them via reviewed Merge-Requests.

How to implement (MVC) Controllers

Controllers are JAX-RS endpoint classes with the naming scheme *Controller e.g. InjectController which provide http based action endpoints and for views to render.

All controller classes need to be annotated with:

  1. @RequestScoped because in MVC we are stateless
  2. @Controller which enables the MVC framework for all contained methods

If not all contained endpoints return a view, then only those endpoint methods need to be annotated with @Controller which return a view.

The http endpoint are named either as:

  1. The http method used e.g. @GET get()
  2. The action name e.g. @Path("/action") action()

The endpoints either return

See the following snippet for an example controller implementation.

import jakarta.ws.rs.core.Response;

@Path("/path")
@RequestScoped
public class MyController {

    @Path("/")
    @GET
    @Controller
    public String get() {
        return "path/index.xhtml";
    }

    @Path("/action")
    @GET
    @Controller
    public String action() {
        // Do something and return the page
        return get();
    }

    @Path("/post")
    @POST
    public Response action() {
        // Do something and return the response
        return Response.ok().build();
    }
}

For further learning about Jakarta-MVC controller see the Jakarta MVC 1.1.0 specification.

How to implement (MVC) JSF views

The template engine we have chosen is JSF where we only use the templating part of JSF to provide us with common components, so that we have consistent views and an easy way to implement views. The rest is actually plain html, css, text and javascript.

The root directory for our views is src/main/webapp/WEB-INF/views where we organize our views with the following structure.

See section for a list of available JSF components for building GUIs.

How to provide static resources

In Jakarta-MVC static resources can be provided when located in the webapp directory. The static resources are referenced via normal links, no JSF involved.

The main thing to consider is that the @ApplicationPath(...) of the JAX-RS Application must not define the root path, because the rest engine cannot provide the static resources.

The static resource are organized in the root directory src/main/webapp/resources and with the following structure.

All provided images must be PNG files.

How to use javascript

Inline javascript must be avoided, and all javascript for a page is implemented in its own file as a javascript ES-6 module.

The root directory for all javascript files is src/main/webapp/resources/js where the javascript files are structured in subdirectories depending on the context they are used for.

Javascript modules are implement at least in the following way.

// Optional state object
const state = {
    attribute: value,
};

// Optional (e.g.: click event listener registration)
const registerElementClickEventListener = (options) => {
    const {
        element,
    } = options;
    element.addEventListener('click', () => console.log('element clicked'));
};

const init = (options) => {
};

export default {
    init,
};

Parameters for the javascript module are always provided as an options object. If html elements are used in any ways, then the html element instance itself is provided and never ids.

Javascript modules are used in a xhtml page the following way.

<!-- Inserts the contained tags at the end of the HTML page -->
<ui:define name="bottom"> 
    <!-- The used javascript is a javascript module -->
    <script type="module">
        // '#{pathHelper.buildResourcePath("/js/mp.js")}' is a EL-Expression which gets resolved to ''/mptraining/resources/js/mp.js''
        // Imports your modules
        import mp from '#{pathHelper.buildResourcePath("/js/mp.js")}'
        import myModule from '#{pathHelper.buildResourcePath("/js/basic/<MP_SPEC>/myModule.js")}'

        // Initializes your javascript module once per page load
        mp.registerOnLoad(() => myModule.init({
            ...
        }));
    </script>
</ui:define>

JSF Components

Tags

The custom JSF tags implement GUI components which are used globally.

xmlns:tag="http://tags.microprofile.training.gepardec.com"

Button

Renders a link acting as a button, for executing GET requests like with a link.

Attributes:

  1. id
    The page unique id
  2. text
    The text for the button
  3. path (Optional, Default=’#’)
    The relative path from the rest application path on, or a in-page references via ‘#’
  4. rendered (Optional, Default=true)
    The rendered flag
<tag:button id="toMyActionOrResource" text="Go to example"/>
<tag:button id="toMyActionOrResource" text="Go to example" path="#otherId"/>
<tag:button id="toMyActionOrResource" text="Go to example" path="/basic/index"/>

Renders an ordinary link with a text for executing GET requests.
The component accepts children, for instance an icon.

Attributes:

  1. id
    The page unique id
  2. text (Optional)
    The text for the link
  3. path (Optional, Default=’#’)
    The relative path from the rest application path on, or a in-page references via ‘#’.
  4. target (Optional, Default=’_self’)
    The link target
  5. rendered (Optional, Default=true)
    The rendered flag
<tag:link id="toMyActionOrResource" text="Go to example"/>
<tag:link id="toMyActionOrResource" text="Go to example" path="#otherId"/>
<tag:link id="toMyActionOrResource" text="Go to example" path="/basic/index" target="_blank"/>
<tag:link id="toMyActionOrResource" text="Go to example" path="/basic/index" target="_blank">
    <i class="fas fa-arrow"/>
</tag:link>

Renders a nav link with a text for executing GET requests from the navbar.
The link is marked active if the user is on the current page or if the active flag ist set.
The component accepts children, for instance an icon.

Attributes:

  1. id
    The page unique id
  2. path
    The relative path from the rest application path on
  3. text (Optional) The text for the link
  4. rendered (Optional, Default=true)
    The rendered flag
  5. active (Optional, Default=false)
    The active flag marking the nav link active
<tag:navLink id="toMyResource" path="/basic/index" text="Go to example"/>
<tag:navLink id="toMyResource" text="Go to example" path="/basic/index" active="#{pathHelper.isOnSubpage('/basic/config')}">
    <i class="fas fa-arrow"/>
</tag:navLink>

Card

Renders a card with a header and button section used for an element in teh index pages.

Attributes:

  1. id
    The unique card id within a view
  2. title
    The card title
  3. rendered (Optional, default true)
    The rendered flag
<tag:card id="indexExampleMpHealth" title="First part">
    <ui:define name="body">
        <p>...</p>
    </ui:define>
    <ui:define name="buttons">
        <tag:button id="toMpHealthExample" text="Go to example" path="/basic/health"/>
    </ui:define>
</tag:card>