© 2017 Created and maintained by Information Catalyst on behalf of DIGICOR Project [+44 (0)745 394 3997, +49 (0)40 743 81514]

How to create new Digicor services

Pre-requisites
Design functionality
  1. define user story and use cases

  2. define front-end (modules/views)

    • what user sees and how can interact with it (GUI look and feel)

    • what API GUI needs from the new service as well as from other services (define required interactions)

  3. define backend services. We promote using micro service architecture where each service has only one responsibility. As a result interaction with several services may be required to fulfil one use case. Define:

    • where is data from front-end stored (which backend service is responsible for providing/managing the data)

    • how is interaction delivered to other user

    • which APIs the service should publish

    • which events the service consumes and produces

      • APIs and events are typically negotiated between developers of producers and consumers

The above analysis is required to define new service and its interaction (GUI, REST API, consumed events, produced events).

Configure maven credentials for Digicor
  1. Get credentials for nexus.digicor-platform.eu - Access of partners to AWS GitLab

  2. add following lines to your .m2/settings.xml (more details at http://maven.apache.org/settings.html) and change your Nexus credentials there

 <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

                          https://maven.apache.org/xsd/settings-1.0.0.xsd">

      <localRepository/>

      <interactiveMode/>

      <usePluginRegistry/>

      <offline/>

      <pluginGroups/>

      <servers>

          <server>

              <id>digicor-maven</id>

              <username>your-username</username>

              <password>your-password</password>

          </server>

          <server>

              <id>archetype</id>

              <username>your-username</username>

              <password>your-password</password>

          </server>          

      </servers>

      <mirrors/>

      <proxies/>

      <profiles>

        <profile>

          <id>digicor</id>

            <repositories>

               <repository>

                 <id>archetype</id>

                 <name>Digicor NEXUS maven</name>

                 <url>https://nexus.digicor-platform.eu/repository/maven_group_digicor/</url>

               </repository>

               <repository>

                 <id>digicor-maven</id>

                 <name>Digicor NEXUS maven</name>

                 <url>https://nexus.digicor-platform.eu/repository/maven_group_digicor/</url>

               </repository>               

            </repositories>

        </profile>

      </profiles>

      <activeProfiles>

          <activeProfile>digicor</activeProfile>

      </activeProfiles>

    </settings>

New service from maven archetype

Our maven archetype can be found in git

https://git.digicor-platform.eu/digicor/java-libs/digicor-service-archetype.git

Now you can simply build new service using the maven archetype -

just fill your data marked in silver below

mvn archetype:generate -U \

    -DarchetypeArtifactId=digicor-service-archetype \

    -DarchetypeGroupId=cz.certicon.digicor \

    -DarchetypeVersion=1.9 \

    -DgroupId=cz.certicon.digicor \

    -DartifactId=service-name \

    -Dversion=1.0-SNAPSHOT \

    -Dpackage=cz.certicon.digicor.servicename \

    -DserviceName=ServiceName \

    -DservicePort=8080 \

    -Dauthor=john.doe@certicon.cz \

    -Ddate=2017-11-27 \

    -DinteractiveMode=false

  • archetypeVersion - use the latest version from pom.xml in our git (21.9. 2018 - current latest version is 1.8)

  • groupID - identification of the developing partner (company). Reversed domain name is recommended.

  • artifactId - name of maven artifact, reflected also in the local service folder name and service name in cloud

  • package - generated default package for your service source code

  • serviceName - service class name. This name will affect names of generated classes e.g. ${serviceName}Handler.class, ${serviceName}HandlerEvent.class, etc.

  • servicePort - port your service will listen at. This must be unique far all services in the cloud - uniqueness will be defined later and conflicting ports will be changed

 

Maven archetype generates service application and its events in the following folder structure.

Apart from java clases it contains build pipeline configuration file​

.gitlab-ci.yml

kubernetes configuration file​

service-name-app/kubernetes/service-name.yaml

and docker file for the service to configure docker image with runnable script

service-name-app/Dockerfile

service-name-app/service-name-app.sh

Generated Java source code

It is necessary to understand general concepts described in Development guidelines to be able to follow. Also for understanding details of following steps see http://eventuate.io/gettingstarted.html

If your service needs to publish some event you need to define it in service-name-events module

  • if you do not need it just remove it

Otherwise:

  • define command in commands package
    You can create new event instance by command only. Command classes must extend an aggregate-specific Command superinterface. (see http://eventuate.io/docs/javav2/java-commands.html for details)

  • define event in events package.
    For each event type implement event Class (see http://eventuate.io/docs/javav2/java-events.html for details) . The class describes the event - it may hold data required for event consumers. i.e. ProductionPlanCreated event holds data for new ProductionPlan.

  • create ServiceNameAggregate class in the domain package defining what events are created when a given command is processed in the process method (see http://eventuate.io/docs/javav2/java-aggregates.html for details)

  • configuration package contains spring configuration for publisher/consumer to configure connection to event store for given Aggregate

  • service package contains service which works with event store.
    Services use AggregateRepository class, parametrized by the given aggregate and the command, that enables saving and updating Aggregate data. (for details see http://eventuate.io/docs/javav2/java-services.html)

    • you can save/find/update entities in event store there

Service functionality will be implemented in service-name-app

  • handler package contains handlers that contain a code to be executed when consuming events (from this service defined in service-name-events)

    • it can be used if service need to persist its own data to event store - local service database is not persisted, if service restarts local data is lost

  • hateos contains basic GET /service-name/{id} method configuration

  • BackendConfiguration spring configuration to configure events, local view service and handler for events

  • RestAPIConfiguration spring configuration to configure Swagger and Eventuate for production use

  • test package contains test spring configuration RestAPITestConfiguration uses embedded event store and application tests for spring context load, /health endpoint and swagger-ui

  • other sources contains application.properties for docker and application_local.properties for direct run from jar

Developing and testing

 

Java JDK 8

Docker compose is not meant to replace unit tests in your service. Please write unit tests. There are some technologies to consider when your are embracing TDD in your development effort.

 

https://site.mockito.org/

 

https://junit.org/junit4/

 

https://spring.io/

 

https://www.baeldung.com/injecting-mocks-in-spring

 

There is plenty of tutorials on the Internet. If you would like, you can find inspiration in source code of:

 

https://git.digicor-platform.eu/digicor/java-services/company

 

https://git.digicor-platform.eu/digicor/java-services/tool-store

 

https://git.digicor-platform.eu/digicor/java-services/tender

 

https://git.digicor-platform.eu/digicor/java-libs/aws-authorizer

 

https://git.digicor-platform.eu/digicor/java-libs/jwt-authorization

Build and run tests locally (build it before each commit and push)

cd service-name

mvn clean install

Build and run service with Eventuate locally

 

If you need to run more services or service with eventuate interaction you can use docker compose. However, using docker-compose is not meant to replace tests in your code. It is meant only for experimenting with eventuate. If you are developing service which is listening for events it is advised to write tests which will "send" the event without need of eventuate infrastructure. Running tests is much faster than sending events by sending REST requests to running services. Some of the services require much more than eventuate to run. For example company service requires ElasticSearch, AWS S3 and AWS Cognito. Company service will be returning Internal Error to every request when ElasticSearch and AWS Cognito is missing. It is not our intention to be able to create Digicor on localhost also it is almost impossible, because of resource requirements (more than 60 GB of RAM).

 

Now your generated code could be build (JDK 1.8 is recommended, there may be some issues when Java 1.9 is used):

cd service-name

mvn clean install

  • service-name-events

  • service-name-app

Login to docker-private.digicor-platform.eu

 

$ docker login docker-private.digicor-platform.eu -u your-nexus-user-name -p your-nexus-password

Login Succeeded

Build your own docker image

cd service-name/service-name-app

mvn package

docker build -t service-name .

you can find docker image in your local docker repo

docker images

you can run docker image

docker run service-name

docker-compose

set DOCKER_HOST_IP environment variable -

http://eventuate.io/docs/usingdocker.html

 

clone repository -

https://git.digicor-platform.eu/digicor/docker-images/local-cluster

 

This configuration of Eventuate infrastructure can send events with payload around 1 000 000 characters. Conventional settings could send only 21 000 characters (default settings only 1000). Be aware that sending events with huge payload is not good practice in Event Sourcing. Huge payload usually means flaws in design of events and interactions between services.

#192.168.99.100 is IP where docker host is running

#bash

export DOCKER_HOST_IP=192.168.99.100

#win cmd

set DOCKER_HOST_IP 192.168.99.100

git clone git@gitssh.digicor-platform.eu:digicor/docker-images/local-cluster.git

cd local-cluster

docker-compose -f docker-compose.yml up -d

If you are on Windows and have some issues with volume mount try to set the following environment variable:

set COMPOSE_CONVERT_WINDOWS_PATHS=1

Deploy your service into digicor-platform.eu

  1. Repository for your service will be create upon request. Please contact us via contact page on this site and provide us a name of your service. Your repository will be created in https://git.digicor-platform.eu/digicor/java-services.

  2. You could push your service into the repository.

  3. After push, the GitLab CI pipeline will start automatically. Pipeline is defined in the file .gitlab-ci.yml. If you have any questions about CI, please do not hesitated to contact us.

  4. Service will be build automatically including docker images.

  5. The deployment step of the pipeline has to be manually confirmed in GitLab -> your-project -> CI/CD -> pipeline. This will deploy your service into Kubernetes cluster. The Kubernetes configuration files are in kubernetes/your-service-name.yaml. There should be no need to change this configuration file. When you need to change this file, please let us know.

 

Currently only project owner is allowed to push into master branch of his project. If you want to participate on project where you are not a owner you have to create new branch and then create a merge request.

Start with empty repository

git clone git@gitssh.digicor-platform.eu:digicor/java-services/production-plan.git

mvn archetype:generate ...

git add -A

git commit -m "message"

git push

Start with existing folder

mvn archetype:generate ...

cd your-service-name

git init

git remote add origin git@gitssh.digicor-platform.eu:digicor/java-services/your-service-name.git

git add -A

git commit -m "Initial commit message"

git push -u origin master

Further reading

For more technical information about the architecture behind the DIGICOR Portal,

please see below: