diff --git a/pom.xml b/pom.xml
index 92eb0334d5643990593bba4876c55bc9493d6b3f..1b111ff100737d5a527f587da4d4a4ddcca473f6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
     <modules>
         <module>smp-parent-pom</module>
         <module>smp-api</module>
-        <!-- module>smp-angular</module -->
+        <module>smp-angular</module>
         <module>smp-server-library</module>
         <module>smp-webapp</module>
     </modules>
diff --git a/smp-angular/angular.json b/smp-angular/angular.json
index c4b1efa5071619fc56ce4ec65185796d031ddb0d..5407fe48fcd069a941882a45d2f3214260c732f8 100644
--- a/smp-angular/angular.json
+++ b/smp-angular/angular.json
@@ -3,8 +3,8 @@
   "version": 1,
   "newProjectRoot": "projects",
   "projects": {
-    "domibus-MSH-web": {
-      "root": "",
+    "SMP-UI": {
+      "root": "ui/",
       "sourceRoot": "src",
       "projectType": "application",
       "architect": {
@@ -49,18 +49,18 @@
         "serve": {
           "builder": "@angular-devkit/build-angular:dev-server",
           "options": {
-            "browserTarget": "domibus-MSH-web:build"
+            "browserTarget": "SMP-UI:build"
           },
           "configurations": {
             "production": {
-              "browserTarget": "domibus-MSH-web:build:production"
+              "browserTarget": "SMP-UI:build:production"
             }
           }
         },
         "extract-i18n": {
           "builder": "@angular-devkit/build-angular:extract-i18n",
           "options": {
-            "browserTarget": "domibus-MSH-web:build"
+            "browserTarget": "SMP-UI:build"
           }
         },
         "test": {
@@ -93,7 +93,7 @@
         }
       }
     },
-    "domibus-MSH-web-e2e": {
+    "SMP-UI-e2e": {
       "root": "e2e",
       "sourceRoot": "e2e",
       "projectType": "application",
@@ -102,7 +102,7 @@
           "builder": "@angular-devkit/build-angular:protractor",
           "options": {
             "protractorConfig": "./protractor.conf.js",
-            "devServerTarget": "domibus-MSH-web:serve"
+            "devServerTarget": "SMP-UI:serve"
           }
         },
         "lint": {
@@ -117,7 +117,7 @@
       }
     }
   },
-  "defaultProject": "domibus-MSH-web",
+  "defaultProject": "SMP-UI",
   "schematics": {
     "@schematics/angular:component": {
       "prefix": "app",
@@ -127,4 +127,4 @@
       "prefix": "app"
     }
   }
-}
\ No newline at end of file
+}
diff --git a/smp-angular/package-lock.json b/smp-angular/package-lock.json
index ce85822ea304eeca9f7ad859cdf0bf81958e6317..7bd1dcb8d76a85dd6cb0acb609d1e9c184705cec 100644
--- a/smp-angular/package-lock.json
+++ b/smp-angular/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "smp-web",
-  "version": "0.0.0",
+  "version": "4.0.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -398,7 +398,7 @@
         },
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         }
@@ -412,6 +412,14 @@
         "tslib": "1.9.3"
       }
     },
+    "@angular/flex-layout": {
+      "version": "6.0.0-beta.18",
+      "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-6.0.0-beta.18.tgz",
+      "integrity": "sha512-1Alv3YSIZYp0CTUIESIaSQLoSVyLzuNKPa5bGM/RzOmeSrndm5plVgI9wopGfJUDiwM18R97rq/4XjDvNT/+ig==",
+      "requires": {
+        "tslib": "1.9.3"
+      }
+    },
     "@angular/forms": {
       "version": "6.1.10",
       "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-6.1.10.tgz",
@@ -555,7 +563,7 @@
     },
     "@types/q": {
       "version": "0.0.32",
-      "resolved": "http://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
+      "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
       "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
       "dev": true
     },
@@ -1386,7 +1394,7 @@
       "dependencies": {
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         }
@@ -1526,7 +1534,7 @@
     },
     "browserify-rsa": {
       "version": "4.0.1",
-      "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
       "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
       "dev": true,
       "requires": {
@@ -1579,7 +1587,7 @@
     },
     "buffer": {
       "version": "4.9.1",
-      "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
       "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
       "dev": true,
       "requires": {
@@ -2661,7 +2669,7 @@
         },
         "readable-stream": {
           "version": "1.1.14",
-          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
           "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
           "dev": true,
           "requires": {
@@ -3007,7 +3015,7 @@
     },
     "events": {
       "version": "1.1.1",
-      "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
+      "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
       "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
       "dev": true
     },
@@ -3396,7 +3404,7 @@
     },
     "file-saver": {
       "version": "1.3.8",
-      "resolved": "http://registry.npmjs.org/file-saver/-/file-saver-1.3.8.tgz",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.3.tgz",
       "integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg=="
     },
     "filename-regex": {
@@ -3836,7 +3844,7 @@
         },
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         },
@@ -4167,7 +4175,7 @@
         },
         "readable-stream": {
           "version": "1.0.34",
-          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
           "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
           "dev": true,
           "requires": {
@@ -4535,7 +4543,7 @@
     },
     "is-builtin-module": {
       "version": "1.0.0",
-      "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
       "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
       "dev": true,
       "requires": {
@@ -5031,7 +5039,7 @@
     },
     "json5": {
       "version": "0.5.1",
-      "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
       "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
       "dev": true
     },
@@ -5282,7 +5290,7 @@
     },
     "load-json-file": {
       "version": "1.1.0",
-      "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
       "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
       "dev": true,
       "requires": {
@@ -5665,7 +5673,7 @@
       "dependencies": {
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         }
@@ -5788,7 +5796,7 @@
     },
     "minimist": {
       "version": "0.0.8",
-      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
       "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
       "dev": true
     },
@@ -5851,7 +5859,7 @@
     },
     "mkdirp": {
       "version": "0.5.1",
-      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "dev": true,
       "requires": {
@@ -6480,7 +6488,7 @@
     },
     "os-locale": {
       "version": "1.4.0",
-      "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+      "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
       "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
       "dev": true,
       "optional": true,
@@ -8431,6 +8439,15 @@
         }
       }
     },
+    "string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.2"
+      }
+    },
     "string-width": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@@ -8442,18 +8459,9 @@
         "strip-ansi": "3.0.1"
       }
     },
-    "string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "5.1.2"
-      }
-    },
     "strip-ansi": {
       "version": "3.0.1",
-      "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
       "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
       "dev": true,
       "requires": {
@@ -8752,7 +8760,7 @@
       "dependencies": {
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         }
@@ -8773,7 +8781,7 @@
       "dependencies": {
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         },
@@ -9697,7 +9705,7 @@
     },
     "wrap-ansi": {
       "version": "2.1.0",
-      "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
       "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
       "dev": true,
       "requires": {
diff --git a/smp-angular/package.json b/smp-angular/package.json
index b6c15c7b0cb5dd89dfc777e13b6308d674889ca4..49773211f46c980bab0c24e9359bc805cea7a350 100644
--- a/smp-angular/package.json
+++ b/smp-angular/package.json
@@ -7,7 +7,7 @@
     "ng": "ng",
     "start": "ng serve --proxy-config proxy-config.json",
     "build": "ng build --dev --base-href /smp/",
-    "prod": "ng build --prod --output-path=./src/main/resources/META-INF/resources",
+    "prod": "ng build --prod --output-path=./src/main/resources/META-INF/resources/ui/",
     "test": "ng test",
     "lint": "ng lint",
     "e2e": "ng e2e"
@@ -26,6 +26,7 @@
     "@angular/platform-browser-dynamic": "^6.1.0",
     "@angular/platform-server": "^6.1.0",
     "@angular/router": "^6.1.0",
+    "@angular/flex-layout": "^6.0.0-beta.16",
     "@swimlane/ngx-datatable": "^13.0.0",
     "core-js": "^2.5.7",
     "file-saver": "^1.3.3",
diff --git a/smp-angular/proxy-config.json b/smp-angular/proxy-config.json
index 5917edca58f63eb5e070bbd941c8d332b902b4ac..a7016ea68517712aab5ed1b9f4317cf828f61d58 100644
--- a/smp-angular/proxy-config.json
+++ b/smp-angular/proxy-config.json
@@ -1,6 +1,6 @@
 {
-  "/ui/**": {
-    "target": "http://localhost:8080/smp/",
+  "/rest/**": {
+    "target": "http://localhost:8080/smp/ui/",
     "changeOrigin": true,
     "secure": false,
     "logLevel": "debug"
diff --git a/smp-angular/src/app/app.component.html b/smp-angular/src/app/app.component.html
index e7dd19fa6dd4e37874b87811e1ca6e1ec55cbfa7..4957b3e62a203a083267dc15e4bbc37ed0624638 100644
--- a/smp-angular/src/app/app.component.html
+++ b/smp-angular/src/app/app.component.html
@@ -8,24 +8,25 @@
       </div>
     </div>
 
-    <button mat-raised-button class="sideNavButton" [routerLink]="['/']" id="messages_id">
-      <mat-icon matTooltip="Search participants" matTooltipDisabled="{{fullMenu}}" matTooltipDisabled="right">search</mat-icon>
-      <span>Participants</span>
+    <button mat-raised-button class="sideNavButton" [routerLink]="['/']" id="search_id">
+      <mat-icon matTooltip="Search" matTooltipDisabled="{{fullMenu}}" matTooltipDisabled="right">search</mat-icon>
+      <span>Search</span>
+    </button>
+    <button mat-raised-button class="sideNavButton" [routerLink]="['/edit']" id="edit_id">
+      <mat-icon matTooltip="Edit" matTooltipDisabled="{{fullMenu}}" matTooltipDisabled="right">edit</mat-icon>
+      <span>Edit</span>
+    </button>
+    <button mat-raised-button class="sideNavButton" [routerLink]="['/domain']" id="domain_id">
+      <mat-icon matTooltip="Domain" matTooltipDisabled="{{fullMenu}}" matTooltipDisabled="right">domain</mat-icon>
+      <span>Domain</span>
     </button>
 
-    <button mat-raised-button class="sideNavButton" [routerLink]="['/user']" *ngIf="hasAdmin()" id="user_id">
+    <!-- button mat-raised-button class="sideNavButton" [routerLink]="['/user']" *ngIf="hasAdmin()" id="user_id" -->
+    <button mat-raised-button class="sideNavButton" [routerLink]="['/user']" id="user_id">
       <mat-icon matTooltip="Users" matTooltipDisabled="{{fullMenu}}" matTooltipDisabled="right">people</mat-icon>
       <span>Users</span>
     </button>
 
-    <button mat-raised-button class="sideNavButton" [routerLink]="['/truststore']" *ngIf="hasAdmin()" id="truststore_id">
-      <mat-icon matTooltip="Truststore" matTooltipDisabled="{{fullMenu}}" matTooltipDisabled="right">vpn_key</mat-icon>
-      <span>Keystore</span>
-    </button>
-    <button mat-raised-button class="sideNavButton" [routerLink]="['/domain']" *ngIf="hasAdmin()" id="domain_id">
-      <mat-icon matTooltip="Domain" matTooltipDisabled="{{fullMenu}}" matTooltipDisabled="right">domain</mat-icon>
-      <span>Domain</span>
-    </button>
 
     <div class="collapse-button">
       <button *ngIf="fullMenu" mat-raised-button id="expand_id" (click)="toggleMenu()">
@@ -99,10 +100,11 @@
         </mat-menu>
       </div>
     </div>
+    <alert style="position:fixed; left:220px; top:0;right:0;z-index: 500"></alert>
     <div id="routerHolder" style="min-height: 100%" >
         <router-outlet></router-outlet>
     </div>
-    <alert></alert>
+
   </div>
 
 </mat-sidenav-container>
diff --git a/smp-angular/src/app/app.component.ts b/smp-angular/src/app/app.component.ts
index 9ba1de72df965f13590ee31d2941247680038866..21632f9e89deb2b06405d7840a4bf3c08482aea9 100644
--- a/smp-angular/src/app/app.component.ts
+++ b/smp-angular/src/app/app.component.ts
@@ -3,7 +3,6 @@ import {SecurityService} from './security/security.service';
 import {Router, RouterOutlet} from '@angular/router';
 import {SecurityEventService} from './security/security-event.service';
 import {Title} from '@angular/platform-browser';
-import {Http, Response} from '@angular/http';
 import {Observable} from 'rxjs';
 import {HttpClient, HttpResponse} from '@angular/common/http';
 
@@ -27,10 +26,13 @@ export class AppComponent implements OnInit {
               private securityEventService: SecurityEventService,
               private http: HttpClient,
               private titleService: Title) {
+
     let applicationNameResponse: Observable<string> = this.http.get<string>('rest/application/name');
 
     applicationNameResponse.subscribe((name: string) => {
       this.titleService.setTitle(name);
+
+
     });
   }
 
diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts
index 09cdd78478ca0f8a148a4ffa8a5312f5d282cec4..2234f5b068e8f4ffe850120bbdcd96ec23f7730e 100644
--- a/smp-angular/src/app/app.module.ts
+++ b/smp-angular/src/app/app.module.ts
@@ -2,6 +2,7 @@ import {BrowserModule} from '@angular/platform-browser';
 import {NgModule} from '@angular/core';
 import {FormsModule, ReactiveFormsModule} from '@angular/forms';
 import {HttpClient, HttpClientModule} from '@angular/common/http';
+import { FlexLayoutModule } from "@angular/flex-layout";
 import {
   MatButtonModule,
   MatDialogModule,
@@ -41,22 +42,20 @@ import {AlertService} from './alert/alert.service';
 import {FooterComponent} from './footer/footer.component';
 import {SmpInfoService} from './app-info/smp-info.service';
 import {AuthorizedAdminGuard} from './guards/authorized-admin.guard';
-import {ServiceGroupComponent} from './service-group/service-group.component';
+import {ServiceGroupComponent} from './service-group-edit/service-group.component';
+import {ServiceGroupSearchComponent} from './service-group-search/service-group-search.component';
 import {DomainComponent} from './domain/domain.component';
 import {UserComponent} from './user/user.component';
-import {TrustStoreComponent} from './trust-store/trust-store.component';
 import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
-import {ServiceGroupMetadataListDialogComponent} from './service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component';
+import {ServiceGroupMetadataListDialogComponent} from './service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component';
 import {RowLimiterComponent} from './common/row-limiter/row-limiter.component';
 import {DatePipe} from './custom-date/date.pipe';
 import {CapitalizeFirstPipe} from './common/capitalize-first.pipe';
 import {DefaultPasswordDialogComponent} from './security/default-password-dialog/default-password-dialog.component';
-import {ServiceGroupDetailsDialogComponent} from './service-group/service-group-details-dialog/service-group-details-dialog.component';
+import {ServiceGroupDetailsDialogComponent} from './service-group-edit/service-group-details-dialog/service-group-details-dialog.component';
 import {CancelDialogComponent} from './common/cancel-dialog/cancel-dialog.component';
 import {DirtyGuard} from './common/dirty.guard';
 import {SaveDialogComponent} from './common/save-dialog/save-dialog.component';
-import {TrustStoreDialogComponent} from './trust-store/trust-store-dialog/trust-store-dialog.component';
-import {TrustStoreUploadComponent} from './trust-store/trust-store-upload/trust-store-upload.component';
 import {ColumnPickerComponent} from './common/column-picker/column-picker.component';
 import {PageHelperComponent} from './common/page-helper/page-helper.component';
 import {SharedModule} from './common/module/shared.module';
@@ -66,12 +65,11 @@ import {DomainSelectorComponent} from './common/domain-selector/domain-selector.
 import {AlertsComponent} from './alerts/alerts.component';
 
 import {SearchTableComponent} from './common/search-table/search-table.component';
-import {ServiceGroupExtensionDialogComponent} from './service-group/service-group-extension-dialog/service-group-extension-dialog.component';
-import {ServiceGroupMetadataDialogComponent} from './service-group/service-group-metadata-dialog/service-group-metadata-dialog.component';
+import {ServiceGroupExtensionDialogComponent} from './service-group-edit/service-group-extension-dialog/service-group-extension-dialog.component';
+import {ServiceGroupMetadataDialogComponent} from './service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component';
 import {DomainDetailsDialogComponent} from './domain/domain-details-dialog/domain-details-dialog.component';
 import {UserDetailsDialogComponent} from './user/user-details-dialog/user-details-dialog.component';
 import {DownloadService} from './download/download.service';
-import {TrustStoreService} from './trust-store/trust-store.service';
 import {UserService} from './user/user.service';
 import {RoleService} from './security/role.service';
 import {CertificateService} from './user/certificate.service';
@@ -82,13 +80,13 @@ import {CertificateService} from './user/certificate.service';
     LoginComponent,
     HomeComponent,
     ServiceGroupComponent,
+    ServiceGroupSearchComponent,
     DomainComponent,
     DomainDetailsDialogComponent,
     UserComponent,
     AlertComponent,
     FooterComponent,
     IsAuthorized,
-    TrustStoreComponent,
     SaveDialogComponent,
     ServiceGroupMetadataListDialogComponent,
     ServiceGroupMetadataDialogComponent,
@@ -99,10 +97,7 @@ import {CertificateService} from './user/certificate.service';
     CapitalizeFirstPipe,
     DefaultPasswordDialogComponent,
     ServiceGroupDetailsDialogComponent,
-    TrustStoreDialogComponent,
-    TrustStoreUploadComponent,
     ColumnPickerComponent,
-    TrustStoreUploadComponent,
     PageHelperComponent,
     ClearInvalidDirective,
     PageHeaderComponent,
@@ -122,11 +117,10 @@ import {CertificateService} from './user/certificate.service';
     CancelDialogComponent,
     SaveDialogComponent,
     DefaultPasswordDialogComponent,
-    TrustStoreDialogComponent,
-    TrustStoreUploadComponent,
   ],
   imports: [
     BrowserModule,
+    FlexLayoutModule,
     HttpClientModule,
     BrowserAnimationsModule,
     FormsModule,
@@ -160,7 +154,6 @@ import {CertificateService} from './user/certificate.service';
     SmpInfoService,
     AlertService,
     DownloadService,
-    TrustStoreService,
     UserService,
     CertificateService,
     RoleService,
diff --git a/smp-angular/src/app/app.routes.ts b/smp-angular/src/app/app.routes.ts
index 1fd5f20f504f6166cbf0f53ab5119cd7eadba425..6d09b43e6dbb38723cc9d1b084e9be070f88bd43 100644
--- a/smp-angular/src/app/app.routes.ts
+++ b/smp-angular/src/app/app.routes.ts
@@ -1,20 +1,19 @@
 import {RouterModule, Routes} from '@angular/router';
 import {LoginComponent} from './login/login.component';
-import {ServiceGroupComponent} from './service-group/service-group.component';
+import {ServiceGroupSearchComponent} from './service-group-search/service-group-search.component';
+import {ServiceGroupComponent} from './service-group-edit/service-group.component';
 import {DomainComponent} from './domain/domain.component';
 import {AuthenticatedGuard} from './guards/authenticated.guard';
-import {AuthorizedAdminGuard} from './guards/authorized-admin.guard';
 import {UserComponent} from './user/user.component';
-import {TrustStoreComponent} from 'app/trust-store/trust-store.component';
 
 
 const appRoutes: Routes = [
-  {path: '', component: ServiceGroupComponent},
-  {path: 'servicegroup', component: ServiceGroupComponent},
+  {path: '', component: ServiceGroupSearchComponent},
+  {path: 'search', component: ServiceGroupSearchComponent},
+  {path: 'edit', component: ServiceGroupComponent},
   {path: 'domain', component: DomainComponent},
   {path: 'user', component: UserComponent},
 
-  {path: 'truststore', component: TrustStoreComponent, canActivate: [AuthenticatedGuard, AuthorizedAdminGuard]},
 
   {path: 'login', component: LoginComponent},
   {path: '**', component: ServiceGroupComponent, canActivate: [AuthenticatedGuard]}
diff --git a/smp-angular/src/app/common/domain-selector/domain-selector.component.ts b/smp-angular/src/app/common/domain-selector/domain-selector.component.ts
index 6f626df8e14d849e7edb516751c196cbf1255ec1..99b79b946154dfbf57467087f4050c1c441d2569 100644
--- a/smp-angular/src/app/common/domain-selector/domain-selector.component.ts
+++ b/smp-angular/src/app/common/domain-selector/domain-selector.component.ts
@@ -24,13 +24,14 @@ export class DomainSelectorComponent implements OnInit {
   }
 
   ngOnInit () {
+    /*
     this.domainService.isMultiDomain().subscribe((isMultiDomain: boolean) => {
       if (isMultiDomain && this.securityService.isCurrentUserSuperAdmin()) {
         this.showDomains = true;
         this.domainService.getCurrentDomain().subscribe((domain: Domain) => this.domainCode = this.currentDomainCode = domain ? domain.code : null);
         this.domainService.getDomains().subscribe((domains: Domain[]) => this.domains = domains);
       }
-    });
+    });*/
   }
 
   changeDomain () {
diff --git a/smp-angular/src/app/common/page-header/page-header.component.ts b/smp-angular/src/app/common/page-header/page-header.component.ts
index f20b8d68d02204683337655686846f3d16dcaba6..bed560e909c536fc10d7840e29b7f179a7fd88c7 100644
--- a/smp-angular/src/app/common/page-header/page-header.component.ts
+++ b/smp-angular/src/app/common/page-header/page-header.component.ts
@@ -16,12 +16,13 @@ export class PageHeaderComponent implements OnInit {
   }
 
   ngOnInit() {
+    /*
     this.domainService.isMultiDomain().subscribe((isMultiDomain: boolean) => {
       this.isMultiDomain = isMultiDomain;
       if (isMultiDomain) {
         this.domainService.getCurrentDomain().subscribe((domain: Domain) => this.currentDomain = domain ? domain.name : '');
       }
-    });
+    });*/
   }
 
 }
diff --git a/smp-angular/src/app/common/row-limiter/row-limiter.component.html b/smp-angular/src/app/common/row-limiter/row-limiter.component.html
index 9e6e95a3d46c0607c141683925dbebf381db198a..1285fcb5119e77928d6ba9f99572f14a1315f965 100644
--- a/smp-angular/src/app/common/row-limiter/row-limiter.component.html
+++ b/smp-angular/src/app/common/row-limiter/row-limiter.component.html
@@ -1,5 +1,5 @@
 <div>
-  <mat-select placeholder="Rows" [(ngModel)]="pageSize" name="pageSize" (change)="changePageSize($event)"
+  <mat-select placeholder="Rows" [(ngModel)]="pageSize" name="pageSize" (selectionChange)="changePageSize($event)"
              id="pagesize_id">
     <mat-option *ngFor="let rowLimit of pageSizes" [value]="rowLimit.value">
       {{rowLimit.key}}
diff --git a/smp-angular/src/app/common/row-limiter/row-limiter.component.ts b/smp-angular/src/app/common/row-limiter/row-limiter.component.ts
index ea93761affe26003f3a819c8c5a1b55a2f0d6e1f..6d9b6315954686bf0e68cc6e1c9760bd09f117d8 100644
--- a/smp-angular/src/app/common/row-limiter/row-limiter.component.ts
+++ b/smp-angular/src/app/common/row-limiter/row-limiter.component.ts
@@ -22,6 +22,7 @@ export class RowLimiterComponent implements OnInit {
   }
 
   changePageSize(newPageLimit:number) {
+
     this.onPageSizeChanged.emit(newPageLimit);
     console.log('New page limit:', newPageLimit);
   }
diff --git a/smp-angular/src/app/common/search-table/search-table.component.css b/smp-angular/src/app/common/search-table/search-table.component.css
index 163929e63bb1ffe88f047c87a83d0045c52a8263..9cdb4f04898b062cc8287c4f9a45e319793a9ce3 100644
--- a/smp-angular/src/app/common/search-table/search-table.component.css
+++ b/smp-angular/src/app/common/search-table/search-table.component.css
@@ -25,3 +25,7 @@
   left: 8px;
   bottom: 8px;
 }
+.table-button-expand {
+  padding: 0 !important;
+  margin: 0 !important;
+}
diff --git a/smp-angular/src/app/common/search-table/search-table.component.html b/smp-angular/src/app/common/search-table/search-table.component.html
index 52ac7828d90d93f5785387c4c1f4a315a1e47336..5f1075801fcdb3a60f2f369d58779014170d600a 100644
--- a/smp-angular/src/app/common/search-table/search-table.component.html
+++ b/smp-angular/src/app/common/search-table/search-table.component.html
@@ -1,13 +1,12 @@
-<div style="position: absolute; top: 5px; bottom: 5px; left: 5px; right: 5px;">
-  <page-header id="{{id}}_header_id">{{title}}</page-header>
+<div fxLayout="column" style="position: absolute; top: 5px; bottom: 5px; left: 5px; right: 5px;">
+  <page-header flex id="{{id}}_header_id">{{title}}</page-header>
 
-  <div class="selectionCriteria">
+  <div *ngIf="showSearchPanel" fxFlex="20" class="selectionCriteria">
     <mat-card>
       <mat-card-content>
         <div class="panel">
           <form name="filterForm" #filterForm="ngForm" (ngSubmit)="search()">
             <ng-container *ngTemplateOutlet="searchPanel"></ng-container>
-
             <div class="searchArea">
               <button mat-raised-button color="primary" [disabled]="!filterForm.form.valid" id="searchbutton_id">
                 <mat-icon>search</mat-icon>
@@ -20,51 +19,87 @@
     </mat-card>
   </div>
 
-  <div class="panel" style="position: absolute; top: 270px; bottom: 5px; left: 5px; right: 5px;">
-    <div class="group-filter-button">
+  <div class="panel" fxFlex fxLayout="column">
+    <div class="group-filter-button" fxFlex="50px">
       <span class="row-button">
         <app-row-limiter [pageSizes]="rowLimiter.pageSizes"
                          (onPageSizeChanged)="changePageSize($event.value)"></app-row-limiter>
       </span>
-      <span class="column-filter-button">
+      <!-- no need for this span class="column-filter-button">
         <app-column-picker [allColumns]="columnPicker.allColumns" [selectedColumns]="columnPicker.selectedColumns"
                            (onSelectedColumnsChanged)="columnPicker.changeSelectedColumns($event)"></app-column-picker>
-      </span>
+      </span -->
     </div>
-    <!-- temporal solution <div - absolut - wrapping> for stretch table height to fit screen size: scrollbarV does not work - virtual scrolling has
-    row bugs.-->
-    <div class="panel">
-      <ngx-datatable
-        id="searchTable"
-        class="material striped"
-        [rowClass]="getRowClass"
-        [rows]="rows"
-        [columns]="columnPicker.selectedColumns"
-        [columnMode]="'force'"
-        [headerHeight]="50"
-        [footerHeight]="50"
-        [rowHeight]="'auto'"
-        [scrollbarH]="true"
-        [externalPaging]="true"
-        [externalSorting]="true"
-        [loadingIndicator]="loading"
-        [count]="rows.length"
-        [offset]="offset"
-        [limit]="rowLimiter.pageSize"
-        (page)="onPage($event)"
-        (sort)="onSort($event)"
-        [selected]="selected"
-        [selectionType]="'multi'"
-        (activate)="onActivate($event)"
-        (select)="onSelect($event)">
-      </ngx-datatable>
+    <ngx-datatable #searchTable fxFlex id="searchTable"
+                   class="material striped"
+                   [rowClass]="getRowClass"
+                   [rows]="rows"
+                   [columns]="columnPicker.selectedColumns"
+                   [columnMode]="'force'"
+                   [headerHeight]="50"
+                   [footerHeight]="50"
+                   [rowHeight]="'auto'"
+                   [scrollbarH]="true"
+                   [scrollbarV]="true"
+                   [virtualization]="false"
+                   [externalPaging]="true"
+                   [externalSorting]="true"
+                   [loadingIndicator]="loading"
+                   [count]="count"
+                   [offset]="offset"
+                   [limit]="rowLimiter.pageSize"
+                   (page)="onPage($event)"
+                   (sort)="onSort($event)"
+                   [selected]="selected"
+                   [selectionType]="'single'"
+                   (activate)="onActivate($event)"
+                   (select)="onSelect($event)">
+      <!-- Row Detail Template -->
+      <ngx-datatable-row-detail id="rowDetail" [rowHeight]="'auto'" #searchTableDetailRow
+                                (toggle)="onDetailToggle($event)">
+        <ng-template let-row="row" let-expanded="expanded" let-enabled="enabled"  ngx-datatable-row-detail-template>
+          <ng-container [ngTemplateOutlet]="tableRowDetailContainer"
+                        [ngTemplateOutletContext]="{row:row}"></ng-container>
+        </ng-template>
+      </ngx-datatable-row-detail>
+    </ngx-datatable>
+
+    <ng-template #rowIndex let-row="row" ngx-datatable-cell-template>
+      <span>{{row.index}}</span>
+    </ng-template>
+
+    <ng-template #rowActions let-row="row" ngx-datatable-cell-template>
+      <div>
+        <button mat-icon-button color="primary" [disabled]="row.deleted || loading"
+                (click)="editSearchTableEntityRow(row)" tooltip="Edit">
+          <mat-icon>edit</mat-icon>
+        </button>
+        <button mat-icon-button color="primary" [disabled]="row.deleted || loading"
+                (click)="onDeleteRowActionClicked(row)" tooltip="Delete">
+          <mat-icon>delete</mat-icon>
+        </button>
+      </div>
+    </ng-template>
 
-      <div class="group-action-button">
-        <button id="cancelButton" mat-raised-button (click)="onCancelButtonClicked()" color="primary" [disabled]="!submitButtonsEnabled">
+    <ng-template #rowExpand let-row="row" let-expanded="expanded" let-disabled="disabled" ngx-datatable-cell-template >
+      <span *ngIf="!!disabled">( )</span>
+      <a *ngIf="!disabled" class="table-button-expand"
+        href="javascript:void(0)"
+        title="Expand/Collapse Row"
+        (click)="toggleExpandRow(row)">{{expanded?'(-)':'(+)'}}
+      </a>
+    </ng-template>
+  </div>
+  <div fxFlex="50px">
+    <ng-container *ngIf=showActionButtons>
+
+        <button id="cancelButton" mat-raised-button (click)="onCancelButtonClicked()" color="primary"
+                [disabled]="!submitButtonsEnabled">
           <mat-icon>cancel</mat-icon>
           <span>Cancel</span>
         </button>
-        <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked(false)" color="primary" [disabled]="!submitButtonsEnabled">
+        <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked(false)" color="primary"
+                [disabled]="!submitButtonsEnabled">
           <mat-icon>save</mat-icon>
           <span>Save</span>
         </button>
@@ -72,31 +107,17 @@
           <mat-icon>add</mat-icon>
           <span>New</span>
         </button>
-        <button id="editButton" mat-raised-button (click)="onEditButtonClicked()" [disabled]="!editButtonEnabled || loading" color="primary">
+        <button id="editButton" mat-raised-button (click)="onEditButtonClicked()"
+                [disabled]="!editButtonEnabled || loading" color="primary">
           <mat-icon>edit</mat-icon>
           <span>Edit</span>
         </button>
-        <button id="deleteButton" mat-raised-button (click)="onDeleteButtonClicked()" [disabled]="!deleteButtonEnabled || loading" color="primary">
+        <button id="deleteButton" mat-raised-button (click)="onDeleteButtonClicked()"
+                [disabled]="!deleteButtonEnabled || loading" color="primary">
           <mat-icon>delete</mat-icon>
           <span>Delete</span>
         </button>
-
-        <ng-container *ngTemplateOutlet="additionalToolButtons"></ng-container>
-
-      </div>
-
-      <ng-template #rowActions let-row="row" ngx-datatable-cell-template>
-        <div>
-          <button mat-icon-button color="primary" [disabled]="row.deleted || loading"
-                  (click)="onEditRowActionClicked(row.$$index)" tooltip="Edit">
-            <mat-icon>edit</mat-icon>
-          </button>
-          <button mat-icon-button color="primary" [disabled]="row.deleted || loading"
-                  (click)="onDeleteRowActionClicked(row)" tooltip="Delete">
-            <mat-icon>delete</mat-icon>
-          </button>
-        </div>
-      </ng-template>
-    </div>
+    </ng-container>
+    <ng-container *ngTemplateOutlet="additionalToolButtons"></ng-container>
   </div>
 </div>
diff --git a/smp-angular/src/app/common/search-table/search-table.component.ts b/smp-angular/src/app/common/search-table/search-table.component.ts
index 289c1172f033ca472facb263b8a60844d2c88b31..821648863b7d4cbca5b60b3ad75761d8a7bcbcb0 100644
--- a/smp-angular/src/app/common/search-table/search-table.component.ts
+++ b/smp-angular/src/app/common/search-table/search-table.component.ts
@@ -15,16 +15,23 @@ import {SaveDialogComponent} from '../save-dialog/save-dialog.component';
 import {DownloadService} from '../../download/download.service';
 import {HttpClient, HttpParams} from '@angular/common/http';
 
+
 @Component({
   selector: 'smp-search-table',
   templateUrl: './search-table.component.html',
   styleUrls: ['./search-table.component.css']
 })
+
+
 export class SearchTableComponent implements OnInit {
+  @ViewChild('searchTable') searchTable: any;
   @ViewChild('rowActions') rowActions: TemplateRef<any>;
+  @ViewChild('rowExpand') rowExpand: TemplateRef<any>;
+  @ViewChild('rowIndex') rowIndex: TemplateRef<any>;
 
   @Input() @ViewChild('additionalToolButtons') additionalToolButtons: TemplateRef<any>;
   @Input() @ViewChild('searchPanel') searchPanel: TemplateRef<any>;
+  @Input() @ViewChild('tableRowDetailContainer') tableRowDetailContainer: TemplateRef<any>;
 
   @Input() id: String = "";
   @Input() title: String = "";
@@ -32,10 +39,15 @@ export class SearchTableComponent implements OnInit {
   @Input() url: string = '';
   @Input() searchTableController: SearchTableController;
   @Input() filter: any = {};
+  @Input() showActionButtons: boolean = true;
+  @Input() showSearchPanel: boolean = true;
+  @Input() showIndexColumn: boolean = false;
 
   loading = false;
 
   columnActions: any;
+  columnExpandDetails: any;
+  columnIndex: any;
 
   rowLimiter: RowLimiter = new RowLimiter();
 
@@ -56,17 +68,45 @@ export class SearchTableComponent implements OnInit {
   }
 
   ngOnInit() {
+    this.columnIndex = {
+      cellTemplate: this.rowIndex,
+      name: 'Index',
+      width: 50,
+      maxWidth:80,
+      sortable: false
+    };
+
     this.columnActions = {
       cellTemplate: this.rowActions,
       name: 'Actions',
-      width: 80,
+      width: 120,
+      maxWidth:150,
+      sortable: false
+    };
+    this.columnExpandDetails= {
+      cellTemplate: this.rowExpand,
+      name: ' ',
+      width: 40,
+      maxWidth:50,
       sortable: false
     };
 
     // Add actions to last column
     if (this.columnPicker) {
-      this.columnPicker.allColumns.push(this.columnActions);
-      this.columnPicker.selectedColumns.push(this.columnActions);
+      // prepend columns
+      if (!!this.tableRowDetailContainer){
+        this.columnPicker.allColumns.unshift(this.columnExpandDetails);
+        this.columnPicker.selectedColumns.unshift(this.columnExpandDetails);
+      }
+      if (this.showIndexColumn){
+        this.columnPicker.allColumns.unshift(this.columnIndex);
+        this.columnPicker.selectedColumns.unshift(this.columnIndex);
+      }
+
+      if (this.showActionButtons) {
+        this.columnPicker.allColumns.push(this.columnActions);
+        this.columnPicker.selectedColumns.push(this.columnActions);
+      }
     }
     this.page(this.offset, this.rowLimiter.pageSize, this.orderBy, this.asc);
   }
@@ -76,30 +116,16 @@ export class SearchTableComponent implements OnInit {
   }
 
   getTableDataEntries$(offset: number, pageSize: number, orderBy: string, asc: boolean): Observable<SearchTableResult> {
-    let params: HttpParams = new HttpParams();
-    params.set('page', offset.toString());
-    params.set('pageSize', pageSize.toString());
-    params.set('orderBy', orderBy);
-
-    //filters
-    if (this.filter.userName) {
-      params.set('userName', this.filter.userName);
-    }
-
-    if (this.filter.participantId) {
-      params.set('participantId', this.filter.participantId);
-    }
 
-    if (this.filter.participantSchema) {
-      params.set('participantSchema', this.filter.participantSchema);
-    }
+    let params: HttpParams = new HttpParams()
+       .set('page', offset.toString())
+       .set('pageSize', pageSize.toString());
 
-    if(this.filter.domain) {
-      params.set('domain', this.filter.domain )
-    }
 
-    if (asc != null) {
-      params.set('asc', asc.toString());
+    for (let filterProperty in this.filter) {
+      if (this.filter.hasOwnProperty(filterProperty)) {
+        params = params.set(filterProperty, this.filter[filterProperty]);
+      }
     }
 
     // TODO move to the HTTP service
@@ -119,21 +145,14 @@ export class SearchTableComponent implements OnInit {
       this.asc = asc;
 
       this.unselectRows();
-      const count = result.count;
-      const start = offset * pageSize;
-      const end = Math.min(start + pageSize, count);
-      const newRows = [...result.serviceEntities];
-
-      let index = 0;
-      for (let i = start; i < end; i++) {
-        newRows[i] = {...result.serviceEntities[index++],
+      this.count = result.count; // must be set else table can not calculate page numbers
+      this.rows = result.serviceEntities.map(serviceEntity => {
+        return {...serviceEntity,
           status: SearchTableEntityStatus.PERSISTED,
-          deleted: false
-        };
-      }
-      this.rows = newRows;
+          deleted: false}
+      });
 
-      if(count > AlertComponent.MAX_COUNT_CSV) {
+      if(this.count > AlertComponent.MAX_COUNT_CSV) {
         this.alertService.error("Maximum number of rows reached for downloading CSV");
       }
     }, (error: any) => {
@@ -159,11 +178,12 @@ export class SearchTableComponent implements OnInit {
 
   onActivate(event) {
     if ("dblclick" === event.type) {
-      this.details(event.row);
+      this.editSearchTableEntityRow(event.row);
     }
   }
 
   changePageSize(newPageLimit: number) {
+    alert("new page size");
     this.page(0, newPageLimit, this.orderBy, this.asc);
   }
 
@@ -171,13 +191,6 @@ export class SearchTableComponent implements OnInit {
     this.page(0, this.rowLimiter.pageSize, this.orderBy, this.asc);
   }
 
-  details(selectedRow: any) {
-    this.searchTableController.showDetails(selectedRow);
-  }
-
-  onEditRowActionClicked(rowNumber: number) {
-    this.editSearchTableEntity(rowNumber);
-  }
 
   onDeleteRowActionClicked(row: SearchTableEntity) {
     this.deleteSearchTableEntities([row]);
@@ -190,6 +203,9 @@ export class SearchTableComponent implements OnInit {
     formRef.afterClosed().subscribe(result => {
       if (result) {
         this.rows = [...this.rows, {...formRef.componentInstance.current}];
+        //this.rows = this.rows.concat(formRef.componentInstance.current);
+        this.count++;
+       // this.searchTable.refresh();
       } else {
         this.unselectRows();
       }
@@ -217,12 +233,13 @@ export class SearchTableComponent implements OnInit {
       this.dialog.open(SaveDialogComponent).afterClosed().subscribe(result => {
         if (result) {
           // this.unselectRows();
-          const modifiedUsers = this.rows.filter(el => el.status !== SearchTableEntityStatus.PERSISTED);
+          const modifiedRowEntities = this.rows.filter(el => el.status !== SearchTableEntityStatus.PERSISTED);
           // this.isBusy = true;
-          this.http.put(/*UserComponent.USER_USERS_URL TODO: use PUT url*/'', modifiedUsers).subscribe(res => {
+          this.http.put(/*UserComponent.USER_USERS_URL TODO: use PUT url*/this.url, modifiedRowEntities).subscribe(res => {
             // this.isBusy = false;
             // this.getUsers();
             this.alertService.success('The operation \'update\' completed successfully.', false);
+            this.onRefresh();
             if (withDownloadCSV) {
               this.downloadService.downloadNative(/*UserComponent.USER_CSV_URL TODO: use CSV url*/ '');
             }
@@ -243,10 +260,14 @@ export class SearchTableComponent implements OnInit {
     }
   }
 
+  onRefresh() {
+    this.page(this.offset, this.rowLimiter.pageSize, this.orderBy, this.asc);
+  }
+
   onCancelButtonClicked() {
     this.dialog.open(CancelDialogComponent).afterClosed().subscribe(result => {
       if (result) {
-        this.page(this.offset, this.rowLimiter.pageSize, this.orderBy, this.asc);
+        this.onRefresh();
       }
     });
   }
@@ -284,6 +305,10 @@ export class SearchTableComponent implements OnInit {
       }
     });
   }
+  private editSearchTableEntityRow(row: SearchTableEntity) {
+      let rowNumber = this.rows.indexOf(row);
+      this.editSearchTableEntity(rowNumber);
+  }
 
   private deleteSearchTableEntities(rows: Array<SearchTableEntity>) {
     // TODO: add validation support to existing controllers
@@ -307,4 +332,13 @@ export class SearchTableComponent implements OnInit {
   private unselectRows() {
     this.selected = [];
   }
+
+  toggleExpandRow(selectedRow: any){
+    //this.searchTableController.toggleExpandRow(selectedRow);
+    this.searchTable.rowDetail.toggleExpandRow(selectedRow);
+  }
+
+  onDetailToggle (event){
+
+  }
 }
diff --git a/smp-angular/src/app/domain/domain-controller.ts b/smp-angular/src/app/domain/domain-controller.ts
index 6051654b95157ca6a98fed06f335e060f22efd0e..38499f3da01dfb0fe2abceefcdd5aeb3547f9dd9 100644
--- a/smp-angular/src/app/domain/domain-controller.ts
+++ b/smp-angular/src/app/domain/domain-controller.ts
@@ -3,22 +3,25 @@ import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material';
 import {DomainDetailsDialogComponent} from './domain-details-dialog/domain-details-dialog.component';
 import {DomainRo} from './domain-ro.model';
 import {SearchTableEntityStatus} from '../common/search-table/search-table-entity-status.model';
+import {UserDetailsDialogComponent} from "../user/user-details-dialog/user-details-dialog.component";
 
 export class DomainController implements SearchTableController {
 
-  constructor(public dialog: MatDialog) { }
+  constructor(public dialog: MatDialog) {
+  }
 
   public showDetails(row: any) {
     let dialogRef: MatDialogRef<DomainDetailsDialogComponent> = this.dialog.open(DomainDetailsDialogComponent);
-    dialogRef.componentInstance.domain = row;
     dialogRef.afterClosed().subscribe(result => {
       //Todo:
     });
   }
 
-  public edit(row: any) { }
+  public edit(row: any) {
+  }
 
-  public  delete(row: any) { }
+  public delete(row: any) {
+  }
 
   public newDialog(config?: MatDialogConfig): MatDialogRef<DomainDetailsDialogComponent> {
     return this.dialog.open(DomainDetailsDialogComponent, config);
@@ -26,11 +29,13 @@ export class DomainController implements SearchTableController {
 
   public newRow(): DomainRo {
     return {
-      domainId: '',
-      bdmslClientCertHeader: '',
-      bdmslClientCertAlias: '',
-      bdmslSmpId: '',
-      signatureCertAlias: '',
+      domainCode: '',
+      smlSubdomain: '',
+      smlSmpId: '',
+      smlParticipantIdentifierRegExp: '',
+      smlClientCertHeader: '',
+      smlClientKeyAlias: '',
+      signatureKeyAlias: '',
       status: SearchTableEntityStatus.NEW
     }
   }
diff --git a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html
index 29bf59ba325ecb5f012bb29d06d9f79778e5069d..ebb925e0ecbb5d1f00035c70f4336fb39c1bb3b2 100644
--- a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html
+++ b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html
@@ -1,46 +1,63 @@
-<h2 mat-dialog-title>Domain details</h2>
-<mat-dialog-content style="height:460px;width:650px">
+<h2 mat-dialog-title>{{formTitle}}</h2>
+<mat-dialog-content>
+
   <mat-card>
     <mat-card-content>
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="Domain id" value="{{domain.domainId}}" readonly/>
-      </mat-form-field>
-
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="SML SMP id" value="{{domain.bdmslSmpId}}" readonly/>
-      </mat-form-field>
-
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="ClienCert header" value="{{domain.bdmslClientCertHeader}}" readonly/>
-      </mat-form-field>
-
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="ClienCert alias" value="{{domain.bdmslClientCertAlias}}" readonly/>
-      </mat-form-field>
-
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="Signature alias" value="{{domain.signatureCertAlias}}" readonly/>
-      </mat-form-field>
-
+      <div class="panel">
+        <fieldset style="border: none;">
+          <mat-form-field style="width:100%">
+            <input matInput placeholder="Domain Code ()" name="domainCode" value="{{current.domainCode}}" id="domainCode_id"
+                   (blur)="updateDomainCode($event)" [formControl]="domainForm.controls['domainCode']" maxlength="255" required>
+            <div *ngIf="(!editMode && domainForm.controls['domainCode'].touched || editMode) &&  domainForm.controls['domainCode'].hasError('pattern')" style="color:red; font-size: 70%">
+             Domain could must contain only chars.
+            </div>
+          </mat-form-field>
+          <mat-form-field style="width:100%">
+            <input matInput placeholder="SML domain (Part of DNS Zone: ex.eHealth: 'ehealth', peppol: '', ..)" name="smlSubdomain" value="{{current.smlSubdomain}}" id="smldomain_id"
+                   (blur)="updateSmlDomain($event)" [formControl]="domainForm.controls['smlSubdomain']" maxlength="255" required>
+            <div *ngIf="(!editMode && domainForm.controls['smlSubdomain'].touched || editMode) &&  domainForm.controls['smlSubdomain'].hasError('pattern')" style="color:red; font-size: 70%">
+              SML domain must be valid DNS part (AlphaNumeric with optional char -).
+            </div>
+          </mat-form-field>
+          <mat-form-field style="width:100%">
+            <input matInput placeholder="SML SMP identifier (SMP ID used for SML )" name="smlSmpId" value="{{current.smlSmpId}}" id="smlSMPId_id"
+                   (blur)="updateSmlSmpId($event)" [formControl]="domainForm.controls['smlSmpId']" maxlength="255" required>
+            <div *ngIf="(!editMode && domainForm.controls['smlSmpId'].touched || editMode) &&  domainForm.controls['smlSmpId'].hasError('pattern')" style="color:red; font-size: 70%">
+              SML SMP ID  must be valid DNS part (AlphaNumeric with optional char -).
+            </div>
+
+          </mat-form-field>
+          <mat-form-field style="width:100%">
+            <input matInput placeholder="SML Client certificate" name="Client certificate" value="{{current.smlClientKeyAlias}}" id="smlClientKeyAlias_id"
+                   (blur)="updateSmlClientKeyAlias($event)" [formControl]="domainForm.controls['smlClientKeyAlias']" maxlength="255" required>
+          </mat-form-field>
+          <mat-form-field style="width:100%">
+            <input matInput placeholder="Response signature Certificate" name="signatureKeyAlias" value="{{current.signatureKeyAlias}}" id="signatureKeyAlias_id"
+                   (blur)="updateSignatureKeyAlias($event)" [formControl]="domainForm.controls['signatureKeyAlias']" maxlength="255" required>
+          </mat-form-field>
+        </fieldset>
+        <!-- label class="custom-file-upload">
+          <input #fileInput type="file" id="custom-file-upload" accept=".cer" (change)="uploadCertificate()" >
+          <span class="custom-file-upload-inner">Import</span>
+        </label-->
+      </div>
     </mat-card-content>
   </mat-card>
-
 </mat-dialog-content>
 
-<mat-dialog-actions>
-  <div class="group-action-button" >
-  <button id="ServiceGroupsSaveButton" mat-raised-button color="primary" (click)="dialogRef.close({})"
-          style="margin-top:10px">
-    <mat-icon>save</mat-icon>
-    <span>Save</span>
-  </button>
-
-
-  <button id="ServiceGroupsCloseButton" mat-raised-button color="primary" (click)="dialogRef.close({})"
-          style="margin-top:10px">
-    <mat-icon>close</mat-icon>
-    <span>Close</span>
-  </button>
-  </div>
-</mat-dialog-actions>
+<table class="buttonsRow">
+  <tr>
+    <td>
+      <button mat-raised-button color="primary" [mat-dialog-close]="true" (click)="submitForm()" [disabled]="!domainForm.valid">
+        <mat-icon>ok</mat-icon>
+        <span>OK</span>
+      </button>
+      <button mat-raised-button color="primary" mat-dialog-close>
+        <mat-icon>cancel</mat-icon>
+        <span>Cancel</span>
+      </button>
+    </td>
+  </tr>
+</table>
+<div  style="text-align: right; font-size: 70%">* required fields</div>
 
diff --git a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts
index 146e73b941c1a33864a2cdfb8eb0b79bd7f5ba90..3e4478b989cfb0b721f03d5f8213238a01aab6e4 100644
--- a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts
+++ b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts
@@ -1,5 +1,14 @@
-import {Component} from '@angular/core';
-import {MatDialogRef} from '@angular/material';
+import {Component, Inject} from '@angular/core';
+import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material';
+import {UserRo} from "../../user/user-ro.model";
+import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
+import {DomainRo} from "../domain-ro.model";
+import {AlertService} from "../../alert/alert.service";
+import {RoleService} from "../../security/role.service";
+import {UserDetailsDialogComponent} from "../../user/user-details-dialog/user-details-dialog.component";
+import {CertificateService} from "../../user/certificate.service";
+import {UserService} from "../../user/user.service";
+import {SearchTableEntityStatus} from "../../common/search-table/search-table-entity-status.model";
 
 @Component({
   selector: 'domain-details-dialog',
@@ -7,9 +16,92 @@ import {MatDialogRef} from '@angular/material';
 })
 export class DomainDetailsDialogComponent {
 
+  static readonly NEW_MODE = 'New Domain';
+  static readonly EDIT_MODE = 'Domain Edit';
+  readonly dnsDomainPattern = '^(?!(\\d|-|_)+)[a-zA-Z0-9-]{1,63}$';
+  readonly domainCodePattern = '^[a-zA-Z]{1,255}$';
+
+  editMode: boolean;
+  formTitle: string;
+  current: DomainRo & { confirmation?: string };
+  domainForm: FormGroup;
+
+  userSwitch: boolean;
+  certificateSwitch: boolean;
+
   domain;
-  dateFormat: String = 'yyyy-MM-dd HH:mm:ssZ';
 
-  constructor(public dialogRef: MatDialogRef<DomainDetailsDialogComponent>) {
+
+  constructor(private dialogRef: MatDialogRef<DomainDetailsDialogComponent>,
+              private alertService: AlertService,
+              @Inject(MAT_DIALOG_DATA) public data: any,
+              private fb: FormBuilder) {
+
+    this.editMode = data.edit;
+    this.formTitle = this.editMode ?  DomainDetailsDialogComponent.EDIT_MODE: DomainDetailsDialogComponent.NEW_MODE;
+    this.current = this.editMode
+      ? {
+        ...data.row,
+      }
+      : {
+        domainCode: '',
+        email: '',
+        password: '',
+        confirmation: '',
+        role: '',
+        status: SearchTableEntityStatus.NEW,
+        certificate: {},
+      };
+
+    this.domainForm = fb.group({
+
+      'domainCode': new FormControl({value: this.current.domainCode, disabled: this.editMode}, [Validators.pattern(this.domainCodePattern)]),
+      'smlSubdomain': new FormControl({value: this.current.smlSubdomain, disabled: this.editMode},  [Validators.pattern(this.dnsDomainPattern)]),
+      'smlSmpId': new FormControl({value: this.current.smlSmpId}, [Validators.required, Validators.pattern(this.dnsDomainPattern)]),
+      'smlClientKeyAlias': new FormControl({value: this.current.signatureKeyAlias}, null),
+      'signatureKeyAlias': new FormControl({value: this.current.signatureKeyAlias}, null),
+
+
+    }, {
+      //validator: this.passwordConfirmationValidator
+    });
+  }
+  submitForm() {
+    this.checkValidity(this.domainForm)
+     this.dialogRef.close(true);
+  }
+
+  checkValidity(g: FormGroup) {
+    Object.keys(g.controls).forEach(key => {
+      g.get(key).markAsDirty();
+    });
+    Object.keys(g.controls).forEach(key => {
+      g.get(key).markAsTouched();
+    });
+    //!!! updateValueAndValidity - else some filed did no update current / on blur never happened
+    Object.keys(g.controls).forEach(key => {
+      g.get(key).updateValueAndValidity();
+    });
   }
+
+
+  updateDomainCode(event) {
+    this.current.domainCode = event.target.value;
+  }
+  updateSmlDomain(event) {
+    this.current.smlSubdomain = event.target.value;
+  }
+  updateSmlSmpId(event) {
+    this.current.smlSmpId = event.target.value;
+  }
+
+  updateSmlClientKeyAlias(event) {
+    this.current.smlClientKeyAlias = event.target.value;
+  }
+
+  updateSignatureKeyAlias(event) {
+    this.current.signatureKeyAlias = event.target.value;
+  }
+
+
 }
diff --git a/smp-angular/src/app/domain/domain-ro.model.ts b/smp-angular/src/app/domain/domain-ro.model.ts
index 6dd27cfe93d71501f6656db0180573de739a5ee9..bc61ffbf3bc330964c74a28436a6407c9594d32a 100644
--- a/smp-angular/src/app/domain/domain-ro.model.ts
+++ b/smp-angular/src/app/domain/domain-ro.model.ts
@@ -1,12 +1,12 @@
 import {SearchTableEntity} from '../common/search-table/search-table-entity.model';
 
 export interface DomainRo extends SearchTableEntity {
-  domainId: string;
-  bdmslClientCertHeader: string;
-  bdmslClientCertAlias: string;
-  bdmslSmpId: string;
-  signatureCertAlias: string;
+  domainCode: string;
+  smlSubdomain: string;
+  smlSmpId: string;
+  smlParticipantIdentifierRegExp: string;
+  smlClientCertHeader: string;
+  smlClientKeyAlias: string;
+  signatureKeyAlias: string;
 }
 
-
-
diff --git a/smp-angular/src/app/domain/domain.component.html b/smp-angular/src/app/domain/domain.component.html
index 2522d251d56ce53c6ffa5f951df4138c07d62f85..89d894c64bde8d4481e31de00c9c4354cb313717 100644
--- a/smp-angular/src/app/domain/domain.component.html
+++ b/smp-angular/src/app/domain/domain.component.html
@@ -3,36 +3,13 @@
   page_id= 'domain_id'
   title= 'Domains'
   [columnPicker] = "columnPicker"
-  url="ui/domain"
+  url="rest/domain"
   [additionalToolButtons]="additionalToolButtons"
   [searchTableController]="domainController"
-  [searchPanel]="searchPanel"
+  [showSearchPanel]="false"
   [filter]="filter"
 
 >
   <ng-template #additionalToolButtons >
-
-  </ng-template>
-
-  <ng-template #searchPanel>
-    <mat-form-field>
-      <input matInput placeholder="Domain Id" name="Domain Id" [(ngModel)]="filter.messageId"
-             #messageId="ngModel" id="Domain_id">
-    </mat-form-field>
-    <mat-form-field>
-      <input matInput placeholder="SMP Id" name="SMP Id" [(ngModel)]="filter.messageId"
-             #messageId="ngModel" id="SMPid">
-    </mat-form-field>
-    <mat-form-field>
-    <input matInput placeholder="ClientCert Header" name="ClientCert Header" [(ngModel)]="filter.messageId"
-           #messageId="ngModel" id="ClientCert_header">
-    </mat-form-field>
-
-    <mat-form-field>
-    <input matInput placeholder="ClientCert Alias" name="ClientCert Alias" [(ngModel)]="filter.messageId"
-           #messageId="ngModel" id="ClientCert_Alias">
-    </mat-form-field>
-
   </ng-template>
-
 </smp-search-table>
diff --git a/smp-angular/src/app/domain/domain.component.ts b/smp-angular/src/app/domain/domain.component.ts
index 756eb6261c1c01bf22178bc7601f360d5693b47d..49167818efb8aadb164b74d7bcd2a0fd9c9d4550 100644
--- a/smp-angular/src/app/domain/domain.component.ts
+++ b/smp-angular/src/app/domain/domain.component.ts
@@ -29,32 +29,39 @@ export class DomainComponent implements OnInit {
 
     this.columnPicker.allColumns = [
       {
-        name: 'Domain Id',
-        prop: 'domainId',
+        name: 'Domain code',
+        prop: 'domainCode',
         width: 275
+
       },
       {
-        name: 'ClientCert Header',
-        prop: 'bdmslClientCertHeader',
+        name: 'SML Domain',
+        prop: 'smlSubdomain',
+        width: 275
       },
       {
-        name: 'ClientCert Alias',
-        prop: 'bdmslClientCertAlias',
+        name: 'SML SMP Id',
+        prop: 'smlSmpId',
+        width: 120
       },
       {
-        name: 'SMP Id',
-        prop: 'bdmslSmpId',
-        width: 120
+        name: 'ClientCert Header',
+        prop: 'smlClientCertHeader',
       },
+      {
+        name: 'ClientCert Alias',
+        prop: 'smlClientKeyAlias',
+      },
+
       {
         name: 'Signature CertAlias',
-        prop: 'signatureCertAlias',
+        prop: 'signatureKeyAlias',
         width: 120
       },
     ];
 
     this.columnPicker.selectedColumns = this.columnPicker.allColumns.filter(col => {
-      return ["Domain Id", "ClientCert Header", "ClientCert Alias", "SMP Id"].indexOf(col.name) != -1
+      return ["Domain code", "SML Domain", "SML SMP Id", "ClientCert Header", "ClientCert Alias", "Signature CertAlias"].indexOf(col.name) != -1
     });
   }
 
diff --git a/smp-angular/src/app/security/domain.service.ts b/smp-angular/src/app/security/domain.service.ts
index aa43586327738f1812c1bd8468721e826ef66057..027b2385cf5e8d1c309ad44e5066b0bc149cea53 100644
--- a/smp-angular/src/app/security/domain.service.ts
+++ b/smp-angular/src/app/security/domain.service.ts
@@ -7,30 +7,18 @@ import {Domain} from './domain.model';
 @Injectable()
 export class DomainService {
 
-  static readonly MULTI_TENANCY_URL: string = 'rest/application/multitenancy';
   static readonly CURRENT_DOMAIN_URL: string = 'rest/security/user/domain';
   static readonly DOMAIN_LIST_URL: string = 'rest/application/domains';
 
-  private isMultiDomainSubject: ReplaySubject<boolean>;
   private domainSubject: ReplaySubject<Domain>;
 
   constructor (private http: HttpClient) {
   }
 
-  isMultiDomain (): Observable<boolean> {
-    if (!this.isMultiDomainSubject) {
-      this.isMultiDomainSubject = new ReplaySubject<boolean>();
-      this.http.get(DomainService.MULTI_TENANCY_URL).subscribe((res: HttpResponse<boolean>) => {
-        this.isMultiDomainSubject.next(res.body);
-      }, (error: any) => {
-        console.log('get isMultiDomain:' + error);
-        this.isMultiDomainSubject.next(false);
-      });
-    }
-    return this.isMultiDomainSubject.asObservable();
-  }
+
 
   getCurrentDomain (): Observable<Domain> {
+    /*
     if (!this.domainSubject) {
       this.domainSubject = new ReplaySubject<Domain>();
       this.http.get(DomainService.CURRENT_DOMAIN_URL).subscribe((res: HttpResponse<Domain>) => {
@@ -41,6 +29,8 @@ export class DomainService {
       });
     }
     return this.domainSubject.asObservable();
+    */
+    return null;
   }
 
   resetDomain (): void {
@@ -51,7 +41,10 @@ export class DomainService {
   }
 
   getDomains (): Observable<Domain[]> {
+    /*
     return this.http.get<Domain[]>(DomainService.DOMAIN_LIST_URL);
+    */
+    return null;
   }
 
   setCurrentDomain (domain: Domain) {
diff --git a/smp-angular/src/app/service-group/service-group-controller.ts b/smp-angular/src/app/service-group-edit/service-group-controller.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-controller.ts
rename to smp-angular/src/app/service-group-edit/service-group-controller.ts
diff --git a/smp-angular/src/app/service-group/service-group-details-dialog/service-group-details-dialog.component.html b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-details-dialog/service-group-details-dialog.component.html
rename to smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
diff --git a/smp-angular/src/app/service-group/service-group-details-dialog/service-group-details-dialog.component.spec.ts b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.spec.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-details-dialog/service-group-details-dialog.component.spec.ts
rename to smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.spec.ts
diff --git a/smp-angular/src/app/service-group/service-group-details-dialog/service-group-details-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-details-dialog/service-group-details-dialog.component.ts
rename to smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
diff --git a/smp-angular/src/app/service-group/service-group-extension-dialog/service-group-extension-dialog.component.html b/smp-angular/src/app/service-group-edit/service-group-extension-dialog/service-group-extension-dialog.component.html
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-extension-dialog/service-group-extension-dialog.component.html
rename to smp-angular/src/app/service-group-edit/service-group-extension-dialog/service-group-extension-dialog.component.html
diff --git a/smp-angular/src/app/service-group/service-group-extension-dialog/service-group-extension-dialog.component.spec.ts b/smp-angular/src/app/service-group-edit/service-group-extension-dialog/service-group-extension-dialog.component.spec.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-extension-dialog/service-group-extension-dialog.component.spec.ts
rename to smp-angular/src/app/service-group-edit/service-group-extension-dialog/service-group-extension-dialog.component.spec.ts
diff --git a/smp-angular/src/app/service-group/service-group-extension-dialog/service-group-extension-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-group-extension-dialog/service-group-extension-dialog.component.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-extension-dialog/service-group-extension-dialog.component.ts
rename to smp-angular/src/app/service-group-edit/service-group-extension-dialog/service-group-extension-dialog.component.ts
diff --git a/smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.css b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.css
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.css
rename to smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.css
diff --git a/smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.html b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.html
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.html
rename to smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.html
diff --git a/smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.spec.ts b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.spec.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.spec.ts
rename to smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.spec.ts
diff --git a/smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-dialog/service-group-metadata-dialog.component.ts
rename to smp-angular/src/app/service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component.ts
diff --git a/smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.css b/smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.css
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.css
rename to smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.css
diff --git a/smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.html b/smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.html
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.html
rename to smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.html
diff --git a/smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.spec.ts b/smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.spec.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.spec.ts
rename to smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.spec.ts
diff --git a/smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.ts
rename to smp-angular/src/app/service-group-edit/service-group-metadata-list-dialog/service-group-metadata-list-dialog.component.ts
diff --git a/smp-angular/src/app/service-group/service-group-ro-id.model.ts b/smp-angular/src/app/service-group-edit/service-group-ro-id.model.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-ro-id.model.ts
rename to smp-angular/src/app/service-group-edit/service-group-ro-id.model.ts
diff --git a/smp-angular/src/app/service-group/service-group-ro.model.ts b/smp-angular/src/app/service-group-edit/service-group-ro.model.ts
similarity index 100%
rename from smp-angular/src/app/service-group/service-group-ro.model.ts
rename to smp-angular/src/app/service-group-edit/service-group-ro.model.ts
diff --git a/smp-angular/src/app/service-group/service-group.component.css b/smp-angular/src/app/service-group-edit/service-group.component.css
similarity index 100%
rename from smp-angular/src/app/service-group/service-group.component.css
rename to smp-angular/src/app/service-group-edit/service-group.component.css
diff --git a/smp-angular/src/app/service-group/service-group.component.html b/smp-angular/src/app/service-group-edit/service-group.component.html
similarity index 98%
rename from smp-angular/src/app/service-group/service-group.component.html
rename to smp-angular/src/app/service-group-edit/service-group.component.html
index f8b1282f6f9ac55349981aa4ad019258577a1be5..0bdf69b5bfde596a446e45656788df3b8e5b5049 100644
--- a/smp-angular/src/app/service-group/service-group.component.html
+++ b/smp-angular/src/app/service-group-edit/service-group.component.html
@@ -2,7 +2,7 @@
   page_id='participants_id'
   title='Participants'
   [columnPicker]="columnPicker"
-  url="ui/servicegroup"
+  url="rest/servicegroup"
   [additionalToolButtons]="additionalToolButtons"
   [searchPanel]="searchPanel"
   [filter]="filter"
diff --git a/smp-angular/src/app/service-group/service-group.component.ts b/smp-angular/src/app/service-group-edit/service-group.component.ts
similarity index 94%
rename from smp-angular/src/app/service-group/service-group.component.ts
rename to smp-angular/src/app/service-group-edit/service-group.component.ts
index 0edccfd6a11400e469def552ec3264672cd8a69e..3edbb969c6be831ee961e2b6427594dc51ff3688 100644
--- a/smp-angular/src/app/service-group/service-group.component.ts
+++ b/smp-angular/src/app/service-group-edit/service-group.component.ts
@@ -1,7 +1,6 @@
 import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
 import {ColumnPicker} from '../common/column-picker/column-picker.model';
 import {MatDialog, MatDialogRef} from '@angular/material';
-import {ServiceGroupDetailsDialogComponent} from './service-group-details-dialog/service-group-details-dialog.component';
 import {AlertService} from '../alert/alert.service';
 import {ServiceGroupController} from './service-group-controller';
 import {HttpClient} from '@angular/common/http';
diff --git a/smp-angular/src/app/service-group-search/service-group-search-controller.ts b/smp-angular/src/app/service-group-search/service-group-search-controller.ts
new file mode 100644
index 0000000000000000000000000000000000000000..28c1698b66eeffa59163d88512b243bde5630a89
--- /dev/null
+++ b/smp-angular/src/app/service-group-search/service-group-search-controller.ts
@@ -0,0 +1,26 @@
+import {SearchTableController} from '../common/search-table/search-table-controller';
+import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material';
+import {ServiceGroupSearchRo} from './service-group-search-ro.model';
+
+export class ServiceGroupSearchController implements SearchTableController {
+
+  constructor(public dialog: MatDialog) { }
+
+  public showDetails(row: any) {
+  }
+
+  public showExtension(row: any) {
+  }
+
+  public edit(row: any) { }
+
+  public delete(row: any) { }
+
+  public newDialog(config?: MatDialogConfig) {
+    return null;
+  }
+
+  public newRow(): ServiceGroupSearchRo {
+    return null;
+  }
+}
diff --git a/smp-angular/src/app/service-group-search/service-group-search-ro.model.ts b/smp-angular/src/app/service-group-search/service-group-search-ro.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f20d01a53d4aa8c52d24b9375f98f98f4b915b8f
--- /dev/null
+++ b/smp-angular/src/app/service-group-search/service-group-search-ro.model.ts
@@ -0,0 +1,8 @@
+import { ServiceMetadataSearchRo } from './service-metadata-search-ro.model';
+import {SearchTableEntity} from "../common/search-table/search-table-entity.model";
+
+export interface ServiceGroupSearchRo extends SearchTableEntity {
+  participantIdentifier: string;
+  participantScheme: string;
+  serviceMetadata: Array<ServiceMetadataSearchRo>;
+}
diff --git a/smp-angular/src/app/service-group-search/service-group-search.component.css b/smp-angular/src/app/service-group-search/service-group-search.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..d1a612141160e70f00bfe5aee114e010052ee4a5
--- /dev/null
+++ b/smp-angular/src/app/service-group-search/service-group-search.component.css
@@ -0,0 +1,18 @@
+/* --- Select ---*/
+.mat-select{
+  padding:20px 0;
+}
+
+/* --- Button  ---*/
+.group-btn {
+   margin-top:20px;
+ }
+
+#hiddenButtonId {
+  position: fixed;
+}
+
+
+.datatable-body{
+  overflow-y: scroll;
+}
diff --git a/smp-angular/src/app/service-group-search/service-group-search.component.html b/smp-angular/src/app/service-group-search/service-group-search.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..d9f40a701964ec8f183017c322dffa907e7b87e9
--- /dev/null
+++ b/smp-angular/src/app/service-group-search/service-group-search.component.html
@@ -0,0 +1,109 @@
+<smp-search-table
+  page_id='search_id'
+  title='Search'
+  [columnPicker]="columnPicker"
+  url="rest/search"
+  [additionalToolButtons]="additionalToolButtons"
+  [searchPanel]="searchPanel"
+  [filter]="filter"
+  [searchTableController]="serviceGroupSearchController"
+  [tableRowDetailContainer]="tableRowDetailContainer"
+  [showActionButtons]="false"
+  [showIndexColumn]="true"
+>
+
+
+  <ng-template #rowExtensionAction let-row="row" let-value="value" ngx-datatable-cell-template>
+
+    <button mat-button color="primary"
+            (click)="extensionRowButtonAction(row)" id="extensionRowButtonAction{{row.$$index}}_id" tooltip="Extension">
+      <mat-icon>code</mat-icon>
+      <span>Extension</span>
+    </button>
+
+  </ng-template>
+
+  <ng-template #rowSMPUrlLinkAction let-row="row" let-value="value" ngx-datatable-cell-template>
+    <a target="_blank"
+       href="{{contextPath}}{{row.participantScheme}}::{{row.participantIdentifier}}" >Open URL</a>
+
+  </ng-template>
+
+
+  <ng-template #searchPanel>
+    <mat-form-field>
+      <input matInput placeholder="Participant Identifier" name="ParticipantIdentifier"
+             [(ngModel)]="filter.participantIdentifier"
+             #messageId="ngModel" id="participantIdentifier">
+    </mat-form-field>
+    <mat-form-field>
+      <input matInput placeholder="Participant scheme" name="patricipantScheme" [(ngModel)]="filter.participantScheme"
+             #messageId="ngModel" id="participantScheme">
+    </mat-form-field>
+    <mat-select placeholder="Domain " [(ngModel)]="filter.domain" name="domain"
+                id="domain_id">
+      <mat-option [value]="''">
+      </mat-option>
+      <mat-option *ngFor="let domain of domainlist" [value]="domain.smlSubdomain">
+        {{domain.smlSubdomain}}
+      </mat-option>
+    </mat-select>
+  </ng-template>
+
+
+
+
+  <ng-template #additionalToolButtons>
+    <!-- button mat-raised-button color="primary"
+            id="extensionbutton_id">
+      <mat-icon>code</mat-icon>
+      <span>Extension</span>
+    </button -->
+  </ng-template>
+
+  <ng-template #tableRowDetailContainer let-row="row">
+
+    <div *ngIf="row.serviceMetadata.length===0" style="padding-left:20px;">
+      No service metadata
+    </div>
+    <div *ngIf="row.serviceMetadata.length !== 0" >
+
+      <!-- ngx-datatable
+        class='material striped'
+        style="width: 80%"
+        [loadingIndicator]="loading"
+        [rows]='row.serviceMetadata'
+        [columns]='[{name:"Domain", prop:"domainCode", maxWidth: 250 },{name:"Document identifier scheme",prop:"documentIdentifierScheme",maxWidth: 350},{name:"Document identifier", prop:"documentIdentifier"},{name:"OASIS SMP URL",maxWidth: 350}]'
+        [columnMode]='"force"'
+        [headerHeight]='50'
+        [footerHeight]='50'
+        [rowHeight]='"auto"'>
+        <ng-template #rowMetadataSMPUrlLinkAction let-row="smdRow" let-value="value" ngx-datatable-cell-template>
+
+          <a target="_blank"
+             href="{{contextPath}}{{row.participantScheme}}::{{row.participantIdentifier}}/services/{{smdRow.documentIdentifierScheme}}::{{smdRow.documentIdentifier}}" >Open URL</a>
+
+        </ng-template>
+      </ngx-datatable -->
+
+      <table style="width: 80%">
+        <tr>
+          <th>Domain</th>
+          <th>Document identifier scheme</th>
+          <th>Document identifier</th>
+          <th>OASIS SMP URL</th>
+        </tr>
+        <tr *ngFor="let smd of row.serviceMetadata">
+          <td style="width: 100em">{{smd.domainCode}}</td>
+          <td style="width: 250em">{{smd.documentIdentifierScheme}}</td>
+          <td >{{smd.documentIdentifier}}</td>
+          <td style="width: 50em">
+            <a target="_blank"
+               href="{{contextPath}}{{row.participantScheme}}::{{row.participantIdentifier}}/services/{{smd.documentIdentifierScheme}}::{{smd.documentIdentifier}}">OASIS ServiceMetadata URL</a>
+          </td>
+        </tr>
+      </table>
+    </div>
+  </ng-template>
+
+</smp-search-table>
diff --git a/smp-angular/src/app/service-group-search/service-group-search.component.ts b/smp-angular/src/app/service-group-search/service-group-search.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c2768351135ab9b90256a7ec3973d8cd0198a228
--- /dev/null
+++ b/smp-angular/src/app/service-group-search/service-group-search.component.ts
@@ -0,0 +1,90 @@
+import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
+import {ColumnPicker} from '../common/column-picker/column-picker.model';
+import {MatDialog, MatDialogRef} from '@angular/material';
+import {AlertService} from '../alert/alert.service';
+import {ServiceGroupSearchController} from './service-group-search-controller';
+import {HttpClient} from '@angular/common/http';
+import {Observable} from "rxjs/index";
+import {SearchTableResult} from "../common/search-table/search-table-result.model";
+import {DomainRo} from "../domain/domain-ro.model";
+
+@Component({
+  moduleId: module.id,
+  templateUrl:'./service-group-search.component.html',
+  styleUrls: ['./service-group-search.component.css']
+})
+export class ServiceGroupSearchComponent implements OnInit {
+
+  @ViewChild('rowExtensionAction') rowExtensionAction: TemplateRef<any>
+  @ViewChild('rowSMPUrlLinkAction') rowSMPUrlLinkAction: TemplateRef<any>
+  @ViewChild('rowActions') rowActions: TemplateRef<any>;
+
+  columnPicker: ColumnPicker = new ColumnPicker();
+  serviceGroupSearchController: ServiceGroupSearchController;
+  filter: any = {};
+  domainlist: Array<any>;
+  domainObserver:  Observable< SearchTableResult> ;
+  contextPath: string = location.pathname.substring(0,location.pathname.length -3); // remove /ui s
+
+  constructor(protected http: HttpClient, protected alertService: AlertService, public dialog: MatDialog) {
+    this.domainObserver = this.http.get<SearchTableResult>('rest/domain');
+    this.domainObserver.subscribe((domains: SearchTableResult) => {
+      this.domainlist = new Array(domains.serviceEntities.length)
+        .map((v, index) => domains.serviceEntities[index] as DomainRo);
+
+      this.domainlist = domains.serviceEntities.map(serviceEntity => {
+        return {...serviceEntity}
+      });
+    });
+  }
+
+  ngOnDestroy() {
+  //  this.domainObserver.unsubscribe();
+  }
+
+  ngOnInit() {
+    this.serviceGroupSearchController = new ServiceGroupSearchController(this.dialog);
+
+    this.columnPicker.allColumns = [
+      {
+        name: 'Metadata count',
+        prop: 'serviceMetadata.length',
+        width: 60,
+        maxWidth: 80
+      },
+      {
+        name: 'Participant scheme',
+        prop: 'participantScheme',
+        maxWidth: 300
+      },
+      {
+        name: 'Participant identifier',
+        prop: 'participantIdentifier',
+      },
+      {
+        cellTemplate: this.rowSMPUrlLinkAction,
+        name: 'OASIS ServiceGroup URL',
+        width: 150,
+        maxWidth: 250,
+        sortable: false
+      },
+      /*
+      {
+        cellTemplate: this.rowExtensionAction,
+        name: 'Extension',
+        width: 80,
+        sortable: false
+      }*/
+    ];
+
+
+    this.columnPicker.selectedColumns = this.columnPicker.allColumns.filter(col => {
+      return ["Metadata count", "Participant scheme", "Participant identifier","OASIS ServiceGroup URL"].indexOf(col.name) != -1
+    });
+  }
+
+  details(row: any) {
+    this.serviceGroupSearchController.showDetails(row);
+
+  }
+}
diff --git a/smp-angular/src/app/service-group-search/service-metadata-search-ro.model.ts b/smp-angular/src/app/service-group-search/service-metadata-search-ro.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d6260aa78e784f02c4b08b7469819e42568d2511
--- /dev/null
+++ b/smp-angular/src/app/service-group-search/service-metadata-search-ro.model.ts
@@ -0,0 +1,8 @@
+import {SearchTableEntity} from "../common/search-table/search-table-entity.model";
+
+export interface ServiceMetadataSearchRo extends SearchTableEntity {
+  documentIdentifier: string;
+  documentIdentifierScheme: string;
+  smlSubdomain: string;
+  domainCode: string;
+}
diff --git a/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.html b/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.html
deleted file mode 100644
index 8bf7a2db74f2c8a61d6334459a8fc95da3ee9d0a..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<h2 mat-dialog-title>Truststore entry</h2>
-<mat-dialog-content style="height:450px;width:650px">
-  <mat-card>
-    <mat-card-content>
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="Name" value="{{trustStoreEntry.name}}" readonly/>
-      </mat-form-field>
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="Subject" value="{{trustStoreEntry.subject}}" readonly/>
-      </mat-form-field>
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="Issuer" value="{{trustStoreEntry.issuer}}" readonly/>
-      </mat-form-field>
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="Valid from" value="{{trustStoreEntry.validFrom| smpDate: dateFormat}}"
-               readonly/>
-      </mat-form-field>
-      <mat-form-field style="width:100%">
-        <input matInput placeholder="Valid until" value="{{trustStoreEntry.validUntil| smpDate: dateFormat}}"
-               readonly/>
-      </mat-form-field>
-    </mat-card-content>
-  </mat-card>
-</mat-dialog-content>
-
-<mat-dialog-actions>
-  <button id="closebutton_id" mat-raised-button color="primary" (click)="dialogRef.close({})"
-          style="margin-top:10px">
-    <mat-icon>close</mat-icon>
-    <span>Close</span>
-  </button>
-</mat-dialog-actions>
diff --git a/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.spec.ts b/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.spec.ts
deleted file mode 100644
index 5efd3c584496c5a06ece4b0ea5e2d81e45018109..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.spec.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import {async, ComponentFixture, TestBed} from '@angular/core/testing';
-
-import {TrustStoreDialogComponent} from './trust-store-dialog.component';
-
-describe('TrustStoreDialogComponent', () => {
-  let component: TrustStoreDialogComponent;
-  let fixture: ComponentFixture<TrustStoreDialogComponent>;
-
-  beforeEach(async(() => {
-    TestBed.configureTestingModule({
-      declarations: [TrustStoreDialogComponent]
-    })
-      .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(TrustStoreDialogComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should be created', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.ts b/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.ts
deleted file mode 100644
index 7645eb66097cd13cf810c0bcd3b2a6d2e60ec57c..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store-dialog/trust-store-dialog.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import {Component, Inject} from '@angular/core';
-import {TrustStoreEntry} from '../trust-store-entry.model';
-import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material';
-
-/**
- * @Author Dussart Thomas
- */
-@Component({
-  selector: 'app-truststore-dialog',
-  templateUrl: './trust-store-dialog.component.html'
-})
-export class TrustStoreDialogComponent {
-
-  dateFormat: String = 'yyyy-MM-dd HH:mm:ssZ';
-  trustStoreEntry: TrustStoreEntry;
-
-  constructor(public dialogRef: MatDialogRef<TrustStoreDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {
-    this.trustStoreEntry = data.trustStoreEntry;
-  }
-
-}
diff --git a/smp-angular/src/app/trust-store/trust-store-entry.model.ts b/smp-angular/src/app/trust-store/trust-store-entry.model.ts
deleted file mode 100644
index 61fac53014edba9ee9316d5f47b9d9017662a65e..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store-entry.model.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * @author Thomas Dussart
- */
-export interface TrustStoreEntry {
-  name: string;
-  subject: string;
-  issuer: string;
-  validFrom: string;
-  validUntil: string;
-}
-
diff --git a/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.html b/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.html
deleted file mode 100644
index 79e18950ecccb176f008f2dde7402b2483c60a51..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<h2 mat-dialog-title>Upload truststore</h2>
-<mat-dialog-content style="height:150px;width:350px">
-  <mat-card>
-    <mat-card-content>
-      <div class="divTableRow">
-        <div class="divTableCell">
-          <input #fileInput type="file" id="trustsore" accept=".jks" (change)="checkFile()">
-        </div>
-        <div class="divTableCell">
-        </div>
-      </div>
-      <mat-form-field style="width:100%;margin-top: 1em;">
-        <input matInput placeholder="Password" id="password_id" name="password" type="password" [(ngModel)]="password">
-      </mat-form-field>
-    </mat-card-content>
-  </mat-card>
-</mat-dialog-content>
-
-<table class="buttonsRow">
-  <tr>
-    <td>
-      <button id="okbuttonupload_id" mat-raised-button color="primary" (click)="submit()" style="margin-top:10px" [disabled]="!enableSubmit">
-        <mat-icon>check_circle</mat-icon>
-        <span>OK</span>
-      </button>
-      <button id="cancelbuttonupload_id" mat-raised-button color="primary" (click)="dialogRef.close({})"
-              style="margin-top:10px">
-        <mat-icon>cancel</mat-icon>
-        <span>Cancel</span>
-      </button>
-    </td>
-  </tr>
-</table>
-
-
-
diff --git a/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.spec.ts b/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.spec.ts
deleted file mode 100644
index b7bcbc773bf14082d66dde6dbdd9e64c780fcafc..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.spec.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import {async, ComponentFixture, TestBed} from '@angular/core/testing';
-
-import {TrustStoreUploadComponent} from './trust-store-upload.component';
-
-describe('TrustStoreUploadComponent', () => {
-  let component: TrustStoreUploadComponent;
-  let fixture: ComponentFixture<TrustStoreUploadComponent>;
-
-  beforeEach(async(() => {
-    TestBed.configureTestingModule({
-      declarations: [TrustStoreUploadComponent]
-    })
-      .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(TrustStoreUploadComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should be created', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.ts b/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.ts
deleted file mode 100644
index 96b6ad330943120b948a32a9ca441bd3434a360b..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store-upload/trust-store-upload.component.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import {Component, EventEmitter, Inject, ViewChild} from '@angular/core';
-import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material';
-import {TrustStoreService} from '../trust-store.service';
-import {AlertService} from '../../alert/alert.service';
-
-@Component({
-  selector: 'app-trustore-upload',
-  templateUrl: './trust-store-upload.component.html',
-})
-export class TrustStoreUploadComponent {
-
-  @ViewChild('fileInput')
-  private fileInput;
-
-  password: any;
-  onTruststoreUploaded = new EventEmitter();
-  enableSubmit = false;
-
-  constructor(public dialogRef: MatDialogRef<TrustStoreUploadComponent>,
-              private trustStoreService: TrustStoreService, private alertService: AlertService,
-              @Inject(MAT_DIALOG_DATA) public data: any) {
-  }
-
-  public checkFile() {
-    this.enableSubmit = this.fileInput.nativeElement.files.length != 0;
-  }
-
-  public submit() {
-    let fi = this.fileInput.nativeElement;
-    this.trustStoreService.saveTrustStore(fi.files[0], this.password).subscribe(res => {
-        this.alertService.success(res, false);
-        this.onTruststoreUploaded.emit();
-      },
-      err => {
-        if(!err.ok && err.statusText.length == 0) {
-          this.alertService.error("Error updating truststore file (" + fi.files[0].name + ")", false);
-        } else {
-          this.alertService.error(err.text() + " (" + fi.files[0].name + ")", false);
-        }
-      }
-    );
-    this.dialogRef.close();
-  }
-}
diff --git a/smp-angular/src/app/trust-store/trust-store.component.css b/smp-angular/src/app/trust-store/trust-store.component.css
deleted file mode 100644
index 9b9214e1bf67e162955da2b8067b189b3a0d7e0d..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store.component.css
+++ /dev/null
@@ -1,43 +0,0 @@
-label:hover, label:active, input:hover + label, input:active + label {
-  color: #3f51b5;
-}
-
-.divTable {
-  display: table;
-  width: 100%;
-}
-
-.divTableRow {
-  display: table-row;
-}
-
-.divTableHeading {
-  background-color: #EEE;
-  display: table-header-group;
-}
-
-.divTableCell, .divTableHead {
-  /*border: 1px solid #999999;*/
-  display: table-cell;
-  padding: 3px 3px;
-}
-
-.divTableHeading {
-  background-color: #EEE;
-  display: table-header-group;
-  font-weight: bold;
-}
-
-.divTableFoot {
-  background-color: #EEE;
-  display: table-footer-group;
-  font-weight: bold;
-}
-
-.divTableBody {
-  display: table-row-group;
-}
-
-.firstColumn {
-  width: 20%;
-}
diff --git a/smp-angular/src/app/trust-store/trust-store.component.html b/smp-angular/src/app/trust-store/trust-store.component.html
deleted file mode 100644
index b8f40997138bf510cb26f5febd1830c13a36f0b1..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store.component.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<page-header id="truststoreheader_id">Truststore</page-header>
-<div class="panel">
-  <div class="selectionCriteria">
-    <mat-card>
-      <mat-card-content>
-        <div class="group-filter-button">
-          <span class="row-button">
-            <app-row-limiter [pageSizes]="rowLimiter.pageSizes"
-                             (onPageSizeChanged)="changePageSize($event.value)"></app-row-limiter>
-          </span>
-          <span class="column-filter-button">
-            <app-column-picker [allColumns]="columnPicker.allColumns" [selectedColumns]="columnPicker.selectedColumns"
-                               (onSelectedColumnsChanged)="columnPicker.changeSelectedColumns($event)"></app-column-picker>
-          </span>
-          <button mat-icon-button color="primary" [disabled]="!isSaveAsCSVButtonEnabled()" (click)="saveAsCSV()"
-                  id="saveascsvbutton_id" matTooltip="Export as CSV">
-            <img src="assets/images/exportCSV.svg" width="30" height="30">
-          </button>
-        </div>
-
-      <ngx-datatable
-        id="errorLogTable"
-        class="material striped"
-        [rows]="trustStoreEntries"
-        [columnMode]="'force'"
-        [columns]="columnPicker.selectedColumns"
-        [headerHeight]="50"
-        [footerHeight]="50"
-        [rowHeight]="'auto'"
-        [scrollbarH]="true"
-        [loadingIndicator]="loading"
-        [selectionType]="'multi'"
-        [selected]="selectedMessages"
-        [limit]="rowLimiter.pageSize"
-        [sorts]="[{prop: 'alias', dir: 'desc'}]"
-        (activate)="onActivate($event)"
-        (select)="onSelect($event)">
-
-
-      </ngx-datatable>
-
-      <ng-template #rowWithDateFormatTpl let-row="row" let-value="value" ngx-datatable-cell-template>
-        <span class="text-select">{{value | smpDate: dateFormat}}</span>
-      </ng-template>
-
-        <table class="group-action-button">
-          <tr>
-            <td>
-              <button mat-raised-button color="primary" (click)="openEditTrustStore()" id="uploadbutton_id">
-                <mat-icon>file_upload</mat-icon>
-                <span>Upload</span>
-              </button>
-            </td>
-          </tr>
-        </table>
-      </mat-card-content>
-    </mat-card>
-  </div>
-</div>
-
diff --git a/smp-angular/src/app/trust-store/trust-store.component.spec.ts b/smp-angular/src/app/trust-store/trust-store.component.spec.ts
deleted file mode 100644
index 5b9f23c7c1599a6ac1af9fa4558c000991f4e684..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store.component.spec.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { TrustStoreComponent } from './trust-store.component';
-
-describe('TrustStoreComponent', () => {
-  let component: TrustStoreComponent;
-  let fixture: ComponentFixture<TrustStoreComponent>;
-
-  beforeEach(async(() => {
-    TestBed.configureTestingModule({
-      declarations: [ TrustStoreComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(TrustStoreComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/smp-angular/src/app/trust-store/trust-store.component.ts b/smp-angular/src/app/trust-store/trust-store.component.ts
deleted file mode 100644
index 5b4247ec25316487308fb2fe8830c7f12852ba6e..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store.component.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
-import {TrustStoreService} from './trust-store.service';
-import {TrustStoreEntry} from './trust-store-entry.model';
-import {TrustStoreDialogComponent} from './trust-store-dialog/trust-store-dialog.component';
-import {MatDialog, MatDialogRef} from '@angular/material';
-import {TrustStoreUploadComponent} from './trust-store-upload/trust-store-upload.component';
-import {ColumnPicker} from '../common/column-picker/column-picker.model';
-import {RowLimiter} from '../common/row-limiter/row-limiter.model';
-import {DownloadService} from '../download/download.service';
-import {AlertComponent} from '../alert/alert.component';
-import {AlertService} from '../alert/alert.service';
-
-@Component({
-  selector: 'app-truststore',
-  templateUrl: './trust-store.component.html',
-  styleUrls: ['./trust-store.component.css']
-})
-export class TrustStoreComponent implements OnInit {
-
-  columnPicker: ColumnPicker = new ColumnPicker();
-
-  rowLimiter: RowLimiter = new RowLimiter();
-
-  @ViewChild('rowWithDateFormatTpl') rowWithDateFormatTpl: TemplateRef<any>;
-
-  trustStoreEntries: Array<TrustStoreEntry> = [];
-  selectedMessages: Array<any> = [];
-  loading: boolean = false;
-
-  rows: Array<any> = [];
-
-  static readonly TRUSTSTORE_URL: string = "rest/truststore";
-  static readonly TRUSTSTORE_CSV_URL: string = TrustStoreComponent.TRUSTSTORE_URL + "/csv";
-
-  constructor(private trustStoreService: TrustStoreService, public dialog: MatDialog, public alertService: AlertService, private downloadService: DownloadService) {
-  }
-
-  ngOnInit(): void {
-    this.columnPicker.allColumns = [
-      {
-
-        name: 'Name',
-        prop: 'name'
-      },
-      {
-        name: 'Subject',
-        prop: 'subject',
-      },
-      {
-        name: 'Issuer',
-        prop: 'issuer',
-      },
-      {
-        cellTemplate: this.rowWithDateFormatTpl,
-        name: 'Valid from',
-        prop: 'validFrom'
-
-      },
-      {
-        cellTemplate: this.rowWithDateFormatTpl,
-        name: 'Valid until',
-        prop: 'validUntil',
-      }
-
-    ];
-
-    this.columnPicker.selectedColumns = this.columnPicker.allColumns.filter(col => {
-      return ["Name", "Subject", "Issuer", "Valid from", "Valid until"].indexOf(col.name) != -1
-    });
-    this.getTrustStoreEntries();
-
-    if(this.trustStoreEntries.length > AlertComponent.MAX_COUNT_CSV) {
-      this.alertService.error("Maximum number of rows reached for downloading CSV");
-    }
-  }
-
-  getTrustStoreEntries(): void {
-    this.trustStoreService.getEntries().subscribe(trustStoreEntries => this.trustStoreEntries = trustStoreEntries);
-  }
-
-  onSelect({selected}) {
-    console.log('Select Event');
-    this.selectedMessages.splice(0, this.selectedMessages.length);
-    this.selectedMessages.push(...selected);
-  }
-
-  onActivate(event) {
-    console.log('Activate Event', event);
-    if ("dblclick" === event.type) {
-      this.details(event.row);
-    }
-  }
-
-  details(selectedRow: any) {
-    let dialogRef: MatDialogRef<TrustStoreDialogComponent> = this.dialog.open(TrustStoreDialogComponent, {data: {trustStoreEntry: selectedRow}});
-    dialogRef.afterClosed().subscribe(result => {
-
-    });
-  }
-
-  changePageSize(newPageSize: number) {
-    this.rowLimiter.pageSize = newPageSize;
-    this.getTrustStoreEntries();
-  }
-
-  openEditTrustStore() {
-    let dialogRef: MatDialogRef<TrustStoreUploadComponent> = this.dialog.open(TrustStoreUploadComponent);
-    dialogRef.componentInstance.onTruststoreUploaded.subscribe(updated => {
-        this.getTrustStoreEntries();
-    });
-  }
-
-  /**
-   * Method that checks if CSV Button export can be enabled
-   * @returns {boolean} true, if button can be enabled; and false, otherwise
-   */
-  isSaveAsCSVButtonEnabled() : boolean {
-    return this.rows.length < AlertComponent.MAX_COUNT_CSV;
-  }
-
-  /**
-   * Saves the content of the datatable into a CSV file
-   */
-  saveAsCSV() {
-    this.downloadService.downloadNative(TrustStoreComponent.TRUSTSTORE_CSV_URL);
-  }
-}
diff --git a/smp-angular/src/app/trust-store/trust-store.service.ts b/smp-angular/src/app/trust-store/trust-store.service.ts
deleted file mode 100644
index 8a31016a0afa7ef23fd17b4dccea75758275d95b..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/trust-store/trust-store.service.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import {HttpClient, HttpResponse} from '@angular/common/http';
-import {AlertService} from 'app/alert/alert.service';
-import {Injectable} from '@angular/core';
-import {Observable} from 'rxjs';
-import {TrustStoreEntry} from './trust-store-entry.model';
-import {catchError} from 'rxjs/operators';
-
-/**
- * @Author Dussart Thomas
- */
-@Injectable()
-export class TrustStoreService {
-
-  url = "rest/truststore";
-
-  constructor(private http: HttpClient, private alertService: AlertService) {
-  }
-
-  getEntries(): Observable<TrustStoreEntry[]> {
-    return this.http.get<TrustStoreEntry[]>(this.url + '/list')
-      .pipe(catchError(err => this.handleError(err)));
-  }
-
-  saveTrustStore(file, password): Observable<string> {
-    let input = new FormData();
-    input.append('truststore', file);
-    input.append('password', password);
-    return this.http.post<string>(this.url + '/save', input);
-  }
-
-  private handleError(error) {
-    this.alertService.error(error, false);
-    let errMsg: string;
-    if (error instanceof HttpResponse) {
-      const body = error || '';
-      const err = body['error'] || JSON.stringify(body);
-      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
-    } else {
-      errMsg = error.message ? error.message : error.toString();
-    }
-    console.error(errMsg);
-    return Promise.reject(errMsg);
-  }
-}
diff --git a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
index 54583422572dfeb84f5cac008ebb3e3695a1608f..90dd083ec00ff4fa0234b9c824990c5decf92fc7 100644
--- a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
+++ b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
@@ -25,6 +25,8 @@ export class UserDetailsDialogComponent {
   editMode: boolean;
   formTitle: string;
   userRoles = [];
+  role: string; // temporally added by JRC just to compile the code
+  dateFormat: string; // temporally added by JRC just to compile the code
   existingRoles = [];
   current: UserRo & { confirmation?: string };
   userForm: FormGroup;
diff --git a/smp-angular/src/app/user/user.component.html b/smp-angular/src/app/user/user.component.html
index 53c2470d9d611bf5eeb26ac0d0b6c77ecbaaf4b2..4ff6670bfabbd16692fdef038dc1917cb8c64f75 100644
--- a/smp-angular/src/app/user/user.component.html
+++ b/smp-angular/src/app/user/user.component.html
@@ -2,7 +2,7 @@
   page_id= 'user_id'
   title= 'Users'
   [columnPicker] = "columnPicker"
-  [url]="'ui/user'"
+  [url]="'rest/user'"
   [additionalToolButtons]="additionalToolButtons"
   [searchTableController]="userController"
   [searchPanel]="searchPanel"
diff --git a/smp-angular/src/main/resources/META-INF/web-fragment.xml b/smp-angular/src/main/resources/META-INF/web-fragment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..11e584bd0107d040a00a03f78c130e0e0fa87f1a
--- /dev/null
+++ b/smp-angular/src/main/resources/META-INF/web-fragment.xml
@@ -0,0 +1,16 @@
+<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xsi:schemaLocation="
+        http://java.sun.com/xml/ns/javaee
+        http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
+              version="3.0">
+
+
+  <distributable/>
+  <ordering>
+    <after>
+      <others/>
+    </after>
+  </ordering>
+
+</web-fragment>
diff --git a/smp-angular/src/styles.css b/smp-angular/src/styles.css
index e1d7a7f2f1f99ea9fdcaa982cfe45b305a401180..95c98d1931a264c7fbe7cc46dca41019056b5e51 100644
--- a/smp-angular/src/styles.css
+++ b/smp-angular/src/styles.css
@@ -23,6 +23,7 @@ html, body {
 .mat-button, .mat-raised-button, .mat-icon-button {
   font-family: 'Open Sans', sans-serif !important;
   font-weight: bolder !important;
+  margin: 0 2px  !important;
 }
 
 .text-select {
@@ -119,6 +120,7 @@ mat-sidenav[_ngcontent-c0] {
   border-radius: 0;
   line-height: 50px !important;
   letter-spacing: 1px;
+
 }
 
 .sideNavButton {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java
index 40515f875f63a9c0a9453c733e318ef0fb67b80c..f941d6f161af8843a9c23f2d67141afb6bd50417 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java
@@ -17,16 +17,15 @@ import eu.europa.ec.edelivery.smp.data.model.BaseEntity;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ServiceGroupService;
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.criterion.MatchMode;
 import org.springframework.core.GenericTypeResolver;
 
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.PersistenceContext;
 import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import javax.persistence.criteria.*;
 import javax.transaction.Transactional;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -45,6 +44,8 @@ public abstract class BaseDao<E extends BaseEntity> {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(BaseDao.class);
 
+    protected String defaultSortMethod;
+
     @PersistenceContext
     protected EntityManager memEManager;
 
@@ -114,11 +115,10 @@ public abstract class BaseDao<E extends BaseEntity> {
     /**
      * Clear the persistence context, causing all managed entities to become detached.
      * Changes made to entities that have not been flushed to the database will not be persisted.
-     *
+     * <p>
      * Main purpose is to clear cache for unit testing
-     *
      */
-    public void clearPersistenceContext(){
+    public void clearPersistenceContext() {
         memEManager.clear();
     }
 
@@ -126,7 +126,7 @@ public abstract class BaseDao<E extends BaseEntity> {
      * Method generates CriteriaQuery for search or count. If filter property value should match multiple values eg: column in (:list)
      * than filter method must end with List and returned value must be list. If property is comparable (decimal, int, date)
      * if filter method ends with From, than predicate greaterThanOrEqualTo is set to quer. If Method end To, than
-     * predicate cb.lessThan is setted. If filter property  has null value, than filter parameter is ignored.
+     * predicate cb.lessThan is set. If filter property  has null value, than filter parameter is ignored.
      *
      * @param searchParams
      * @param forCount
@@ -134,11 +134,10 @@ public abstract class BaseDao<E extends BaseEntity> {
      * @param sortOrder
      * @return
      */
-    protected < D> CriteriaQuery createSearchCriteria(Object searchParams, Class<D> filterType,
-                                                        boolean forCount, String sortField, String sortOrder) {
+    protected <D> CriteriaQuery createSearchCriteria(Object searchParams, Class<D> filterType,
+                                                     boolean forCount, String sortField, String sortOrder) {
         CriteriaBuilder cb = memEManager.getCriteriaBuilder();
-        CriteriaQuery cq = forCount ? cb.createQuery(Long.class
-        ) : cb.createQuery(entityClass);
+        CriteriaQuery cq = forCount ? cb.createQuery(Long.class) : cb.createQuery(entityClass);
         Root<E> om = cq.from(filterType == null ? entityClass : filterType);
         if (forCount) {
             cq.select(cb.count(om));
@@ -149,86 +148,117 @@ public abstract class BaseDao<E extends BaseEntity> {
                 cq.orderBy(cb.desc(om.get(sortField)));
             }
         } else {
-            // cq.orderBy(cb.desc(om.get("Id")));
+            if (!StringUtils.isBlank(defaultSortMethod)) {
+                cq.orderBy(cb.desc(om.get(defaultSortMethod)));
+            }
         }
-        List<Predicate> lstPredicate = new ArrayList<>();
+
+
         // set order by
         if (searchParams != null) {
-            Class cls = searchParams.getClass();
-            Method[] methodList = cls.getMethods();
-            for (Method m : methodList) {
-                // only getters (public, starts with get, no arguments)
-                String mName = m.getName();
-                if (Modifier.isPublic(m.getModifiers()) && m.getParameterCount() == 0
-                        && !m.getReturnType().equals(Void.TYPE)
-                        && (mName.startsWith("get") || mName.startsWith("is"))) {
-                    String fieldName = mName.substring(mName.startsWith("get") ? 3 : 2);
-                    // get return parameter
-                    Object searchValue;
-                    try {
-                        searchValue = m.invoke(searchParams, new Object[]{});
-                    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
-                        LOG.error("Error setting retrieveing search parameters", ex);
-                        continue;
-                    }
+            List<Predicate> lstPredicate = createPredicates(searchParams, om, cb);
+            if (!lstPredicate.isEmpty()) {
+                Predicate[] tblPredicate = lstPredicate.stream().toArray(Predicate[]::new);
+                cq.where(cb.and(tblPredicate));
+            }
+        }
+        return cq;
+    }
+
+    /**
+     * Method crates list of predicates for Query
+     *
+     * @param searchParams - filter object
+     * @param om
+     * @param cb
+     * @return
+     */
+    protected List<Predicate> createPredicates(Object searchParams, Root<E> om, CriteriaBuilder cb) {
+        List<Predicate> lstPredicate = new ArrayList<>();
+
+        Class cls = searchParams.getClass();
+        Method[] methodList = cls.getMethods();
+        for (Method m : methodList) {
+            // only getters (public, starts with get, no arguments)
+            String mName = m.getName();
+
+            if (Modifier.isPublic(m.getModifiers()) && m.getParameterCount() == 0
+                    && !m.getReturnType().equals(Void.TYPE)
+                    && !mName.equalsIgnoreCase("getClass")
+                    && (mName.startsWith("get") || mName.startsWith("is"))) {
+                String fieldName = mName.substring(mName.startsWith("get") ? 3 : 2);
+                // get return parameter
+                Object searchValue;
+                try {
+                    searchValue = m.invoke(searchParams, new Object[]{});
+                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                    LOG.error("Error setting retrieveing search parameters", ex);
+                    continue;
+                }
 
-                    if (searchValue == null) {
+                if (searchValue == null) {
+                    continue;
+                }
+
+                if (fieldName.endsWith("List") && searchValue instanceof List) {
+                    Path path = getPath(om, fieldName, "List");
+                    if (!((List) searchValue).isEmpty()) {
+                        lstPredicate.add(path.in(
+                                ((List) searchValue).toArray()));
+                    } else {
+                        lstPredicate.add(path.isNull());
+                    }
+                } else {
+                    try {
+                        cls.getMethod("set" + fieldName, new Class[]{m.getReturnType()});
+                    } catch (NoSuchMethodException | SecurityException ex) {
+                        // method does not have setter // ignore other methods
+                        LOG.error("Field '" + fieldName + "' does not have a setter!", ex);
                         continue;
                     }
 
-                    if (fieldName.endsWith("List") && searchValue instanceof List) {
-                        String property = fieldName.substring(0, fieldName.lastIndexOf(
-                                "List"));
-                        if (!((List) searchValue).isEmpty()) {
-                            lstPredicate.add(om.get(property).in(
-                                    ((List) searchValue).toArray()));
-                        } else {
-                            lstPredicate.add(om.get(property).isNull());
+                    if (fieldName.endsWith("From") && searchValue instanceof Comparable) {
+                        lstPredicate.add(cb.greaterThanOrEqualTo(
+                                getPath(om, fieldName, "From"),
+                                (Comparable) searchValue));
+                    } else if (fieldName.endsWith("To") && searchValue instanceof Comparable) {
+                        lstPredicate.add(cb.lessThan(getPath(om, fieldName, "To"),
+                                (Comparable) searchValue));
+                    } else if (searchValue instanceof String && fieldName.endsWith("Like")) {
+                        if (!((String) searchValue).isEmpty()) {
+                            lstPredicate.add(cb.like(getPath(om, fieldName, "Like"), "%" + (String) searchValue + "%"));
                         }
-                    } else {
-                        try {
-                            cls.getMethod("set" + fieldName, new Class[]{m.getReturnType()});
-                        } catch (NoSuchMethodException | SecurityException ex) {
-                            // method does not have setter // ignore other methods
-                            LOG.error("Field '"+fieldName+"' does not have a setter!", ex);
-                            continue;
-                        }
-
-                        if (fieldName.endsWith("From") && searchValue instanceof Comparable) {
-                            lstPredicate.add(cb.greaterThanOrEqualTo(
-                                    om.get(fieldName.substring(0, fieldName.
-                                            lastIndexOf("From"))),
-                                    (Comparable) searchValue));
-                        } else if (fieldName.endsWith("To") && searchValue instanceof Comparable) {
-                            lstPredicate.add(cb.lessThan(
-                                    om.
-                                            get(fieldName.substring(0, fieldName.lastIndexOf(
-                                                    "To"))),
-                                    (Comparable) searchValue));
-                        } else if (searchValue instanceof String) {
-                            if (!((String) searchValue).isEmpty()) {
-                                lstPredicate.add(cb.equal(om.get(fieldName), searchValue));
-                            }
-                        } else if (searchValue instanceof BigInteger) {
-                            lstPredicate.add(cb.equal(om.get(fieldName), searchValue));
-                        } else {
-                            LOG.warn("Unknown search value type %s for method %s! "
-                                            + "Parameter is ignored!",
-                                    searchValue, fieldName);
+                    } else if (searchValue instanceof String) {
+                        if (!((String) searchValue).isEmpty()) {
+                            lstPredicate.add(cb.equal(getPath(om, fieldName), searchValue));
                         }
+                    } else if (searchValue instanceof BigInteger) {
+                        lstPredicate.add(cb.equal(getPath(om, fieldName), searchValue));
+                    } else if (searchValue instanceof Long) {
+                        lstPredicate.add(cb.equal(getPath(om, fieldName), searchValue));
+                    } else {
+                        LOG.warn("Unknown search value type %s for method %s! Parameter is ignored!",
+                                searchValue, fieldName);
                     }
-
                 }
-            }
-            if (!lstPredicate.isEmpty()) {
-                Predicate[] tblPredicate = lstPredicate.stream().toArray(
-                        Predicate[]::new);
-                cq.where(cb.and(tblPredicate));
+
             }
         }
-        return cq;
+        return lstPredicate;
+    }
+
+
+    public Path getPath(Root<E> om, String fieldName) {
+        return getPath(om, fieldName, null);
     }
 
+    public Path getPath(Root<E> om, String fieldName, String trimRight) {
+        String fn = StringUtils.uncapitalize(fieldName);
+        if (!StringUtils.isBlank(trimRight)) {
+            fn = fn.substring(0, fn.lastIndexOf(trimRight));
+        }
+        return om.get(fn);
+    }
 
     /**
      * Method returns paginated entity list with give pagination parameters and filters.
@@ -246,8 +276,8 @@ public abstract class BaseDao<E extends BaseEntity> {
      */
 
     public List<E> getDataList(int startingAt, int maxResultCnt,
-                                   String sortField,
-                                   String sortOrder, Object filters) {
+                               String sortField,
+                               String sortOrder, Object filters) {
 
         return getDataList(startingAt, maxResultCnt, sortField, sortOrder,
                 filters, null);
@@ -269,9 +299,9 @@ public abstract class BaseDao<E extends BaseEntity> {
      * @return List
      */
     public <D> List<E> getDataList(int startingAt,
-                                      int maxResultCnt,
-                                      String sortField,
-                                      String sortOrder, Object filters, Class<D> filterType) {
+                                   int maxResultCnt,
+                                   String sortField,
+                                   String sortOrder, Object filters, Class<D> filterType) {
 
         List<E> lstResult;
         try {
@@ -287,7 +317,7 @@ public abstract class BaseDao<E extends BaseEntity> {
             }
             lstResult = q.getResultList();
         } catch (NoResultException ex) {
-            LOG.warn("No result for '"+filterType.getName()+"' does not have a setter!", ex);
+            LOG.warn("No result for '" + filterType.getName() + "' does not have a setter!", ex);
             lstResult = new ArrayList<>();
         }
 
@@ -300,7 +330,7 @@ public abstract class BaseDao<E extends BaseEntity> {
      * than filter method must end with List and returned value must be list. If property is comparable (decimal, int, date)
      * if filter method ends with From, than predicate greaterThanOrEqualTo is set to quer. If Method end To, than
      * predicate cb.lessThan is setted. If filter property  has null value, than filter parameter is ignored.
-
+     *
      * @param filters
      * @return
      */
@@ -313,5 +343,4 @@ public abstract class BaseDao<E extends BaseEntity> {
     }
 
 
-
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/BaseRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/BaseRO.java
new file mode 100644
index 0000000000000000000000000000000000000000..b19a0fec8baa9b0dba52dcd516c4fabdaad85acc
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/BaseRO.java
@@ -0,0 +1,27 @@
+package eu.europa.ec.edelivery.smp.data.ui;
+
+import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
+
+import java.io.Serializable;
+
+public class BaseRO  implements Serializable {
+
+    private int status;
+    private int index = EntityROStatus.PERSISTED.getStatusNumber();
+
+    public int getStatus() {
+        return status;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainRO.java
index 11f1a5010dfb73d02f816d7573385cc6e49b18f0..fbf9b04a166b481ab45a6705644f8a2bfbeac939 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainRO.java
@@ -8,13 +8,12 @@ import java.io.Serializable;
  * @since 4.1
  */
 
-public class DomainRO implements Serializable {
+public class DomainRO extends BaseRO  {
 
 
     private static final long serialVersionUID = -9008583888835630560L;
 
     Long id;
-
     String domainCode;
     String smlSubdomain;
     String smlSmpId;
@@ -22,7 +21,6 @@ public class DomainRO implements Serializable {
     String smlClientCertHeader;
     String smlClientKeyAlias;
     String signatureKeyAlias;
- ;
 
 
     public DomainRO() {
@@ -92,4 +90,5 @@ public class DomainRO implements Serializable {
     public void setSignatureKeyAlias(String signatureKeyAlias) {
         this.signatureKeyAlias = signatureKeyAlias;
     }
+
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupRO.java
index 88fe3ee5eda1e9e494945807e2828ba817172299..9755ed0418a1d82b2d9dadafef0385f25377b1ac 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupRO.java
@@ -2,6 +2,8 @@ package eu.europa.ec.edelivery.smp.data.ui;
 
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author Joze Rihtarsic
@@ -9,13 +11,15 @@ import java.io.Serializable;
  */
 
 
-public class ServiceGroupRO implements Serializable {
+public class ServiceGroupRO extends BaseRO {
 
 
     private static final long serialVersionUID = -7523221767041516157L;
     private String participantIdentifier;
     private String participantScheme;
     private boolean smlRegistered = false;
+    private List<ServiceMetadataRO> lstServiceMetadata = new ArrayList<>();
+
 
 
     private String domain;
@@ -52,4 +56,10 @@ public class ServiceGroupRO implements Serializable {
     public void setSmlRegistered(boolean smlRegistered) {
         this.smlRegistered = smlRegistered;
     }
+
+
+    public List<ServiceMetadataRO> getServiceMetadata() {
+        return lstServiceMetadata;
+    }
+
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataRO.java
index b2e3ecb8129a2aaf1d63b64c0e5707251425f83a..f47c78dc5a976a3521aa2c44bd93a56c7eac7223 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceMetadataRO.java
@@ -7,48 +7,45 @@ import java.io.Serializable;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-
-
-public class ServiceMetadataRO implements Serializable {
+public class ServiceMetadataRO extends BaseRO {
 
 
     private static final long serialVersionUID = 67944640449327185L;
-    private String participantId;
-    private String participantSchema;
-    private String documentIdScheme;
-    private String documentIdValue;
-
 
-        public String getParticipantId() {
-            return participantId;
-        }
+    String documentIdentifier;
+    String documentIdentifierScheme;
+    String smlSubdomain;
+    String domainCode;
 
-        public void setParticipantId(String participantId) {
-            this.participantId = participantId;
-        }
+    public String getDocumentIdentifier() {
+        return documentIdentifier;
+    }
 
-        public String getParticipantSchema() {
-            return participantSchema;
-        }
+    public void setDocumentIdentifier(String documentIdentifier) {
+        this.documentIdentifier = documentIdentifier;
+    }
 
-        public void setParticipantSchema(String participantSchema) {
-            this.participantSchema = participantSchema;
-        }
+    public String getDocumentIdentifierScheme() {
+        return documentIdentifierScheme;
+    }
 
-        public String getDocumentIdScheme() {
-            return documentIdScheme;
-        }
+    public void setDocumentIdentifierScheme(String documentIdentifierScheme) {
+        this.documentIdentifierScheme = documentIdentifierScheme;
+    }
 
-        public void setDocumentIdScheme(String documentIdScheme) {
-            this.documentIdScheme = documentIdScheme;
-        }
+    public String getSmlSubdomain() {
+        return smlSubdomain;
+    }
 
-        public String getDocumentIdValue() {
-            return documentIdValue;
-        }
+    public void setSmlSubdomain(String smlSubdomain) {
+        this.smlSubdomain = smlSubdomain;
+    }
 
-        public void setDocumentIdValue(String documentIdValue) {
-            this.documentIdValue = documentIdValue;
-        }
+    public String getDomainCode() {
+        return domainCode;
+    }
 
-}
+    public void setDomainCode(String domainCode) {
+        this.domainCode = domainCode;
+    }
+}
\ No newline at end of file
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java
index c81c50ebcac948c44523decd55ea798cdb42aff8..dd6c885c5b95e260144684d48304d0b11e13269d 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java
@@ -12,7 +12,7 @@ import java.time.LocalDateTime;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-public class UserRO implements Serializable {
+public class UserRO extends BaseRO {
 
 
     private static final long serialVersionUID = -4971552086560325302L;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/EntityROStatus.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/EntityROStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb3542bce51feaa26906fba132f51e3b9fd7f358
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/EntityROStatus.java
@@ -0,0 +1,24 @@
+package eu.europa.ec.edelivery.smp.data.ui.enums;
+
+
+/**
+ * Enumeraton of Resourceobject statuse .
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+public enum EntityROStatus {
+    PERSISTED(0),
+    UPDATED(1),
+    NEW(2),
+    REMOVE(3);
+
+    int statusNumber;
+
+    EntityROStatus(int statusNumber) {
+        this.statusNumber = statusNumber;
+    }
+
+    public int getStatusNumber() {
+        return statusNumber;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java
index 999cc6ef25d4f666bc08a684a30e41f6f126e2c9..aeb63d031a43a2d6b16348d52f0f25178fda714a 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPMessageCode.java
@@ -10,10 +10,27 @@ import eu.europa.ec.edelivery.smp.logging.api.MessageCode;
 public enum SMPMessageCode implements MessageCode {
 
 
-    BUS_SAVE_SERVICE_GROUP ("BUS-001", "Start inserting/updating ServiceGroup for part. Id: {} part. schema {}."),
-    BUS_SAVE_SERVICE_GROUP_FAILED ("BUS-002", "Inserting/updating ServiceGroup for part. Id: {} part. schema {} failed! Error: [{}]"),
+    BUS_HTTP_PUT_SERVICE_GROUP ("BUS-001", "Http PUT ServiceGroup from user {} from host: {} for owner: {}. ServiceGroup with domain: {}, id: {}."),
+    BUS_HTTP_PUT_END_SERVICE_GROUP ("BUS-002", "End http PUT ServiceGroup from user {}, host: {}, owner {}. ServiceGroup with domain {}, id: {}, created {}"),
+    BUS_HTTP_DELETE_SERVICE_GROUP ("BUS-003", "Http DELETE ServiceGroup from user {} from host: {}. ServiceGroup id: {}."),
+    BUS_HTTP_DELETE_END_SERVICE_GROUP ("BUS-004", "End Http DELETE ServiceGroup from user {} from host: {}. ServiceGroup id: {}."),
+    BUS_HTTP_GET_SERVICE_GROUP ("BUS-005", "Http GET ServiceGroup from host: {}, ServiceGroup id: {}."),
+    BUS_HTTP_GET_END_SERVICE_GROUP ("BUS-006", "End Http GET ServiceGroup from host: {}, ServiceGroup id: {}."),
 
-    BUS_INVALID_XML("BUS-010", "Invalid XML for {}. Error: [{}]"),
+
+    BUS_HTTP_PUT_SERVICE_METADATA ("BUS-007", "Http PUT ServiceGroupMetadata from user {} from host: {}. ServiceGroup with domain: {}, ServiceGroup id: {} , metadata id {}."),
+    BUS_HTTP_PUT_END_SERVICE_METADATA ("BUS-008", "End http PUT ServiceGroupMetadata from user {}, host: {}. ServiceGroup with domain {}, ServiceGroup id: {} , metadata id {}, created {}"),
+    BUS_HTTP_DELETE_SERVICE_METADATA ("BUS-009", "Http DELETE ServiceGroupMetadata from user {} from host: {}. ServiceGroup id: {} , metadata id {}."),
+    BUS_HTTP_DELETE_END_SERVICE_METADATA ("BUS-010", "End Http DELETE ServiceGroupMetadata from user {} from host: {}. ServiceGroup id: {} , metadata id {}."),
+
+    BUS_HTTP_GET_SERVICE_METADATA ("BUS-011", "Http GET ServiceGroup from host: {}, ServiceGroup id: {}, metadata id {}."),
+    BUS_HTTP_GET_END_SERVICE_METADATA ("BUS-012", "End Http GET ServiceGroup from host: {}, ServiceGroup id: {}, metadata id {}."),
+
+    BUS_SAVE_SERVICE_GROUP ("BUS-013", "Start inserting/updating ServiceGroup for domain {}, part. Id: {} part. schema {}."),
+    BUS_SAVE_SERVICE_GROUP_FAILED ("BUS-014", "Inserting/updating ServiceGroup for domain {}, part. Id: {} part. schema {} failed! Error: [{}]"),
+
+
+    BUS_INVALID_XML("BUS-030", "Invalid XML for {}. Error: [{}]"),
 
 
     SEC_UNSECURED_LOGIN_ALLOWED("SEC-001", "Unsecure login is allowed, no authentication will be performed"),
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java
index e740304c2a6703b7c955003660cb4413e4005cd4..e534efe6b74e63bea19a0aeb5d13e4a9f32a0987 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java
@@ -5,10 +5,14 @@ import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.time.LocalDateTime;
+import java.util.List;
+
 @Service
 public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
 
@@ -27,14 +31,41 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
      * @param pageSize
      * @param sortField
      * @param sortOrder
+     * @param filter
      * @return
      */
     @Transactional
     public ServiceResult<DomainRO> getTableList(int page, int pageSize,
                                                  String sortField,
-                                                 String sortOrder) {
+                                                 String sortOrder, Object filter) {
+
+        return super.getTableList(page, pageSize, sortField, sortOrder, filter);
+    }
+
+    @Transactional
+    public void updateDomainList(List<DomainRO> lst) {
+        boolean suc = false;
+        for (DomainRO dRo: lst){
+
 
-        return super.getTableList(page, pageSize, sortField, sortOrder);
+            if (dRo.getStatus() == EntityROStatus.NEW.getStatusNumber()) {
+                DBDomain dDb = convertFromRo(dRo);
+                domainDao.persistFlushDetach(dDb);
+            } else if (dRo.getStatus() == EntityROStatus.UPDATED.getStatusNumber()) {
+                DBDomain upd = domainDao.find(dRo.getId());
+                upd.setSmlSmpId(dRo.getSmlSmpId());
+                upd.setSmlClientKeyAlias(dRo.getSmlClientKeyAlias());
+                upd.setSmlClientCertHeader(dRo.getSmlClientCertHeader());
+                upd.setSmlParticipantIdentifierRegExp(dRo.getSmlParticipantIdentifierRegExp());
+                upd.setSmlSubdomain(dRo.getSmlSubdomain());
+                upd.setDomainCode(dRo.getDomainCode());
+                upd.setSignatureKeyAlias(dRo.getSignatureKeyAlias());
+                upd.setLastUpdatedOn(LocalDateTime.now());
+                domainDao.update(upd);
+            } else if (dRo.getStatus() == EntityROStatus.REMOVE.getStatusNumber()) {
+                domainDao.removeByDomainCode(dRo.getDomainCode());
+            }
+        }
     }
 
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java
index b68026665553eff290f9ae979079ec5ca96b25b0..edf8b64afcf5a83dabaf868a85ce68ac1b74f418 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java
@@ -22,11 +22,13 @@ abstract class UIServiceBase<E extends BaseEntity, R> {
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIServiceBase.class);
 
     private final Class<R> roClass;
+    private final Class<E> dbClass;
 
 
     public UIServiceBase() {
         Class[] clsArg = GenericTypeResolver.resolveTypeArguments(getClass(), UIServiceBase.class);
         roClass =(Class<R>)clsArg[1];
+        dbClass =(Class<E>)clsArg[0];
 
     }
 
@@ -43,26 +45,29 @@ abstract class UIServiceBase<E extends BaseEntity, R> {
     @Transactional
     public ServiceResult<R> getTableList(int page, int pageSize,
                                          String sortField,
-                                         String sortOrder) {
+                                         String sortOrder,
+                                         Object filter) {
 
         ServiceResult<R> sg = new ServiceResult<>();
         sg.setPage(page<0?0:page);
         sg.setPageSize(pageSize);
-        long iCnt = getDatabaseDao().getDataListCount(null);
+        long iCnt = getDatabaseDao().getDataListCount(filter);
         sg.setCount(iCnt);
 
         if (iCnt > 0) {
             int iStartIndex = pageSize<0?-1:page * pageSize;
-            List<E> lst = getDatabaseDao().getDataList(iStartIndex, pageSize, sortField, sortOrder, null);
+            List<E> lst = getDatabaseDao().getDataList(iStartIndex, pageSize, sortField, sortOrder, filter);
 
             List<R>  lstRo = new ArrayList<>();
             for (E d : lst) {
-                try {
-                    R dro = roClass.newInstance();
-                    BeanUtils.copyProperties(dro,d);
+                R dro = convertToRo(d);
+                 try {
+                    BeanUtils.setProperty(dro, "index", iStartIndex++);
                     lstRo.add(dro);
-                } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
-                    LOG.error("Error occured while retrieving list for " +roClass.getName(), e );
+                } catch (InvocationTargetException | IllegalAccessException e) {
+                     String msg = "Error occured while retrieving list for " +roClass.getName();
+                    LOG.error(msg, e );
+                    throw new RuntimeException(msg, e);
                 }
 
 
@@ -72,5 +77,38 @@ abstract class UIServiceBase<E extends BaseEntity, R> {
         return sg;
     }
 
+    /**
+     * Simple method for converting types. Property name and property type must match
+     * @param d
+     * @return
+     */
+    public R convertToRo(E d) {
+        try {
+            R dro = roClass.newInstance();
+            BeanUtils.copyProperties(dro, d);
+            return dro;
+         } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
+            String msg = "Error occured while converting to RO Entity for " +roClass.getName();
+            LOG.error(msg, e );
+            throw new RuntimeException(msg, e);
+        }
+    }
+    /*
+     * Simple method for converting types. Property name and property type must match
+     * @param d
+     * @return
+             */
+    public E convertFromRo(R d) {
+        try {
+            E e = dbClass.newInstance();
+            BeanUtils.copyProperties(e, d);
+            return e;
+        } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
+            String msg = "Error occured while converting to DB entity for " +dbClass.getName();
+            LOG.error(msg, e );
+            throw new RuntimeException(msg, e);
+        }
+    }
+
     protected abstract BaseDao<E> getDatabaseDao();
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
index fa69336908e528a689cd87951d11c974cb0c2acb..0782d9830e14edda44908c23af22320b68b5c379 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
@@ -4,11 +4,15 @@ import eu.europa.ec.edelivery.smp.data.dao.BaseDao;
 import eu.europa.ec.edelivery.smp.data.dao.ServiceGroupDao;
 import eu.europa.ec.edelivery.smp.data.model.DBServiceGroup;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceMetadataRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @Service
 public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, ServiceGroupRO> {
 
@@ -21,20 +25,53 @@ public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, Service
     }
 
     /**
-     * Method returns Domain resource object list for page.
+     * Method return list of service group entities with service metadata for given search parameters and page.
      *
      * @param page
      * @param pageSize
      * @param sortField
      * @param sortOrder
+     * @param filter
      * @return
      */
     @Transactional
     public ServiceResult<ServiceGroupRO> getTableList(int page, int pageSize,
                                                  String sortField,
-                                                 String sortOrder) {
+                                                 String sortOrder, Object filter) {
+
+        ServiceResult<ServiceGroupRO> sg = new ServiceResult<>();
+        sg.setPage(page < 0 ? 0 : page);
+        sg.setPageSize(pageSize);
+        long iCnt = getDatabaseDao().getDataListCount(filter);
+        sg.setCount(iCnt);
+
+        if (iCnt > 0) {
+            int iStartIndex = pageSize < 0 ? -1 : page * pageSize;
+            List<DBServiceGroup> lst = getDatabaseDao().getDataList(iStartIndex, pageSize, sortField, sortOrder, filter);
+
+            List<ServiceGroupRO> lstRo = new ArrayList<>();
+            for (DBServiceGroup dbServiceGroup : lst) {
+                ServiceGroupRO serviceGroupRo = new ServiceGroupRO();
+                serviceGroupRo.setIndex(iStartIndex++);
+                serviceGroupRo.setParticipantIdentifier(dbServiceGroup.getParticipantIdentifier());
+                serviceGroupRo.setParticipantScheme(dbServiceGroup.getParticipantScheme());
+
+                dbServiceGroup.getServiceGroupDomains().forEach(sgd -> {
+                    sgd.getServiceMetadata().forEach(sgmd -> {
+                        ServiceMetadataRO smdro = new ServiceMetadataRO();
+                        smdro.setDocumentIdentifier(sgmd.getDocumentIdentifier());
+                        smdro.setDocumentIdentifierScheme(sgmd.getDocumentIdentifierScheme());
+                        smdro.setDomainCode(sgd.getDomain().getDomainCode());
+                        smdro.setSmlSubdomain(sgd.getDomain().getSmlSubdomain());
+                        serviceGroupRo.getServiceMetadata().add(smdro);
+                    });
+                });
+                lstRo.add(serviceGroupRo);
+            }
 
-        return super.getTableList(page, pageSize, sortField, sortOrder);
+            sg.getServiceEntities().addAll(lstRo);
+        }
+        return sg;
     }
 
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
index 14af6dd50efd1c858e5f923ac39bdc369c663b26..6a0ef1eb8b9227ff2f047b96f8e413493aa5595c 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
@@ -27,14 +27,15 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
      * @param pageSize
      * @param sortField
      * @param sortOrder
+     * @param filter
      * @return
      */
     @Transactional
     public ServiceResult<UserRO> getTableList(int page, int pageSize,
                                                  String sortField,
-                                                 String sortOrder) {
+                                                 String sortOrder, Object filter) {
 
-        return super.getTableList(page, pageSize, sortField, sortOrder);
+        return super.getTableList(page, pageSize, sortField, sortOrder, filter);
     }
 
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/AbstractBaseDao.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/AbstractBaseDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..538f03dcbcf1157250f9182a299c266f70a615a4
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/AbstractBaseDao.java
@@ -0,0 +1,23 @@
+package eu.europa.ec.edelivery.smp.data.dao;
+
+
+import eu.europa.ec.edelivery.smp.config.H2JPATestConfiguration;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.jdbc.SqlConfig;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {H2JPATestConfiguration.class,
+        ServiceGroupDao.class, ServiceMetadataDao.class, DomainDao.class, UserDao.class})
+@Sql(scripts = "classpath:cleanup-database.sql",
+        executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, config = @SqlConfig
+        (transactionMode = SqlConfig.TransactionMode.ISOLATED,
+                transactionManager = "transactionManager",
+                dataSource = "h2DataSource"))
+public abstract class AbstractBaseDao {
+
+
+}
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/BaseDaoTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/BaseDaoTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..71c9679f38fa0d328b74e43e7d4f0b85655d6897
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/BaseDaoTest.java
@@ -0,0 +1,203 @@
+package eu.europa.ec.edelivery.smp.data.dao;
+
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Parameter;
+import javax.persistence.PersistenceContext;
+import javax.persistence.criteria.*;
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ *  Purpose of class is to test implemented methods of BaseDao on DomainDao instance.
+ *
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+public class BaseDaoTest extends AbstractBaseDao {
+
+
+    @Autowired
+    DomainDao testInstance;
+
+    @PersistenceContext
+    protected EntityManager memEManager;
+
+    @Test
+    public void testSelectAndCountResult() {
+        // given
+        TestFilter filter = null;
+        Class cls = DBDomain.class;
+        // when
+        CriteriaQuery res = testInstance.createSearchCriteria(filter, cls, false, null, null);
+        //Then
+        Assert.assertNotNull(res);
+        Assert.assertNull(res.getSelection());
+
+        // when
+        res = testInstance.createSearchCriteria(filter, cls, true, null, null);
+        //Then
+        Assert.assertNotNull(res);
+        Assert.assertNotNull(res.getSelection());
+        Assert.assertEquals(java.lang.Long.class, res.getSelection().getJavaType());
+    }
+
+    @Test
+    public void testFilterEmpty() {
+        // given
+        TestFilter filter = new TestFilter();
+        Class cls = DBDomain.class;
+        // when
+        CriteriaQuery res = testInstance.createSearchCriteria(filter, cls, false, null, null);
+        //Then
+        Assert.assertNotNull(res);
+        Assert.assertEquals(0,res.getParameters().size() );
+    }
+
+    @Test
+    public void testPredicatesStringValue() {
+        // given
+        TestFilter filter = new TestFilter();
+        String filterValue = "TestValue";
+        filter.setDomainCode("TestValue");
+
+        CriteriaBuilder cb = memEManager.getCriteriaBuilder();
+        CriteriaQuery<DBDomain> cq = cb.createQuery(DBDomain.class);
+        Root<DBDomain> om = cq.from(DBDomain.class);
+        Predicate expected = cb.equal(testInstance.getPath(om, "DomainCode"), filterValue);
+
+        // when
+        List<Predicate> lst = testInstance.createPredicates(filter,om,cb );
+
+        //Then
+        Assert.assertNotNull(lst);
+        Assert.assertEquals(1,lst.size() );
+    }
+
+    @Test
+    public void testPredicatesStringListValue() {
+        // given
+        TestFilter filter = new TestFilter();
+        List<String > filterValue  = Collections.singletonList("TestValue");
+        filter.setDomainCodeList(filterValue);
+
+        CriteriaBuilder cb = memEManager.getCriteriaBuilder();
+        CriteriaQuery<DBDomain> cq = cb.createQuery(DBDomain.class);
+        Root<DBDomain> om = cq.from(DBDomain.class);
+        Predicate expected = cb.equal(testInstance.getPath(om, "DomainCodeList", "List"), filterValue);
+
+        // when
+        List<Predicate> lst = testInstance.createPredicates(filter,om,cb );
+
+        //Then
+        Assert.assertNotNull(lst);
+        Assert.assertEquals(1,lst.size() );
+    }
+
+    @Test
+    public void testPredicatesStringLikeValue() {
+        // given
+        TestFilter filter = new TestFilter();
+        String filterValue = "TestValue";
+        filter.setDomainCodeLike(filterValue);
+
+        CriteriaBuilder cb = memEManager.getCriteriaBuilder();
+        CriteriaQuery<DBDomain> cq = cb.createQuery(DBDomain.class);
+        Root<DBDomain> om = cq.from(DBDomain.class);
+        Predicate expected = cb.equal(testInstance.getPath(om, "DomainCodeLike", "Like"), filterValue);
+
+        // when
+        List<Predicate> lst = testInstance.createPredicates(filter,om,cb );
+
+        //Then
+        Assert.assertNotNull(lst);
+        Assert.assertEquals(1,lst.size() );
+    }
+
+    @Test
+    public void testPredicatesLong() {
+        // given
+        TestFilter filter = new TestFilter();
+        Long filterValue = (long)10;
+        filter.setId(filterValue);
+
+        CriteriaBuilder cb = memEManager.getCriteriaBuilder();
+        CriteriaQuery<DBDomain> cq = cb.createQuery(DBDomain.class);
+        Root<DBDomain> om = cq.from(DBDomain.class);
+        Predicate expected = cb.equal(testInstance.getPath(om, "Id"), filterValue);
+
+        // when
+        List<Predicate> lst = testInstance.createPredicates(filter,om,cb );
+
+        //Then
+        Assert.assertNotNull(lst);
+        Assert.assertEquals(1,lst.size() );
+    }
+
+
+
+
+}
+class TestFilter {
+    String domainCode;
+    String domainCodeLike;
+    Long  id;
+    Long idFrom;
+    Long idTo;
+    List<String> domainCodeList;
+
+    public String getDomainCode() {
+        return domainCode;
+    }
+
+    public void setDomainCode(String domainCode) {
+        this.domainCode = domainCode;
+    }
+
+    public String getDomainCodeLike() {
+        return domainCodeLike;
+    }
+
+    public void setDomainCodeLike(String domainCodeLike) {
+        this.domainCodeLike = domainCodeLike;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getIdFrom() {
+        return idFrom;
+    }
+
+    public void setIdFrom(Long idFrom) {
+        this.idFrom = idFrom;
+    }
+
+    public Long getIdTo() {
+        return idTo;
+    }
+
+    public void setIdTo(Long idTo) {
+        this.idTo = idTo;
+    }
+
+    public List<String> getDomainCodeList() {
+        return domainCodeList;
+    }
+
+    public void setDomainCodeList(List<String> domainCodeList) {
+        this.domainCodeList = domainCodeList;
+    }
+}
\ No newline at end of file
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoIntegrationTest.java
index 082bdd1d85a49cb9e2525594a54238c69363befc..413448452226257d79c8124b0d24577db7ae2bce 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoIntegrationTest.java
@@ -24,14 +24,7 @@ import static org.junit.Assert.*;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {H2JPATestConfiguration.class, DomainDao.class})
-@Sql(scripts = "classpath:cleanup-database.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, config = @SqlConfig
-        (transactionMode = SqlConfig.TransactionMode.ISOLATED,
-                transactionManager = "transactionManager",
-                dataSource = "h2DataSource"))
-public class DomainDaoIntegrationTest {
+public class DomainDaoIntegrationTest extends AbstractBaseDao {
 
     @Autowired
     DomainDao testInstance;
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationBase.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationBase.java
index 9f3582fb152e40378ce5433b862812602c6a022a..af6e2beb987aa41d427538cac30be3e7aa93314d 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationBase.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationBase.java
@@ -25,12 +25,8 @@ import static eu.europa.ec.edelivery.smp.testutil.TestConstants.*;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-@ContextConfiguration(classes = {H2JPATestConfiguration.class, ServiceGroupDao.class, DomainDao.class, UserDao.class})
-@Sql(scripts = "classpath:cleanup-database.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, config = @SqlConfig
-        (transactionMode = SqlConfig.TransactionMode.ISOLATED,
-                transactionManager = "transactionManager",
-                dataSource = "h2DataSource"))
-public class ServiceGroupDaoIntegrationBase {
+
+public abstract class ServiceGroupDaoIntegrationBase extends AbstractBaseDao{
     @Autowired
     ServiceGroupDao testInstance;
 
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationTest.java
index d10dc9696a9da7ecd8d2272a7055e0b1a48a3065..a59b51b753c51a4a41188f8c761d5f173dc05659 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoIntegrationTest.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.*;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-@RunWith(SpringJUnit4ClassRunner.class)
 public class ServiceGroupDaoIntegrationTest extends ServiceGroupDaoIntegrationBase {
 
     @Test
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoMetadataIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoMetadataIntegrationTest.java
index efcac9f16095a87c6c698f5ec120f3c6492fe004..86c1527ce90a32bcfe275603bf93bdf75bd1133a 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoMetadataIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoMetadataIntegrationTest.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.*;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-@RunWith(SpringJUnit4ClassRunner.class)
 public class ServiceGroupDaoMetadataIntegrationTest extends ServiceGroupDaoIntegrationBase {
 
 
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoOwnershipIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoOwnershipIntegrationTest.java
index 9c5a93a3377d61ea17ce6f2a32ccf5053467196d..fce192d71160267ad5ad255480518617cf7e6728 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoOwnershipIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDaoOwnershipIntegrationTest.java
@@ -22,7 +22,6 @@ import static org.junit.Assert.*;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-@RunWith(SpringJUnit4ClassRunner.class)
 public class ServiceGroupDaoOwnershipIntegrationTest extends ServiceGroupDaoIntegrationBase {
 
 
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceMetadataDaoIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceMetadataDaoIntegrationTest.java
index 70db93f7c735f58026d7f1e9341f2e4f72d9e3de..8ef4e1198fb7f5a880e51d50f8b2333f18e9e1c1 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceMetadataDaoIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ServiceMetadataDaoIntegrationTest.java
@@ -32,15 +32,7 @@ import static org.junit.Assert.assertTrue;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {H2JPATestConfiguration.class, ServiceMetadataDao.class, DomainDao.class, UserDao.class,
-        ServiceGroupDao.class})
-@Sql(scripts = "classpath:cleanup-database.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, config = @SqlConfig
-        (transactionMode = SqlConfig.TransactionMode.ISOLATED,
-                transactionManager = "transactionManager",
-                dataSource = "h2DataSource"))
-public class ServiceMetadataDaoIntegrationTest {
+public class ServiceMetadataDaoIntegrationTest extends AbstractBaseDao {
 
     @Autowired
     ServiceMetadataDao testInstance;
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java
index 65a6a4c1735be199b97fefdcef76972c615f14ee..746ba3d83a2fb616dc1987193db58f485ad06eea 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java
@@ -28,13 +28,7 @@ import static org.junit.Assert.*;
  * @author Joze Rihtarsic
  * @since 4.1
  */
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {H2JPATestConfiguration.class, UserDao.class})
-@Sql(scripts = "classpath:cleanup-database.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, config = @SqlConfig
-        (transactionMode = SqlConfig.TransactionMode.ISOLATED,
-                transactionManager = "transactionManager",
-                dataSource = "h2DataSource"))
-public class UserDaoIntegrationTest {
+public class UserDaoIntegrationTest extends AbstractBaseDao{
 
     @Autowired
     UserDao testInstance;
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceIntegrationTest.java
index 8ff10cc252ea76f03b3b7f6923f7b809a07520b6..74a1277eb7daed99162a9eb4d55ae7476ea55a4f 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceIntegrationTest.java
@@ -42,7 +42,7 @@ public class UIDomainServiceIntegrationTest extends AbstractServiceIntegrationTe
         // given
 
         //when
-        ServiceResult<DomainRO> res = testInstance.getTableList(-1,-1,null, null);
+        ServiceResult<DomainRO> res = testInstance.getTableList(-1,-1,null, null, null);
         // then
         assertNotNull(res);
         assertEquals(0, res.getCount().intValue());
@@ -58,7 +58,7 @@ public class UIDomainServiceIntegrationTest extends AbstractServiceIntegrationTe
         // given
         insertDataObjects(15);
         //when
-        ServiceResult<DomainRO> res = testInstance.getTableList(-1,-1,null, null);
+        ServiceResult<DomainRO> res = testInstance.getTableList(-1,-1,null, null,null);
 
 
         // then
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java
index fd5ae27e83e6f39bd9f0a70924147153ef5147e0..6813cda9ce64df381f85c52db54c290aec982491 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupServiceIntegrationTest.java
@@ -43,7 +43,7 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
         // given
 
         //when
-        ServiceResult<ServiceGroupRO> res = testInstance.getTableList(-1,-1,null, null);
+        ServiceResult<ServiceGroupRO> res = testInstance.getTableList(-1,-1,null, null,null);
         // then
         assertNotNull(res);
         assertEquals(0, res.getCount().intValue());
@@ -59,7 +59,7 @@ public class UIServiceGroupServiceIntegrationTest extends AbstractServiceIntegra
         // given
         insertDataObjects(15);
         //when
-        ServiceResult<ServiceGroupRO> res = testInstance.getTableList(-1,-1,null, null);
+        ServiceResult<ServiceGroupRO> res = testInstance.getTableList(-1,-1,null, null, null);
 
 
         // then
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java
index 9cf69b392ff3900fbc2ae7cbe97dcee83acf838e..4950f5255efad8589205b4539330c504e7bf4781 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java
@@ -42,7 +42,7 @@ public class UIUserServiceIntegrationTest extends AbstractServiceIntegrationTest
         // given
 
         //when
-        ServiceResult<UserRO> res = testInstance.getTableList(-1,-1,null, null);
+        ServiceResult<UserRO> res = testInstance.getTableList(-1,-1,null, null,null);
         // then
         assertNotNull(res);
         assertEquals(0, res.getCount().intValue());
@@ -58,7 +58,7 @@ public class UIUserServiceIntegrationTest extends AbstractServiceIntegrationTest
         // given
         insertDataObjects(15);
         //when
-        ServiceResult<UserRO> res = testInstance.getTableList(-1,-1,null, null);
+        ServiceResult<UserRO> res = testInstance.getTableList(-1,-1,null, null,null);
 
 
         // then
diff --git a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data-mysql.sql b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data-mysql.sql
index 234487b72d4bdef7fe9796720ea9f112cc5c4113..9f1bcf7ed1cacc10e328a2579ccd5b34e333429a 100644
--- a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data-mysql.sql
+++ b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data-mysql.sql
@@ -36,6 +36,17 @@ insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_O
 insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (19, 'SMP_1000000181,O=DIGIT,C=DK:123456789', '$2a$10$v2d/2E99dWHBM2ipTIip1enyaRKBTi.Xj/Iz0K8g0gjHBWdKRsHaC', 'SMP_ADMIN', 1, NOW(), NOW());
 insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (19, 'CN=SMP_1000000181,O=DIGIT,C=DK:123456789', null,null, NOW(), NOW());
 
+update SMP_USER_SEQ set next_val=100 where next_val=1;
+
+
 -- insert domain
 insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (1, 'domain','subdomain','sig-key', NOW(), NOW());
-
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (2, 'domainB','subdomain002', 'CEF-SMP-002','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (3, 'domainC','subdomain003', 'CEF-SMP-003','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (4, 'domainD','subdomain004', 'CEF-SMP-004','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (5, 'domainE','subdomain005', 'CEF-SMP-005','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (6, 'domainF','subdomain006', 'CEF-SMP-006','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (7, 'domainG','subdomain007', 'CEF-SMP-007','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (8, 'domainH','subdomain008', 'CEF-SMP-008','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (9, 'domainI','subdomain009', 'CEF-SMP-009','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+update SMP_DOMAIN_SEQ set next_val=100 where next_val=1;
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java
index 4856b6c9bb79a5c9bf967005ff5e796b0226ec2f..d496bb6c9a1557714d88ab5ee22927d26b923e09 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java
@@ -38,15 +38,22 @@ public class SmpWebAppConfig implements WebMvcConfigurer {
     @Override
     public void addViewControllers(ViewControllerRegistry registry) {
         registry.addViewController("/").setViewName("/index.html");
+        registry.addRedirectViewController("/ui/","/ui/index.html");
+
         //Home page used by SMP 2.x and 3.x - needed for backward compatibility in some EC's environments
         registry.addViewController("/web/index.html").setViewName("/index.html");
     }
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
+
         registry.setOrder(HIGHEST_PRECEDENCE)
-                .addResourceHandler("/index.html", "/favicon-16x16.png")
-                .addResourceLocations("/static_resources/");
+                .addResourceHandler("/index.html", "/favicon-16x16.png").addResourceLocations("/static_resources/");
+
+        registry.setOrder(HIGHEST_PRECEDENCE-2)
+                .addResourceHandler("/ui/rest/").addResourceLocations("/"); // ui rest resources
+        registry.setOrder(HIGHEST_PRECEDENCE-3)
+                .addResourceHandler("/ui/**").addResourceLocations("/ui/"); // angular pages
     }
 
     @Override
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
index 0d114eabd3531bee70ea065e7bb982babfac0d3b..909a0d78653d8c083bc067fd2e59449a6b7bff24 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
@@ -15,12 +15,16 @@ package eu.europa.ec.edelivery.smp.controllers;
 
 import eu.europa.ec.edelivery.smp.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.logging.SMPMessageCode;
 import eu.europa.ec.edelivery.smp.services.ServiceGroupService;
 import eu.europa.ec.edelivery.smp.services.ServiceMetadataService;
 import eu.europa.ec.edelivery.smp.validation.ServiceGroupValidator;
 import eu.europa.ec.smp.api.Identifiers;
 import eu.europa.ec.smp.api.exceptions.XmlInvalidAgainstSchemaException;
 import eu.europa.ec.smp.api.validators.BdxSmpOasisValidator;
+import org.apache.commons.lang.StringUtils;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.DocumentIdentifier;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.ParticipantIdentifierType;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.ServiceGroup;
@@ -29,14 +33,20 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpHeaders;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.annotation.Secured;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
 import java.util.List;
 
+import static eu.europa.ec.edelivery.smp.controllers.WebConstans.HTTP_PARAM_DOMAIN;
+import static eu.europa.ec.edelivery.smp.controllers.WebConstans.HTTP_PARAM_OWNER;
 import static eu.europa.ec.smp.api.Identifiers.asParticipantId;
+import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
 import static org.springframework.http.ResponseEntity.created;
 import static org.springframework.http.ResponseEntity.ok;
 
@@ -46,10 +56,9 @@ import static org.springframework.http.ResponseEntity.ok;
 
 @RestController
 @RequestMapping("/{serviceGroupId}")
-@Order
 public class ServiceGroupController {
 
-    private static final Logger log = LoggerFactory.getLogger(ServiceGroupController.class);
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ServiceGroupController.class);
 
     @Autowired
     private ServiceGroupValidator serviceGroupValidator;
@@ -65,26 +74,29 @@ public class ServiceGroupController {
 
 
     @GetMapping(produces = "text/xml; charset=UTF-8")
-    public ServiceGroup getServiceGroup(@PathVariable String serviceGroupId) {
-        log.info("GET ServiceGrooup: {}", serviceGroupId);
+    public ServiceGroup getServiceGroup(HttpServletRequest httpReq, @PathVariable String serviceGroupId) {
+        String host = httpReq.getRemoteHost();
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_GET_SERVICE_GROUP,host, serviceGroupId);
 
         ServiceGroup serviceGroup = serviceGroupService.getServiceGroup(asParticipantId(serviceGroupId));
         addReferences(serviceGroup);
 
-        log.info("Finished GET ServiceGrooup: {}", serviceGroupId);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_GET_END_SERVICE_GROUP,host, serviceGroupId);
         return serviceGroup;
     }
 
 
     @PutMapping
     @Secured({SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_SMP_ADMIN})
-    public ResponseEntity saveServiceGroup(
+    public ResponseEntity saveServiceGroup(HttpServletRequest httpReq,
             @PathVariable String serviceGroupId,
-            @RequestHeader(name = "ServiceGroup-Owner", required = false) String serviceGroupOwner,
-            @RequestHeader(name = "Domain", required = false) String domain,
+            @RequestHeader(name = HTTP_PARAM_OWNER, required = false) String serviceGroupOwner,
+            @RequestHeader(name = HTTP_PARAM_DOMAIN, required = false) String domain,
             @RequestBody byte[] body) throws XmlInvalidAgainstSchemaException {
 
-        log.info("PUT ServiceGroup: {} domain {} owner {} \n{}", serviceGroupId,domain, serviceGroupOwner, new String(body));
+        String authentUser = SecurityContextHolder.getContext().getAuthentication().getName();
+        String host = getRemoteHost(httpReq);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_PUT_SERVICE_GROUP,authentUser, host, serviceGroupOwner, domain, serviceGroupId);
 
         // Validations
         BdxSmpOasisValidator.validateXSD(body);
@@ -92,23 +104,24 @@ public class ServiceGroupController {
         serviceGroupValidator.validate(serviceGroupId, serviceGroup);
 
         // Service action
-         boolean newServiceGroupCreated = serviceGroupService.saveServiceGroup(serviceGroup, domain, serviceGroupOwner, SecurityContextHolder.getContext().getAuthentication().getName());
-
-        log.info("Finished PUT ServiceGroup: {}", serviceGroupId);
+         boolean newServiceGroupCreated = serviceGroupService.saveServiceGroup(serviceGroup, domain, serviceGroupOwner, authentUser);
 
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_PUT_SERVICE_GROUP,authentUser, host, serviceGroupOwner, domain, serviceGroupId, newServiceGroupCreated);
         return newServiceGroupCreated ? created(pathBuilder.getCurrentUri()).build() : ok().build();
     }
 
     @DeleteMapping
     @Secured({SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_SMP_ADMIN})
-    public void deleteServiceGroup(@PathVariable String serviceGroupId) {
+    public void deleteServiceGroup(HttpServletRequest httpReq, @PathVariable String serviceGroupId) {
+        String authentUser = SecurityContextHolder.getContext().getAuthentication().getName();
+        String host = getRemoteHost(httpReq);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_DELETE_SERVICE_GROUP,authentUser, host, serviceGroupId);
 
-        log.info("DELETE ServiceGroup: {}", serviceGroupId);
 
         final ParticipantIdentifierType aServiceGroupID = Identifiers.asParticipantId(serviceGroupId);
         serviceGroupService.deleteServiceGroup(aServiceGroupID);
 
-        log.info("Finished DELETE ServiceGroup: {}", serviceGroupId);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_DELETE_END_SERVICE_GROUP,authentUser, host, serviceGroupId);
     }
 
     private void addReferences(ServiceGroup serviceGroup) {
@@ -121,4 +134,9 @@ public class ServiceGroupController {
         }
     }
 
+    public String getRemoteHost(HttpServletRequest httpReq){
+        String host = httpReq.getHeader("X-Forwarded-For");
+        return StringUtils.isBlank(host)?httpReq.getRemoteHost():host;
+    }
+
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java
index 9843cee5059c508869c47b6d4c54033759bfa47a..9a8c649d9bc368933786da34b320004f25df64df 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java
@@ -14,21 +14,28 @@
 package eu.europa.ec.edelivery.smp.controllers;
 
 import eu.europa.ec.edelivery.smp.conversion.ServiceMetadataConverter;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.logging.SMPMessageCode;
 import eu.europa.ec.edelivery.smp.services.ServiceGroupService;
 import eu.europa.ec.edelivery.smp.services.ServiceMetadataService;
 import eu.europa.ec.edelivery.smp.validation.ServiceMetadataValidator;
 import eu.europa.ec.smp.api.exceptions.XmlInvalidAgainstSchemaException;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.bind.annotation.*;
 import org.w3c.dom.Document;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.xml.transform.TransformerException;
 import java.io.UnsupportedEncodingException;
 
+import static eu.europa.ec.edelivery.smp.controllers.WebConstans.HTTP_PARAM_DOMAIN;
 import static eu.europa.ec.smp.api.Identifiers.asDocumentId;
 import static eu.europa.ec.smp.api.Identifiers.asParticipantId;
 import static org.springframework.http.ResponseEntity.created;
@@ -41,7 +48,7 @@ import static org.springframework.http.ResponseEntity.ok;
 @RequestMapping("/{serviceGroupId}/services/{serviceMetadataId}")
 public class ServiceMetadataController {
 
-    private static final Logger log = LoggerFactory.getLogger(ServiceMetadataController.class);
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ServiceGroupController.class);
 
     @Autowired
     private ServiceMetadataValidator serviceMetadataValidator;
@@ -56,33 +63,37 @@ public class ServiceMetadataController {
     private ServiceMetadataPathBuilder pathBuilder;
 
     @GetMapping(produces = "text/xml; charset=UTF-8")
-    public String getServiceMetadata(@PathVariable String serviceGroupId,
+    public String getServiceMetadata(HttpServletRequest httpReq,
+                                     @PathVariable String serviceGroupId,
                                      @PathVariable String serviceMetadataId) throws TransformerException, UnsupportedEncodingException {
 
-        log.info("GET ServiceMetadata: {} - {}", serviceGroupId, serviceMetadataId);
+        String host = httpReq.getRemoteHost();
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_GET_SERVICE_METADATA,host, serviceGroupId, serviceMetadataId);
 
         Document serviceMetadata = serviceMetadataService.getServiceMetadataDocument(asParticipantId(serviceGroupId), asDocumentId(serviceMetadataId));
 
-        log.info("GET ServiceMetadata finished: {} - {}", serviceGroupId, serviceMetadataId);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_GET_END_SERVICE_METADATA,host, serviceGroupId, serviceMetadataId);
         return ServiceMetadataConverter.toString(serviceMetadata);
     }
 
     @PutMapping
     @PreAuthorize("hasAnyAuthority(T(eu.europa.ec.edelivery.smp.auth.SMPAuthority).S_AUTHORITY_SMP_ADMIN) OR" +
             " @serviceGroupService.isServiceGroupOwner(authentication.name, #serviceGroupId)")
-    public ResponseEntity saveServiceMetadata(
+    public ResponseEntity saveServiceMetadata(HttpServletRequest httpReq,
             @PathVariable String serviceGroupId,
             @PathVariable String serviceMetadataId,
-            @RequestHeader(name = "Domain", required = false) String domain,
+            @RequestHeader(name = HTTP_PARAM_DOMAIN, required = false) String domain,
             @RequestBody byte[] body) throws XmlInvalidAgainstSchemaException {
 
-        log.info("PUT ServiceMetadata: {} - {}\n{}", serviceGroupId, serviceMetadataId, new String(body));
+        String authentUser = SecurityContextHolder.getContext().getAuthentication().getName();
+        String host = getRemoteHost(httpReq);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_PUT_SERVICE_METADATA,authentUser, host, domain, serviceGroupId, serviceMetadataId);
 
         serviceMetadataValidator.validate(serviceGroupId, serviceMetadataId, body);
 
         boolean newServiceMetadataCreated = serviceMetadataService.saveServiceMetadata(domain, asParticipantId(serviceGroupId), asDocumentId(serviceMetadataId), body);
 
-        log.info("PUT ServiceMetadata finished: {} - {}", serviceGroupId, serviceMetadataId);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_PUT_END_SERVICE_METADATA,authentUser, host, domain, serviceGroupId, serviceMetadataId, newServiceMetadataCreated);
 
         return newServiceMetadataCreated ? created(pathBuilder.getCurrentUri()).build() : ok().build();
     }
@@ -90,15 +101,24 @@ public class ServiceMetadataController {
     @DeleteMapping
      @PreAuthorize("hasAnyAuthority(T(eu.europa.ec.edelivery.smp.auth.SMPAuthority).S_AUTHORITY_SMP_ADMIN) OR" +
               " @serviceGroupService.isServiceGroupOwner(authentication.name, #serviceGroupId)")
-    public ResponseEntity deleteServiceMetadata(@PathVariable String serviceGroupId,
-                                                @PathVariable String serviceMetadataId,
-                                                @RequestHeader(name = "Domain", required = false) String domain ) {
-        log.info("DELETE ServiceMetadata: {} - {}", serviceGroupId, serviceMetadataId);
+    public ResponseEntity deleteServiceMetadata(HttpServletRequest httpReq,
+                                  @PathVariable String serviceGroupId,
+                                  @PathVariable String serviceMetadataId,
+                                  @RequestHeader(name = "Domain", required = false) String domain ) {
 
-        serviceMetadataService.deleteServiceMetadata(domain, asParticipantId(serviceGroupId), asDocumentId(serviceMetadataId));
 
-        log.info("DELETE ServiceMetadata finished: {} - {}", serviceGroupId, serviceMetadataId);
+        String authentUser = SecurityContextHolder.getContext().getAuthentication().getName();
+        String host = getRemoteHost(httpReq);
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_DELETE_SERVICE_METADATA,authentUser, host, domain, serviceGroupId, serviceMetadataId);
+
+        serviceMetadataService.deleteServiceMetadata(domain, asParticipantId(serviceGroupId), asDocumentId(serviceMetadataId));
 
+        LOG.businessInfo(SMPMessageCode.BUS_HTTP_DELETE_END_SERVICE_METADATA,authentUser, host, domain, serviceGroupId, serviceMetadataId);
         return ok().build();
     }
+
+    public String getRemoteHost(HttpServletRequest httpReq){
+        String host = httpReq.getHeader("X-Forwarded-For");
+        return StringUtils.isBlank(host)?httpReq.getRemoteHost():host;
+    }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/WebConstans.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/WebConstans.java
new file mode 100644
index 0000000000000000000000000000000000000000..6efab566c3a1df31ddfe0ec7e916f29aad8c57da
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/WebConstans.java
@@ -0,0 +1,7 @@
+package eu.europa.ec.edelivery.smp.controllers;
+
+public class WebConstans {
+
+    public static final String HTTP_PARAM_DOMAIN="Domain";
+    public static final String HTTP_PARAM_OWNER="ServiceGroup-Owner";
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..397288592f1c495e4f85a4601e30070a509a9dbf
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java
@@ -0,0 +1,39 @@
+package eu.europa.ec.edelivery.smp.ui;
+
+
+import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.services.ui.UIServiceGroupService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+
+@RestController
+@RequestMapping(value = "/ui/rest/application")
+public class ApplicationResource {
+
+    @Autowired
+    private Environment env;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationResource.class);
+
+
+    @RequestMapping(method = RequestMethod.GET, path = "name")
+    public  String getName() {
+        return "SMP TEST";
+    }
+
+    @RequestMapping(method = RequestMethod.GET, path = "rootContext")
+    public  String getRootContext() {
+        return env  .getProperty("server.contextPath", "/");
+    }
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
index 9b4d36b033a5854653bf9ed1aad062beb03ace58..7e9fff5b4c4a3aa25a959ce795708cbd32e8be88 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
@@ -3,6 +3,8 @@ package eu.europa.ec.edelivery.smp.ui;
 
 import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UIDomainService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -10,6 +12,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.PostConstruct;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * @author Joze Rihtarsic
@@ -17,10 +21,10 @@ import javax.annotation.PostConstruct;
  */
 
 @RestController
-@RequestMapping(value = "/ui/domain")
+@RequestMapping(value = "/ui/rest/domain")
 public class DomainResource {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainResource.class);
 
     @Autowired
     private UIDomainService uiDomainService;
@@ -33,15 +37,20 @@ public class DomainResource {
     @PutMapping(produces = {"application/json"})
     @ResponseBody
     @RequestMapping(method = RequestMethod.GET)
-    public ServiceResult<DomainRO> getServiceGroupList(
+    public ServiceResult<DomainRO> geDomainList(
             @RequestParam(value = "page", defaultValue = "0") int page,
             @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
             @RequestParam(value = "orderBy", required = false) String orderBy,
             @RequestParam(value = "orderType", defaultValue = "asc", required = false) String orderType,
             @RequestParam(value = "user", required = false) String user
             ) {
+        return uiDomainService.getTableList(page,pageSize, orderBy, orderType, null );
+    }
 
-
-        return uiDomainService.getTableList(page,pageSize, orderBy, orderType );
+    @PutMapping(produces = {"application/json"})
+    @RequestMapping(method = RequestMethod.PUT)
+    public void updateDomainList(@RequestBody(required = true) DomainRO [] updateEntities ){
+        LOG.info("GOT LIST OF DomainRO to UPDATE: " + updateEntities.length);
+        uiDomainService.updateDomainList(Arrays.asList(updateEntities));
     }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/SearchResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/SearchResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..64ff10bfb4136947a141de31d20269bcbc74debc
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/SearchResource.java
@@ -0,0 +1,57 @@
+package eu.europa.ec.edelivery.smp.ui;
+
+
+import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.services.ui.UIServiceGroupService;
+import eu.europa.ec.edelivery.smp.ui.filters.ServiceGroupFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+
+@RestController
+@RequestMapping(value = "/ui/rest/search")
+public class SearchResource {
+
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SearchResource.class);
+
+    @Autowired
+    private UIServiceGroupService uiServiceGroupService;
+
+    @PostConstruct
+    protected void init() {
+
+    }
+
+    @PutMapping(produces = {"application/json"})
+    @ResponseBody
+    @RequestMapping(method = RequestMethod.GET)
+    public  ServiceResult<ServiceGroupRO> getServiceGroupList(
+            @RequestParam(value = "page", defaultValue = "0") int page,
+            @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
+            @RequestParam(value = "orderBy", required = false) String orderBy,
+            @RequestParam(value = "orderType", defaultValue = "asc", required = false) String orderType,
+            @RequestParam(value = "participantIdentifier", required = false) String participantIdentifier,
+            @RequestParam(value = "participantScheme", required = false) String participantScheme,
+            @RequestParam(value = "domain", required = false) String domain
+            ) {
+
+        LOG.info("Search for page: {}, page size: {}, part. id: {}, part sch: {}, domain {}",page, pageSize, participantIdentifier, participantScheme, domain );
+        ServiceGroupFilter sgf = new ServiceGroupFilter();
+        sgf.setParticipantIdentifierLike(participantIdentifier);
+        sgf.setParticipantSchemeLike(participantScheme);
+
+
+        return uiServiceGroupService.getTableList(page,pageSize, orderBy, orderType, sgf );
+    }
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
index b2fc0ae7d28dbc9210b1424ef61b9ebc3b7b5ea5..f28b7c3dc531d8414551d4f32d7c302ac02b5e87 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
@@ -17,7 +17,7 @@ import javax.annotation.PostConstruct;
  */
 
 @RestController
-@RequestMapping(value = "/ui/servicegroup")
+@RequestMapping(value = "/ui/rest/servicegroup")
 public class ServiceGroupResource {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ServiceGroupResource.class);
@@ -40,10 +40,10 @@ public class ServiceGroupResource {
             @RequestParam(value = "orderType", defaultValue = "asc", required = false) String orderType,
             @RequestParam(value = "participantId", required = false) String participantId,
             @RequestParam(value = "participantSchema", required = false) String participantSchema,
-            @RequestParam(value = "domain", required = false) String domainwe
+            @RequestParam(value = "domain", required = false) String domain
             ) {
 
 
-        return uiServiceGroupService.getTableList(page,pageSize, orderBy, orderType );
+        return uiServiceGroupService.getTableList(page,pageSize, orderBy, orderType, null );
     }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java
index 1d8f8a4956b988e909743dd45e22dc0bc87242b9..0898cbec527ef683db4b5392a918f1e48c76f7b1 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java
@@ -17,7 +17,7 @@ import javax.annotation.PostConstruct;
  */
 
 @RestController
-@RequestMapping(value = "/ui/user")
+@RequestMapping(value = "/ui/rest/user")
 public class UserResource {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
@@ -42,6 +42,6 @@ public class UserResource {
             ) {
 
 
-        return  uiUserService.getTableList(page,pageSize, orderBy, orderType );
+        return  uiUserService.getTableList(page,pageSize, orderBy, orderType, null);
     }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/filters/ServiceGroupFilter.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/filters/ServiceGroupFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e2fa893ed94f3dbba4fd4eeb41528e51bd900da
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/filters/ServiceGroupFilter.java
@@ -0,0 +1,22 @@
+package eu.europa.ec.edelivery.smp.ui.filters;
+
+public class ServiceGroupFilter {
+    private String participantIdentifier;
+    private String participantScheme;
+
+    public String getParticipantIdentifierLike() {
+        return participantIdentifier;
+    }
+
+    public void setParticipantIdentifierLike(String participantIdentifier) {
+        this.participantIdentifier = participantIdentifier;
+    }
+
+    public String getParticipantSchemeLike() {
+        return participantScheme;
+    }
+
+    public void setParticipantSchemeLike(String participantScheme) {
+        this.participantScheme = participantScheme;
+    }
+}
diff --git a/smp-webapp/src/test/resources/webapp_integration_test_data.sql b/smp-webapp/src/test/resources/webapp_integration_test_data.sql
index a9b2cfbba6a0980b926c91e191e6aebb593f40ae..c049c0018ab9fee8ef31e7d041e2ae8c32b61350 100644
--- a/smp-webapp/src/test/resources/webapp_integration_test_data.sql
+++ b/smp-webapp/src/test/resources/webapp_integration_test_data.sql
@@ -25,8 +25,9 @@ insert into SMP_SERVICE_GROUP(ID, PARTICIPANT_IDENTIFIER, PARTICIPANT_SCHEME,SML
 insert into SMP_SERVICE_GROUP(ID, PARTICIPANT_IDENTIFIER, PARTICIPANT_SCHEME,SML_REGISTRED, CREATED_ON, LAST_UPDATED_ON) values (200000, 'urn:brazil:ncpb', 'ehealth-actorid-qns', 1,CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
 --insert into SMP_SERVICE_GROUP(ID, PARTICIPANT_IDENTIFIER, PARTICIPANT_SCHEME,SML_REGISTRED) values (3, 'urn:poland:ncpb', 'ehealth-participantid-qns', 1);
 
-insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (1, 'domain','subdomain','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
---insert into SMP_OWNERSHIP (FK_SG_ID, FK_USER_ID) values (3, 1);
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, CREATED_ON, LAST_UPDATED_ON) values (1, 'domain','subdomain', 'CEF-SMP-001','sig-key',CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP());
+
+ --insert into SMP_OWNERSHIP (FK_SG_ID, FK_USER_ID) values (3, 1);
 --insert into SMP_SERVICE_GROUP_DOMAIN (ID, FK_SG_ID, FK_DOMAIN_ID) values (1, 3, 1);
 -- insert into smp_ownership(username, businessidentifier, businessidentifierscheme) values ('CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', 'urn:australia:ncpb', 'ehealth-actorid-qns');