commit | 4cfdcfc5ad0ea4f247ef44bdd8dab67843b51b04 | [log] [tgz] |
---|---|---|
author | Florian Schmitt <florian.schmitt@atos.net> | Thu Aug 31 16:51:00 2017 +0200 |
committer | Florian Schmitt <florian.schmitt@atos.net> | Mon Sep 04 13:37:15 2017 +0200 |
tree | 80f9c05c7428020601667c750131ca2660aac9e1 | |
parent | b576fc9c721362e4a0cfbf660bd32b2773ea945a [diff] |
521665: Name convention rename Entity.nameMatches() to Entity.nameEquals() rename Relationship to RelationType rename Join to JoinType rename Operation to ComparisonOperator Change-Id: I170e290f43b84364b8516584fc07d5c9b468caba Signed-off-by: Florian Schmitt <florian.schmitt@atos.net>
Before you can install and build the application, you have to checkout and install: (gradlew install)
Business Object: Environment
Business Object: Test
Business Object: TestStep
Business Object: Measurement
Business Object: ChannelGroup
Business Object: Channel
Business Object: Project
Business Object: Pool
Query endpoint
http://SERVER:PORT/APPLICATIONROOT/mdm/query
_example:curl -POST -H "Content-Type: application/json" -d '{"resultType": "test", "columns": ["Test.Name", "TestStep.Name"], "filters": { "sourceName": "SOURCENAME", "filter": "Test.Id gt 1", "searchString": ""}}'http://sa:sa@localhost:8080/org.eclipse.mdm.nucleus/mdm/query
http://SERVER:PORT/APPLICATIONROOT/mdm/suggestions
_example: curl -POST -H "Content-Type: application/json" -d '{"sourceNames": ["SOURCENAME"], "type": "Test", "attrName": "Name"}' http://sa:sa@localhost:8080/org.eclipse.mdm.nucleus/mdm/suggestions
Preference service stores its data to a relational database. The database connection is looked up by JNDI and the JNDI name and other database relevant parameters are specified in src/main/resources/META-INF/persistence.xml. The default JNDI name for the JDBC resource is set to jdbc/openMDM. This JDBC resource and its dependent JDBC Connection Pool has to be created and configured within the glassfish web administration console or through asadmin command line tool.
Furthermore the schema has to be created in the configured database. Therefore database DDL scripts are available for PostgreSQL and Apache Derby databases in the folder schema/org.eclipse.mdm.preferences
of the distribution. Other databases supported by EclipseLink may also work, but is up to the user to adapt the DDL scripts.
curl -GET -H "Content-Type: application/json" http://localhost:8080/org.eclipse.mdm.nucleus/mdm/preferences?scope=SYSTEM&key=ignoredAttributes
curl -PUT -H "Content-Type: application/json" -d '{"scope": "SYSTEM", "key": "ignoredAttributes", "value": "[\"*.MimeType\"]"}' http://localhost:8080/org.eclipse.mdm.nucleus/mdm/preferences
curl -DELETE http://localhost:8080/org.eclipse.mdm.nucleus/mdm/preferences/ID
The Indexing is completely independent from the searching. So the Indexer can be freely deployed at any other machine. In the simplest case, the same steps as in Configuration have to be done. The application can then be deployed on any other machine. All components besides the FreeTextIndexer and its dependencies are not user. Those can be left out, if desired.
##Known issues: If you run into “java.lang.ClassNotFoundException: javax.xml.parsers.ParserConfigurationException not found by org.eclipse.persistence.moxy” this is a bug described in https://bugs.eclipse.org/bugs/show_bug.cgi?id=463169 and https://java.net/jira/browse/GLASSFISH-21440. This solution is to replace GLASSFISH_HOME/glassfish/modules/org.eclipse.persistence.moxy.jar with this: http://central.maven.org/maven2/org/eclipse/persistence/org.eclipse.persistence.moxy/2.6.1/org.eclipse.persistence.moxy-2.6.1.jar
If you run into “java.lang.ClassNotFoundException: com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector not found by com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider” you have to download http://central.maven.org/maven2/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.5.1/jackson-module-jaxb-annotations-2.5.1.jar and put it under GLASSFISH_HOME/glassfish/domains/domain1/autodeploy/bundles
The applications preferences are managed in the administration section. This section can be accessed via the Administration
button in the main navigation bar or via
http://../administration
. A preference is a pair of a unique key and a value. The key is composed of a prefix defining the purpose of the preference followed by an arbitrary but unique identifier string. It is recommended to choose the identifier the same as the preferences ‘name’ field, in case there is one. The value holds the preference's data in a Json string. The following preferences, sorted by their scope, can be set:User:
System:
Source:
However, it might be necessary to reload the application before a newly defined preference is available or any changes on an existing preferences are applied. WARNING: Corrupted preferences can result in malfunctions of the application.
A user scoped preference's area of effect is limited to the logged in user. All user scoped preferences can also be set in dialogs in the main application.
1.) Basket Basket preferences keys must start with the prefix basket.nodes.
. This preference has the fields ‘items’ and ‘name’ and holds all the information for saved baskets. The field ‘items’ holds an array of MDMItems, providing the relevant information of a related node, i.e. ‘source’, ‘type’ and ‘id’. The field ‘name’ defines the name, which is provided in the main application to load this basket.
** Example: { “items”: [{“source”:“MDMNVH”,“type”:“Test”,“id”:38}], “name”: “basketExample” }
2.) View View preferences keys must start with the prefix tableview.view.
This preference has the fields ‘columns’ and ‘name’ and holds the layout information for the tables displaying the search results and the basket nodes. The field ‘columns’ holds an array of ViewColumn objects. A ViewColumn is an Object with the fields ‘type’, ‘name’, ‘sortOrder’ and an optional field ‘style’. The ViewColumn‘s ‘type’ can be set to all available MDM data types, i.e. Project
, Pool
, Test
, TestStep
, Measurement
, ChannelGroup
, Channel
. The ViewColumn’s ‘name’ field specifies an attribute, which must be an searchable attribute for the given ‘type’. The ViewColumn‘s sortOrder can be set by the number 1
(ascending), -1
(descending), or null (unsorted). Only one column of the array can have a non-null value sortOrder at a time. The ViewColumn’s style element can hold any CSS-style object. However, it is supposed to contain only the columns width. The column order in the array is identically with the appearance in the table. The view's field ‘name’ defines the name, which is provided in the main application to load this view.
**Example: { “columns”: [{“type”:“Test”,“name”:“Id”,“style”:{“width”:“75px”},“sortOrder”:null}], “name”: “viewExample” }
3.) Filter Filter preferences keys must start with the prefix filter.nodes.
. This preference has the fields ‘conditions’, ‘name’, ‘environments’, ‘resultType’ and ‘fulltextQuery’. It provides the information for the attribute based / advanced search. The field ‘conditions’ holds an array of Condition objects. A Condition specifies a search condition for attribute based search. It consists of the fields ‘type’, ‘name’, ‘operator’, ‘value’ and ‘valueType’. The Condition‘s ‘type’ can be set to all available MDM data types, i.e. Project
, Pool
, Test
, TestStep
, Measurement
, ChannelGroup
, Channel
. The Condition’s ‘name’ field specifies an attribute, which must be an searchable attribute for the given ‘type’. The Condition‘s ‘operator’ field, holds on of the following numbers: 0
(=), 1
(<), 2
(>), 3
(like). The Condition’s ‘value’ field holds a string array containing input for the attribute based search. The Condition‘s ‘resultType’ field should match the type corresponding to the attribute specified in the ‘name’ filed, e.g. string
, date
or long
. The Filter’s field ‘name’ defines the name, which is provided in the main application to load this filter. The Filter‘s field ‘environments’ holds an string array with the names of the sources that should be included in the search. The Filter’s field ‘resultType’ can be set to all available MDM data types (see above). Only nodes of this type will be included in the search. The Filter's field ‘fulltextQuery’ holds a string containing full text search input.
**Example: { “conditions”:[{“type”:“Test”,“attribute”:“Name”,“operator”:0,“value”:[],“valueType”:“string”}], “name”:“filterExample”, “environments”:[“sourceName”], “resultType”:“Test”, “fulltextQuery”:"" }
System scoped preference are applied globally.
1.) Node provider
The navigation tree structure can be defined via a node provider. The default node provider is set in
I.) Structure
a) First layer/root nodes In the node provider each layer of nodes of the navigation tree is defined in a nested object. The first layer of nodes, is always the environment level. This is necessary due to the provided endpoints. The first layer consists of the fields 'name', 'type', and 'children'. The field 'name' sets the name, which is displayed in the application to select the corresponding node provider. The field 'type' defines the data type of the nodes, which is always `Environments` on the first layer. The next layer of nodes are defined via the field 'children'. b) Children A child object consists of the fields 'type', 'query', and 'children'. The field 'type' sets the data type of this layer of nodes. It can be set to all available MDM data types, i.e. `Project`, `Pool`, `Test`, `TestStep`, `Measurement`, `ChannelGroup`, `Channel`. The filed 'query' holds the URL to load this layer of nodes. The first part of the query for each child object should be `/` plus the type of the layer in small letters followed by an `s`. For a nested child objected a filter is attached to the query in the form: `?filter=<parentType>.Id eq {<parentType>.Id}`. The placeholder <parentType> has to be replaced by the actual parent type (set in the field 'type' in the parent child or root layer, see example below). At runtime the curly braces will be replaced by the Id of the parent node. Further child objects, and thereby more sublayers, can be nested via the field 'children'. The children field does not need to be set for the last layer of nodes.
II.) Examples
a) Minimal node provider { "name": "My name to display", "type": "Environment"} b) node provider with two child layers { "name": "My name to display", "type": "Environment", "children": { "type": "Project", "query": "/projects", "children": { "type": "Pool", "query": "/pools?filter=Project.Id eq {Project.Id}" } } }
Source scoped preferences are applied at any user but limited to the specified source. The source can be specified in the Add Preference
or Edit Preference
dialog.
1.) Ignored Attributes The ignore attributes preference must have the exact key ignoredAttributes
. An identifier must not be added. The preference specifies all attributes, which are supposed to be ignored in the detail view. The preference is a simple Json string holding a list of attributes in the form {“.”}. The placeholders and have to be replaced by the actual type and name of the attribute which should be ignored, respectively.
**Example: [“*.MimeType”, “TestStep.Sortindex”]
##Create a module Any MDM module needs to be a valid angular2 module. An angular2 module consists of one angular2 component and one ng-module at least. In the angular2 component any content can be defined. The component must be declared in a ng-module to grant accessibility in the rest of the application. In a module additional components and services can be defined. All related files should be stored in a new subfolder in the app folder
###Angular2 components (see example 1) A component is defined in a typescript file starting with the @Component() identifier. Any html content can be provided here in an inline template or via a link to an external html resource. Thereafter the component itself, which is supposed to hold any logic needed, is defined and exported.
###Ng-module (see example 2) On one hand the ng-module provides other MDM modules of the application, and thereby all the services and components declared within them, in this MDM module. The ‘imports’ array holds all modules from the application needed in this MDM module. It should always hold the MDMCoreModule, which provides basic functionalities. On the other hand a ng-module grants accessibility of components of this module in other directives (including the html template) within the module (in a ‘declaration’ array) or even in other parts of the application (in an ‘export’ array). For more details see *https://angular.io/docs/ts/latest/guide/ngmodule.html.
** Minimal example First create a new folder
import {Component} from ‘@angular/core’; @Component({template: ‘Example Module’}) export class MDMNewComponent {}
import { NgModule } from ‘@angular/core’; import { MDMCoreModule } from ‘../core/mdm-core.module’; import { MDMNewComponent } from ‘./mdm-new.component’; @NgModule({imports: [MDMCoreModule], declarations: [MDMNewComponent]}) export class MDMNewModule {}
###Embedding a module (no lazy loading) To embed this new module in MDM you have to register this module in the MDMModules Module. This is done by registering the component to moduleRoutes in modules-routing.module.ts:
{ path: ‘new’, component: MDMNewComponent}
Furthermore you have to define a display name for the registered route in the array returned by getLinks in modules.component.ts:
{ path: ‘new’, name: ‘New Module’ }
For further information refer to the Angular 2 documentation for modules & router:
###Lazy loading and routing module For lazy-loading (recommended in case there is a high number of modules) embedding of the module is slightly different.
{ path: ‘example’, loadChildren: ‘../example-module/mdm-example.module#MDMExampleModule’}
Additionally, a ng-module, the so called routing module, is needed to provide the routes to this modules components.
const moduleRoutes: Routes = [{ path: '', component: MDMExampleComponent }]; @NgModule({imports: [RouterModule.forChild(moduleRoutes)], exports: [RouterModule]}) export class MDMExampleRoutingModule {}
The routing module needs to be declared in the ng-module of this module as well. A full example is provided in
###Filerelease module The filerelease module is stored in the following folder: *..\org.eclipse.mdm.nucleus\org.eclipse.mdm.application\src\main\webapp\src\app\filerelease
It can be embedded as any other module described above. Register to moduleRoutes in modules-routing.module.ts:
{ path: ‘filerelease’, component: MDMFilereleaseComponent }
Add entry to links array in MDMModulesComponent:
{ name: ‘MDM Suche’, path: ‘search’}
To make the filerelease module available in the detail view it needs to be imported in the corresponding ng-module mdm-detail.module.ts. Thereafter, the MDMFilereleaseCreateComponent can be imported to the mdm-detail-view.component.ts. Then the following has to be added to the mdm-detail-view.component.html file:
<mdm-filerelease-create [node]=selectedNode [disabled]=“isReleasable()”>
It should be located right after the add to basket button: