You are viewing the documentation for Blueriq 15. Documentation for other versions is available in our documentation directory.

This page applies to you when you want a different data storage for the Persistence API than the default which is provided in the Customerdata service [old]

The default implementation for the Persistence API is the Customerdata service. This page provides information about implementing a custom data storage for the Customerdata service by extending the existing Customerdata service [old]. This is suitable in case of an different database or different database scheme.

Please note that the Customerdata service is written in Java and Spring. Because of this, extending the Customerdata Service with custom implementation also requires you to use Java and Spring. Also, maven is used as build tool.

This page assumes that you have basic knowledge of Java, Spring and Spring Boot.

Custom components

For creating this custom data store implementation, two components of the existing Customerdata service need to be replaced with a custom implementation.

  • blueriq-customerdata-sql-store-service → custom data store implementation
  • blueriq-customerdata-sql-store-application → custom war application

 

blueriq-customerdata-sql-store-service

The blueriq-customerdata-sql-store-service is a Hibernate implementation which stores the data in the database. For storing the data in a different database or different data structure you need to replace this part with your own implementation which handles the data storage using blueriq-customerdata-api-v1.

blueriq-customerdata-sql-store-application

The blueriq-customerdata-sql-store-application packages a war file for deployment on a application server. When you create a custom data store implementation you need to package a new war containing the needed components(see: Custom war implementation).

blueriq-customerdata-api-v1

When you are implementing a custom data store you need to implement some interfaces from the blueriq-customerdata-api-v1 and use the model classes of the api-v1.

The blueriq-customerdata-api-v1 consists out of the following packages:

  • com.blueriq.customerdata.api.v1.exception
  • com.blueriq.customerdata.api.v1.expression
  • com.blueriq.customerdata.api.v1.model
  • com.blueriq.customerdata.api.v1.order
  • com.blueriq.customerdata.api.v1.repository
  • com.blueriq.customerdata.api.v1.select

The following packages are needed for filtering, ordering and selecting data: com.blueriq.customerdata.api.v1.expression, com.blueriq.customerdata.api.v1.order and com.blueriq.customerdata.api.v1.select.

In the com.blueriq.customerdata.api.v1.repository package, you will find the interface needed for retrieving, storing and deleting the data using the expression, model, order and select packages as input. The model package is also used as return results for some operations. for more information see the javadocs


Example project

There are multiple ways how you can create your custom implementation, there is no fixed way to do this. In order to get you started you can download an example project with an example implementation that just logs the operations called.

custom-implementation-example.zip

 Maven structure:

  • example-custom-customerdata
    • example-customerdata-parent 
    • example-customerdata-data-store-service
    • example-customerdata-data-store-application
    • example-customerdata-data-store-standalone

example-customerdata-parent

The project parent definition contains the required Customerdata Service dependencies.

Customerdata Service dependencies
<!-- Required Customerdata Service dependencies -->
<dependency>
  <groupId>com.blueriq</groupId>
  <artifactId>blueriq-customerdata-parent</artifactId>
  <version>${com.blueriq.customerdata.version}</version>
  <type>pom</type>
  <scope>import</scope>
</dependency>
<dependency>
  <groupId>com.blueriq</groupId>
  <artifactId>blueriq-customerdata-api-v1</artifactId>
  <version>${com.blueriq.customerdata.version}</version>
</dependency>

example-customerdata-data-store-service

This part is meant for the custom implementation. In the example it contains a config and an example implementation of the IAggregateRepository that just logs every action and returns defaults where needed. See: Creating a custom data store implementation for information.

example-customerdata-data-store-application

Here a war file gets packaged for deployment on a application server. Please see Creating a custom war implementation for more information about this module.

example-customerdata-data-store-standalone

This is a standalone Spring Boot application which is running on embedded Tomcat. Not required, but added for easy local development.

Creating a custom data store implementation

In order for custom implementation to work there needs to be:

  • at least one config class annotated with org.springframework.context.annotation.Configuration (for your custom java bean configuration)
  • at least one bean of type: org.springframework.transaction.PlatformTransactionManager (to ensure transactionality within other components of the Customerdata service)
  • only one bean of type: com.blueriq.customerdata.api.v1.repository.IAggregateRepository (to handle the aggregate storage)

In the example project above the minimal needed classes and configuration is already provided. There is a custom @Configuration class available (CustomDataStoreConfig.java) which initializes the required transactionManager bean (of type PlatformTransactionManager). It also makes sure that the ExampleAggregateRepository.java (implements IAggregateRepository) is include by component scanning.

Transaction management

Within the Customerdata service, there are components that require transactionality and the data store implementation is one of them. Since you are building a custom implementation of the data storage you will need to provide a transaction manager for it. The transaction managers work in a chain to ensure the correct transaction order. In order to let the chain work in the correct order you will need to add a correct order value to your transaction manager bean as done in the example above (annotate your transaction manager bean with @Order(10)).

Application properties

If you follow the same application structure as provided in the example above, all the Customerdata service properties will still work. The exception is of course the datasource and hibernate properties. Those properties are not used because you are providing your own data storage implementation.

Implementing the IAggregateRepository

To have your own data storage you need to implement the com.blueriq.customerdata.api.v1.repository.IAggregateRepository. This interface contains all the operations done on the data storage.The example project provided has an ExampleAggregateRepository which just logs when the methods from the interface gets called (just for example purposes).

The summary of the IAggregateRepository:

  • creating or updating data will done by using the com.blueriq.customerdata.api.v1.model.AggregateModel
  • for returning a single record the com.blueriq.customerdata.api.v1.model.AggregateModel is used
  • for returning multiple records the com.blueriq.customerdata.api.v1.repository.AggregateModelResult.AggregateModelResult is used
  • when specific fields are requested the com.blueriq.customerdata.api.v1.select.SelectItem is used
  • to return results in a specific order the com.blueriq.customerdata.api.v1.order.OrderItem is used
  • for filtering data the com.blueriq.customerdata.api.v1.expression.Expression is used
  • the flexibel metadata fields are represented in com.blueriq.customerdata.api.v1.model.MetadataModel

 For more information see the javadoc 

AggregateModel data field

The com.blueriq.customerdata.api.v1.model.AggregateModel has a data field which contains an XML representation of the Aggregate defined in the Blueriq model. The nodes in this XML are flexible because business engineers can model this, based on their needs, in the Blueriq Studio.

Example Aggregate XML of the AggregateModel.data

<aggregate type="Dossier">
        <entity type="Ondernemer" root="true"
            id="f2ba0707-d1a4-47d0-abab-f9edb6cb638a">
            <attribute name="AantalWerknemers" multivalue="false">456</attribute>
            <attribute name="Ondernemersvorm" multivalue="false">BV</attribute>
            <attribute name="Openingstijden" multivalue="false">09:00 - 17:00</attribute>
            <attribute name="Bedrijfsnaam" multivalue="false">Blueriq</attribute>
            <relation name="HeeftAdres" multivalue="false">4d0d932c-6184-4c9b-9609-05c12c99825b</relation>
            <attribute name="Domein" multivalue="false">ICT</attribute>
            <attribute name="KvKNummer" multivalue="false">456</attribute>
            <attribute name="Activiteit" multivalue="false">Realisatie IT
                platform voor ondersteuning primaire processen</attribute>
            <attribute name="Handelsnaam" multivalue="false">Blueriq</attribute>
        </entity>
        <entity type="Betrokkene" root="true"
            id="bbc424e0-523d-4c3b-8646-baed13578141">
            <attribute name="Aanvrager" multivalue="false">456</attribute>
            <attribute name="BehandelaarBeoordelaar" multivalue="false">daniel</attribute>
            <attribute name="BehandelaarIntaker" multivalue="false">maarten</attribute>
            <attribute name="AanvragerReferentieId" multivalue="false">456</attribute>
        </entity>
        <entity type="PrimaireBeslissing" root="true"
            id="fe49f20a-6214-4c02-a024-d03a7f711d75" />
        <entity type="Zaakgegevens" root="true"
            id="5fd13154-4ddf-4ede-b39c-2331bc87da44">
            <attribute name="Ingediend" multivalue="false">true</attribute>
        </entity>
        <entity type="Contact" root="true"
            id="bb09d0d3-de9e-4020-bf71-f7931d0b80fc" />
        <entity type="Zaak" root="true" id="b83488dc-7232-4e94-b6de-28b76a6dda97">
            <attribute name="ProcessId" multivalue="false">101607</attribute>
            <attribute name="DatumAanmaken" multivalue="false">2018-04-26T02:41:05,385</attribute>
            <attribute name="Zaaktype" multivalue="false">WindEnergie</attribute>
            <attribute name="DossierId" multivalue="false">118181</attribute>
            <relation name="Documenten" multivalue="false">a3cfbc40-c014-4662-a61b-5587d27f951a</relation>
            <attribute name="Id" multivalue="false">118182</attribute>
            <attribute name="DatumAfsluiten" multivalue="false">2018-05-10T02:41:05,385</attribute>
        </entity>
        <entity type="Advies" root="true"
            id="66c74978-4bdc-4b2e-b6d0-09e3199c71d5" />
        <entity type="Norm" root="true" id="1738a6d5-04df-4d42-bea0-ba6d548a42d7">
            <attribute name="Juistheidsvraag" multivalue="false">true</attribute>
        </entity>
        <entity type="WindmolenProject" root="true"
            id="b81d50ba-b49d-41b6-a78d-1d6651b7672e">
            <attribute name="Aantal" multivalue="false">55</attribute>
            <attribute name="GrootteRotorBladen" multivalue="false">54</attribute>
            <attribute name="Hoogte" multivalue="false">57</attribute>
            <attribute name="Beschrijving" multivalue="false">coovslorrzohjo</attribute>
            <attribute name="Duur" multivalue="false">9</attribute>
            <attribute name="GewenstSubsidieBedrag" multivalue="false">15812.0</attribute>
            <attribute name="Naam" multivalue="false">stbtzahjjgenqixvflok</attribute>
            <attribute name="Doel" multivalue="false">rqzyuhbdavxums</attribute>
        </entity>
        <entity type="Adres" root="true"
            id="4d0d932c-6184-4c9b-9609-05c12c99825b">
            <attribute name="Plaatsnaam" multivalue="false">s Hertogenbosch</attribute>
            <attribute name="Huisnummer" multivalue="false">8</attribute>
            <attribute name="FunctieAdres" multivalue="false">vestigingadres</attribute>
            <attribute name="HuisnummerToevoeging" multivalue="false">F</attribute>
            <attribute name="Postcode" multivalue="false">5222AE</attribute>
            <attribute name="Land" multivalue="false">NL</attribute>
            <attribute name="Straatnaam" multivalue="false">Veemarktkade</attribute>
        </entity>
        <entity type="Document" root="false"
            id="a3cfbc40-c014-4662-a61b-5587d27f951a">
            <attribute name="Datum" multivalue="false">2018-04-26T02:41:20,000</attribute>
            <attribute name="FileType" multivalue="false">application/pdf</attribute>
            <attribute name="FileName" multivalue="false">Document.pdf</attribute>
            <attribute name="FileSize" multivalue="false">46314</attribute>
            <attribute name="Id" multivalue="false">2a6e0f8e-2db8-4957-a1ce-f0b4f4776761</attribute>
            <attribute name="Eigenaar" multivalue="false">456</attribute>
        </entity>
    </aggregate>

The format of the data field is XML at this moment but might change in later version to another format.

Usage Expression for filtering

The expressions for filtering can be of different types. For example if you have an filter which wants all the values 'X' to be greater then 'Y' the com.blueriq.customerdata.api.v1.expression.GreaterThanExpression is used.

The following Types of Expressions can be used in a filter → 

There can be multiple filter conditions in a filter expression. When this is the case the Expression object will be a tree of expressions using the AndExpression and the OrExpression to separate the filters.

 

Creating a custom WAR implementation

In order to use your custom implementation it needs to be deployed to an application server. To be able to do that you need to package a WAR (Web application ARchive).

Because we use Spring Boot, the WAR application should contain a class that initializes the web application. When you look at the example project provided above, you will find the class:com.blueriq.example.customerdata.data.store.application.config.CustomerdataDataStoreApplicationConfig.java
In order to start the Customerdata service Spring-boot application correctly you will need to add two application.sources:

  • CustomerdataOdataServiceConfig.class: this is the Main config of the Customerdata Service.

  • The second application.source is your custom Configuration class(with the @Configuration annotation) for initializing your custom data store implementation. In the example below it is CustomDataStoreConfig.class: because in the provided example project this is the custom config.

CustomerdataDataStoreApplicationConfig.java
public class CustomerdataDataStoreApplicationConfig extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(CustomerdataOdataServiceConfig.class, CustomDataStoreConfig.class);
  }

}

Deployment on JBoss-EAP (6.4 and 7)

If you are deploying you WAR application on JBoss-EAP, you will need to add an additional deployment information to the WEB-INF. In the provided example there is already a jboss-web.xml to provide a context-root (<context-root>customerdata</context-root>). There is also and deployment-structure.xml provided which contains the needed deployment-structure for the example to work on JBoss-eap-6.4. If you want to deploy the war of the example on JBoss-eap-7, you will need to modify the deployment-structure.xml, see comments in the provided deployment-structure.xml for details.

Depending on your custom data store implementation, it can be necessary to modify the deployment-structure.xml because of conflicting libraries.

Test

For the Aggregate functionality in the Blueriq Runtime, it is important that the behavior of the Customerdata Service with a custom data store implementation is the same as the original Customerdata Service. There are ReadyAPI (regression) tests available to test the Persistence API. These tests are data storage independent. Please contact support if you wish to use the ReadyAPI regression tests to verify your custom implementation.