From 575e165f8b5434f7738f3d41814e09da71a44974 Mon Sep 17 00:00:00 2001
From: RIHTARSIC Joze <joze.rihtarsic@ext.ec.europa.eu>
Date: Mon, 10 Apr 2023 18:17:05 +0200
Subject: [PATCH] Implement domain management

---
 smp-angular/src/_smp-all-themes.scss          |   2 +-
 smp-angular/src/app/app.module.ts             |   2 -
 .../click-stop-propagation.directive.ts       |  11 -
 .../src/app/common/enums/visibility.enum.ts   |  14 ++
 .../src/app/common/module/shared.module.ts    |  14 --
 smp-angular/src/app/guards/auth.guard.ts      |   5 -
 smp-angular/src/app/login/login.component.css |   2 +
 .../src/app/login/login.component.html        |  33 +--
 .../service-group-details-dialog.component.ts |   2 +-
 smp-angular/src/app/smp.constants.ts          |  29 ++-
 .../admin-domain/admin-domain.component.html  |  44 ++--
 .../admin-domain/admin-domain.component.ts    | 197 ++++++++++++++-
 .../admin-domain/admin-domain.service.ts      |  66 ++++-
 .../domain-panel/domain-panel.component.html  |  94 ++++---
 .../domain-panel/domain-panel.component.ts    | 104 +++++---
 .../domain-resource-type-panel.component.html |  27 +-
 .../domain-resource-type-panel.component.ts   |  61 +++--
 .../admin-domain/domain-ro.model.ts           |  20 ++
 ...omain-sml-integration-panel.component.html |  95 ++++++-
 .../domain-sml-integration-panel.component.ts | 237 +++++++++++++++++-
 .../domain/domain-controller.ts               |   3 +-
 .../domain-details-dialog.component.ts        |   2 +-
 .../domain/domain-result.model.ts             |   2 +-
 .../system-settings/domain/domain-ro.model.ts |  16 --
 .../domain/domain.component.ts                |   2 +-
 .../DBDomainToDomainROConverter.java          |   6 +
 .../ec/edelivery/smp/data/dao/BaseDao.java    |   1 -
 .../ec/edelivery/smp/data/dao/DomainDao.java  |  26 +-
 .../smp/data/dao/DomainResourceDefDao.java    |   7 +
 .../ec/edelivery/smp/data/dao/QueryNames.java |   3 +-
 .../edelivery/smp/data/dao/ResourceDao.java   |   7 +
 .../ec/edelivery/smp/data/model/DBDomain.java |  20 +-
 .../smp/data/model/doc/DBResource.java        |  33 +--
 .../edelivery/smp/data/ui/CredentialRO.java   |   2 +-
 .../ec/edelivery/smp/data/ui/DomainRO.java    |  60 +++--
 .../data/ui/DomainResourceDefinitionRO.java   |  42 ++++
 .../ec/edelivery/smp/data/ui/GroupRO.java     |  92 +++++++
 .../smp/services/ui/UIDomainService.java      | 182 ++++++++++----
 .../smp/data/dao/AbstractBaseDao.java         |   2 +-
 .../data/dao/DomainDaoIntegrationTest.java    |  34 ++-
 .../smp/services/AbstractServiceTest.java     |  15 ++
 .../ui/UIDomainServiceIntegrationTest.java    |  35 ---
 .../smp/services/ui/UIDomainServiceTest.java  | 112 +++++++++
 .../mysql-4.1_integration_test_data.sql       |   4 +-
 .../error/AbstractErrorControllerAdvice.java  |  10 +-
 .../smp/error/UIErrorControllerAdvice.java    |  11 +-
 .../smp/ui/internal/DomainAdminResource.java  | 103 +++++---
 .../smp/test/testutils/MockMvcUtils.java      |  16 ++
 .../DomainResourceIntegrationTest.java        |   4 +-
 .../DomainAdminResourceIntegrationTest.java   | 192 +++++++++++---
 .../webapp_integration_test_data.sql          |   3 +-
 51 files changed, 1636 insertions(+), 470 deletions(-)
 delete mode 100644 smp-angular/src/app/common/directive/attribute/click-stop-propagation.directive.ts
 create mode 100644 smp-angular/src/app/common/enums/visibility.enum.ts
 delete mode 100644 smp-angular/src/app/common/module/shared.module.ts
 create mode 100644 smp-angular/src/app/system-settings/admin-domain/domain-ro.model.ts
 delete mode 100644 smp-angular/src/app/system-settings/domain/domain-ro.model.ts
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainResourceDefinitionRO.java
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/GroupRO.java
 create mode 100644 smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceTest.java
 create mode 100644 smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java

diff --git a/smp-angular/src/_smp-all-themes.scss b/smp-angular/src/_smp-all-themes.scss
index 16ce626ff..bc95c360d 100644
--- a/smp-angular/src/_smp-all-themes.scss
+++ b/smp-angular/src/_smp-all-themes.scss
@@ -20,7 +20,7 @@
   }
 
   .datatable-row-odd {
-    background-color: smp.get-theme-color($theme, primary, 0.2)  !important;
+    background-color: smp.get-theme-color($theme, primary,50, 0.2)  !important;
   }
 
   .datatable-row-selected {
diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts
index d9066bee7..a0ac74f8b 100644
--- a/smp-angular/src/app/app.module.ts
+++ b/smp-angular/src/app/app.module.ts
@@ -99,7 +99,6 @@ import {ServiceGroupExtensionWizardDialogComponent} from './service-group-edit/s
 import {ServiceGroupMetadataDialogComponent} from './service-group-edit/service-group-metadata-dialog/service-group-metadata-dialog.component';
 import {ServiceGroupSearchComponent} from './service-group-search/service-group-search.component';
 import {ServiceMetadataWizardDialogComponent} from './service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component';
-import {SharedModule} from './common/module/shared.module';
 import {SidenavComponent} from './window/sidenav/sidenav.component';
 import {SmlIntegrationService} from "./system-settings/domain/sml-integration.service";
 import {SmpInfoService} from './app-info/smp-info.service';
@@ -232,7 +231,6 @@ import {
     NgxMatDatetimePickerModule,
     NgxMatMomentModule,
     ReactiveFormsModule,
-    SharedModule,
     routing,
   ],
   providers: [
diff --git a/smp-angular/src/app/common/directive/attribute/click-stop-propagation.directive.ts b/smp-angular/src/app/common/directive/attribute/click-stop-propagation.directive.ts
deleted file mode 100644
index 2b55e17de..000000000
--- a/smp-angular/src/app/common/directive/attribute/click-stop-propagation.directive.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import {Directive, HostListener} from '@angular/core';
-
-@Directive({
-  selector: "[click-stop-propagation]"
-})
-export class ClickStopPropagationDirective {
-  @HostListener("click", ["$event"])
-  public onClick(event: any): void {
-    event.preventDefault();
-  }
-}
diff --git a/smp-angular/src/app/common/enums/visibility.enum.ts b/smp-angular/src/app/common/enums/visibility.enum.ts
new file mode 100644
index 000000000..446815b94
--- /dev/null
+++ b/smp-angular/src/app/common/enums/visibility.enum.ts
@@ -0,0 +1,14 @@
+export enum VisibilityEnum {
+  /**
+   * Resource, group of domain is marked as PUBLIC.
+   */
+  Public= 'PUBLIC',
+  /**
+   * Access to the resource is within the domain/group. Users must be authenticated and must be members of the domain/group/resource in order to read it.
+   */
+  Internal= 'INTERNAL',
+  /**
+   *  Access to the resource is possible only to the resource members
+   */
+  Private= 'PRIVATE'
+}
diff --git a/smp-angular/src/app/common/module/shared.module.ts b/smp-angular/src/app/common/module/shared.module.ts
deleted file mode 100644
index 412ffe7e3..000000000
--- a/smp-angular/src/app/common/module/shared.module.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import {NgModule} from '@angular/core';
-
-import {ClickStopPropagationDirective} from 'app/common/directive/attribute/click-stop-propagation.directive';
-
-@NgModule({
-  declarations: [
-    ClickStopPropagationDirective
-  ],
-  exports: [
-    ClickStopPropagationDirective
-  ]
-})
-export class SharedModule {
-}
diff --git a/smp-angular/src/app/guards/auth.guard.ts b/smp-angular/src/app/guards/auth.guard.ts
index 278a3f716..4b8f9fc1e 100644
--- a/smp-angular/src/app/guards/auth.guard.ts
+++ b/smp-angular/src/app/guards/auth.guard.ts
@@ -10,16 +10,11 @@ export const authGuard = () => {
   const alertService = inject(AlertMessageService);
   const router = inject(Router);
 
-  console.log("guard - check for authentication: " + router.url)
-
   // test if logged in
   securityService.isAuthenticated(true).subscribe((isAuthenticated: boolean) => {
-    console.log("Refresh application configuration is authenticated " + isAuthenticated )
     if (isAuthenticated) {
-      console.log("guard - it is authenticated")
       return true;
     } else {
-      console.log("guard - it is not authenticated")
       alertService.error('You have been logged out because of inactivity or missing access permissions.', true);
       // Redirect to the login page
       navigationService.reset();
diff --git a/smp-angular/src/app/login/login.component.css b/smp-angular/src/app/login/login.component.css
index 6d50e21e7..bb1da45b6 100644
--- a/smp-angular/src/app/login/login.component.css
+++ b/smp-angular/src/app/login/login.component.css
@@ -2,3 +2,5 @@ a:link { text-decoration: none; }
 a:visited { text-decoration: none; }
 a:hover { text-decoration: none; }
 a:active { text-decoration: none; }
+
+
diff --git a/smp-angular/src/app/login/login.component.html b/smp-angular/src/app/login/login.component.html
index 338b1044e..5e74eaad3 100644
--- a/smp-angular/src/app/login/login.component.html
+++ b/smp-angular/src/app/login/login.component.html
@@ -3,44 +3,37 @@
     <mat-card *ngIf="isUserAuthSSOEnabled()  == true" fxFlex="400px" [style]="'width:400px;height:300px;margin:10px'">
       <mat-card-title>SSO Login: {{lookups.cachedApplicationInfo.ssoAuthenticationLabel}}</mat-card-title>
       <mat-card-content style="align-items: center;justify-content: center;display: flex;height: 200px;">
-        <a mat-raised-button color="primary" href="{{lookups.cachedApplicationInfo.ssoAuthenticationURI}}" [style]="'width=150px'">
+        <a mat-raised-button color="primary" href="{{lookups.cachedApplicationInfo.ssoAuthenticationURI}}"
+           [style]="'width=150px'">
           <mat-icon>input</mat-icon>
           <span> SSO Login</span>
         </a>
       </mat-card-content>
     </mat-card>
-    <mat-card *ngIf="isUserAuthPasswdEnabled() == true" fxFlex="400px" [style]="'width:400px;height:300px;margin:10px'">
+    <mat-card *ngIf="isUserAuthPasswdEnabled() == true" fxFlex="400px" [style]="'width:400px;height:300px;margin:10px;'">
       <mat-card-title>SMP Login</mat-card-title>
-      <mat-card-content style="align-items: center;justify-content: center;display: flex;height: 200px;">
+      <mat-card-content style="align-items: center;justify-content: center;display: flex;flex-direction:column; height: 200px;">
         <form name="loginForm" #loginForm="ngForm" (ngSubmit)="login()">
-          <table cellspacing="0">
-            <tr>
-              <td>
-                <mat-form-field>
+                <mat-form-field style="width: 100%">
+                  <mat-label>Username</mat-label>
                   <input matInput placeholder="Username" name="username" [(ngModel)]="model.username"
                          #username="ngModel"
-                         required id="username_id">
+                         id="username_id"
+                         auto-focus-directive
+                         required>
                 </mat-form-field>
-              </td>
-            </tr>
-            <tr>
-              <td>
-                <mat-form-field>
+                <mat-form-field style="width: 100%">
+                  <mat-label>Password</mat-label>
                   <input type="password" matInput placeholder="Password" name="password" [(ngModel)]="model.password"
                          #password="ngModel" required id="password_id">
                 </mat-form-field>
-              </td>
-            </tr>
-            <tr>
-              <td>
+
                 <button mat-raised-button color="primary" [disabled]="!loginForm.form.valid" id="loginbutton_id"
                         [style]="'width:150px'">
                   <mat-icon>input</mat-icon>
                   <span> Login</span>
                 </button>
-              </td>
-            </tr>
-          </table>
+
         </form>
       </mat-card-content>
     </mat-card>
diff --git a/smp-angular/src/app/service-group-edit/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
index 435755996..9812820ac 100644
--- a/smp-angular/src/app/service-group-edit/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
@@ -10,7 +10,7 @@ import {ServiceGroupEditRo} from "../service-group-edit-ro.model";
 import {GlobalLookups} from "../../common/global-lookups";
 import {ServiceGroupExtensionWizardDialogComponent} from "../service-group-extension-wizard-dialog/service-group-extension-wizard-dialog.component";
 import {ServiceGroupValidationRo} from "./service-group-validation-edit-ro.model";
-import {DomainRo} from "../../system-settings/domain/domain-ro.model";
+import {DomainRo} from "../../system-settings/admin-domain/domain-ro.model";
 import {ServiceGroupDomainEditRo} from "../service-group-domain-edit-ro.model";
 import {ConfirmationDialogComponent} from "../../common/dialogs/confirmation-dialog/confirmation-dialog.component";
 import {SecurityService} from "../../security/security.service";
diff --git a/smp-angular/src/app/smp.constants.ts b/smp-angular/src/app/smp.constants.ts
index cfb427ed2..fc490b5fe 100644
--- a/smp-angular/src/app/smp.constants.ts
+++ b/smp-angular/src/app/smp.constants.ts
@@ -6,7 +6,15 @@ export class SmpConstants {
   public static readonly DATE_TIME_FORMAT = 'dd/MM/yyyy HH:mm:ss z';
   public static readonly DATE_FORMAT = 'dd/MM/yyyy';
 
+
+  public static readonly PATH_ACTION_DELETE = 'delete';
+  public static readonly PATH_ACTION_UPDATE = 'update';
+  public static readonly PATH_ACTION_CREATE = 'create';
+  public static readonly PATH_ACTION_UPDATE_RESOURCE_TYPES = 'update-resource-types';
+
+  public static readonly PATH_ACTION_UPDATE_SML_INTEGRATION = 'update-sml-integration-data';
   public static readonly PATH_PARAM_ENC_USER_ID = '{user-id}';
+  public static readonly PATH_PARAM_ENC_DOMAIN_ID = '{domainr-id}';
   public static readonly PATH_PARAM_CERT_ALIAS = '{cert-alias}';
   public static readonly PATH_PARAM_ENC_CREDENTIAL_ID = '{credential-id}';
   public static readonly PATH_PARAM_ENC_MANAGED_USER_ID = '{managed-user-id}';
@@ -57,6 +65,23 @@ export class SmpConstants {
   public static readonly REST_INTERNAL_DOMAIN_MANAGE = SmpConstants.REST_INTERNAL + 'domain' +
     '/' + SmpConstants.PATH_PARAM_ENC_USER_ID;
 
+  public static readonly REST_INTERNAL_DOMAIN_MANAGE_DELETE = SmpConstants.REST_INTERNAL + 'domain' +
+    '/' + SmpConstants.PATH_PARAM_ENC_USER_ID +  '/' +SmpConstants.PATH_PARAM_ENC_DOMAIN_ID + '/' + SmpConstants.PATH_ACTION_DELETE;
+
+  public static readonly REST_INTERNAL_DOMAIN_MANAGE_UPDATE = SmpConstants.REST_INTERNAL + 'domain' +
+    '/' + SmpConstants.PATH_PARAM_ENC_USER_ID +  '/' +SmpConstants.PATH_PARAM_ENC_DOMAIN_ID + '/' + SmpConstants.PATH_ACTION_UPDATE;
+
+  public static readonly REST_INTERNAL_DOMAIN_MANAGE_CREATE = SmpConstants.REST_INTERNAL + 'domain' +
+    '/' + SmpConstants.PATH_PARAM_ENC_USER_ID +  '/' + SmpConstants.PATH_ACTION_CREATE;
+
+
+  public static readonly REST_INTERNAL_DOMAIN_MANAGE_UPDATE_SML_INTEGRATION = SmpConstants.REST_INTERNAL + 'domain' +
+    '/' + SmpConstants.PATH_PARAM_ENC_USER_ID +  '/' +SmpConstants.PATH_PARAM_ENC_DOMAIN_ID + '/' + SmpConstants.PATH_ACTION_UPDATE_SML_INTEGRATION;
+
+
+  public static readonly REST_INTERNAL_DOMAIN_MANAGE_UPDATE_RESOURCE_TYPES = SmpConstants.REST_INTERNAL + 'domain' +
+    '/' + SmpConstants.PATH_PARAM_ENC_USER_ID +  '/' +SmpConstants.PATH_PARAM_ENC_DOMAIN_ID + '/' + SmpConstants.PATH_ACTION_UPDATE_RESOURCE_TYPES;
+
   public static readonly REST_INTERNAL_EXTENSION_MANAGE = SmpConstants.REST_INTERNAL + 'extension';
   public static readonly REST_INTERNAL_PROPERTY_MANAGE = SmpConstants.REST_INTERNAL + 'property';
   public static readonly REST_INTERNAL_PROPERTY_VALIDATE = SmpConstants.REST_INTERNAL_PROPERTY_MANAGE + '/validate';
@@ -74,12 +99,12 @@ export class SmpConstants {
 
   public static readonly REST_INTERNAL_KEYSTORE_UPLOAD = SmpConstants.REST_INTERNAL_KEYSTORE_MANAGE + '/' + 'upload'
     + '/' + SmpConstants.PATH_PARAM_KEYSTORE_TYPE + '/' + SmpConstants.PATH_PARAM_KEYSTORE_PWD;
-  public static readonly REST_INTERNAL_KEYSTORE_DELETE_ENTRY = SmpConstants.REST_INTERNAL_KEYSTORE_MANAGE + '/' + 'delete'
+  public static readonly REST_INTERNAL_KEYSTORE_DELETE_ENTRY = SmpConstants.REST_INTERNAL_KEYSTORE_MANAGE + '/' + SmpConstants.PATH_ACTION_DELETE
     + '/' + SmpConstants.PATH_PARAM_CERT_ALIAS;
 
   public static readonly REST_INTERNAL_TRUSTSTORE_MANAGE = SmpConstants.REST_INTERNAL + 'truststore' + '/' + SmpConstants.PATH_PARAM_ENC_USER_ID;
   public static readonly REST_INTERNAL_TRUSTSTORE_UPLOAD_CERT = SmpConstants.REST_INTERNAL_TRUSTSTORE_MANAGE + '/' + 'upload-certificate';
-  public static readonly REST_INTERNAL_TRUSTSTORE_DELETE_CERT = SmpConstants.REST_INTERNAL_TRUSTSTORE_MANAGE + '/' + 'delete' + '/' + SmpConstants.PATH_PARAM_CERT_ALIAS;
+  public static readonly REST_INTERNAL_TRUSTSTORE_DELETE_CERT = SmpConstants.REST_INTERNAL_TRUSTSTORE_MANAGE + '/' + SmpConstants.PATH_ACTION_DELETE + '/' + SmpConstants.PATH_PARAM_CERT_ALIAS;
 
 
   public static readonly REST_PUBLIC_USER_NAVIGATION_TREE = SmpConstants.REST_PUBLIC_USER + '/' + SmpConstants.PATH_PARAM_ENC_USER_ID + '/' + 'navigation-tree';
diff --git a/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.html b/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.html
index d996f6d2c..6659889fa 100644
--- a/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.html
+++ b/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.html
@@ -5,25 +5,37 @@
               [labelColumnContent]="searchDomainPanel">
 
 
-    <mat-tab-group style="height: 100%">
+    <mat-tab-group #domainTabs style="height: 100%" >
       <mat-tab label="Domain data">
-        <domain-panel
-          [domain]="selected"
-          [keystoreCertificates]="keystoreCertificates"
+        <domain-panel #domainPanelComponent
+                      [domain]="selected"
+                      [keystoreCertificates]="keystoreCertificates"
+                      [domiSMPResourceDefinitions]="domiSMPResourceDefinitions"
+                      (onSaveBasicDataEvent)="onSaveEvent($event)"
+                      (onDiscardNew)="onDiscardNew()"
         ></domain-panel>
       </mat-tab>
-      <mat-tab label="Resources">
-        <domain-resource-type-panel [domain]="selected"></domain-resource-type-panel>
+      <mat-tab label="Resource Types">
+        <domain-resource-type-panel  #domainResourceTypePanelComponent
+          [domain]="selected"
+          [domiSMPResourceDefinitions]="domiSMPResourceDefinitions"
+          (onSaveResourceTypesEvent)="onSaveResourceTypesEvent($event)"
+        ></domain-resource-type-panel>
       </mat-tab>
       <mat-tab label="SML integration">
-        <domain-sml-integration-panel [domain]="selected"></domain-sml-integration-panel>
+        <domain-sml-integration-panel #domainSmlIntegrationPanelComponent
+          [keystoreCertificates]="keystoreCertificates"
+          [domain]="selected"
+          (onSaveSmlIntegrationDataEvent)="onSaveSmlIntegrationDataEvent($event)"
+        ></domain-sml-integration-panel>
+      </mat-tab>
+      <mat-tab label="Members">
+        Content 3
       </mat-tab>
-      <mat-tab label="Members"> Content 3</mat-tab>
     </mat-tab-group>
   </data-panel>
 </div>
 
-
 <ng-template #searchDomainPanel>
   <mat-form-field id="domain-filter">
     <mat-label>Filter Domain by domain code</mat-label>
@@ -32,12 +44,15 @@
 
   <mat-toolbar>
     <mat-toolbar-row class="mat-elevation-z5">
-      <button mat-raised-button mat-flat-button color="primary"
-              (click)="onCreateDomainClicked()">Create domain
+      <button mat-raised-button
+              mat-flat-button color="primary"
+              onDiscardNew
+              (click)="onCreateDomainClicked()"
+              >Create domain
       </button>
 
       <button mat-raised-button
-              [disabled]="!selected"
+              [disabled]="canNotDelete"
               color="primary"
               (click)="onDeleteSelectedDomainClicked()">
         <mat-icon>delete</mat-icon>
@@ -59,8 +74,8 @@
 
 
     <tr class="mat-row" *matNoDataRow>
-      <td *ngIf="inputDomainFilter.value;else noDataFound" class="mat-cell" colspan="2">No data matching the filter "{{inputDomainFilter.value}}
-        "
+      <td *ngIf="inputDomainFilter.value;else noDataFound" class="mat-cell" colspan="2">No data matching the filter
+        "{{inputDomainFilter.value}}"
       </td>
       <ng-template #noDataFound>
         <td class="mat-cell" colspan="2">No data</td>
@@ -74,4 +89,3 @@
                  [pageSize]="5" aria-label="Select page"></mat-paginator>
 
 </ng-template>
--->
diff --git a/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts b/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts
index 73dc9f5b3..fc99742e9 100644
--- a/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts
+++ b/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts
@@ -7,10 +7,18 @@ import {AlertMessageService} from "../../common/alert-message/alert-message.serv
 import {ConfirmationDialogComponent} from "../../common/dialogs/confirmation-dialog/confirmation-dialog.component";
 import {MatDialog} from "@angular/material/dialog";
 import {EntityStatus} from "../../common/model/entity-status.model";
-import {DomainRo} from "../domain/domain-ro.model";
+import {DomainRo} from "./domain-ro.model";
 import {AdminKeystoreService} from "../admin-keystore/admin-keystore.service";
 import {CertificateRo} from "../user/certificate-ro.model";
 import {BeforeLeaveGuard} from "../../window/sidenav/navigation-on-leave-guard";
+import {ResourceDefinitionRo} from "../admin-extension/resource-definition-ro.model";
+import {ExtensionService} from "../admin-extension/extension.service";
+import {ExtensionRo} from "../admin-extension/extension-ro.model";
+import {MatTabGroup} from "@angular/material/tabs";
+import {CancelDialogComponent} from "../../common/dialogs/cancel-dialog/cancel-dialog.component";
+import {DomainPanelComponent} from "./domain-panel/domain-panel.component";
+import {DomainResourceTypePanelComponent} from "./domain-resource-type-panel/domain-resource-type-panel.component";
+import {DomainSmlIntegrationPanelComponent} from "./domain-sml-panel/domain-sml-integration-panel.component";
 
 
 @Component({
@@ -22,15 +30,27 @@ export class AdminDomainComponent implements OnInit, AfterViewInit, BeforeLeaveG
   displayedColumns: string[] = ['domainCode'];
   dataSource: MatTableDataSource<DomainRo> = new MatTableDataSource();
   selected?: DomainRo;
-  domainList: DomainRo[];
-  keystoreCertificates: CertificateRo[];
+  domainList: DomainRo[] = [];
+  keystoreCertificates: CertificateRo[] = [];
+  domiSMPResourceDefinitions: ResourceDefinitionRo[] = [];
+
+  currenTabIndex: number = 0;
+  handleTabClick;
 
 
   @ViewChild(MatPaginator) paginator: MatPaginator;
   @ViewChild(MatSort) sort: MatSort;
 
+  @ViewChild('domainPanelComponent') domainPanelComponent: DomainPanelComponent;
+  @ViewChild('domainResourceTypePanelComponent') domainResourceTypePanelComponent: DomainResourceTypePanelComponent;
+  @ViewChild('domainSmlIntegrationPanelComponent') domainSmlIntegrationPanelComponent: DomainSmlIntegrationPanelComponent;
+
+
+  @ViewChild('domainTabs') domainTabs: MatTabGroup;
+
   constructor(private domainService: AdminDomainService,
               private keystoreService: AdminKeystoreService,
+              private extensionService: ExtensionService,
               private alertService: AlertMessageService,
               private dialog: MatDialog) {
 
@@ -43,15 +63,28 @@ export class AdminDomainComponent implements OnInit, AfterViewInit, BeforeLeaveG
         this.updateDomain(updatedCertificate);
       }
     );
-
     keystoreService.onKeystoreUpdatedEvent().subscribe(keystoreCertificates => {
         this.keystoreCertificates = keystoreCertificates;
       }
     );
+    extensionService.onExtensionsUpdatesEvent().subscribe(updatedExtensions => {
+        this.updateExtensions(updatedExtensions);
+      }
+    );
+
+    extensionService.getExtensions();
     domainService.getDomains();
     keystoreService.getKeystoreData();
   }
 
+  updateExtensions(extensions: ExtensionRo[]) {
+
+    let allResourceDefinition: ResourceDefinitionRo[] = [];
+    extensions.forEach(ext => allResourceDefinition.push(...ext.resourceDefinitions))
+
+    this.domiSMPResourceDefinitions = allResourceDefinition;
+  }
+
   ngOnInit(): void {
     // filter predicate for search the domain
     this.dataSource.filterPredicate =
@@ -63,6 +96,39 @@ export class AdminDomainComponent implements OnInit, AfterViewInit, BeforeLeaveG
   ngAfterViewInit() {
     this.dataSource.paginator = this.paginator;
     this.dataSource.sort = this.sort;
+    // currenctly  MatTab has only onTabChanged which is a bit to late. Register new listener to  internal
+    // _handleClick handler
+    this.registerTabClick();
+  }
+
+  registerTabClick(): void {
+    // Get the handler reference
+    this.handleTabClick = this.domainTabs._handleClick;
+
+    this.domainTabs._handleClick = (tab, header, newTabIndex) => {
+
+      if (newTabIndex == this.currenTabIndex) {
+        return;
+      }
+
+      if (this.isCurrentTabDirty()) {
+        let canChangeTab = this.dialog.open(CancelDialogComponent).afterClosed().toPromise<boolean>();
+        canChangeTab.then((canChange: boolean) => {
+          if (canChange) {
+            // reset
+            this.resetCurrentTabData()
+            this.handleTabClick.apply(this.domainTabs, [tab, header, newTabIndex]);
+            this.currenTabIndex = newTabIndex;
+            if (this.isNewDomain()){
+              this.selected = null;
+            }
+          }
+        });
+      } else {
+        this.handleTabClick.apply(this.domainTabs, [tab, header, newTabIndex]);
+        this.currenTabIndex = newTabIndex;
+      }
+    }
   }
 
   updateDomainList(domainList: DomainRo[]) {
@@ -80,7 +146,13 @@ export class AdminDomainComponent implements OnInit, AfterViewInit, BeforeLeaveG
       this.domainList.push(domain)
       this.selected = domain;
       this.alertService.success("Domain: [" + domain.domainCode + "] was created!");
-    } else if (domain.status == EntityStatus.REMOVED) {
+    } else if (domain.status == EntityStatus.UPDATED) {
+      // update value in the array
+      let itemIndex = this.domainList.findIndex(item => item.domainId == domain.domainId);
+      this.domainList[itemIndex] = domain;
+      this.selected = domain;
+    }
+    else if (domain.status == EntityStatus.REMOVED) {
       this.alertService.success("Domain: [" + domain.domainCode + "]  is removed!");
       this.selected = null;
       this.domainList = this.domainList.filter(item => item.domainCode !== domain.domainCode)
@@ -99,10 +171,65 @@ export class AdminDomainComponent implements OnInit, AfterViewInit, BeforeLeaveG
     }
   }
 
+  resetUnsavedDataValidation() {
+    // current tab not changed - OK to change it
+    if (!this.isCurrentTabDirty()) {
+      return true;
+    }
+
+    let canChangeTab = this.dialog.open(CancelDialogComponent).afterClosed().toPromise<boolean>();
+    canChangeTab.then((canChange: boolean) => {
+      if (canChange) {
+        // reset
+        this.resetCurrentTabData()
+      }
+    });
+  }
+
   onCreateDomainClicked() {
+    this.domainTabs.selectedIndex = 0;
+    this.selected = this.newDomain();
+    this.domainPanelComponent.setFocus();
 
   }
 
+  public newDomain(): DomainRo {
+    return {
+      index: null,
+      domainCode: '',
+      smlSubdomain: '',
+      smlSmpId: '',
+      smlParticipantIdentifierRegExp: '',
+      smlClientCertHeader: '',
+      smlClientKeyAlias: '',
+      signatureKeyAlias: '',
+      status: EntityStatus.NEW,
+      smlRegistered: false,
+      smlClientCertAuth: false,
+    }
+  }
+
+  onSaveEvent(domain: DomainRo){
+    if (this.isNewDomain()) {
+      this.domainService.createDomain(domain);
+    } else {
+      this.domainService.updateDomain(domain);
+    }
+  }
+
+  onDiscardNew(){
+    this.selected = null;
+  }
+
+  onSaveResourceTypesEvent(domain: DomainRo){
+    this.domainService.updateDomainResourceTypes(domain);
+  }
+
+  onSaveSmlIntegrationDataEvent(domain: DomainRo){
+    this.domainService.updateDomainSMLIntegrationData(domain);
+  }
+
+
   onDeleteSelectedDomainClicked() {
     this.dialog.open(ConfirmationDialogComponent, {
       data: {
@@ -117,16 +244,70 @@ export class AdminDomainComponent implements OnInit, AfterViewInit, BeforeLeaveG
   }
 
   deleteDomain(domain: DomainRo) {
-
+      this.domainService.deleteDomains(domain);
   }
 
-  public domainSelected(selected: DomainRo) {
-    this.selected = selected;
+  public domainSelected(domainSelected: DomainRo) {
+    if (this.selected === domainSelected) {
+      return;
+    }
+    if (this.isCurrentTabDirty()) {
+      let canChangeTab = this.dialog.open(CancelDialogComponent).afterClosed().toPromise<boolean>();
+      canChangeTab.then((canChange: boolean) => {
+        if (canChange) {
+          // reset
+          this.resetCurrentTabData();
+          this.selected = domainSelected;
+        }
+      });
+    } else {
+      this.selected = domainSelected;
+    }
   }
 
+
   isDirty(): boolean {
+    return  this.isCurrentTabDirty();
+  }
+
+  isCurrentTabDirty(): boolean {
+
+    switch (this.currenTabIndex) {
+      case 0:
+        return this.domainPanelComponent?.isDirty();
+      case 1:
+        return this.domainResourceTypePanelComponent?.isDirty();
+      case 2:
+        return this.domainSmlIntegrationPanelComponent?.isDirty();
+    }
     return false;
   }
 
+  isNewDomain():boolean{
+    return this.selected!=null && !this.selected.domainId
+  }
+
 
+  resetCurrentTabData(): void {
+
+    switch (this.currenTabIndex) {
+      case 0:
+        this.domainPanelComponent.onResetButtonClicked();
+        break;
+      case 1:
+        this.domainPanelComponent.onResetButtonClicked();
+        break
+      case 2:
+        this.domainSmlIntegrationPanelComponent.onResetButtonClicked();
+        break
+    }
+  }
+
+  get canNotDelete():boolean{
+    return !this.selected || this.domainSmlIntegrationPanelComponent.isDomainRegistered || this.isNewDomain()
+  }
+
+  get editMode(): boolean {
+    return this.isCurrentTabDirty();
+  }
 }
diff --git a/smp-angular/src/app/system-settings/admin-domain/admin-domain.service.ts b/smp-angular/src/app/system-settings/admin-domain/admin-domain.service.ts
index d96105d61..3c9969c09 100644
--- a/smp-angular/src/app/system-settings/admin-domain/admin-domain.service.ts
+++ b/smp-angular/src/app/system-settings/admin-domain/admin-domain.service.ts
@@ -4,7 +4,7 @@ import {Observable, Subject} from 'rxjs';
 import {HttpClient} from '@angular/common/http';
 import {SecurityService} from "../../security/security.service";
 import {AlertMessageService} from "../../common/alert-message/alert-message.service";
-import {DomainRo} from "../domain/domain-ro.model";
+import {DomainRo} from "./domain-ro.model";
 import {User} from "../../security/user.model";
 import {SmpConstants} from "../../smp.constants";
 
@@ -31,6 +31,70 @@ export class AdminDomainService {
       });
   }
 
+  public deleteDomains(domain: DomainRo) {
+    const currentUser: User = this.securityService.getCurrentUser();
+    this.http.delete<DomainRo>(SmpConstants.REST_INTERNAL_DOMAIN_MANAGE_DELETE
+      .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+      .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId))
+      .subscribe((result: DomainRo) => {
+        this.notifyDomainEntryUpdated(result);
+      }, (error: any) => {
+        this.alertService.error(error.error?.errorDescription)
+      });
+  }
+
+  public updateDomain(domain: DomainRo) {
+    const currentUser: User = this.securityService.getCurrentUser();
+    this.http.post<DomainRo>(SmpConstants.REST_INTERNAL_DOMAIN_MANAGE_UPDATE
+        .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+        .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId)
+      , domain)
+      .subscribe((result: DomainRo) => {
+        this.notifyDomainEntryUpdated(result);
+      }, (error: any) => {
+        this.alertService.error(error.error?.errorDescription)
+      });
+  }
+
+
+  public createDomain(domain: DomainRo) {
+    const currentUser: User = this.securityService.getCurrentUser();
+    this.http.put<DomainRo>(SmpConstants.REST_INTERNAL_DOMAIN_MANAGE_CREATE
+        .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+      , domain)
+      .subscribe((result: DomainRo) => {
+        this.notifyDomainEntryUpdated(result);
+      }, (error: any) => {
+        this.alertService.error(error.error?.errorDescription)
+      });
+  }
+
+  public updateDomainSMLIntegrationData(domain: DomainRo) {
+    const currentUser: User = this.securityService.getCurrentUser();
+    this.http.post<DomainRo>(SmpConstants.REST_INTERNAL_DOMAIN_MANAGE_UPDATE_SML_INTEGRATION
+        .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+        .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId)
+      , domain)
+      .subscribe((result: DomainRo) => {
+        this.notifyDomainEntryUpdated(result);
+      }, (error: any) => {
+        this.alertService.error(error.error?.errorDescription)
+      });
+  }
+
+  public updateDomainResourceTypes(domain: DomainRo) {
+    const currentUser: User = this.securityService.getCurrentUser();
+    this.http.post<DomainRo>(SmpConstants.REST_INTERNAL_DOMAIN_MANAGE_UPDATE_RESOURCE_TYPES
+        .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+        .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId)
+      , domain.resourceDefinitions)
+      .subscribe((result: DomainRo) => {
+        this.notifyDomainEntryUpdated(result);
+      }, (error: any) => {
+        this.alertService.error(error.error?.errorDescription)
+      });
+  }
+
 
   notifyDomainsUpdated(res: DomainRo[]) {
     this.domainUpdateSubject.next(res);
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html b/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html
index 1c0c9390e..dd7b49082 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html
@@ -1,14 +1,31 @@
 <div id="domain-panel" class="mat-elevation-z2" >
-  <form [formGroup]="domainForm" (ngSubmit)="onSaveClicked()">
+  <form [formGroup]="domainForm" >
+    <mat-toolbar>
+      <mat-toolbar-row>
+        <button id="cancelButton" mat-raised-button (click)="onResetButtonClicked()" color="primary"
+                [disabled]="!resetButtonEnabled">
+          <mat-icon>refresh</mat-icon>
+          <span>Reset</span>
+        </button>
+        <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()" color="primary"
+                [disabled]="!submitButtonEnabled">
+          <mat-icon>save</mat-icon>
+          <span>Save</span>
+        </button>
+
+      </mat-toolbar-row>
+    </mat-toolbar>
     <h3>Domain details</h3>
+    <div class="panel" *ngIf="_domain!=null &&  !_domain.domainId"><p style="font-weight: bold">Enter data and click 'Save' to create new domain</div>
     <mat-form-field style="width:100%">
       <mat-label>Domain Code</mat-label>
       <input matInput placeholder="Domain Code"
              id="domainCode_id" #domainCode
-             matTooltip="The SMP's domain code. The code must be unique and is used in HTTP header 'Domain' or URL path sequence when retrieving /creating the resource using the webservice API"
+             matTooltip="The SMP's domain code. The code must be unique and is used in HTTP header 'Domain' or URL path sequence when retrieving/creating the resource using the webservice API"
              formControlName="domainCode" maxlength="63"
              (keydown)="onFieldKeyPressed('domainCode', 'domainCodeTimeout')"
-             required>
+             required
+             auto-focus-directive>
       <mat-hint align="end">For WS API integration: the Domain property</mat-hint>
       <div
         *ngIf="(!editMode && domainForm.controls['domainCode'].touched || editMode) &&  domainForm.controls['domainCode'].hasError('pattern')"
@@ -27,43 +44,9 @@
       </div>
     </mat-form-field>
     <mat-form-field style="width:100%">
-      <input matInput placeholder="SML domain"
-             matTooltip="The domain-specific part of the SML DNS zone (e.g., ‘mydomain’ for mydomain.sml.dns.zone or leave empty for sml.dns.zone). Note: has informative value only, SML DNS zone used for publishing is based on SML configuration."
-             name="smlSubdomain"
-             (keydown)="onFieldKeyPressed('domainCode', 'smlSubdomainTimeout')"
-             id="smldomain_id"
-             formControlName="smlSubdomain" maxlength="63">
-      <mat-hint align="end">The domain-specific part of the SML DNS zone (e.g., ‘mydomain’ for
-        mydomain.sml.dns.zone).
-      </mat-hint>
-      <div
-        *ngIf="(!editMode && domainForm.controls['smlSubdomain'].touched || editMode)
-              &&  domainForm.controls['smlSubdomain'].hasError('pattern')"
-        style="color:red; font-size: 70%">
-        SML domain should be up to 63 characters long, should only contain alphanumeric and hyphen characters,
-        should not start with a digit nor a hyphen and should not end with a hyphen.
-      </div>
-      <div
-        *ngIf="!!fieldWarningTimeoutMap.smlSubdomainTimeout"
-        style="color:darkorange; font-size: 70%">
-        SML domain should be up to 63 characters long, should only contain alphanumeric and hyphen characters,
-        should not start with a digit nor a hyphen and should not end with a hyphen.
-      </div>
-      <div
-        *ngIf="(!editMode && domainForm.controls['smlSubdomain'].touched || editMode) &&  domainForm.controls['smlSubdomain'].hasError('notInList')"
-        style="color:red; font-size: 70%">
-        The SML subdomain is already defined!
-      </div>
-      <div
-        *ngIf="(!editMode &&  domainForm.controls['smlSubdomain'].hasError('blankDomainError'))"
-        style="color:red; font-size: 70%">
-        Domain with empty sml subdomain already exists!
-      </div>
-    </mat-form-field>
-    <mat-form-field style="width:100%">
+      <mat-label>Response signature Certificate (Signature CertAlias)</mat-label>
       <mat-select placeholder="Response signature Certificate (Signature CertAlias)"
                   formControlName="signatureKeyAlias"
-                  name="cert"
                   matTooltip="Certificate is used for signing REST responses for the domain."
                   id="signatureKeyAlias_id">
         <mat-option [value]="''">Choose certificate for signing soap response</mat-option>
@@ -74,5 +57,40 @@
       <mat-hint align="end">Empty value will cause that Resource responses will not be signed by SMP!
       </mat-hint>
     </mat-form-field>
+
+    <mat-form-field style="width:100%">
+      <mat-label>Visibility of the domain</mat-label>
+      <mat-select placeholder="Visibility of the domain"
+                  formControlName="visibility"
+                  name="visibility"
+                  matTooltip="Visibility of the domain."
+                  id="domainVisibility_id">
+        <mat-option [value]="''" diabled>Choose visibility of the domain</mat-option>
+        <mat-option *ngFor="let visibility of domainVisibilityOptions"
+                    [value]="visibility.value">
+          {{visibility.key}}
+        </mat-option>
+      </mat-select>
+      <mat-hint align="end">Domain visibility. In case of Internal user must be authenticated
+        to get read the domain resources
+      </mat-hint>
+    </mat-form-field>
+
+  <mat-form-field style="width:100%">
+    <mat-label>Default resource type for the domain</mat-label>
+    <mat-select placeholder="Default resource type for the domain"
+                formControlName="defaultResourceTypeIdentifier"
+                matTooltip="Default resource type for the domain."
+                id="domainDefaultResourceType_id">
+      <mat-option [value]="''">Choose Default resource type for the domain</mat-option>
+      <mat-option *ngFor="let resDef of domainResourceTypes"
+                  [value]="resDef.identifier">
+        {{resDef.name}} ({{resDef.identifier}})
+      </mat-option>
+    </mat-select>
+    <mat-hint align="end">Domain visibility. In case of Internal user must be authenticated
+      to get read the domain resources
+    </mat-hint>
+  </mat-form-field>
   </form>
 </div>
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.ts b/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.ts
index 885fbeef0..312422f3d 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.ts
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.ts
@@ -1,10 +1,13 @@
-import {Component, Input,} from '@angular/core';
-import {DomainRo} from "../../domain/domain-ro.model";
+import {Component, ElementRef, EventEmitter, Input, Output, ViewChild,} from '@angular/core';
+import {DomainRo} from "../domain-ro.model";
 import {AbstractControl, FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
 import {AdminDomainService} from "../admin-domain.service";
 import {AlertMessageService} from "../../../common/alert-message/alert-message.service";
 import {MatDialog} from "@angular/material/dialog";
 import {CertificateRo} from "../../user/certificate-ro.model";
+import {VisibilityEnum} from "../../../common/enums/visibility.enum";
+import {ResourceDefinitionRo} from "../../admin-extension/resource-definition-ro.model";
+import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard";
 
 
 @Component({
@@ -12,18 +15,19 @@ import {CertificateRo} from "../../user/certificate-ro.model";
   templateUrl: './domain-panel.component.html',
   styleUrls: ['./domain-panel.component.scss']
 })
-export class DomainPanelComponent {
+export class DomainPanelComponent implements BeforeLeaveGuard {
+  @Output() onSaveBasicDataEvent: EventEmitter<DomainRo> = new EventEmitter();
 
-  // Request from test team can not automate test if this is less than 10 seconds :(. Initialy it was 2s
-  readonly warningTimeout : number = 10000;
+  @Output() onDiscardNew: EventEmitter<any> = new EventEmitter();
+  readonly warningTimeout: number = 50000;
   readonly domainCodePattern = '^[a-zA-Z0-9]{1,63}$';
-  readonly dnsDomainPattern = '^([a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){0,63}$';
-  readonly subDomainPattern = this.dnsDomainPattern;
-  readonly smpIdDomainPattern = this.dnsDomainPattern;
+  readonly domainVisibilityOptions = Object.keys(VisibilityEnum)
+    .filter(el => el !== "Private").map(el => {
+      return {key: el, value: VisibilityEnum[el]}
+    });
 
   fieldWarningTimeoutMap = {
     domainCodeTimeout: null,
-    smlSubdomainTimeout: null,
   };
 
   _domain: DomainRo = null;
@@ -31,8 +35,12 @@ export class DomainPanelComponent {
   editMode: boolean;
   createMode: boolean;
 
-  @Input() keystoreCertificates:CertificateRo[];
-  @Input() currentDomains:DomainRo[];
+  @Input() keystoreCertificates: CertificateRo[];
+  @Input() currentDomains: DomainRo[];
+  @Input() domiSMPResourceDefinitions: ResourceDefinitionRo[];
+
+
+  @ViewChild('domainCode', {static: false}) domainCodeField: ElementRef;
 
   notInList(list: string[], exception: string) {
     if (!list || !exception) {
@@ -52,7 +60,7 @@ export class DomainPanelComponent {
    * Show warning if domain code exceed the maxlength.
    * @param value
    */
-  onFieldKeyPressed(controlName: string, showTheWarningReference:string) {
+  onFieldKeyPressed(controlName: string, showTheWarningReference: string) {
     let value = this.domainForm.get(controlName).value
 
     if (!!value && value.length >= 63 && !this.fieldWarningTimeoutMap[showTheWarningReference]) {
@@ -63,23 +71,27 @@ export class DomainPanelComponent {
   }
 
 
-
   constructor(private domainService: AdminDomainService,
               private alertService: AlertMessageService,
               private dialog: MatDialog,
               private formBuilder: FormBuilder) {
 
     this.domainForm = formBuilder.group({
-      'domainCode': new FormControl({value: '', readonly: this.createMode},  [Validators.pattern(this.domainCodePattern),
+      'domainCode': new FormControl({value: '', readonly: true}, [Validators.pattern(this.domainCodePattern),
         this.notInList(this.currentDomains?.map(a => a.domainCode), this._domain?.domainCode)]),
-      'smlSubdomain': new FormControl({value: '', readonly: this.editMode}, [Validators.pattern(this.subDomainPattern),
-        this.notInList(this.currentDomains?.map(a => a.smlSubdomain), this._domain?.smlSubdomain)]),
-      'signatureKeyAlias': new FormControl({value: '', readonly: this.editMode}),
+      'signatureKeyAlias': new FormControl({value: '', readonly: true}),
+      'visibility': new FormControl({value: '', readonly: true}),
+      'defaultResourceTypeIdentifier': new FormControl({value: '', disabled: this.isNewDomain()}),
     });
   }
 
   get domain(): DomainRo {
-    return this._domain;
+    let newDomain = {...this._domain};
+    newDomain.domainCode = this.domainForm.get('domainCode').value;
+    newDomain.signatureKeyAlias = this.domainForm.get('signatureKeyAlias').value;
+    newDomain.visibility = this.domainForm.get('visibility').value;
+    newDomain.defaultResourceTypeIdentifier = this.domainForm.get('defaultResourceTypeIdentifier').value;
+    return newDomain;
   }
 
   @Input() set domain(value: DomainRo) {
@@ -87,28 +99,56 @@ export class DomainPanelComponent {
 
     if (!!value) {
       this.domainForm.controls['domainCode'].setValue(this._domain.domainCode);
-      this.domainForm.controls['smlSubdomain'].setValue(this._domain.smlSubdomain);
-      this.domainForm.controls['smlSmpId'].setValue(this._domain.smlSmpId);
-      this.domainForm.controls['smlClientKeyAlias'].setValue(this._domain.smlClientKeyAlias);
-      this.domainForm.controls['smlClientCertHeader'].setValue(this._domain.smlClientCertHeader);
       this.domainForm.controls['signatureKeyAlias'].setValue(this._domain.signatureKeyAlias);
-      this.domainForm.controls['smlRegistered'].setValue(this._domain.smlRegistered);
-      this.domainForm.controls['smlClientCertAuth'].setValue(this._domain.smlClientCertAuth);
+      this.domainForm.controls['visibility'].setValue(this._domain.visibility);
+      this.domainForm.controls['defaultResourceTypeIdentifier'].setValue(this._domain.defaultResourceTypeIdentifier);
+      this.domainForm.enable();
     } else {
       this.domainForm.controls['domainCode'].setValue("");
-      this.domainForm.controls['smlSubdomain'].setValue("");
-      this.domainForm.controls['smlSmpId'].setValue("");
-      this.domainForm.controls['smlClientKeyAlias'].setValue("");
-      this.domainForm.controls['smlClientCertHeader'].setValue("");
       this.domainForm.controls['signatureKeyAlias'].setValue("");
-      this.domainForm.controls['smlRegistered'].setValue("");
-      this.domainForm.controls['smlClientCertAuth'].setValue("");
+      this.domainForm.controls['visibility'].setValue(VisibilityEnum.Public);
+      this.domainForm.controls['defaultResourceTypeIdentifier'].setValue("");
+      this.domainForm.disable();
     }
-
     this.domainForm.markAsPristine();
   }
 
-  onSaveClicked(){
+  isNewDomain(): boolean {
+    return this._domain != null && !this._domain.domainId
+  }
 
+  isDirty(): boolean {
+    return this.isNewDomain() || this.domainForm?.dirty;
   }
+
+  get domainResourceTypes(){
+    if (!this._domain || !this._domain.resourceDefinitions){
+      return [];
+    }
+    return this.domiSMPResourceDefinitions.filter(resType => this._domain.resourceDefinitions.includes(resType.identifier))
+  }
+  get submitButtonEnabled(): boolean {
+    return this.domainForm.valid && this.domainForm.dirty;
+  }
+
+  get resetButtonEnabled(): boolean {
+    return this.domainForm.dirty || this.isNewDomain();
+  }
+
+  public onSaveButtonClicked() {
+    this.onSaveBasicDataEvent.emit(this.domain);
+  }
+
+  public onResetButtonClicked() {
+    if (this.isNewDomain()) {
+      this.onDiscardNew.emit();
+    } else {
+      this.domainForm.reset(this._domain);
+    }
+  }
+
+  public setFocus() {
+    setTimeout(() => this.domainCodeField.nativeElement.focus());
+  }
+
 }
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.html b/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.html
index d039a4943..a25e11f6f 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.html
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.html
@@ -1,13 +1,28 @@
-<form [formGroup]="domainForm" (ngSubmit)="onSaveClicked()">
+<form [formGroup]="domainForm" >
 
   <div id="domain-resource-type-panel" class="mat-elevation-z2">
+    <mat-toolbar>
+      <mat-toolbar-row>
+        <button id="cancelButton" mat-raised-button (click)="onResetButtonClicked()" color="primary"
+                [disabled]="!resetButtonEnabled">
+          <mat-icon>refresh</mat-icon>
+          <span>Reset</span>
+        </button>
+        <button id="saveButton" mat-raised-button (click)="onSaveClicked()" color="primary"
+                [disabled]="!submitButtonEnabled">
+          <mat-icon>save</mat-icon>
+          <span>Save</span>
+        </button>
+
+      </mat-toolbar-row>
+    </mat-toolbar>
     <h3>Domain resource type configuration</h3>
-    <mat-selection-list #shoes>
-      <mat-list-option *ngFor="let resDef of domiSMPResourceDefinitions">
-        {{resDef.identifier}}
+    <mat-selection-list formControlName="resourceDefinitions">
+      <mat-list-option *ngFor="let resDef of domiSMPResourceDefinitions"
+                       [matTooltip]="resDef.description"
+                       [value]="resDef.identifier">
+        {{resDef.identifier}} ({{resDef.urlSegment}})
       </mat-list-option>
     </mat-selection-list>
-
-
   </div>
 </form>
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.ts b/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.ts
index 9eb20b304..f6879ded4 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.ts
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-resource-type-panel/domain-resource-type-panel.component.ts
@@ -1,9 +1,8 @@
-import {Component, Input,} from '@angular/core';
-import {DomainRo} from "../../domain/domain-ro.model";
-import {FormBuilder, FormGroup} from "@angular/forms";
-import {ExtensionService} from "../../admin-extension/extension.service";
-import {ExtensionRo} from "../../admin-extension/extension-ro.model";
+import {Component, EventEmitter, Input, Output,} from '@angular/core';
+import {DomainRo} from "../domain-ro.model";
+import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
 import {ResourceDefinitionRo} from "../../admin-extension/resource-definition-ro.model";
+import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard";
 
 
 @Component({
@@ -11,44 +10,58 @@ import {ResourceDefinitionRo} from "../../admin-extension/resource-definition-ro
   templateUrl: './domain-resource-type-panel.component.html',
   styleUrls: ['./domain-resource-type-panel.component.scss']
 })
-export class DomainResourceTypePanelComponent {
-
+export class DomainResourceTypePanelComponent implements BeforeLeaveGuard {
+  @Output() onSaveResourceTypesEvent: EventEmitter<DomainRo> = new EventEmitter();
   _domain: DomainRo = null;
-
-  domiSMPResourceDefinitions: ResourceDefinitionRo[] = [];
+  createMode: boolean = false;
+  @Input() domiSMPResourceDefinitions: ResourceDefinitionRo[] = [];
   domainForm: FormGroup;
 
-
   get domain(): DomainRo {
-    return this._domain;
+    let newDomain = {...this._domain};
+    newDomain.resourceDefinitions = this.domainForm.get('resourceDefinitions').value;
+    return newDomain;
   }
 
   @Input() set domain(value: DomainRo) {
     this._domain = value;
 
+    if (!!value) {
+      this.domainForm.controls['resourceDefinitions'].setValue(this._domain.resourceDefinitions);
+      this.domainForm.enable();
+    } else {
+      this.domainForm.controls['resourceDefinitions'].setValue([]);
+      this.domainForm.disable();
+    }
+    this.domainForm.markAsPristine();
   }
 
   constructor(
-    private formBuilder: FormBuilder,
-    extensionService: ExtensionService
-  ) {
-    extensionService.onExtensionsUpdatesEvent().subscribe(updatedExtensions => {
-        this.updateExtensions(updatedExtensions);
-      }
-    );
+    private formBuilder: FormBuilder) {
 
-    extensionService.getExtensions();
+    this.domainForm = formBuilder.group({
+      'resourceDefinitions': new FormControl({value: '', readonly: this.createMode})
+    });
   }
 
-  updateExtensions(extensions: ExtensionRo[]) {
+  onSaveClicked() {
+    this.onSaveResourceTypesEvent.emit(this.domain);
+  }
 
-    let allResourceDefinition: ResourceDefinitionRo[] = [];
-    extensions.forEach(ext => allResourceDefinition.push(...ext.resourceDefinitions))
 
-    this.domiSMPResourceDefinitions = allResourceDefinition;
+
+  get submitButtonEnabled(): boolean {
+    return this.domainForm.valid && this.domainForm.dirty;
   }
 
-  onSaveClicked() {
+  get resetButtonEnabled(): boolean {
+    return this.domainForm.dirty;
+  }
+  public onResetButtonClicked(){
+    this.domainForm.reset(this._domain);
+  }
 
+  isDirty(): boolean {
+    return this.domainForm.dirty;
   }
 }
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-ro.model.ts b/smp-angular/src/app/system-settings/admin-domain/domain-ro.model.ts
new file mode 100644
index 000000000..f80a78cf6
--- /dev/null
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-ro.model.ts
@@ -0,0 +1,20 @@
+import {SearchTableEntity} from '../../common/search-table/search-table-entity.model';
+import {VisibilityEnum} from "../../common/enums/visibility.enum";
+
+export interface DomainRo extends SearchTableEntity {
+  domainId?: string;
+  domainCode?: string;
+  smlSubdomain?: string;
+  smlSmpId?: string;
+  smlParticipantIdentifierRegExp?: string;
+  smlClientCertHeader?: string;
+  smlClientKeyAlias?: string;
+  signatureKeyAlias?: string;
+  smlRegistered?: boolean;
+  smlClientCertAuth?: boolean;
+  visibility?:VisibilityEnum;
+  defaultResourceTypeIdentifier?:string;
+  resourceDefinitions?: string[]
+
+}
+
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html b/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html
index 128585c2a..8b3d5eb79 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html
@@ -1,25 +1,108 @@
-<form [formGroup]="domainForm" (ngSubmit)="onSaveClicked()">
+<form [formGroup]="domainForm" >
 
   <div id="domain-sml-integration-panel" class="mat-elevation-z2">
+    <mat-toolbar>
+      <mat-toolbar-row>
+        <button id="cancelButton" mat-raised-button (click)="onResetButtonClicked()" color="primary"
+                [disabled]="!resetButtonEnabled">
+          <mat-icon>refresh</mat-icon>
+          <span>Reset</span>
+        </button>
+        <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()" color="primary"
+                [disabled]="!submitButtonEnabled">
+          <mat-icon>save</mat-icon>
+          <span>Save</span>
+        </button>
+        <tool-button-spacer></tool-button-spacer>
+
+        <button  id="registerButton" mat-raised-button (click)="smlRegisterSelectedDomain()"
+                 [disabled]="!enableSMLRegister()" color="primary">
+          <mat-icon>link</mat-icon>
+          <span>Register</span>
+        </button>
+        <button  id="unregisterButton" mat-raised-button (click)="smlUnregisterSelectedDomain()"
+                 [disabled]="!enableSMLUnregister()" color="primary">
+          <mat-icon>link_off</mat-icon>
+          <span>Unregister</span>
+        </button>
+      </mat-toolbar-row>
+    </mat-toolbar>
     <h3>SML integration data</h3>
+    <div class="panel" *ngIf="isDomainRegistered"><p style="font-weight: bold">Domain is registered to SML!</p>The Registered domain can not be deleted or changed the SMP SML identifier</div>
+    <mat-form-field style="width:100%">
+      <input matInput placeholder="SML domain"
+             matTooltip="The domain-specific part of the SML DNS zone (e.g., ‘mydomain’ for mydomain.sml.dns.zone or leave empty for sml.dns.zone). Note: has informative value only, SML DNS zone used for publishing is based on SML configuration."
+             name="smlSubdomain"
+             id="smldomain_id"
+             (keydown)="onFieldKeyPressed('smlSubdomain', 'smlDomainCodeTimeout')"
+             formControlName="smlSubdomain"
+          maxlength="63">
+      <mat-hint align="end">The domain-specific part of the SML DNS zone (e.g., ‘mydomain’ for
+        mydomain.sml.dns.zone).
+      </mat-hint>
+      <div
+        *ngIf="(!editMode && domainForm.controls['smlSubdomain'].touched || editMode)
+              &&  domainForm.controls['smlSubdomain'].hasError('pattern')"
+        style="color:red; font-size: 70%">
+        SML domain should be up to 63 characters long, should only contain alphanumeric and hyphen characters,
+        should not start with a digit nor a hyphen and should not end with a hyphen.
+      </div>
+      <div
+        *ngIf="!!fieldWarningTimeoutMap.smlDomainCodeTimeout"
+        style="color:darkorange; font-size: 70%">
+        SML domain should be up to 63 characters long, should only contain alphanumeric and hyphen characters,
+        should not start with a digit nor a hyphen and should not end with a hyphen.
+      </div>
+      <div
+        *ngIf="(!editMode && domainForm.controls['smlSubdomain'].touched || editMode) &&  domainForm.controls['smlSubdomain'].hasError('notInList')"
+        style="color:red; font-size: 70%">
+        The SML subdomain is already defined!
+      </div>
+      <div
+        *ngIf="(!editMode &&  domainForm.controls['smlSubdomain'].hasError('blankDomainError'))"
+        style="color:red; font-size: 70%">
+        Domain with empty sml subdomain already exists!
+      </div>
+    </mat-form-field>
     <mat-form-field style="width:100%">
       <mat-label>SML SMP identifier</mat-label>
       <input matInput placeholder="SML SMP identifier" name="smlSmpId"
              id="smlSMPId_id" #smlSMPId
-             formControlName="smlSmpId" maxlength="63">
+             formControlName="smlSmpId"
+             (keydown)="onFieldKeyPressed('smlSmpId', 'smlsmpidTimeout')"
+
+             maxlength="63">
       <mat-hint align="end">SMP ID used for SML</mat-hint>
+      <div
+        *ngIf="(!editMode && domainForm.controls['smlSmpId'].touched || editMode) &&  domainForm.controls['smlSmpId'].hasError('pattern')"
+        style="color:red; font-size: 70%">
+        SML SMP ID should be up to 63 characters long, should only contain alphanumeric and hyphen characters,
+        should not start with a digit nor a hyphen and should not end with a hyphen.
+      </div>
+      <div
+        *ngIf="!!fieldWarningTimeoutMap.smlsmpidTimeout"
+        style="color:darkorange; font-size: 70%">
+        SML SMP ID should be up to 63 characters long, should only contain alphanumeric and hyphen characters,
+        should not start with a digit nor a hyphen and should not end with a hyphen.
+      </div>
+      <div
+        *ngIf="(!editMode && domainForm.controls['smlSmpId'].touched || editMode) &&  domainForm.controls['smlSmpId'].hasError('notInList')"
+        style="color:red; font-size: 70%">
+        SML SMP ID already exists!
+      </div>
     </mat-form-field>
 
     <mat-form-field style="width:100%"
                     matTooltip="Client Certificate used for SML authentication. The SML Client-Cert http Header is also generated from the certificate">
-
       <mat-label>SML Client Certificate Alias</mat-label>
       <mat-select
         placeholder="SML ClientCert Alias"
         formControlName="smlClientKeyCertificate"
-        name="cert"
         id="smlClientKeyAlias_id">
-        <mat-option [value]="''">Choose certificate for SML integration</mat-option>
+        <mat-option [value]="''">Choose certificate for signing soap response</mat-option>
+        <mat-option *ngFor="let cert of keystoreCertificates" [value]="cert.alias">
+          {{cert.alias}} ({{cert.certificateId}})
+        </mat-option>
 
       </mat-select>
     </mat-form-field>
@@ -30,6 +113,6 @@
                       id="smlClientCertHeaderAuth_id">
       Use ClientCert http header authentication.
     </mat-slide-toggle>
-
   </div>
+
 </form>
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.ts b/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.ts
index e4d3619b1..9d71722ac 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.ts
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.ts
@@ -1,9 +1,15 @@
-import {Component, Input,} from '@angular/core';
-import {DomainRo} from "../../domain/domain-ro.model";
-import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
+import {Component, EventEmitter, Input, Output,} from '@angular/core';
+import {DomainRo} from "../domain-ro.model";
+import {AbstractControl, FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
 import {AdminDomainService} from "../admin-domain.service";
 import {AlertMessageService} from "../../../common/alert-message/alert-message.service";
 import {MatDialog} from "@angular/material/dialog";
+import {CertificateRo} from "../../user/certificate-ro.model";
+import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard";
+import {ConfirmationDialogComponent} from "../../../common/dialogs/confirmation-dialog/confirmation-dialog.component";
+import {SMLResult} from "../../domain/sml-result.model";
+import {SmlIntegrationService} from "../../domain/sml-integration.service";
+import {GlobalLookups} from "../../../common/global-lookups";
 
 
 @Component({
@@ -11,52 +17,259 @@ import {MatDialog} from "@angular/material/dialog";
   templateUrl: './domain-sml-integration-panel.component.html',
   styleUrls: ['./domain-sml-integration-panel.component.scss']
 })
-export class DomainSmlIntegrationPanelComponent {
-
+export class DomainSmlIntegrationPanelComponent implements BeforeLeaveGuard {
+  @Output() onSaveSmlIntegrationDataEvent: EventEmitter<DomainRo> = new EventEmitter();
+  readonly dnsDomainPattern = '^([a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){0,63}$';
+  readonly subDomainPattern = this.dnsDomainPattern;
+  readonly smpIdDomainPattern = this.dnsDomainPattern;
   _domain: DomainRo = null;
 
   domainForm: FormGroup;
 
+  readonly warningTimeout: number = 50000;
+  fieldWarningTimeoutMap = {
+    domainCodeTimeout: null,
+    smlDomainCodeTimeout: null,
+    smlsmpidTimeout: null,
+  };
+  editMode: boolean;
+
+
+  notInList(list: string[], exception: string) {
+    if (!list || !exception) {
+      return (c: AbstractControl): { [key: string]: any } => {
+        return null;
+      }
+    }
+
+    return (c: AbstractControl): { [key: string]: any } => {
+      if (c.value && c.value !== exception && list.includes(c.value))
+        return {'notInList': {valid: false}};
+      return null;
+    }
+  }
+
+  /**
+   * Show warning if domain code exceed the maxlength.
+   * @param value
+   */
+  onFieldKeyPressed(controlName: string, showTheWarningReference: string) {
+    let value = this.domainForm.get(controlName).value
+
+    if (!!value && value.length >= 63 && !this.fieldWarningTimeoutMap[showTheWarningReference]) {
+      this.fieldWarningTimeoutMap[showTheWarningReference] = setTimeout(() => {
+        this.fieldWarningTimeoutMap[showTheWarningReference] = null;
+      }, this.warningTimeout);
+    }
+  }
+
   constructor(private domainService: AdminDomainService,
               private alertService: AlertMessageService,
+              protected smlIntegrationService: SmlIntegrationService,
+              protected lookups: GlobalLookups,
               private dialog: MatDialog,
               private formBuilder: FormBuilder) {
 
     this.domainForm = formBuilder.group({
-
-      'smlSmpId': new FormControl({value: '', readonly: true}),
+      'smlSubdomain': new FormControl({
+        value: '',
+        disabled: this.editMode
+      }, [Validators.pattern(this.subDomainPattern),
+        this.notInList(this.lookups.cachedDomainList.map(a => a.smlSubdomain), this._domain?.smlSubdomain)]),
+      'smlSmpId': new FormControl({
+        value: '',
+        disabled: this.isDomainRegistered
+      }, [Validators.pattern(this.smpIdDomainPattern),
+        this.notInList(this.lookups.cachedDomainList.map(a => a.smlSmpId), this._domain?.smlSmpId)]),
       'smlClientCertHeader': new FormControl({value: '', readonly: true}),
       'smlClientKeyAlias': new FormControl({value: '', readonly: true}),
+      'smlClientCertAuth': new FormControl({value: '', readonly: true}),
       'smlClientKeyCertificate': new FormControl({value: '', readonly: true}),
       'smlRegistered': new FormControl({value: '', readonly: true}),
-      'smlClientCertAuth': new FormControl({value: '', readonly: true}),
+
     });
   }
 
   get domain(): DomainRo {
-    return this._domain;
+
+    let newDomain = {...this._domain};
+    newDomain.smlSubdomain = this.domainForm.get('smlSubdomain').value;
+    newDomain.smlSmpId = this.domainForm.get('smlSmpId').value;
+    newDomain.smlClientKeyAlias = this.domainForm.get('smlClientKeyAlias').value;
+    newDomain.smlClientCertHeader = this.domainForm.get('smlClientCertHeader').value;
+    newDomain.smlClientCertAuth = this.domainForm.get('smlClientCertAuth').value;
+    return newDomain;
   }
 
   @Input() set domain(value: DomainRo) {
     this._domain = value;
-  if (!!this._domain) {
+    if (!!this._domain) {
+      this.domainForm.controls['smlSubdomain'].setValue(this._domain.smlSubdomain);
       this.domainForm.controls['smlSmpId'].setValue(this._domain.smlSmpId);
       this.domainForm.controls['smlClientKeyAlias'].setValue(this._domain.smlClientKeyAlias);
       this.domainForm.controls['smlClientCertHeader'].setValue(this._domain.smlClientCertHeader);
       this.domainForm.controls['smlRegistered'].setValue(this._domain.smlRegistered);
       this.domainForm.controls['smlClientCertAuth'].setValue(this._domain.smlClientCertAuth);
+      this.domainForm.enable();
     } else {
-       this.domainForm.controls['smlSmpId'].setValue("");
+      this.domainForm.controls['smlSubdomain'].setValue("");
+      this.domainForm.controls['smlSmpId'].setValue("");
       this.domainForm.controls['smlClientKeyAlias'].setValue("");
       this.domainForm.controls['smlClientCertHeader'].setValue("");
       this.domainForm.controls['smlRegistered'].setValue("");
       this.domainForm.controls['smlClientCertAuth'].setValue("");
+      this.domainForm.disable();
     }
 
     this.domainForm.markAsPristine();
   }
 
-  onSaveClicked(){
+  @Input() keystoreCertificates: CertificateRo[];
+
+  get submitButtonEnabled(): boolean {
+    return this.domainForm.valid && this.domainForm.dirty;
+  }
+
+  get resetButtonEnabled(): boolean {
+    return this.domainForm.dirty;
+  }
+
+  public onSaveButtonClicked() {
+    this.onSaveSmlIntegrationDataEvent.emit(this.domain);
+  }
 
+  public onResetButtonClicked() {
+    this.domainForm.reset(this._domain);
   }
+
+  isDirty(): boolean {
+    return this.domainForm.dirty;
+  }
+
+
+  get isSMPIntegrationOn() {
+    return this.lookups.cachedApplicationConfig?.smlIntegrationOn
+  }
+
+  enableSMLRegister(): boolean {
+    if (!this._domain || !this.isSMPIntegrationOn || this.isDirty()) {
+      return false;
+    }
+
+    if (!this._domain.smlClientCertHeader && this._domain.smlClientCertAuth) {
+      return false;
+    }
+    if (!this._domain.smlClientKeyAlias && !this._domain.smlClientCertAuth) {
+      return false;
+    }
+
+    // entity must be first persisted in order to be enabled to registering to SML
+    return !this._domain.smlRegistered;
+  }
+
+  enableSMLUnregister(): boolean {
+    if (!this._domain || !this.isSMPIntegrationOn || this.isDirty()) {
+      return false;
+    }
+
+    if (this._domain.smlClientCertHeader && this._domain.smlClientCertAuth) {
+      return false;
+    }
+    if (!this._domain.smlClientKeyAlias && !this._domain.smlClientCertAuth) {
+      return false;
+    }
+
+    // entity must be first persisted in order to be enabled to registering to SML
+    return this.isDomainRegistered;
+  }
+
+  get isDomainRegistered() {
+    return this._domain?.smlRegistered;
+  }
+
+
+  smlUnregisterSelectedDomain() {
+    if (!this._domain) {
+      return false;
+    }
+
+    this.dialog.open(ConfirmationDialogComponent, {
+      data: {
+        title: "Unregister domain to SML",
+        description: "Action will unregister domain: " + this._domain + " and all its resources from SML. Do you wish to continue?"
+      }
+    }).afterClosed().subscribe(result => {
+      if (result) {
+        this.smlUnregisterDomain(this._domain);
+      }
+    })
+  }
+
+  smlRegisterSelectedDomain() {
+    if (!this._domain) {
+      return false;
+    }
+
+    this.dialog.open(ConfirmationDialogComponent, {
+      data: {
+        title: "Register domain to SML",
+        description: "Action will register domain: " + this._domain + " and all its service groups to SML. Do you wish to continue?"
+      }
+    }).afterClosed().subscribe(result => {
+      if (result) {
+        this.smlRegisterDomain(this._domain);
+      }
+    })
+  }
+
+  smlRegisterDomain(domain: DomainRo) {
+    //this.searchTable.showSpinner = true;
+
+    this.smlIntegrationService.registerDomainToSML$(domain.domainCode).toPromise().then((res: SMLResult) => {
+        // this.searchTable.showSpinner = false;
+        if (res) {
+          if (res.success) {
+            this.alertService.success("Domain " + domain.domainCode + " registered to sml!");
+            this.lookups.refreshDomainLookupForLoggedUser();
+            domain.smlRegistered = true;
+          } else {
+            this.alertService.exception('Error occurred while registering domain:' + domain.domainCode, res.errorMessage);
+          }
+        } else {
+          this.alertService.exception('Error occurred while registering domain:' + domain.domainCode, "Unknown error. Check logs.");
+        }
+      },
+      err => {
+        //  this.searchTable.showSpinner = false;
+        this.alertService.exception('Error occurred while registering domain:' + domain.domainCode, err);
+      }
+    )
+  }
+
+  smlUnregisterDomain(domain: DomainRo) {
+    //  this.searchTable.showSpinner = true;
+    this.smlIntegrationService.unregisterDomainToSML$(domain.domainCode).toPromise().then((res: SMLResult) => {
+        // this.searchTable.showSpinner = false;
+        if (res) {
+          if (res.success) {
+            this.alertService.success("Domain " + domain.domainCode + " unregistered from sml!");
+            this.lookups.refreshDomainLookupForLoggedUser();
+            domain.smlRegistered = false;
+          } else {
+            this.alertService.exception('Error occurred while unregistering domain:' + domain.domainCode, res.errorMessage);
+          }
+        } else {
+          this.alertService.exception('Error occurred while registering domain:' + domain.domainCode, "Unknown error. Check logs.");
+        }
+      }
+      ,
+      err => {
+        // this.searchTable.showSpinner = false;
+        this.alertService.exception('Error occurred while unregistering domain:' + domain.domainCode, err);
+      }
+    )
+
+  }
+
+
 }
diff --git a/smp-angular/src/app/system-settings/domain/domain-controller.ts b/smp-angular/src/app/system-settings/domain/domain-controller.ts
index 87efd4c2c..e89b284f1 100644
--- a/smp-angular/src/app/system-settings/domain/domain-controller.ts
+++ b/smp-angular/src/app/system-settings/domain/domain-controller.ts
@@ -1,10 +1,9 @@
 import {SearchTableController} from '../../common/search-table/search-table-controller';
 import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
 import {DomainDetailsDialogComponent} from './domain-details-dialog/domain-details-dialog.component';
-import {DomainRo} from './domain-ro.model';
+import {DomainRo} from '../admin-domain/domain-ro.model';
 import {EntityStatus} from '../../common/model/entity-status.model';
 import {GlobalLookups} from "../../common/global-lookups";
-import {of} from "rxjs/internal/observable/of";
 import {SearchTableValidationResult} from "../../common/search-table/search-table-validation-result.model";
 import {SearchTableEntity} from "../../common/search-table/search-table-entity.model";
 import {SmpConstants} from "../../smp.constants";
diff --git a/smp-angular/src/app/system-settings/domain/domain-details-dialog/domain-details-dialog.component.ts b/smp-angular/src/app/system-settings/domain/domain-details-dialog/domain-details-dialog.component.ts
index 7d8ed9099..74d8f06f1 100644
--- a/smp-angular/src/app/system-settings/domain/domain-details-dialog/domain-details-dialog.component.ts
+++ b/smp-angular/src/app/system-settings/domain/domain-details-dialog/domain-details-dialog.component.ts
@@ -1,7 +1,7 @@
 import {Component, Inject} from '@angular/core';
 import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog';
 import {AbstractControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators} from "@angular/forms";
-import {DomainRo} from "../domain-ro.model";
+import {DomainRo} from "../../admin-domain/domain-ro.model";
 import {AlertMessageService} from "../../../common/alert-message/alert-message.service";
 import {EntityStatus} from "../../../common/model/entity-status.model";
 import {GlobalLookups} from "../../../common/global-lookups";
diff --git a/smp-angular/src/app/system-settings/domain/domain-result.model.ts b/smp-angular/src/app/system-settings/domain/domain-result.model.ts
index bfc5bd6ee..5800872e2 100644
--- a/smp-angular/src/app/system-settings/domain/domain-result.model.ts
+++ b/smp-angular/src/app/system-settings/domain/domain-result.model.ts
@@ -1,4 +1,4 @@
-import {DomainRo} from './domain-ro.model';
+import {DomainRo} from '../admin-domain/domain-ro.model';
 
 export interface DomainResult {
   serviceEntities: Array<DomainRo>;
diff --git a/smp-angular/src/app/system-settings/domain/domain-ro.model.ts b/smp-angular/src/app/system-settings/domain/domain-ro.model.ts
deleted file mode 100644
index ac8f8ffc5..000000000
--- a/smp-angular/src/app/system-settings/domain/domain-ro.model.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import {SearchTableEntity} from '../../common/search-table/search-table-entity.model';
-
-export interface DomainRo extends SearchTableEntity {
-  domainCode: string;
-  smlSubdomain: string;
-  smlSmpId: string;
-  smlParticipantIdentifierRegExp: string;
-  smlClientCertHeader: string;
-  smlClientKeyAlias: string;
-  signatureKeyAlias: string;
-  smlRegistered: boolean;
-  smlClientCertAuth: boolean;
-
-
-}
-
diff --git a/smp-angular/src/app/system-settings/domain/domain.component.ts b/smp-angular/src/app/system-settings/domain/domain.component.ts
index c52208983..fe627f996 100644
--- a/smp-angular/src/app/system-settings/domain/domain.component.ts
+++ b/smp-angular/src/app/system-settings/domain/domain.component.ts
@@ -17,7 +17,7 @@ import {SmpConstants} from "../../smp.constants";
 import {GlobalLookups} from "../../common/global-lookups";
 import {SearchTableComponent} from "../../common/search-table/search-table.component";
 import {SecurityService} from "../../security/security.service";
-import {DomainRo} from "./domain-ro.model";
+import {DomainRo} from "../admin-domain/domain-ro.model";
 import {ConfirmationDialogComponent} from "../../common/dialogs/confirmation-dialog/confirmation-dialog.component";
 import {EntityStatus} from "../../common/model/entity-status.model";
 import {KeystoreEditDialogComponent} from "./keystore-edit-dialog/keystore-edit-dialog.component";
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainToDomainROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainToDomainROConverter.java
index bc8e6da1b..240afa3de 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainToDomainROConverter.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainToDomainROConverter.java
@@ -4,11 +4,14 @@ import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.apache.commons.beanutils.BeanUtils;
 import org.springframework.core.convert.converter.Converter;
 import org.springframework.stereotype.Component;
 
 import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.stream.Collectors;
 
 
 /**
@@ -24,6 +27,9 @@ public class DBDomainToDomainROConverter implements Converter<DBDomain, DomainRO
         DomainRO target = new DomainRO();
         try {
             BeanUtils.copyProperties(target, source);
+            List<String> domainDocuments = source.getDomainResourceDefs().stream().map(dbDomainResourceDef -> dbDomainResourceDef.getResourceDef().getIdentifier()).collect(Collectors.toList());
+            target.getResourceDefinitions().addAll(domainDocuments);
+            target.setDomainId(SessionSecurityUtils.encryptedEntityId(source.getId()));
         } catch (IllegalAccessException | InvocationTargetException e) {
             LOG.error("Error occurred while converting DBExtension", e);
             return null;
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 1adc588db..cfed00e87 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
@@ -85,7 +85,6 @@ public abstract class BaseDao<E extends BaseEntity> {
         memEManager.detach(entity);
     }
 
-
     public void persist(E entity) {
         memEManager.persist(entity);
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
index a46c240ae..3be0c7592 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
@@ -14,13 +14,14 @@
 package eu.europa.ec.edelivery.smp.data.dao;
 
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
-import eu.europa.ec.edelivery.smp.data.model.DBDomainDeleteValidation;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Repository;
 
-import javax.persistence.*;
+import javax.persistence.NoResultException;
+import javax.persistence.NonUniqueResultException;
+import javax.persistence.TypedQuery;
 import javax.transaction.Transactional;
 import java.util.List;
 import java.util.Optional;
@@ -37,7 +38,6 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.ILLEGAL_STATE_DOMA
 public class DomainDao extends BaseDao<DBDomain> {
 
 
-
     /**
      * Returns the only single record from smp_domain table.
      * Returns Optional.empty() if there is more than 1 record present.
@@ -103,6 +103,13 @@ public class DomainDao extends BaseDao<DBDomain> {
         }
     }
 
+    public Long getResourceCountForDomain(Long domainId) {
+        TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCES_BY_DOMAIN_ID_COUNT, Long.class);
+
+        query.setParameter(PARAM_DOMAIN_ID, domainId);
+        return query.getSingleResult();
+    }
+
     /**
      * Check if domain for domain code exists. If not SMPRuntimeException with DOMAIN_NOT_EXISTS is thrown.
      * If code is null or blank - then null is returned.
@@ -139,17 +146,4 @@ public class DomainDao extends BaseDao<DBDomain> {
         return false;
     }
 
-    /**
-     * Validation report for domain which are used by  service groups from list of domain ids..
-     *
-     * @param domainIds
-     * @return
-     */
-    public List<DBDomainDeleteValidation> validateDomainsForDelete(List<Long> domainIds) {
-        TypedQuery<DBDomainDeleteValidation> query = memEManager.createNamedQuery("DBDomainDeleteValidation.validateDomainUsage",
-                DBDomainDeleteValidation.class);
-        query.setParameter("domainIds", domainIds);
-        return query.getResultList();
-    }
-
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainResourceDefDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainResourceDefDao.java
index fd99331b6..120294a51 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainResourceDefDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainResourceDefDao.java
@@ -93,5 +93,12 @@ public class DomainResourceDefDao extends BaseDao<DBDomainResourceDef> {
         }
     }
 
+    public DBDomainResourceDef create(DBDomain domain, DBResourceDef resourceDef) {
+        DBDomainResourceDef domainResourceDef = new DBDomainResourceDef();
+        domainResourceDef.setDomain(domain);
+        domainResourceDef.setResourceDef(resourceDef);
+        return merge(domainResourceDef);
+    }
+
 
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
index 25906a1be..91adae188 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
@@ -12,7 +12,6 @@ public class QueryNames {
 
 
     public static final String QUERY_DOMAIN_ALL = "DBDomain.getAll";
-    public static final String QUERY_DOMAIN_IMPLEMENTATION_NAME = "DBDomain.getByClassName";
     public static final String QUERY_DOMAIN_CODE = "DBDomain.getDomainByCode";
     public static final String QUERY_EXTENSION_ALL = "DBExtension.getAll";
     public static final String QUERY_EXTENSION_BY_IDENTIFIER = "DBExtension.getByIdentifier";
@@ -36,6 +35,8 @@ public class QueryNames {
 
 
     public static final String QUERY_RESOURCE_BY_IDENTIFIER_RESOURCE_DEF_DOMAIN = "DBResource.getResByIdentifierAndResourceDefAndDomain";
+    public static final String QUERY_RESOURCES_BY_DOMAIN_ID_COUNT = "DBResource.getResByDomainIdCount";
+    public static final String QUERY_RESOURCES_BY_DOMAIN_ID_RESOURCE_DEF_ID_COUNT = "DBResource.getResByDomainIdAndResourceDefCount";
 
 
     public static final String QUERY_RESOURCE_MEMBER_ALL = "DBResourceMember.getAll";
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
index d74c04211..4cf1de938 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
@@ -135,6 +135,13 @@ public class ResourceDao extends BaseDao<DBResource> {
         }
     }
 
+    public Long getResourceCountForDomainIdAndResourceDefId(Long domainId, Long resourceDefId) {
+            TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCES_BY_DOMAIN_ID_RESOURCE_DEF_ID_COUNT, Long.class);
+            query.setParameter(PARAM_DOMAIN_ID, domainId);
+            query.setParameter(PARAM_RESOURCE_DEF_ID, resourceDefId);
+            return query.getSingleResult();
+    }
+
     /**
      * Method removes the resource from DB. Related entities (cascade): sub-resources, Document, Document version,
      * group memberships,
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
index 8141623cb..63e5c96bf 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
@@ -24,8 +24,7 @@ import javax.persistence.*;
 import java.util.ArrayList;
 import java.util.List;
 
-import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_DOMAIN_ALL;
-import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_DOMAIN_CODE;
+import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 
 /**
  * Created by gutowpa on 16/01/2018.
@@ -37,24 +36,11 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_DOMAIN_CODE;
         })
 @NamedQuery(name = QUERY_DOMAIN_ALL, query = "SELECT d FROM DBDomain d order by d.id asc")
 @NamedQuery(name = QUERY_DOMAIN_CODE, query = "SELECT d FROM DBDomain d WHERE d.domainCode = :domain_code")
-@NamedNativeQuery(name = "DBDomainDeleteValidation.validateDomainUsage",
-        resultSetMapping = "DBDomainDeleteValidationMapping",
-        query = "select D.ID as id, D.DOMAIN_CODE as domainCode, D.SML_SUBDOMAIN as smlSubdomain, COUNT(SGD.ID) as useCount " +
-                "   from SMP_DOMAIN D  INNER JOIN SMP_DOMAIN_RESOURCE_DEF SGD ON (D.ID =SGD.FK_DOMAIN_ID) " +
-                "   WHERE D.ID IN (:domainIds)" +
-                "      GROUP BY D.ID, D.DOMAIN_CODE, D.SML_SUBDOMAIN")
 @NamedNativeQuery(name = "DBDomain.updateNullSignAlias",
         query = "update SMP_DOMAIN set SIGNATURE_KEY_ALIAS=:alias WHERE SIGNATURE_KEY_ALIAS IS null")
 @NamedNativeQuery(name = "DBDomain.updateNullSMLAlias",
         query = "update SMP_DOMAIN set SIGNATURE_KEY_ALIAS=:alias " +
                 "WHERE SML_CLIENT_KEY_ALIAS IS null")
-@SqlResultSetMapping(name = "DBDomainDeleteValidationMapping", classes = {
-        @ConstructorResult(targetClass = DBDomainDeleteValidation.class,
-                columns = {@ColumnResult(name = "id", type = Long.class),
-                        @ColumnResult(name = "domainCode", type = String.class),
-                        @ColumnResult(name = "smlSubdomain", type = String.class),
-                        @ColumnResult(name = "useCount", type = Integer.class)})
-})
 @org.hibernate.annotations.Table(appliesTo = "SMP_DOMAIN", comment = "SMP can handle multiple domains. This table contains domain specific data")
 public class DBDomain extends BaseEntity {
 
@@ -115,7 +101,7 @@ public class DBDomain extends BaseEntity {
             orphanRemoval = true,
             fetch = FetchType.LAZY
     )
-    private List<DBGroup> domainGroups;
+    private List<DBGroup> domainGroups = new ArrayList<>();
 
     @OneToMany(
             mappedBy = "domain",
@@ -123,7 +109,7 @@ public class DBDomain extends BaseEntity {
             orphanRemoval = true,
             fetch = FetchType.LAZY
     )
-    private List<DBDomainResourceDef> domainResourceDefs;
+    private List<DBDomainResourceDef> domainResourceDefs= new ArrayList<>();
 
     @Override
     public Long getId() {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java
index b90f19f72..5f14b3f37 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java
@@ -29,7 +29,7 @@ import java.util.List;
 import java.util.Objects;
 import java.util.StringJoiner;
 
-import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_RESOURCE_BY_IDENTIFIER_RESOURCE_DEF_DOMAIN;
+import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 
 @Entity
 @Audited
@@ -40,19 +40,24 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.QUERY_RESOURCE_BY_I
                 @Index(name = "SMP_RS_SCH_IDX", columnList = "IDENTIFIER_SCHEME")
         })
 @org.hibernate.annotations.Table(appliesTo = "SMP_RESOURCE", comment = "SMP resource Identifier and scheme")
-@NamedQueries({
-        @NamedQuery(name = QUERY_RESOURCE_BY_IDENTIFIER_RESOURCE_DEF_DOMAIN, query = "SELECT d FROM DBResource d WHERE d.domainResourceDef.domain.id = :domain_id " +
-                " AND d.domainResourceDef.resourceDef.id=:resource_def_id" +
-                " AND d.identifierValue = :identifier_value " +
-                " AND (:identifier_scheme IS NULL AND d.identifierScheme IS NULL " +
-                " OR d.identifierScheme = :identifier_scheme)"
-        ),
-        @NamedQuery(name = "DBResource.getServiceGroupByID", query = "SELECT d FROM DBResource d WHERE d.id = :id"),
-        @NamedQuery(name = "DBResource.getServiceGroupByIdentifier", query = "SELECT d FROM DBResource d WHERE d.identifierValue = :participantIdentifier " +
-                " AND (:participantScheme IS NULL AND d.identifierScheme IS NULL " +
-                " OR d.identifierScheme = :participantScheme)"),
-        @NamedQuery(name = "DBResource.deleteById", query = "DELETE FROM DBResource d WHERE d.id = :id"),
-})
+@NamedQuery(name = QUERY_RESOURCE_BY_IDENTIFIER_RESOURCE_DEF_DOMAIN, query = "SELECT d FROM DBResource d WHERE d.domainResourceDef.domain.id = :domain_id " +
+    " AND d.domainResourceDef.resourceDef.id=:resource_def_id" +
+    " AND d.identifierValue = :identifier_value " +
+    " AND (:identifier_scheme IS NULL AND d.identifierScheme IS NULL " +
+    " OR d.identifierScheme = :identifier_scheme)")
+
+@NamedQuery(name = QUERY_RESOURCES_BY_DOMAIN_ID_RESOURCE_DEF_ID_COUNT, query = "SELECT count(d.id) FROM DBResource d WHERE d.domainResourceDef.domain.id = :domain_id " +
+        " and d.domainResourceDef.resourceDef.id = :resource_def_id ")
+
+@NamedQuery(name = QUERY_RESOURCES_BY_DOMAIN_ID_COUNT, query = "SELECT count(d.id) FROM DBResource d WHERE d.domainResourceDef.domain.id = :domain_id ")
+
+
+@NamedQuery(name = "DBResource.getServiceGroupByID", query = "SELECT d FROM DBResource d WHERE d.id = :id")
+@NamedQuery(name = "DBResource.getServiceGroupByIdentifier", query = "SELECT d FROM DBResource d WHERE d.identifierValue = :participantIdentifier " +
+        " AND (:participantScheme IS NULL AND d.identifierScheme IS NULL " +
+        " OR d.identifierScheme = :participantScheme)")
+@NamedQuery(name = "DBResource.deleteById", query = "DELETE FROM DBResource d WHERE d.id = :id")
+
 @NamedNativeQueries({
         @NamedNativeQuery(name = "DBResource.deleteAllOwnerships", query = "DELETE FROM SMP_RESOURCE_MEMBER WHERE FK_SG_ID=:serviceGroupId")
 })
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CredentialRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CredentialRO.java
index febcbe804..2f7a6f97b 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CredentialRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CredentialRO.java
@@ -11,7 +11,7 @@ import java.time.OffsetDateTime;
  */
 public class CredentialRO extends BaseRO {
 
-    static final long serialVersionUID = 9008583888835630000L;
+    private static final long serialVersionUID = 9008583888835630000L;
 
     String credentialId;
     String name;
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 93a862cf3..51fca3e65 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
@@ -1,6 +1,11 @@
 package eu.europa.ec.edelivery.smp.data.ui;
 
 
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
+
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author Joze Rihtarsic
  * @since 4.1
@@ -8,25 +13,28 @@ package eu.europa.ec.edelivery.smp.data.ui;
 
 public class DomainRO extends BaseRO {
 
-
     private static final long serialVersionUID = 9008583888835630008L;
 
-    Long id;
-    String domainCode;
-    String smlSubdomain;
-    String smlSmpId;
-    String smlClientCertHeader;
-    String smlClientKeyAlias;
-    String signatureKeyAlias;
-    boolean smlClientCertAuth;
-    boolean smlRegistered;
+    private String domainId;
+    private String domainCode;
+    private String smlSubdomain;
+    private String smlSmpId;
+    private String smlClientCertHeader;
+    private String smlClientKeyAlias;
+    private String signatureKeyAlias;
+    private boolean smlClientCertAuth;
+    private boolean smlRegistered;
+    private VisibilityType visibility;
+    private String defaultResourceTypeIdentifier;
+    private List<GroupRO> groups = new ArrayList<>();
+    private List<String> resourceDefinitions = new ArrayList<>();
 
-    public Long getId() {
-        return id;
+    public String getDomainId() {
+        return domainId;
     }
 
-    public void setId(Long id) {
-        this.id = id;
+    public void setDomainId(String domainId) {
+        this.domainId = domainId;
     }
 
     public String getDomainCode() {
@@ -92,4 +100,28 @@ public class DomainRO extends BaseRO {
     public void setSmlRegistered(boolean smlRegistered) {
         this.smlRegistered = smlRegistered;
     }
+
+    public VisibilityType getVisibility() {
+        return visibility;
+    }
+
+    public void setVisibility(VisibilityType visibility) {
+        this.visibility = visibility;
+    }
+
+    public String getDefaultResourceTypeIdentifier() {
+        return defaultResourceTypeIdentifier;
+    }
+
+    public void setDefaultResourceTypeIdentifier(String defaultResourceTypeIdentifier) {
+        this.defaultResourceTypeIdentifier = defaultResourceTypeIdentifier;
+    }
+
+    public List<GroupRO> getGroups() {
+        return groups;
+    }
+
+    public List<String> getResourceDefinitions() {
+        return resourceDefinitions;
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainResourceDefinitionRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainResourceDefinitionRO.java
new file mode 100644
index 000000000..c1278c4ac
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainResourceDefinitionRO.java
@@ -0,0 +1,42 @@
+package eu.europa.ec.edelivery.smp.data.ui;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Joze Rihtarsic
+ * @since 5.0
+ */
+
+public class DomainResourceDefinitionRO extends BaseRO {
+    private static final long serialVersionUID = 9008583888835630027L;
+
+    String domainResourceId;
+    private String resourceId;
+    private String resourceIdentifier;
+
+    public String getDomainResourceId() {
+        return domainResourceId;
+    }
+
+    public void setDomainResourceId(String domainResourceId) {
+        this.domainResourceId = domainResourceId;
+    }
+
+    public String getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(String resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public String getResourceIdentifier() {
+        return resourceIdentifier;
+    }
+
+    public void setResourceIdentifier(String resourceIdentifier) {
+        this.resourceIdentifier = resourceIdentifier;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/GroupRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/GroupRO.java
new file mode 100644
index 000000000..14201214c
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/GroupRO.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 European Commission | CEF eDelivery
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ *
+ * You may obtain a copy of the Licence attached in file: LICENCE-EUPL-v1.2.pdf
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and limitations under the Licence.
+ */
+
+package eu.europa.ec.edelivery.smp.data.ui;
+
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+
+/**
+ * The group of resources with shared resource management rights. The user with group admin has rights to create/delete
+ * resources for the group.
+ *
+ * @author Joze Rihtarsic
+ * @since 5.0
+ */
+public class GroupRO extends BaseRO {
+    private static final long serialVersionUID = 9008583888835630026L;
+
+    private String groupId;
+    private String groupName;
+    private String groupDescription;
+    private VisibilityType visibility = VisibilityType.PUBLIC;
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public void setGroupName(String groupName) {
+        this.groupName = groupName;
+    }
+
+    public String getGroupDescription() {
+        return groupDescription;
+    }
+
+    public void setGroupDescription(String groupDescription) {
+        this.groupDescription = groupDescription;
+    }
+
+    public VisibilityType getVisibility() {
+        return visibility;
+    }
+
+    public void setVisibility(VisibilityType visibility) {
+        this.visibility = visibility;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+
+        if (o == null || getClass() != o.getClass()) return false;
+
+        GroupRO groupRO = (GroupRO) o;
+
+        return new EqualsBuilder().append(groupId, groupRO.groupId).append(groupName, groupRO.groupName).append(groupDescription, groupRO.groupDescription).append(visibility, groupRO.visibility).isEquals();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder(17, 37).append(groupId).toHashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "GroupRO{" +
+                "groupId='" + groupId + '\'' +
+                ", groupName='" + groupName + '\'' +
+                ", groupDescription='" + groupDescription + '\'' +
+                ", visibility=" + visibility +
+                '}';
+    }
+}
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 9475d3def..1154bd5cc 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
@@ -1,19 +1,23 @@
 package eu.europa.ec.edelivery.smp.services.ui;
 
-import eu.europa.ec.edelivery.smp.data.dao.BaseDao;
-import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
+import eu.europa.ec.edelivery.smp.data.dao.*;
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
-import eu.europa.ec.edelivery.smp.data.model.DBDomainDeleteValidation;
-import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
+import eu.europa.ec.edelivery.smp.data.model.DBDomainResourceDef;
+import eu.europa.ec.edelivery.smp.data.model.ext.DBResourceDef;
 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 eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.sml.SmlConnector;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.io.StringWriter;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -25,13 +29,22 @@ import java.util.stream.Collectors;
 @Service
 public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
 
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDomainService.class);
+
+
     private DomainDao domainDao;
+    private ResourceDao resourceDao;
+    private ResourceDefDao resourceDefDao;
+    private DomainResourceDefDao domainResourceDefDao;
     private ConversionService conversionService;
     private SmlConnector smlConnector;
 
-    public UIDomainService(ConversionService conversionService, DomainDao domainDao, SmlConnector smlConnector) {
+    public UIDomainService(ConversionService conversionService, DomainDao domainDao, ResourceDao resourceDao, ResourceDefDao resourceDefDao, DomainResourceDefDao domainResourceDefDao, SmlConnector smlConnector) {
         this.conversionService = conversionService;
         this.domainDao = domainDao;
+        this.resourceDao = resourceDao;
+        this.resourceDefDao = resourceDefDao;
+        this.domainResourceDefDao = domainResourceDefDao;
         this.smlConnector = smlConnector;
     }
 
@@ -59,58 +72,135 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
         return super.getTableList(page, pageSize, sortField, sortOrder, filter);
     }
 
+    @Transactional
     public List<DomainRO> getAllDomains() {
         List<DBDomain> domains = domainDao.getAllDomains();
-
         return domains.stream().map(domain -> conversionService.convert(domain, DomainRO.class))
                 .collect(Collectors.toList());
     }
 
 
     @Transactional
-    public void updateDomainList(List<DomainRO> lst) {
-        for (DomainRO dRo : lst) {
-            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.setSmlSubdomain(dRo.getSmlSubdomain());
-                upd.setDomainCode(dRo.getDomainCode());
-                upd.setSignatureKeyAlias(dRo.getSignatureKeyAlias());
-                upd.setSmlClientCertAuth(dRo.isSmlClientCertAuth());
-                domainDao.update(upd);
-            } else if (dRo.getStatus() == EntityROStatus.REMOVE.getStatusNumber()) {
-                domainDao.removeByDomainCode(dRo.getDomainCode());
-            }
+    public void createDomainData(DomainRO data) {
+        DBDomain domain = new DBDomain();
+        domain.setDomainCode(data.getDomainCode());
+        domain.setDefaultResourceTypeIdentifier(data.getDefaultResourceTypeIdentifier());
+        domain.setSignatureKeyAlias(data.getSignatureKeyAlias());
+        domain.setVisibility(data.getVisibility() == null? VisibilityType.PUBLIC:data.getVisibility());
+        domainDao.persistFlushDetach(domain);
+    }
+
+
+    /**
+     * Update only basic domain data from DomainRO object. Ignore other
+     * @param domainId
+     * @param data
+     * @return
+     */
+    @Transactional
+    public void updateBasicDomainData(Long domainId, DomainRO data) {
+        DBDomain domain = domainDao.find(domainId);
+        if (domain == null) {
+            LOG.warn("Can not delete domain for ID [{}], because it does not exists!", domainId);
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+        }
+        domain.setDomainCode(data.getDomainCode());
+        domain.setDefaultResourceTypeIdentifier(data.getDefaultResourceTypeIdentifier());
+        domain.setSignatureKeyAlias(data.getSignatureKeyAlias());
+        domain.setVisibility(data.getVisibility());
+    }
+
+    @Transactional
+    public void updateDomainSmlIntegrationData(Long domainId, DomainRO data) {
+        DBDomain domain = domainDao.find(domainId);
+        if (domain == null) {
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
         }
+        if (domain.isSmlRegistered() && StringUtils.equals(data.getSmlSmpId(), domain.getSmlSmpId())){
+            String msg = "SMP-SML identifier must not change for registered domain ["+domain.getDomainCode()+"]!";
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, msg);
+        }
+
+        domain.setSmlSubdomain(data.getSmlSubdomain());
+        domain.setSmlSmpId(data.getSmlSmpId());
+        domain.setSmlClientKeyAlias(data.getSmlClientKeyAlias());
+        domain.setSmlClientCertHeader(data.getSmlClientCertHeader());
+        domain.setSmlClientCertAuth(data.isSmlClientCertAuth());
     }
 
-    public DeleteEntityValidation validateDeleteRequest(DeleteEntityValidation dev) {
-        List<Long> idList = dev.getListIds().stream().map(encId -> Long.parseLong(encId)).collect(Collectors.toList());
-        List<DBDomainDeleteValidation> lstMessages = domainDao.validateDomainsForDelete(idList);
-        dev.setValidOperation(lstMessages.isEmpty());
-        if (!dev.isValidOperation()) {
-            StringWriter sw = new StringWriter();
-            sw.write("Could not delete domains used by Service groups! ");
-            lstMessages.forEach(msg -> {
-                dev.getListDeleteNotPermitedIds().add(msg.getId() + "");
-                sw.write("Domain: ");
-                sw.write(msg.getDomainCode());
-                sw.write(" (");
-                sw.write(msg.getDomainCode());
-                sw.write(" )");
-                sw.write(" uses by:");
-                sw.write(msg.getCount().toString());
-                sw.write(" SG.");
-
-            });
-            dev.setStringMessage(sw.toString());
+    @Transactional
+    public void updateResourceDefDomainList(Long domainId, List<String> resourceDefIds) {
+        DBDomain domain = domainDao.find(domainId);
+        if (domain == null) {
+            LOG.warn("Can not delete domain for ID [{}], because it does not exists!", domainId);
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
         }
-        return dev;
+
+        //filter and validate resources to be removed
+        List<DBDomainResourceDef> removedDoReDef = domain.getDomainResourceDefs().stream()
+                .filter(doredef -> !resourceDefIds.contains(doredef.getResourceDef().getIdentifier())
+                        && validateRemoveDomainResourceDef(domain, doredef.getResourceDef())
+                ).collect(Collectors.toList());
+
+        removedDoReDef.forEach(domainResourceDef -> domain.getDomainResourceDefs().remove(domainResourceDef));
+        List<String> currentIdentifiers = domain.getDomainResourceDefs().stream().map(domainResourceDef -> domainResourceDef.getResourceDef().getIdentifier()).collect(Collectors.toList());
+
+        resourceDefIds.stream()
+                .filter(identifier -> !currentIdentifiers.contains(identifier))
+                .map(identifier -> resourceDefDao.getResourceDefByIdentifier(identifier)
+                        .orElseThrow(() -> new BadRequestException(ErrorBusinessCode.INVALID_INPUT_DATA, "Identifier [" + identifier + "] does not exists")))
+                .forEach(resourceDef ->
+                        domainResourceDefDao.create(domain, resourceDef)
+                );
     }
 
+    @Transactional
+    public DomainRO getDomainData(Long domainId){
+        DBDomain domain =  domainDao.find(domainId);
+        return conversionService.convert(domain, DomainRO.class);
+    }
+
+    @Transactional
+    public DomainRO getDomainDataByDomainCode(String domainCode){
+        DBDomain domain =  domainDao.getDomainByCode(domainCode).orElse(null);
+        return conversionService.convert(domain, DomainRO.class);
+    }
+
+    private boolean validateRemoveDomainResourceDef(DBDomain domain, DBResourceDef resourceDef) {
+
+        Long count = resourceDao.getResourceCountForDomainIdAndResourceDefId(domain.getId(), resourceDef.getId());
+        if (count > 0) {
+            String msg = "Can not remove resource definition [" + resourceDef.getIdentifier() + "] from domain [" + domain.getDomainCode()
+                    + "], because it has resources. Resource count [" + count + "]!";
+            throw new BadRequestException(ErrorBusinessCode.INVALID_INPUT_DATA, msg);
+        }
+        return true;
+    }
+
+    @Transactional
+    public DomainRO deleteDomain(Long domainId) {
+
+        DBDomain domain = domainDao.find(domainId);
+        if (domain == null) {
+            LOG.warn("Can not delete domain for ID [{}], because it does not exists!", domainId);
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+        }
+        if (domain.isSmlRegistered()) {
+            LOG.info("Can not delete domain for ID [{}], is registered to SML!", domainId);
+            throw new BadRequestException(ErrorBusinessCode.INVALID_INPUT_DATA, "Can not delete domain because it is registered to SML service! Unregister domain from SML service!");
+        }
+
+        Long count = domainDao.getResourceCountForDomain(domainId);
+        if (count > 0) {
+            LOG.info("Can not delete domain for ID [{}], because it has resources. Resource count [{}]!", domainId, count);
+            throw new BadRequestException(ErrorBusinessCode.INVALID_INPUT_DATA, "Can not delete domain because it has resources [" + count + "]! Delete resources first!");
+        }
+
+        domainDao.remove(domain);
+        DomainRO domainRO = conversionService.convert(domain, DomainRO.class);
+        domainRO.setStatus(EntityROStatus.REMOVE.getStatusNumber());
+        return domainRO;
+    }
+
+
 }
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
index 29058e85e..5f1b2dcb5 100644
--- 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
@@ -41,7 +41,7 @@ import static eu.europa.ec.edelivery.smp.testutil.TestConstants.TEST_SML_SUBDOMA
 public abstract class AbstractBaseDao {
 
     @Autowired
-    TestUtilsDao testUtilsDao;
+    protected TestUtilsDao testUtilsDao;
     public static final String BUILD_FOLDER = "target";
     public static final Path SECURITY_PATH= Paths.get(BUILD_FOLDER, "smp");
     public static final String DATABASE_URL = "jdbc:h2:file:./target/DomiSmpTestDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE;";
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 84c1f0772..030c520aa 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
@@ -5,7 +5,7 @@ import eu.europa.ec.edelivery.smp.data.model.doc.DBResource;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.testutil.TestConstants;
 import eu.europa.ec.edelivery.smp.testutil.TestDBUtils;
-import org.junit.Ignore;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -28,8 +28,11 @@ public class DomainDaoIntegrationTest extends AbstractBaseDao {
     @Autowired
     DomainDao testInstance;
 
-    @Autowired
-    ResourceDao serviceGroupDao;
+
+    @Before
+    public void prepareDatabase() {
+        testUtilsDao.clearData();
+    }
 
     @Rule
     public ExpectedException expectedEx = ExpectedException.none();
@@ -155,32 +158,23 @@ public class DomainDaoIntegrationTest extends AbstractBaseDao {
     }
 
     @Test
-    public void testValidateUsersForDeleteOKScenario() {
+    public void testValidateDeleteOKScenario() {
         // set
         DBDomain d = TestDBUtils.createDBDomain();
         testInstance.persistFlushDetach(d);
 
         // execute
-        List<DBDomainDeleteValidation> lst = testInstance.validateDomainsForDelete(Collections.singletonList(d.getId()));
-        assertTrue(lst.isEmpty());
+        Long cnt = testInstance.getResourceCountForDomain(d.getId());
+        assertEquals(0, cnt.intValue());
     }
 
     @Test
-    @Ignore
-    public void testValidateUsersForDeleteUserIsOwner() {
+    public void testValidateDeleteHasResources() {
         // set
-        DBDomain d = TestDBUtils.createDBDomain();
-        testInstance.persistFlushDetach(d);
-
-        DBResource sg = TestDBUtils.createDBResource();
-       // sg.addDomain(d);
+        testUtilsDao.createSubresources();
+        DBDomain d = testUtilsDao.getD1();
+        Long cnt  = testInstance.getResourceCountForDomain(d.getId());
 
-        serviceGroupDao.persistFlushDetach(sg);
-
-        // execute
-        List<DBDomainDeleteValidation> lst = testInstance.validateDomainsForDelete(Collections.singletonList(d.getId()));
-        assertEquals(1, lst.size());
-        assertEquals(d.getDomainCode(), lst.get(0).getDomainCode());
-        assertEquals(1, lst.get(0).getCount().intValue());
+        assertEquals(1, cnt.intValue());
     }
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceTest.java
new file mode 100644
index 000000000..b1ee76acc
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceTest.java
@@ -0,0 +1,15 @@
+package eu.europa.ec.edelivery.smp.services;
+
+import eu.europa.ec.edelivery.smp.data.dao.AbstractBaseDao;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+
+@ContextConfiguration(classes = {AbstractServiceTest.DomiSMPServicesConfig.class})
+public abstract class AbstractServiceTest extends AbstractBaseDao {
+    @Configuration
+    @ComponentScan({"eu.europa.ec.edelivery.smp"})
+    public static class DomiSMPServicesConfig {
+
+    }
+}
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 84e9273db..d9c36484f 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
@@ -81,40 +81,5 @@ public class UIDomainServiceIntegrationTest extends AbstractServiceIntegrationTe
         assertNotNull(res.getServiceEntities().get(0).getSmlSubdomain());
     }
 
-    @Test
-    public void validateDeleteRequest(){
-
-        DeleteEntityValidation dev= new DeleteEntityValidation();
-        dev.getListIds().add("10");
-        DeleteEntityValidation res = testInstance.validateDeleteRequest(dev);
-        assertEquals(true, res.isValidOperation());
-    }
-
-    @Test
-    public void validateDeleteRequestNotToDelete(){
-        // given
-        DBDomain d = TestDBUtils.createDBDomain("domain");
-        DBDomain d2 = TestDBUtils.createDBDomain("domain1");
-
-        domainDao.persistFlushDetach(d);
-        domainDao.persistFlushDetach(d2);
 
-        DBResource sg = TestDBUtils.createDBResource();
-       // sg.addDomain(d);
-        serviceGroupDao.persistFlushDetach(sg);
-
-        // when
-        DeleteEntityValidation dev= new DeleteEntityValidation();
-        dev.getListIds().add(d.getId()+"");
-        dev.getListIds().add(d2.getId()+"");
-
-        DeleteEntityValidation res = testInstance.validateDeleteRequest(dev);
-
-        // then
-        assertEquals(false, res.isValidOperation());
-        assertEquals(1, res.getListDeleteNotPermitedIds().size());
-        assertEquals(d.getId()+"", res.getListDeleteNotPermitedIds().get(0));
-        assertEquals("Could not delete domains used by Service groups! Domain: domain (domain ) uses by:1 SG.", res.getStringMessage());
-
-    }
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java
new file mode 100644
index 000000000..9813f4592
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java
@@ -0,0 +1,112 @@
+package eu.europa.ec.edelivery.smp.services.ui;
+
+import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
+import eu.europa.ec.edelivery.smp.services.AbstractServiceTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class UIDomainServiceTest extends AbstractServiceTest {
+
+    @Autowired
+    UIDomainService testInstance;
+    @Autowired
+    DomainDao domainDao;
+
+    @Before
+    public void prepareDatabase() {
+        testUtilsDao.clearData();
+        testUtilsDao.createResourceDefinitionsForDomains();
+    }
+
+    @Test
+    public void getAllDomains() {
+        List<DomainRO> domainROS = testInstance.getAllDomains();
+        assertEquals(2, domainROS.size());
+    }
+
+    @Test
+    public void updateDomainData() {
+
+        DomainRO domainRO = new DomainRO();
+        domainRO.setDomainCode("NewCode");
+        domainRO.setVisibility(VisibilityType.INTERNAL);
+        domainRO.setSignatureKeyAlias("NewAlias");
+        domainRO.setDefaultResourceTypeIdentifier("New ID");
+        DBDomain domain = testUtilsDao.getD1();
+        testInstance.updateBasicDomainData(domain.getId(), domainRO);
+        DBDomain result = domainDao.find(domain.getId());
+
+        assertEquals(domainRO.getDomainCode(), result.getDomainCode());
+        assertEquals(domainRO.getVisibility(), result.getVisibility());
+        assertEquals(domainRO.getSignatureKeyAlias(), result.getSignatureKeyAlias());
+        assertEquals(domainRO.getDefaultResourceTypeIdentifier(), result.getDefaultResourceTypeIdentifier());
+    }
+
+    @Test
+    public void updateSMLDomainData() {
+
+        DomainRO domainRO = new DomainRO();
+        domainRO.setSmlSubdomain("New SmlSubdomain");
+        domainRO.setSmlSmpId("NewSmlSmpId");
+        domainRO.setSmlClientKeyAlias("NewClientKeyAlias");
+        domainRO.setSmlClientCertHeader("NewtCertHeader");
+        domainRO.setSmlClientCertAuth(false);
+        DBDomain domain = testUtilsDao.getD1();
+        testInstance.updateDomainSmlIntegrationData(domain.getId(), domainRO);
+        DBDomain result = domainDao.find(domain.getId());
+
+        assertEquals(domainRO.getSmlSubdomain(), result.getSmlSubdomain());
+        assertEquals(domainRO.getSmlSmpId(), result.getSmlSmpId());
+        assertEquals(domainRO.getSmlClientKeyAlias(), result.getSmlClientKeyAlias());
+        assertEquals(domainRO.getSmlClientCertHeader(), result.getSmlClientCertHeader());
+        assertEquals(domainRO.isSmlClientCertAuth(), result.isSmlClientCertAuth());
+    }
+
+    @Test
+    public void updateDomainResourceListClear() {
+        DBDomain testDomain = testUtilsDao.getD1();
+        DomainRO domainRO = testInstance.getDomainData(testDomain.getId());
+        assertFalse(domainRO.getResourceDefinitions().isEmpty());
+        testInstance.updateResourceDefDomainList(testDomain.getId(), Collections.emptyList());
+
+        DomainRO result = testInstance.getDomainData(testDomain.getId());
+        assertTrue(result.getResourceDefinitions().isEmpty());
+    }
+
+    @Test
+    public void updateDomainResourceListAddNew() {
+        DBDomain testDomain = testUtilsDao.getD2();
+        DomainRO domainRO = testInstance.getDomainData(testDomain.getId());
+        String restDef2 = testUtilsDao.getResourceDefCpp().getIdentifier();
+
+        List<String> existingList = domainRO.getResourceDefinitions();
+        assertFalse(existingList.contains(restDef2));
+        existingList.add(restDef2);
+        testInstance.updateResourceDefDomainList(testDomain.getId(), existingList);
+
+        DomainRO result = testInstance.getDomainData(testDomain.getId());
+        assertTrue(result.getResourceDefinitions().contains(restDef2));
+    }
+
+    @Test
+    public void deleteDomain() {
+        DBDomain domain = testUtilsDao.getD1();
+        DBDomain test = domainDao.find(domain.getId());
+        assertNotNull(test);
+        testInstance.deleteDomain(domain.getId());
+
+        DBDomain result = domainDao.find(domain.getId());
+        assertNull(result);
+    }
+
+
+}
diff --git a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
index 1bbf75e83..7f56ba1ad 100644
--- a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
+++ b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
@@ -37,7 +37,9 @@ insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, SUBJECT, ISSUER, SERIALNUMBER,V
 
 
 insert into SMP_DOMAIN (ID, DOMAIN_CODE, VISIBILITY, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, SML_CLIENT_CERT_AUTH,SML_REGISTERED, CREATED_ON, LAST_UPDATED_ON) values
-(1, 'testdomain','PUBLIC', 'test-domain', 'CEF-SMP-002','sample_key',1,0, NOW(),  NOW());
+(1, 'testdomain','PUBLIC', 'test-domain', 'CEF-SMP-002','sample_key',1,0, NOW(),  NOW()),
+(2, 'testdomain1','PUBLIC', 'test-domain1', 'CEF-SMP-003','sample_key',1,0, NOW(),  NOW()),
+(3, 'testdomain2','PUBLIC', 'test-domain2', 'CEF-SMP-004','sample_key',1,0, NOW(),  NOW());
 
 insert into SMP_EXTENSION ( ID, IDENTIFIER,  IMPLEMENTATION_NAME, NAME, VERSION, DESCRIPTION, CREATED_ON, LAST_UPDATED_ON) values
 (1, 'edelivery-oasis-smp-extension',  'OasisSMPExtension','Oasis SMP 1.0 and 2.0','1.0', 'Oasis SMP 1.0 and 2.0 extension',  NOW(),  NOW());
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
index 9ed316716..b0599a87e 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
@@ -3,6 +3,7 @@ package eu.europa.ec.edelivery.smp.error;
 import ec.services.smp._1.ErrorResponse;
 import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
 import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
+import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.slf4j.Logger;
@@ -13,8 +14,7 @@ import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.core.AuthenticationException;
 
 import static eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode.TECHNICAL;
-import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
-import static org.springframework.http.HttpStatus.UNAUTHORIZED;
+import static org.springframework.http.HttpStatus.*;
 
 abstract class AbstractErrorControllerAdvice {
 
@@ -34,11 +34,15 @@ abstract class AbstractErrorControllerAdvice {
         }else if (runtimeException instanceof AccessDeniedException){
             AccessDeniedException ex = (AccessDeniedException)runtimeException;
             response = buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex);
+        }else if (runtimeException instanceof BadRequestException){
+            BadRequestException ex = (BadRequestException)runtimeException;
+            response = buildAndLog(UNPROCESSABLE_ENTITY, ex.getErrorBusinessCode(), ex.getMessage(), ex);
         }
         else {
             response = buildAndLog(INTERNAL_SERVER_ERROR, TECHNICAL, "Unexpected technical error occurred.", runtimeException);
         }
-        String errorCodeId = response.getBody() instanceof  ErrorResponseRO?((ErrorResponseRO) response.getBody()).getErrorUniqueId():((ErrorResponse) response.getBody()).getErrorUniqueId();
+        String errorCodeId = response.getBody() instanceof  ErrorResponseRO?
+                ((ErrorResponseRO) response.getBody()).getErrorUniqueId():((ErrorResponse) response.getBody()).getErrorUniqueId();
         LOG.error("Unhandled exception occurred, unique ID: [{}]", errorCodeId, runtimeException);
         return response;
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
index 20a4fc75c..65b28c447 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
@@ -15,6 +15,7 @@ package eu.europa.ec.edelivery.smp.error;
 
 import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
 import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
+import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.springframework.http.HttpStatus;
@@ -34,12 +35,16 @@ import static java.lang.String.format;
  * @author Joze Rihtarsic
  * @since 4.2
  */
-@RestControllerAdvice("eu.europa.ec.edelivery.smp.ui.external")
+@RestControllerAdvice({"eu.europa.ec.edelivery.smp.ui"})
 public class UIErrorControllerAdvice extends AbstractErrorControllerAdvice {
 
-
     @Override
-    @ExceptionHandler({BadCredentialsException.class, RuntimeException.class, SMPRuntimeException.class, SMPResponseStatusException.class, AuthenticationException.class,})
+    @ExceptionHandler({BadCredentialsException.class,
+            RuntimeException.class,
+            SMPRuntimeException.class,
+            SMPResponseStatusException.class,
+            AuthenticationException.class,
+            BadRequestException.class})
     public ResponseEntity handleRuntimeException(RuntimeException ex) {
         return super.handleRuntimeException(ex);
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResource.java
index 8b4c9f8eb..f02320860 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResource.java
@@ -2,23 +2,18 @@ package eu.europa.ec.edelivery.smp.ui.internal;
 
 
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
-import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
-import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
-import eu.europa.ec.edelivery.smp.data.ui.SMLIntegrationResult;
-import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
-import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.data.ui.*;
+import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.DomainService;
 import eu.europa.ec.edelivery.smp.services.ui.UIDomainService;
 import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
-import org.springframework.security.access.annotation.Secured;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.util.MimeTypeUtils;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.Arrays;
 import java.util.List;
 
 import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.*;
@@ -46,18 +41,6 @@ public class DomainAdminResource {
 
     }
 
-    @GetMapping(produces = {MimeTypeUtils.APPLICATION_JSON_VALUE})
-    public ServiceResult<DomainRO> geDomainList(
-            @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page,
-            @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize,
-            @RequestParam(value = PARAM_PAGINATION_ORDER_BY, required = false) String orderBy,
-            @RequestParam(value = PARAM_PAGINATION_ORDER_TYPE, defaultValue = "asc", required = false) String orderType,
-            @RequestParam(value = PARAM_QUERY_USER, required = false) String user) {
-
-        LOG.info("Search for page: {}, page size: {}, user: {}", page, pageSize, user);
-        return uiDomainService.getTableList(page, pageSize, orderBy, orderType, null);
-    }
-
     @GetMapping(path = "/{user-enc-id}", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
     @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isSystemAdministrator")
     public List<DomainRO> getAllDomainList(@PathVariable("user-enc-id") String userEncId) {
@@ -65,33 +48,73 @@ public class DomainAdminResource {
         return uiDomainService.getAllDomains();
     }
 
-    /**
-     * List of domains to be added or updated
-     *
-     * @param updateEntities
-     */
-    @PutMapping(produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN})
-    public void updateDomainList(@RequestBody DomainRO[] updateEntities) {
-        uiDomainService.updateDomainList(Arrays.asList(updateEntities));
+    @DeleteMapping(path = "/{user-enc-id}/{domain-enc-id}/delete", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isSystemAdministrator")
+    public DomainRO deleteDomain(@PathVariable("user-enc-id") String userEncId,
+                                 @PathVariable("domain-enc-id") String domainEncId) {
+        logAdminAccess("deleteDomain:" + domainEncId);
+        Long domainId = SessionSecurityUtils.decryptEntityId(domainEncId);
+        LOG.info("Delete domain with id [{}]", domainId);
+
+        return uiDomainService.deleteDomain(domainId);
     }
+    @PutMapping(path = "/{user-enc-id}/create", produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isSystemAdministrator")
+    public DomainRO createBasicDomainData(@PathVariable("user-enc-id") String userEncId,
+                                          @RequestBody DomainRO domainData) {
+        logAdminAccess("createBasicDomainData" );
 
-    /**
-     * Validated if domains with provided IDs can be deleted and returns the result in DeleteEntityValidation.
-     *
-     * @param listOfDomainIds
-     * @return
-     */
+        uiDomainService.createDomainData(domainData);
 
-    @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN})
-    @PutMapping(value = "validate-delete", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    public DeleteEntityValidation validateDeleteDomain(@RequestBody List<String> listOfDomainIds) {
+        DomainRO domainRO = uiDomainService.getDomainDataByDomainCode(domainData.getDomainCode());
+        domainRO.setStatus(EntityROStatus.NEW.getStatusNumber());
+        return domainRO;
+    }
+    @PostMapping(path = "/{user-enc-id}/{domain-enc-id}/update", produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isSystemAdministrator")
+    public DomainRO updateBasicDomainData(@PathVariable("user-enc-id") String userEncId,
+                                     @PathVariable("domain-enc-id") String domainEncId,
+                                     @RequestBody DomainRO domainData) {
+        logAdminAccess("updateBasicDomainData:" + domainEncId);
+        Long domainId = SessionSecurityUtils.decryptEntityId(domainEncId);
+        LOG.info("Update basic domain with id [{}]", domainId);
+        uiDomainService.updateBasicDomainData(domainId, domainData);
+
+        DomainRO domainRO = uiDomainService.getDomainData(domainId);
+        domainRO.setStatus(EntityROStatus.UPDATED.getStatusNumber());
+        return domainRO;
+    }
 
-        DeleteEntityValidation dres = new DeleteEntityValidation();
-        dres.getListIds().addAll(listOfDomainIds);
-        return uiDomainService.validateDeleteRequest(dres);
+    @PostMapping(path = "/{user-enc-id}/{domain-enc-id}/update-resource-types", produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isSystemAdministrator")
+    public DomainRO updateResourceDefDomainList(@PathVariable("user-enc-id") String userEncId,
+                                          @PathVariable("domain-enc-id") String domainEncId,
+                                          @RequestBody List<String> resourceDefs) {
+        logAdminAccess("updateResourceDefDomainList:" + domainEncId);
+        Long domainId = SessionSecurityUtils.decryptEntityId(domainEncId);
+        LOG.info("Update basic domain with id [{}]", domainId);
+        uiDomainService.updateResourceDefDomainList(domainId, resourceDefs);
+        DomainRO domainRO = uiDomainService.getDomainData(domainId);
+        domainRO.setStatus(EntityROStatus.UPDATED.getStatusNumber());
+        return domainRO;
     }
 
+    @PostMapping(path = "/{user-enc-id}/{domain-enc-id}/update-sml-integration-data", produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isSystemAdministrator")
+    public DomainRO updateSmlIntegrationData(@PathVariable("user-enc-id") String userEncId,
+                                                @PathVariable("domain-enc-id") String domainEncId,
+                                                @RequestBody DomainRO domainData) {
+        logAdminAccess("updateSmlIntegrationData:" + domainEncId);
+        Long domainId = SessionSecurityUtils.decryptEntityId(domainEncId);
+        LOG.info("Update domain integration data for id [{}]", domainId);
+        uiDomainService.updateDomainSmlIntegrationData(domainId, domainData);
+        DomainRO domainRO = uiDomainService.getDomainData(domainId);
+        domainRO.setStatus(EntityROStatus.UPDATED.getStatusNumber());
+        return domainRO;
+    }
+
+
+
     @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
     @PutMapping(value = "/{user-id}/sml-register/{domain-code}")
     public SMLIntegrationResult registerDomainAndParticipants(@PathVariable("user-id") String userId,
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/testutils/MockMvcUtils.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/testutils/MockMvcUtils.java
index 420820e8d..9c911b2aa 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/testutils/MockMvcUtils.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/testutils/MockMvcUtils.java
@@ -1,7 +1,9 @@
 package eu.europa.ec.edelivery.smp.test.testutils;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.type.CollectionType;
 import eu.europa.ec.edelivery.smp.data.ui.UserRO;
 import org.springframework.http.HttpHeaders;
 import org.springframework.mock.web.MockHttpSession;
@@ -16,6 +18,8 @@ import org.springframework.web.context.WebApplicationContext;
 
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
 
 import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLIC_SECURITY;
 import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLIC_SECURITY_AUTHENTICATION;
@@ -136,4 +140,16 @@ public class MockMvcUtils {
         return mvc;
     }
 
+    public static <T> List<T> parseResponseArray(MvcResult result, Class<T> clazz) throws UnsupportedEncodingException, JsonProcessingException {
+        CollectionType collectionType = mapper.getTypeFactory().constructCollectionType(List.class, clazz);
+        return mapper.readValue(result.getResponse().getContentAsString(), collectionType);
+    }
+
+    public static <T> T parseResponse(MvcResult result, Class<T> clazz) throws UnsupportedEncodingException, JsonProcessingException {
+        return mapper.readValue(result.getResponse().getContentAsString(), clazz);
+    }
+
+    public static String serializeObject(Object object) throws JsonProcessingException {
+        return mapper.writeValueAsString(object);
+    }
 }
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIntegrationTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIntegrationTest.java
index dcd87e6df..2df22e760 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIntegrationTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIntegrationTest.java
@@ -84,8 +84,8 @@ public class DomainResourceIntegrationTest {
             DomainRO sgro = mapper.convertValue(sgMap, DomainRO.class);
             assertNotNull(sgro.getDomainCode());
             assertNotNull(sgro.getSmlSubdomain());
-            // for public endpot all other data must be null!
-            assertNull(sgro.getId());
+            // for public endpoint all other data must be null!
+            assertNull(sgro.getDomainId());
             assertNull(sgro.getSmlSmpId());
             assertNull(sgro.getSignatureKeyAlias());
         });
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResourceIntegrationTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResourceIntegrationTest.java
index d2d85719e..43c7fc0d2 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResourceIntegrationTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResourceIntegrationTest.java
@@ -2,10 +2,15 @@ package eu.europa.ec.edelivery.smp.ui.internal;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 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.DeleteEntityValidation;
+import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
+import eu.europa.ec.edelivery.smp.data.ui.UserRO;
+import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
 import eu.europa.ec.edelivery.smp.test.SmpTestWebAppConfig;
 import eu.europa.ec.edelivery.smp.test.testutils.MockMvcUtils;
 import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
+import org.apache.commons.lang3.StringUtils;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -20,12 +25,14 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.MvcResult;
 import org.springframework.web.context.WebApplicationContext;
 
-import static eu.europa.ec.edelivery.smp.test.testutils.MockMvcUtils.loginWithSystemAdmin;
+import java.util.List;
+
+import static eu.europa.ec.edelivery.smp.test.testutils.MockMvcUtils.*;
 import static org.hamcrest.Matchers.stringContainsInOrder;
 import static org.junit.Assert.*;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
 import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.BEFORE_TEST_METHOD;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
@@ -54,31 +61,121 @@ public class DomainAdminResourceIntegrationTest {
     }
 
     @Test
-    public void updateDomainListOkDelete() throws Exception {
-// given when
-        assertEquals("CEF-SMP-002", domainDao.getDomainByCode("domainTwo").get().getSmlSmpId());
+    public void testGetAllDomains() throws Exception {
+        List<DBDomain> domain = domainDao.getAllDomains();
         MockHttpSession session = loginWithSystemAdmin(mvc);
-        MvcResult result = mvc.perform(put(PATH)
-                .session(session)
-                .with(csrf())
-                .header("Content-Type", " application/json")
-                .content("[{\"status\":3,\"index\":9,\"id\":2,\"domainCode\":\"domainTwo\",\"smlSubdomain\":\"newdomain\",\"smlSmpId\":\"CEF-SMP-010\",\"smlParticipantIdentifierRegExp\":null,\"smlClientCertHeader\":null,\"smlClientKeyAlias\":null,\"signatureKeyAlias\":\"sig-key\",\"smlClientCertAuth\":true,\"smlRegistered\":false}]")) // delete domain with id 2
+        UserRO userRO = MockMvcUtils.getLoggedUserData(mvc, session);
+
+        MvcResult result = mvc.perform(get(PATH + "/" + userRO.getUserId())
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json"))
                 .andExpect(status().isOk()).andReturn();
 
-        // check if exists
-        assertFalse(domainDao.getDomainByCode("domainTwo").isPresent());
+        List<DomainRO> response = parseResponseArray(result, DomainRO.class);
+        assertEquals(domain.size(), response.size());
+    }
+
+    @Test
+    public void testDeleteDomainOK() throws Exception {
+        // given - delete domain two :)
+        String domainCode = "domainTwo";
+        MockHttpSession session = loginWithSystemAdmin(mvc);
+        UserRO userRO = MockMvcUtils.getLoggedUserData(mvc, session);
+        DomainRO domainToDelete = getDomain(domainCode, userRO, session);
+        assertNotNull(domainToDelete);
+
+        MvcResult result = mvc.perform(delete(PATH + "/" + userRO.getUserId() + "/" + domainToDelete.getDomainId() + "" + "/delete")
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")) // delete domain with id 2
+                .andExpect(status().isOk()).andReturn();
+        DomainRO resultObject = parseResponse(result, DomainRO.class);
+        //
+        assertNotNull(resultObject);
+        assertEquals(domainCode, resultObject.getDomainCode());
+        assertEquals(EntityROStatus.REMOVE.getStatusNumber(), resultObject.getStatus());
+    }
+
+    @Test
+    public void updateDomainData() throws Exception {
+        String domainCode = "domainTwo";
+        MockHttpSession session = loginWithSystemAdmin(mvc);
+        UserRO userRO = MockMvcUtils.getLoggedUserData(mvc, session);
+        DomainRO domainToUpdate = getDomain(domainCode, userRO, session);
+        domainToUpdate.setDomainCode("NewCode");
+        domainToUpdate.setSignatureKeyAlias("New alias");
+
+        MvcResult result = mvc.perform(post(PATH + "/" + userRO.getUserId() + "/" + domainToUpdate.getDomainId() + "" + "/update")
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")
+                        .content(entitiToString(domainToUpdate)))
+                .andExpect(status().isOk()).andReturn();
+        DomainRO resultObject = parseResponse(result, DomainRO.class);
+        //
+        assertNotNull(resultObject);
+        assertEquals(domainToUpdate.getDomainCode(), resultObject.getDomainCode());
+        assertEquals(EntityROStatus.UPDATED.getStatusNumber(), resultObject.getStatus());
+    }
+    @Test
+    public void updateDomainSmlIntegrationData() throws Exception {
+        String domainCode = "domainTwo";
+        MockHttpSession session = loginWithSystemAdmin(mvc);
+        UserRO userRO = MockMvcUtils.getLoggedUserData(mvc, session);
+        DomainRO domainToUpdate = getDomain(domainCode, userRO, session);
+        domainToUpdate.setSmlSubdomain("NewCode");
+        domainToUpdate.setSmlClientKeyAlias("New alias");
+
+        MvcResult result = mvc.perform(post(PATH + "/" + userRO.getUserId() + "/" + domainToUpdate.getDomainId() + "" + "/update-sml-integration-data")
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")
+                        .content(entitiToString(domainToUpdate)))
+                .andExpect(status().isOk()).andReturn();
+        DomainRO resultObject = parseResponse(result, DomainRO.class);
+        //
+        assertNotNull(resultObject);
+        assertEquals(domainToUpdate.getDomainCode(), resultObject.getDomainCode());
+        assertEquals(EntityROStatus.UPDATED.getStatusNumber(), resultObject.getStatus());
     }
 
+    @Test
+    @Ignore
+    public void updateDomainDataAddNewResourceDef() throws Exception {
+        // set the webapp_integration_test_data.sql for resourceDefID
+        String resourceDefID = "edelivery-oasis-cppa";
+        String domainCode = "domainTwo";
+        MockHttpSession session = loginWithSystemAdmin(mvc);
+        UserRO userRO = MockMvcUtils.getLoggedUserData(mvc, session);
+        DomainRO domainToUpdate = getDomain(domainCode, userRO, session);
+        domainToUpdate.getResourceDefinitions().add(resourceDefID);
 
+        MvcResult result = mvc.perform(post(PATH + "/" + userRO.getUserId() + "/" + domainToUpdate.getDomainId() + "" + "/update-resource-types")
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")
+                        .content(entitiToString(domainToUpdate.getResourceDefinitions())))
+                .andExpect(status().isOk()).andReturn();
+        DomainRO resultObject = parseResponse(result, DomainRO.class);
+        //
+        assertNotNull(resultObject);
+        assertEquals(domainToUpdate.getDomainCode(), resultObject.getDomainCode());
+        assertEquals(EntityROStatus.UPDATED.getStatusNumber(), resultObject.getStatus());
+    }
+
+/*
     @Test
     public void updateDomainListNotExists() throws Exception {
 // given when
         MockHttpSession session = loginWithSystemAdmin(mvc);
+
+
         MvcResult result = mvc.perform(put(PATH)
-                .session(session)
-                .with(csrf())
-                .header("Content-Type", " application/json")
-                .content("[{\"status\":3,\"index\":9,\"id\":10,\"domainCode\":\"domainTwoNotExist\",\"smlSubdomain\":\"newdomain\",\"smlSmpId\":\"CEF-SMP-010\",\"smlParticipantIdentifierRegExp\":null,\"smlClientCertHeader\":null,\"smlClientKeyAlias\":null,\"signatureKeyAlias\":\"sig-key\",\"smlClientCertAuth\":true,\"smlRegistered\":false}]")) // delete domain with id 2
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")
+                        .content("[{\"status\":3,\"index\":9,\"id\":10,\"domainCode\":\"domainTwoNotExist\",\"smlSubdomain\":\"newdomain\",\"smlSmpId\":\"CEF-SMP-010\",\"smlParticipantIdentifierRegExp\":null,\"smlClientCertHeader\":null,\"smlClientKeyAlias\":null,\"signatureKeyAlias\":\"sig-key\",\"smlClientCertAuth\":true,\"smlRegistered\":false}]")) // delete domain with id 2
                 .andExpect(status().isOk()).andReturn();
     }
 
@@ -87,10 +184,10 @@ public class DomainAdminResourceIntegrationTest {
         // given when
         MockHttpSession session = loginWithSystemAdmin(mvc);
         MvcResult result = mvc.perform(put(PATH + "/validate-delete")
-                .session(session)
-                .with(csrf())
-                .header("Content-Type", " application/json")
-                .content("[2]")) // delete domain with id 2
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")
+                        .content("[2]")) // delete domain with id 2
                 .andExpect(status().isOk()).andReturn();
 
         //them
@@ -110,10 +207,10 @@ public class DomainAdminResourceIntegrationTest {
         assertEquals("CEF-SMP-002", domainDao.getDomainByCode("domainTwo").get().getSmlSmpId());
         MockHttpSession session = loginWithSystemAdmin(mvc);
         MvcResult result = mvc.perform(put(PATH)
-                .session(session)
-                .with(csrf())
-                .header("Content-Type", " application/json")
-                .content("[{\"status\":1,\"index\":9,\"id\":2,\"domainCode\":\"domainTwo\",\"smlSubdomain\":\"newdomain\",\"smlSmpId\":\"CEF-SMP-010\",\"smlParticipantIdentifierRegExp\":null,\"smlClientCertHeader\":null,\"smlClientKeyAlias\":null,\"signatureKeyAlias\":\"sig-key\",\"smlClientCertAuth\":true,\"smlRegistered\":false}]")) // delete domain with id 2
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")
+                        .content("[{\"status\":1,\"index\":9,\"id\":2,\"domainCode\":\"domainTwo\",\"smlSubdomain\":\"newdomain\",\"smlSmpId\":\"CEF-SMP-010\",\"smlParticipantIdentifierRegExp\":null,\"smlClientCertHeader\":null,\"smlClientKeyAlias\":null,\"signatureKeyAlias\":\"sig-key\",\"smlClientCertAuth\":true,\"smlRegistered\":false}]")) // delete domain with id 2
                 .andExpect(status().isOk()).andReturn();
 
         // check if exists
@@ -125,10 +222,10 @@ public class DomainAdminResourceIntegrationTest {
         // given when
         MockHttpSession session = loginWithSystemAdmin(mvc);
         MvcResult result = mvc.perform(put(PATH + "/validate-delete")
-                .session(session)
-                .with(csrf())
-                .header("Content-Type", " application/json")
-                .content("[1]")) // delete domain with id 2
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json")
+                        .content("[1]")) // delete domain with id 2
                 .andExpect(status().isOk()).andReturn();
 
         //them
@@ -149,25 +246,50 @@ public class DomainAdminResourceIntegrationTest {
         // domainTwo -  domain code
         MockHttpSession session = loginWithSystemAdmin(mvc);
         mvc.perform(put(PATH + "/3/sml-register/domainTwo")
-                .session(session)
-                .with(csrf())
-                .header("Content-Type", " application/json"))
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json"))
                 .andExpect(status().isOk())
                 .andExpect(content().string(stringContainsInOrder("Configuration error: [SML integration is not enabled!]!")));
     }
 
     @Test
-    @Ignore
     public void unregisterDomainAndParticipants() throws Exception {
         // given when
         // 3- user id
         // domainTwo -  domain code
         MockHttpSession session = loginWithSystemAdmin(mvc);
         mvc.perform(put(PATH + "/3/sml-unregister/domainTwo")
-                .session(session)
-                .with(csrf())
-                .header("Content-Type", " application/json"))
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json"))
                 .andExpect(status().isOk())
                 .andExpect(content().string(stringContainsInOrder("Configuration error: SML integration is not enabled!!")));
     }
+*/
+
+    private List<DomainRO> getAllDomains(UserRO userRO, MockHttpSession session) throws Exception {
+        MvcResult result = mvc.perform(get(PATH + "/" + userRO.getUserId())
+                        .session(session)
+                        .with(csrf())
+                        .header("Content-Type", " application/json"))
+                .andExpect(status().isOk()).andReturn();
+        return parseResponseArray(result, DomainRO.class);
+    }
+
+    private DomainRO getDomain(String domainCode, UserRO userRO, MockHttpSession session) throws Exception {
+        List<DomainRO> allDomains = getAllDomains(userRO, session);
+
+        return allDomains.stream()
+                .filter(domainRO -> StringUtils.equals(domainCode, domainRO.getDomainCode()))
+                .findFirst().orElse(null);
+
+    }
+
+    private String entitiToString(Object object ) throws Exception {
+            return serializeObject(object);
+
+
+    }
+
 }
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 f8604ad49..5adcfae38 100644
--- a/smp-webapp/src/test/resources/webapp_integration_test_data.sql
+++ b/smp-webapp/src/test/resources/webapp_integration_test_data.sql
@@ -107,7 +107,8 @@ insert into SMP_EXTENSION ( ID, IDENTIFIER,  IMPLEMENTATION_NAME, NAME, VERSION,
 (1, 'edelivery-oasis-smp-extension',  'OasisSMPExtension','Oasis SMP 1.0 and 2.0','1.0', 'Oasis SMP 1.0 and 2.0 extension',  NOW(),  NOW());
 
 insert into SMP_RESOURCE_DEF ( ID, FK_EXTENSION_ID, URL_SEGMENT, IDENTIFIER, DESCRIPTION, MIME_TYPE, NAME, CREATED_ON, LAST_UPDATED_ON) values
-(1, 1, 'smp-1', 'edelivery-oasis-smp-1.0-servicegroup', 'Service group', 'application/xml','Oasis SMP ServiceGroup', NOW(),  NOW());
+(1, 1, 'smp-1', 'edelivery-oasis-smp-1.0-servicegroup', 'Service group', 'application/xml','Oasis SMP ServiceGroup', NOW(),  NOW()),
+(2, 1, 'cpa-1', 'edelivery-oasis-cppa', 'Cppa document group', 'application/xml','Oasis SMP cpa document', NOW(),  NOW());
 insert into SMP_SUBRESOURCE_DEF (ID,FK_RESOURCE_DEF_ID,URL_SEGMENT, IDENTIFIER, DESCRIPTION, MIME_TYPE, NAME, CREATED_ON, LAST_UPDATED_ON) values
 (1,1, 'services', 'edelivery-oasis-smp-1.0-servicemetadata', 'ServiceMetadata', 'application/xml','Oasis SMP ServiceMetadata', NOW(),  NOW());
 -- register document types for domain
-- 
GitLab