From 3407cff2b20687a247ae3273c09b2ac9f27a2040 Mon Sep 17 00:00:00 2001
From: Joze RIHTARSIC <joze.rihtarsic@ext.ec.europa.eu>
Date: Tue, 27 Nov 2018 21:23:26 +0100
Subject: [PATCH] - sml integration fix

---
 smp-angular/src/app/app.module.ts             |   2 +
 .../src/app/domain/domain.component.ts        |  47 ++++-
 .../src/app/domain/sml-integration.service.ts |  28 +++
 .../smp/data/dao/ServiceGroupDao.java         |  28 +++
 .../smp/data/model/DBServiceGroupDomain.java  |   5 +
 .../edelivery/smp/services/DomainService.java |  69 ++++++-
 .../smp/services/ui/UIDomainService.java      |  15 +-
 .../edelivery/smp/sml/SmlClientFactory.java   |  20 +-
 .../ec/edelivery/smp/sml/SmlConnector.java    |  14 +-
 .../edelivery/smp/utils/SMPPropertyEnum.java  |   4 +
 .../AbstractServiceIntegrationTest.java       |   2 +-
 .../DomainServiceIntegrationTest.java         | 183 +++++++++++++++++-
 ...nticationByClientCertFromKeystoreTest.java |   6 +-
 ...henticationByClientCertHttpHeaderTest.java |  19 +-
 .../smp/config/PropertiesConfig.java          |  57 +++++-
 .../edelivery/smp/ui/ApplicationResource.java |  34 ++--
 .../ec/edelivery/smp/ui/DomainResource.java   |  38 ++++
 .../ec/edelivery/smp/ui/KeystoreResource.java |   2 +-
 .../src/main/resources/application.properties |   3 +
 .../src/main/resources/config.properties      |   4 -
 .../smp/config/PropertiesTestConfig.java      |  26 +--
 .../smp/ui/ApplicationResourceTest.java       |  38 +++-
 .../smp/ui/KeystoreResourceTest.java          |  91 +++++++++
 23 files changed, 662 insertions(+), 73 deletions(-)
 create mode 100644 smp-angular/src/app/domain/sml-integration.service.ts
 create mode 100644 smp-webapp/src/main/resources/application.properties
 create mode 100644 smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/KeystoreResourceTest.java

diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts
index b8c662cb3..dcdb47728 100644
--- a/smp-angular/src/app/app.module.ts
+++ b/smp-angular/src/app/app.module.ts
@@ -84,6 +84,7 @@ import {KeystoreEditDialogComponent} from "./domain/keystore-edit-dialog/keystor
 import {KeystoreCertificateDialogComponent} from "./domain/keystore-certificate-dialog/keystore-certificate-dialog.component";
 import {InformationDialogComponent} from "./common/information-dialog/information-dialog.component";
 import {KeystoreService} from "./domain/keystore.service";
+import {SmlIntegrationService} from "./domain/sml-integration.service";
 
 @NgModule({
   declarations: [
@@ -183,6 +184,7 @@ import {KeystoreService} from "./domain/keystore.service";
     DownloadService,
     CertificateService,
     KeystoreService,
+    SmlIntegrationService,
     GlobalLookups,
     DatePipe,
     UserService,
diff --git a/smp-angular/src/app/domain/domain.component.ts b/smp-angular/src/app/domain/domain.component.ts
index e9bb5f445..ac87020b7 100644
--- a/smp-angular/src/app/domain/domain.component.ts
+++ b/smp-angular/src/app/domain/domain.component.ts
@@ -15,6 +15,8 @@ import {SearchTableEntityStatus} from "../common/search-table/search-table-entit
 import {KeystoreEditDialogComponent} from "./keystore-edit-dialog/keystore-edit-dialog.component";
 import {SmpInfoService} from "../app-info/smp-info.service";
 import {SmpInfo} from "../app-info/smp-info.model";
+import {SmlIntegrationService} from "./sml-integration.service";
+import {KeystoreResult} from "./keystore-result.model";
 
 @Component({
   moduleId: module.id,
@@ -40,6 +42,7 @@ export class DomainComponent implements OnInit {
 
   constructor(public securityService: SecurityService,
               protected smpInfoService: SmpInfoService,
+              protected smlIntegrationService:SmlIntegrationService,
               protected lookups: GlobalLookups,
               protected http: HttpClient,
               protected alertService: AlertService,
@@ -173,6 +176,27 @@ export class DomainComponent implements OnInit {
     })
   }
 
+  smlUnregisterDomain(domainCode:string){
+    this.smlIntegrationService.unregisterDomainToSML$(domainCode).subscribe((res) => {
+        if (res) {
+          if (res.errorMessage){
+            this.alertService.exception("Error occurred while unregistering domain:" + domainCode , res.errorMessage, false);
+          } else {
+            this.alertService.success("Domain " + domainCode + " unregistering to sml!");
+            this.lookups.refreshDomainLookup();
+
+          }
+        } else {
+          this.alertService.exception("Error occurred while unregistering domain:" + domainCode , "Unknown Error", false);
+        }
+      },
+      err => {
+        this.alertService.exception('Error occurred while unregistering domain:' + domainCode , err);
+      }
+    )
+
+  }
+
   smlRegisterSelectedDomain() {
     if (this.searchTable.selected.length !== 1) {
       return false;
@@ -187,11 +211,32 @@ export class DomainComponent implements OnInit {
       }
     }).afterClosed().subscribe(result => {
       if (result) {
-        domainRo.smlRegistered=true;
+        this.smlRegisterDomain(domainRo.domainCode);
       }
     })
   }
 
+  smlRegisterDomain(domainCode:string){
+    this.smlIntegrationService.registerDomainToSML$(domainCode).subscribe((res) => {
+        if (res) {
+          if (res.errorMessage){
+            this.alertService.exception("Error occurred while registering domain:" + domainCode , res.errorMessage, false);
+          } else {
+            this.alertService.success("Domain " + domainCode + " registered to sml!");
+            this.lookups.refreshDomainLookup();
+
+          }
+        } else {
+          this.alertService.exception("Error occurred while registering domain:" + domainCode , "Unknown Error", false);
+        }
+      },
+      err => {
+        this.alertService.exception('Error occurred while registering domain:' + domainCode , err);
+      }
+    )
+
+  }
+
   openEditKeystoreDialog() {
     const formRef: MatDialogRef<any> = this.dialog.open(KeystoreEditDialogComponent);
     formRef.afterClosed().subscribe(result => {
diff --git a/smp-angular/src/app/domain/sml-integration.service.ts b/smp-angular/src/app/domain/sml-integration.service.ts
new file mode 100644
index 000000000..170c594f7
--- /dev/null
+++ b/smp-angular/src/app/domain/sml-integration.service.ts
@@ -0,0 +1,28 @@
+import {Injectable} from '@angular/core';
+import {Observable} from 'rxjs';
+
+import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
+import {SmpConstants} from "../smp.constants";
+import {SecurityService} from "../security/security.service";
+import {User} from "../security/user.model";
+import {KeystoreResult} from "./keystore-result.model";
+
+@Injectable()
+export class SmlIntegrationService {
+
+  constructor(
+    private http: HttpClient,
+    private securityService: SecurityService) {
+  }
+
+  registerDomainToSML$(domainCode): Observable<KeystoreResult> {
+
+    const currentUser: User = this.securityService.getCurrentUser();
+    return this.http.post<KeystoreResult>(`${SmpConstants.REST_DOMAIN}/${currentUser.id}/smlregister/${domainCode}`, {});
+  }
+
+  unregisterDomainToSML$(domainCode): Observable<KeystoreResult> {
+    const currentUser: User = this.securityService.getCurrentUser();
+    return this.http.post(`${SmpConstants.REST_DOMAIN}/${currentUser.id}/smlunregister/${domainCode}`,{});
+  }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDao.java
index e7027ca35..39c90f718 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ServiceGroupDao.java
@@ -60,6 +60,34 @@ public class ServiceGroupDao extends BaseDao<DBServiceGroup> {
         }
     }
 
+    /**
+     * Method returns ServiceGroupDomain for participant identifie and domain code. If there is no service group
+     * or service group registred to domain it returns empty Option.
+     * If more than one result returns IllegalStateException caused by database data inconsistency. Only one combination of
+     * participant identifier must be in the database.
+     *
+     * @param participantId participant identifier
+     * @param schema        participant identifier schema
+     * @param domainCode     domainCode
+     * @return DBServiceGroup
+     */
+    public Optional<DBServiceGroupDomain> findServiceGroupDomain(String participantId, String schema, String domainCode) {
+
+
+        try {
+            TypedQuery<DBServiceGroupDomain> query = memEManager.createNamedQuery("DBServiceGroupDomain.getServiceGroupDomain", DBServiceGroupDomain.class);
+            query.setParameter("participantIdentifier", participantId);
+            query.setParameter("participantScheme", schema);
+            query.setParameter("domainCode", domainCode);
+            DBServiceGroupDomain res = query.getSingleResult();
+            return Optional.of(res);
+        } catch (NoResultException e) {
+            return Optional.empty();
+        } catch (NonUniqueResultException e) {
+            throw new IllegalStateException(ErrorCode.ILLEGAL_STATE_SG_MULTIPLE_ENTRY.getMessage(participantId, schema));
+        }
+    }
+
     /**
      * Method removes service group from DB. Related entities:Extension, ownerships,
      * metadata clobs, metadata are also deleted.
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroupDomain.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroupDomain.java
index 3f61f7926..0969db1cc 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroupDomain.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroupDomain.java
@@ -16,6 +16,11 @@ import java.util.Objects;
 @Entity
 @Audited
 @Table(name = "SMP_SERVICE_GROUP_DOMAIN")
+@NamedNativeQueries({
+        @NamedNativeQuery(name = "DBServiceGroupDomain.getServiceGroupDomain", query = "SELECT sgd.* FROM SMP_DOMAIN dmn  INNER JOIN SMP_SERVICE_GROUP_DOMAIN sgd ON sgd.FK_DOMAIN_ID = dmn.id " +
+                " INNER JOIN SMP_SERVICE_GROUP sg  ON sg.ID = sgd.FK_SG_ID " +
+                " where sg.PARTICIPANT_IDENTIFIER = :participantIdentifier AND sg.PARTICIPANT_SCHEME=:participantScheme and dmn.DOMAIN_CODE =:domainCode", resultClass=DBServiceGroupDomain.class)
+})
 public class DBServiceGroupDomain extends BaseEntity {
 
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java
index 5a3823b51..35b0eeeba 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java
@@ -1,22 +1,36 @@
 package eu.europa.ec.edelivery.smp.services;
 
 
+import eu.europa.ec.edelivery.smp.conversion.CaseSensitivityNormalizer;
 import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
+import eu.europa.ec.edelivery.smp.data.dao.ServiceGroupDao;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.DBServiceGroup;
+import eu.europa.ec.edelivery.smp.data.model.DBServiceGroupDomain;
 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.ui.filters.ServiceGroupFilter;
+import eu.europa.ec.edelivery.smp.sml.SmlConnector;
 import org.apache.commons.lang3.StringUtils;
+import org.oasis_open.docs.bdxr.ns.smp._2016._05.ParticipantIdentifierType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.validation.constraints.NotNull;
+import java.util.List;
 import java.util.Optional;
 import java.util.regex.Pattern;
 
 import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.*;
+import static eu.europa.ec.edelivery.smp.logging.SMPMessageCode.BUS_SML_REGISTER_SERVICE_GROUP;
+import static eu.europa.ec.edelivery.smp.logging.SMPMessageCode.BUS_SML_REGISTER_SERVICE_GROUP_ALREADY_REGISTERED;
+import static eu.europa.ec.edelivery.smp.logging.SMPMessageCode.BUS_SML_REGISTER_SERVICE_GROUP_FAILED;
 
 
 /**
- * Service group domain
+ * Service for domain
  * @author Joze Rihtarsic
  * @since 4.1
  */
@@ -24,12 +38,21 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.*;
 @Service
 public class DomainService {
 
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainService.class);
+
     public static final Pattern DOMAIN_ID_PATTERN = Pattern.compile("[a-zA-Z0-9]{1,50}");
 
+    @Autowired
+    private SMLIntegrationService smlIntegrationService;
+
+    @Autowired
+    private ServiceGroupDao serviceGroupDao;
+
     @Autowired
     private DomainDao domainDao;
 
 
+
     /**
      * Method checks if domain is in right format. Domain must contains only alphanomeric chars and it shoud
      * not be longer than 50 chars.
@@ -57,4 +80,48 @@ public class DomainService {
         }
         return domEntity.get();
     }
+
+    /**
+     * If domain is not yet registered and sml integration is on. Than it tries to register domain and  all participants
+     * on that domain. If integration is off it return an configuration exception.
+     *
+     * Method is not in transaction - but sub-methods are. if registering domain or particular serviceGroup succeed
+     * then the database flag (SML_REGISTERED) is turned on ( if method fails
+     * while execution the SML_REGISTERED reflect the real status in SML). Running the method again updates only
+     * serviceGroup which are not yet registered.
+     *
+     *
+     * @param domain
+     */
+
+    public void registerDomainAndParticipants(DBDomain domain){
+
+        smlIntegrationService.registerDomain(domain);
+        // get all participant for domain and register them
+        ServiceGroupFilter serviceGroupFilter = new ServiceGroupFilter();
+        serviceGroupFilter.setDomain(domain);
+
+        // register all service groups
+        List<DBServiceGroup> serviceGroupList = serviceGroupDao.getServiceGroupList(-1, -1, null, null, serviceGroupFilter);
+        for (DBServiceGroup sg: serviceGroupList){
+
+            smlIntegrationService.registerParticipant(sg.getParticipantIdentifier(), sg.getParticipantScheme(), domain.getDomainCode());
+        }
+    }
+
+    public void unregisterDomainAndParticipantsFromSml(DBDomain domain){
+
+        // get all participant for domain and register them
+        ServiceGroupFilter serviceGroupFilter = new ServiceGroupFilter();
+        serviceGroupFilter.setDomain(domain);
+
+        // register all service groups
+        List<DBServiceGroup> serviceGroupList = serviceGroupDao.getServiceGroupList(-1, -1, null, null, serviceGroupFilter);
+        for (DBServiceGroup sg: serviceGroupList){
+            smlIntegrationService.unregisterParticipant(sg.getParticipantIdentifier(), sg.getParticipantScheme(), domain.getDomainCode());
+        }
+
+        smlIntegrationService.unRegisterDomain(domain);
+    }
+
 }
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 b1e61b6e1..a890d00a0 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
@@ -9,6 +9,8 @@ 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.ServiceResult;
 import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
+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.beans.factory.annotation.Autowired;
@@ -18,10 +20,12 @@ import org.springframework.transaction.annotation.Transactional;
 import java.io.StringWriter;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Optional;
 
 @Service
 public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
 
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDomainService.class);
     @Autowired
     DomainDao domainDao;
 
@@ -55,8 +59,6 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
     public void updateDomainList(List<DomainRO> lst) {
         boolean suc = false;
         for (DomainRO dRo: lst){
-
-
             if (dRo.getStatus() == EntityROStatus.NEW.getStatusNumber()) {
                 DBDomain dDb = convertFromRo(dRo);
                 domainDao.persistFlushDetach(dDb);
@@ -99,13 +101,4 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
         return dev;
     }
 
-    public void registerDomainToSml(){
-
-     //   smlConnector.registerInDns()
-
-        // get participants for domain
-
-
-    }
-
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlClientFactory.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlClientFactory.java
index 7f489efb8..ca4be757e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlClientFactory.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlClientFactory.java
@@ -39,6 +39,7 @@ import javax.net.ssl.KeyManagerFactory;
 import javax.xml.ws.BindingProvider;
 import javax.xml.ws.handler.MessageContext;
 import java.io.FileInputStream;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.KeyStore;
 import java.util.HashMap;
@@ -96,9 +97,17 @@ public class SmlClientFactory {
         IManageParticipantIdentifierWS smlPort = smlService.getManageBusinessIdentifierServicePort();
         Client client = ClientProxy.getClient(smlPort);
 
+        URL urlParticipantIdentifier;
+        try {
+            urlParticipantIdentifier = new URL(smlUrl.getProtocol(), smlUrl.getHost(), smlUrl.getPort(), smlUrl.getFile() + "/manageparticipantidentifier", null);
+        } catch (MalformedURLException e) {
+            throw new IllegalStateException("Could not create participant URL: " + smlUrl.toString(), e);
+        }
+
+
         HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
         Map<String, Object> requestContext = ((BindingProvider) smlPort).getRequestContext();
-        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, smlUrl.toString());
+        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, urlParticipantIdentifier.toString());
 
         configureFaultHandling(requestContext);
         configureProxy(httpConduit);
@@ -115,9 +124,16 @@ public class SmlClientFactory {
         IManageServiceMetadataWS smlPort = smlService.getManageServiceMetadataServicePort();
         Client client = ClientProxy.getClient(smlPort);
 
+        URL urlSMPManagment;
+        try {
+            urlSMPManagment = new URL(smlUrl.getProtocol(), smlUrl.getHost(), smlUrl.getPort(), smlUrl.getFile() + "/manageservicemetadata", null);
+        } catch (MalformedURLException e) {
+            throw new IllegalStateException("Could not create participant URL: " + smlUrl.toString(), e);
+        }
+
         HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
         Map<String, Object> requestContext = ((BindingProvider) smlPort).getRequestContext();
-        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, smlUrl.toString());
+        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, urlSMPManagment.toString());
 
         configureFaultHandling(requestContext);
         configureProxy(httpConduit);
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java
index 604da7bfc..e82629674 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java
@@ -49,6 +49,12 @@ public class SmlConnector implements ApplicationContextAware {
     @Value("${bdmsl.integration.enabled:false}")
     private boolean smlIntegrationEnabled;
 
+    @Value("${bdmsl.integration.logical.address:}")
+    private String smpLogicalAddress;
+
+    @Value("${bdmsl.integration.physical.address:0.0.0.0}")
+    private String smpPhysicalAddress;
+
     private ApplicationContext ctx;
 
     public boolean registerInDns(ParticipantIdentifierType normalizedParticipantId, DBDomain domain) {
@@ -76,7 +82,8 @@ public class SmlConnector implements ApplicationContextAware {
         try {
             ServiceMetadataPublisherServiceType smlSmpRequest = new ServiceMetadataPublisherServiceType();
             smlSmpRequest.setPublisherEndpoint(new PublisherEndpointType());
-
+            smlSmpRequest.getPublisherEndpoint().setLogicalAddress(smpLogicalAddress);
+            smlSmpRequest.getPublisherEndpoint().setPhysicalAddress(smpPhysicalAddress);
             smlSmpRequest.setServiceMetadataPublisherID(domain.getSmlSmpId());
             getSMPManagerClient(domain).create(smlSmpRequest);
             return true;
@@ -99,13 +106,14 @@ public class SmlConnector implements ApplicationContextAware {
         }
     }
 
-    public void unregisterDomain(DBDomain domain) {
+    public boolean unregisterDomain(DBDomain domain) {
         if (!smlIntegrationEnabled) {
-            return;
+            return true;
         }
         log.info("Removing SMP id (Domain) from BDMSL: {} ", domain.getDomainCode());
         try {
             getSMPManagerClient(domain).delete(domain.getSmlSmpId());
+            return true;
         } catch (Exception e) {
             throw new SMPRuntimeException(ErrorCode.SML_INTEGRATION_EXCEPTION,e, ExceptionUtils.getRootCauseMessage(e));
         }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPPropertyEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPPropertyEnum.java
index 4652b317d..88cb3e08b 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPPropertyEnum.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPPropertyEnum.java
@@ -11,6 +11,10 @@ public enum SMPPropertyEnum {
     CS_DOCUMENTS("identifiersBehaviour.caseSensitive.DocumentIdentifierSchemes","casesensitive-doc-scheme1|casesensitive-doc-scheme2","Specifies schemes of document identifiers that must be considered CASE-SENSITIVE."),
     SML_ENABLED("bdmsl.integration.enabled","false","BDMSL (SML) integration ON/OFF switch"),
     SML_URL("bdmsl.integration.url","http://localhost:8080/edelivery-sml/","BDMSL (SML) endpoint"),
+
+    SML_LOGICAL_ADDRESS("bdmsl.integration.logical.address","http://localhost:8080/smp/","BDMSL (SML) endpoint"),
+    SML_PHYSICAL_ADDRESS("bdmsl.integration.physical.address","0.0.0.0","BDMSL (SML) endpoint"),
+
     SML_PROXY_HOST("bdmsl.integration.proxy.server","","Proxy "),
     SML_PROXY_PORT("bdmsl.integration.proxy.port","","Proxy "),
     SML_PROXY_USER("bdmsl.integration.proxy.user","","Proxy "),
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java
index 9f0beba3a..3c154d1c3 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java
@@ -39,7 +39,7 @@ import static eu.europa.ec.edelivery.smp.testutil.TestConstants.*;
         CaseSensitivityNormalizer.class,SmlConnector.class,ServiceMetadataSigner.class,
         ServiceGroupService.class, DomainService.class, ServiceMetadataService.class,
         ServiceGroupDao.class,ServiceMetadataDao.class, DomainDao.class, UserDao.class,DBAssertion.class,
-        UIKeystoreService.class, ConversionTestConfig.class, SecurityUtilsServices.class})
+        UIKeystoreService.class, ConversionTestConfig.class, SecurityUtilsServices.class, SMLIntegrationService.class})
 @Sql(scripts = "classpath:cleanup-database.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, config = @SqlConfig
         (transactionMode = SqlConfig.TransactionMode.ISOLATED,
                 transactionManager = "transactionManager",
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/DomainServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/DomainServiceIntegrationTest.java
index 6fddbf144..bf7e37947 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/DomainServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/DomainServiceIntegrationTest.java
@@ -13,44 +13,71 @@
 
 package eu.europa.ec.edelivery.smp.services;
 
+import eu.europa.ec.bdmsl.ws.soap.BadRequestFault;
+import eu.europa.ec.bdmsl.ws.soap.InternalErrorFault;
+import eu.europa.ec.bdmsl.ws.soap.NotFoundFault;
+import eu.europa.ec.bdmsl.ws.soap.UnauthorizedFault;
+import eu.europa.ec.edelivery.smp.config.H2JPATestConfig;
+import eu.europa.ec.edelivery.smp.config.SmlIntegrationConfiguration;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.DBServiceGroupDomain;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import eu.europa.ec.edelivery.smp.sml.SmlConnector;
 import eu.europa.ec.edelivery.smp.testutil.TestConstants;
 import eu.europa.ec.edelivery.smp.testutil.TestDBUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.transaction.annotation.Transactional;
 
-import static eu.europa.ec.edelivery.smp.testutil.TestConstants.TEST_DOMAIN_CODE_1;
-import static org.junit.Assert.assertEquals;
+import javax.xml.ws.http.HTTPException;
+
+import static eu.europa.ec.edelivery.smp.testutil.TestConstants.*;
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
 
 /**
- *  Purpose of class is to test ServiceGroupService base methods
+ * Purpose of class is to test ServiceGroupService base methods
  *
  * @author Joze Rihtarsic
  * @since 4.1
  */
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = {SmlIntegrationConfiguration.class,
+        SmlConnector.class, DomainService.class, SMLIntegrationService.class,
+        H2JPATestConfig.class})
+@TestPropertySource(properties = {"bdmsl.integration.enabled=true"})
 public class DomainServiceIntegrationTest extends AbstractServiceIntegrationTest {
 
     @Rule
     public ExpectedException expectedExeption = ExpectedException.none();
 
+    @Autowired
+    SmlIntegrationConfiguration integrationMock;
+
+
     @Autowired
     protected DomainService testInstance;
 
     @Before
     @Transactional
     public void prepareDatabase() {
+        integrationMock.reset();
         prepareDatabaseForSignleDomainEnv();
     }
 
-
     @Test
-    public void getDomainForBlankCodeForSingleDomain(){
+    public void getDomainForBlankCodeForSingleDomain() {
 
         // given
         assertEquals(1, domainDao.getAllDomains().size());
@@ -65,9 +92,9 @@ public class DomainServiceIntegrationTest extends AbstractServiceIntegrationTest
     }
 
     @Test
-    public void getDomainForBlankCodeForMultipleDomain(){
+    public void getDomainForBlankCodeForMultipleDomain() {
         // given
-        DBDomain testDomain02 =TestDBUtils.createDBDomain(TestConstants.TEST_DOMAIN_CODE_2);
+        DBDomain testDomain02 = TestDBUtils.createDBDomain(TEST_DOMAIN_CODE_2);
         domainDao.persistFlushDetach(testDomain02);
         assertEquals(2, domainDao.getAllDomains().size());
         expectedExeption.expect(SMPRuntimeException.class);
@@ -79,9 +106,151 @@ public class DomainServiceIntegrationTest extends AbstractServiceIntegrationTest
     }
 
 
+    @Test
+    public void registerDomainAndParticipantsOK() throws NotFoundFault, UnauthorizedFault, InternalErrorFault, BadRequestFault {
+        /* given (init database - check setup)
+         * Domain: TEST_DOMAIN_CODE_1
+         * Users: USERNAME_1, USER_CERT_2
+         * ServiceGroup1: TEST_SG_ID_1, TEST_SG_SCHEMA_1
+         *    - Domain: TEST_DOMAIN_CODE_1
+         *    - Owners: USERNAME_1, USER_CERT_2
+         *    - Metadata:
+         *          - TEST_DOC_ID_1, TEST_DOC_SCHEMA_1
+         *
+         *
+         * ServiceGroup2: TEST_SG_ID_2, TEST_SG_SCHEMA_2
+         *    - Domain: TEST_DOMAIN_CODE_1
+         *    - Owners: USERNAME_1
+         *    - Metadata: /
+         */
+        DBDomain testDomain01 = domainDao.getDomainByCode(TestConstants.TEST_DOMAIN_CODE_1).get();
+        DBServiceGroupDomain serviceGroupDomain = serviceGroupDao.findServiceGroupDomain(
+                TEST_SG_ID_1, TEST_SG_SCHEMA_1, TEST_DOMAIN_CODE_1).get();
+        DBServiceGroupDomain serviceGroupDomain2 = serviceGroupDao
+                .findServiceGroupDomain(TEST_SG_ID_2, TEST_SG_SCHEMA_2, TEST_DOMAIN_CODE_1).get();
+        assertFalse(testDomain01.isSmlRegistered());
+        assertFalse(serviceGroupDomain.isSmlRegistered());
+        assertFalse(serviceGroupDomain2.isSmlRegistered());
+
+        // when
+        testInstance.registerDomainAndParticipants(testDomain01);
+
+        // then
+        serviceGroupDomain = serviceGroupDao.findServiceGroupDomain(
+                TEST_SG_ID_1, TEST_SG_SCHEMA_1, TEST_DOMAIN_CODE_1).get();
+        serviceGroupDomain2 = serviceGroupDao
+                .findServiceGroupDomain(TEST_SG_ID_2, TEST_SG_SCHEMA_2, TEST_DOMAIN_CODE_1).get();
+        assertTrue(testDomain01.isSmlRegistered());
+        assertTrue(serviceGroupDomain.isSmlRegistered());
+        assertTrue(serviceGroupDomain2.isSmlRegistered());
+
+        // one sml domain create and two participant create was called
+        assertEquals(1, integrationMock.getSmpManagerClientMocks().size());
+        verify(integrationMock.getSmpManagerClientMocks().get(0)).create(any());
+        Mockito.verifyNoMoreInteractions(integrationMock.getSmpManagerClientMocks().toArray());
+
+        assertEquals(2, integrationMock.getParticipantManagmentClientMocks().size());
+        verify(integrationMock.getParticipantManagmentClientMocks().get(0)).create(any());
+        verify(integrationMock.getParticipantManagmentClientMocks().get(1)).create(any());
+        Mockito.verifyNoMoreInteractions(integrationMock.getParticipantManagmentClientMocks().toArray());
+
+    }
+
+    @Test
+    public void registerDomainAndParticipantsFailed() throws NotFoundFault, UnauthorizedFault, InternalErrorFault, BadRequestFault {
+
+        DBDomain testDomain01 = domainDao.getDomainByCode(TestConstants.TEST_DOMAIN_CODE_1).get();
+        DBServiceGroupDomain serviceGroupDomain = serviceGroupDao.findServiceGroupDomain(
+                TEST_SG_ID_1, TEST_SG_SCHEMA_1, TEST_DOMAIN_CODE_1).get();
+        DBServiceGroupDomain serviceGroupDomain2 = serviceGroupDao
+                .findServiceGroupDomain(TEST_SG_ID_2, TEST_SG_SCHEMA_2, TEST_DOMAIN_CODE_1).get();
+        assertFalse(testDomain01.isSmlRegistered());
+        assertFalse(serviceGroupDomain.isSmlRegistered());
+        assertFalse(serviceGroupDomain2.isSmlRegistered());
+        integrationMock.setThrowExceptionAfterParticipantCallCount(1);
+
+
+        // when
+        try {
+            testInstance.registerDomainAndParticipants(testDomain01);
+            fail("Testcase should throw an error with code 400");
+        } catch (Exception ex) {
+            assertEquals(400, ((HTTPException) ExceptionUtils.getRootCause(ex)).getStatusCode());
+        }
+
+
+        // then
+        serviceGroupDomain = serviceGroupDao.findServiceGroupDomain(
+                TEST_SG_ID_1, TEST_SG_SCHEMA_1, TEST_DOMAIN_CODE_1).get();
+        serviceGroupDomain2 = serviceGroupDao
+                .findServiceGroupDomain(TEST_SG_ID_2, TEST_SG_SCHEMA_2, TEST_DOMAIN_CODE_1).get();
+        assertTrue(testDomain01.isSmlRegistered());
+        assertTrue(serviceGroupDomain.isSmlRegistered());
+        assertFalse(serviceGroupDomain2.isSmlRegistered());
+
+        // one sml domain create and two participant create was called
+        assertEquals(1, integrationMock.getSmpManagerClientMocks().size());
+        verify(integrationMock.getSmpManagerClientMocks().get(0)).create(any());
+        Mockito.verifyNoMoreInteractions(integrationMock.getSmpManagerClientMocks().toArray());
+
+        // only first succeeded
+        assertEquals(1, integrationMock.getParticipantManagmentClientMocks().size());
+        verify(integrationMock.getParticipantManagmentClientMocks().get(0)).create(any());
+        Mockito.verifyNoMoreInteractions(integrationMock.getParticipantManagmentClientMocks().toArray());
 
+    }
+
+    @Test
+    @Transactional
+    public void unregisterDomainAndParticipantsFromSmlOK() throws NotFoundFault, UnauthorizedFault, InternalErrorFault, BadRequestFault {
+        /* given (init database - check setup)
+         * Domain: TEST_DOMAIN_CODE_1
+         * Users: USERNAME_1, USER_CERT_2
+         * ServiceGroup1: TEST_SG_ID_1, TEST_SG_SCHEMA_1
+         *    - Domain: TEST_DOMAIN_CODE_1
+         *    - Owners: USERNAME_1, USER_CERT_2
+         *    - Metadata:
+         *          - TEST_DOC_ID_1, TEST_DOC_SCHEMA_1
+         *
+         *
+         * ServiceGroup2: TEST_SG_ID_2, TEST_SG_SCHEMA_2
+         *    - Domain: TEST_DOMAIN_CODE_1
+         *    - Owners: USERNAME_1
+         *    - Metadata: /
+         */
+        DBDomain testDomain01 = domainDao.getDomainByCode(TestConstants.TEST_DOMAIN_CODE_1).get();
+        DBServiceGroupDomain serviceGroupDomain = serviceGroupDao.findServiceGroupDomain(
+                TEST_SG_ID_1, TEST_SG_SCHEMA_1, TEST_DOMAIN_CODE_1).get();
+        DBServiceGroupDomain serviceGroupDomain2 = serviceGroupDao
+                .findServiceGroupDomain(TEST_SG_ID_2, TEST_SG_SCHEMA_2, TEST_DOMAIN_CODE_1).get();
+        testDomain01.setSmlRegistered(true);
+        serviceGroupDomain.setSmlRegistered(true);
+        serviceGroupDomain2.setSmlRegistered(true);
+        serviceGroupDao.updateServiceGroupDomain(serviceGroupDomain);
+        serviceGroupDao.updateServiceGroupDomain(serviceGroupDomain2);
 
+        // when
+        testInstance.unregisterDomainAndParticipantsFromSml(testDomain01);
 
+        // then
+        serviceGroupDomain = serviceGroupDao.findServiceGroupDomain(
+                TEST_SG_ID_1, TEST_SG_SCHEMA_1, TEST_DOMAIN_CODE_1).get();
+        serviceGroupDomain2 = serviceGroupDao
+                .findServiceGroupDomain(TEST_SG_ID_2, TEST_SG_SCHEMA_2, TEST_DOMAIN_CODE_1).get();
+        assertFalse(testDomain01.isSmlRegistered());
+        assertFalse(serviceGroupDomain.isSmlRegistered());
+        assertFalse(serviceGroupDomain2.isSmlRegistered());
 
+        // one sml domain create and two participant create was called
+        assertEquals(1, integrationMock.getSmpManagerClientMocks().size());
+        verify(integrationMock.getSmpManagerClientMocks().get(0)).delete(testDomain01.getSmlSmpId());
+        Mockito.verifyNoMoreInteractions(integrationMock.getSmpManagerClientMocks().toArray());
+
+        assertEquals(2, integrationMock.getParticipantManagmentClientMocks().size());
+        verify(integrationMock.getParticipantManagmentClientMocks().get(0)).delete(any());
+        verify(integrationMock.getParticipantManagmentClientMocks().get(1)).delete(any());
+        Mockito.verifyNoMoreInteractions(integrationMock.getParticipantManagmentClientMocks().toArray());
+
+    }
 
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertFromKeystoreTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertFromKeystoreTest.java
index d6e81b2b7..32f29d546 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertFromKeystoreTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertFromKeystoreTest.java
@@ -84,9 +84,11 @@ public class SmlClientFactoryAuthenticationByClientCertFromKeystoreTest {
         X509Certificate clientCert = getClientCertFromKeystore(cxfClient);
 
         assertEquals("C=EU,O=CEF Digit,OU=SMP,CN=Second domain", clientCert.getSubjectDN().getName());
-        assertEquals("https://sml.url.pl", requestContext.get(Message.ENDPOINT_ADDRESS));
+        assertEquals("https://sml.url.pl/manageparticipantidentifier", requestContext.get(Message.ENDPOINT_ADDRESS));
     }
 
+
+
     @Test
     public void factoryProducesPreconfiguredCxfSMPClientThatAuthenticatesItselfWithGivenCertAlias() {
         //when
@@ -99,7 +101,7 @@ public class SmlClientFactoryAuthenticationByClientCertFromKeystoreTest {
         X509Certificate clientCert = getClientCertFromKeystore(cxfClient);
 
         assertEquals("C=EU,O=CEF Digit,OU=SMP,CN=Second domain", clientCert.getSubjectDN().getName());
-        assertEquals("https://sml.url.pl", requestContext.get(Message.ENDPOINT_ADDRESS));
+        assertEquals("https://sml.url.pl/manageservicemetadata", requestContext.get(Message.ENDPOINT_ADDRESS));
     }
 
     @Test
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertHttpHeaderTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertHttpHeaderTest.java
index 38e445977..c1301b40a 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertHttpHeaderTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/smlintegration/SmlClientFactoryAuthenticationByClientCertHttpHeaderTest.java
@@ -14,6 +14,7 @@
 package eu.europa.ec.edelivery.smp.smlintegration;
 
 import eu.europa.ec.bdmsl.ws.soap.IManageParticipantIdentifierWS;
+import eu.europa.ec.bdmsl.ws.soap.IManageServiceMetadataWS;
 import eu.europa.ec.edelivery.smp.sml.SmlClientFactory;
 import org.apache.cxf.endpoint.Client;
 import org.apache.cxf.frontend.ClientProxy;
@@ -71,7 +72,23 @@ public class SmlClientFactoryAuthenticationByClientCertHttpHeaderTest {
         List clientCerts = (List) httpHeaders.get("Client-Cert");
         assertEquals(1, clientCerts.size());
         assertEquals(CLIENT_CERT_HTTP_HEADER, clientCerts.get(0));
-        assertEquals("https://sml.url.pl", requestContext.get(Message.ENDPOINT_ADDRESS));
+        assertEquals("https://sml.url.pl/manageparticipantidentifier", requestContext.get(Message.ENDPOINT_ADDRESS));
+    }
+
+    @Test
+    public void factoryProducesPreconfiguredCxfCSMPlientThatAuthenticatesItselfWithGivenHttpHeader() {
+        //when
+        IManageServiceMetadataWS client = smlClientFactory.createSmp(null, CLIENT_CERT_HTTP_HEADER);
+
+        //then
+        assertNotNull(client);
+        Client cxfClient = ClientProxy.getClient(client);
+        Map<String, Object> requestContext = cxfClient.getRequestContext();
+        Map httpHeaders = (Map) requestContext.get(Message.PROTOCOL_HEADERS);
+        List clientCerts = (List) httpHeaders.get("Client-Cert");
+        assertEquals(1, clientCerts.size());
+        assertEquals(CLIENT_CERT_HTTP_HEADER, clientCerts.get(0));
+        assertEquals("https://sml.url.pl/manageservicemetadata", requestContext.get(Message.ENDPOINT_ADDRESS));
     }
 
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/PropertiesConfig.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/PropertiesConfig.java
index 361d286aa..a7d8dc5cf 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/PropertiesConfig.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/PropertiesConfig.java
@@ -13,13 +13,14 @@
 
 package eu.europa.ec.edelivery.smp.config;
 
-import eu.europa.ec.edelivery.smp.utils.SMPPropertyEnum;
 import eu.europa.ec.edelivery.smp.data.model.DBConfiguration;
 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.SecurityUtilsServices;
+import eu.europa.ec.edelivery.smp.utils.SMPPropertyEnum;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.*;
 import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
 import org.springframework.jdbc.datasource.DriverManagerDataSource;
@@ -56,10 +57,17 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.INTERNAL_ERROR;
         "eu.europa.ec"})
 @PropertySources({
         @PropertySource(value = "classpath:config.properties", ignoreResourceNotFound = true),
-        @PropertySource(value = "classpath:smp.config.properties", ignoreResourceNotFound = true)
+        @PropertySource(value = "classpath:smp.config.properties", ignoreResourceNotFound = true),
+        @PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true)
 })
 public class PropertiesConfig {
 
+    private static final String PROP_BUILD_NAME="smp.artifact.name";
+    private static final String PROP_BUILD_VERSION="smp.artifact.version";
+    private static final String PROP_BUILD_TIME="smp.artifact.build.time";
+
+    SMPLogger LOG = SMPLoggerFactory.getLogger(PropertiesConfig.class);
+
     // create own instance because at this time SecurityUtilsServices is not ready to instantiate
     SecurityUtilsServices securityUtilsServices = new SecurityUtilsServices();
 
@@ -68,11 +76,32 @@ public class PropertiesConfig {
         PropertySourcesPlaceholderConfigurer propertiesConfig = new PropertySourcesPlaceholderConfigurer();
 
         Properties prop = getDatabaseProperties();
+        logBuildProperties();
+
         propertiesConfig.setProperties(prop);
         propertiesConfig.setLocalOverride(true);
         return propertiesConfig;
     }
 
+    private void logBuildProperties(){
+        InputStream is = PropertiesConfig.class.getResourceAsStream("/application.properties");
+        if(is!=null){
+            Properties applProp = new Properties();
+            try {
+                applProp.load(is);
+
+                LOG.info("Start application: name: {}, version: {}, build time: {}.",applProp.getProperty(PROP_BUILD_NAME)
+                        ,applProp.getProperty(PROP_BUILD_VERSION)
+                        ,applProp.getProperty(PROP_BUILD_TIME));
+            } catch (IOException e) {
+                LOG.error( "Error occurred  while reading application properties. Is file /application.properties included in war!", e);
+            }
+        } else {
+            LOG.error( "Not found application build properties: /application.properties!");
+        }
+
+    }
+
     private Properties getDatabaseProperties() {
 
         Properties fileProperties = getFileProperties();
@@ -108,7 +137,7 @@ public class PropertiesConfig {
      */
     protected void initializeProperties(EntityManager em, Properties fileProperties, Properties initProperties) {
         em.getTransaction().begin();
-
+        LOG.info( "Database configuration table is empty! initialize new values from property file!");
         initNewValues(em, fileProperties, initProperties);
         for (SMPPropertyEnum val : SMPPropertyEnum.values()) {
             DBConfiguration dbConf = null;
@@ -160,6 +189,7 @@ public class PropertiesConfig {
     protected void initNewValues(EntityManager em, Properties fileProperties, Properties initProperties) {
 
         File settingsFolder = calculateSettingsPath(fileProperties);
+        LOG.info( "Generate new keystore to folder: " + settingsFolder.getAbsolutePath());
 
         // add configuration path
         storeDBEntry(em, SMPPropertyEnum.CONFIGURATION_DIR, settingsFolder.getPath());
@@ -169,7 +199,9 @@ public class PropertiesConfig {
 
 
         // store encryption filename
+
         File fEncryption = new File(settingsFolder, SMPPropertyEnum.ENCRYPTION_FILENAME.getDefValue());
+        LOG.info( "Generate new encryption key: " + fEncryption.getName());
         securityUtilsServices.generatePrivateSymmetricKey(fEncryption);
         storeDBEntry(em, SMPPropertyEnum.ENCRYPTION_FILENAME, fEncryption.getName());
         initProperties.setProperty(SMPPropertyEnum.ENCRYPTION_FILENAME.getProperty(), fEncryption.getName());
@@ -194,6 +226,7 @@ public class PropertiesConfig {
             newKeystore.load(null, newKeyPassword.toCharArray());
             // merge keys from signature keystore
           if (!StringUtils.isBlank(sigKeystorePath)) {
+              LOG.info( "Import keys from keystore for signature: " + sigKeystorePath);
                 String keypasswd = fileProperties.getProperty(SMPPropertyEnum.SIGNATURE_KEYSTORE_PASSWORD.getProperty());
                 try (FileInputStream fis = new FileInputStream(sigKeystorePath)) {
                     KeyStore sourceKeystore = KeyStore.getInstance(KeyStore.getDefaultType());
@@ -204,6 +237,7 @@ public class PropertiesConfig {
 
             // merge keys from integration keystore
             if (!StringUtils.isBlank(smlKeystorePath) && !StringUtils.equalsIgnoreCase(smlKeystorePath, sigKeystorePath)) {
+                LOG.info( "Import keys from keystore for sml integration: " + smlKeystorePath);
                 String keypasswd = fileProperties.getProperty(SMPPropertyEnum.SML_KEYSTORE_PASSWORD.getProperty());
                 try (FileInputStream fis = new FileInputStream(smlKeystorePath)) {
                     KeyStore sourceKeystore = KeyStore.getInstance(KeyStore.getDefaultType());
@@ -251,13 +285,14 @@ public class PropertiesConfig {
      * @return
      */
     private DataSource getDatasource(Properties connectionProp) {
-
+        LOG.info( "Start database properties");
         DataSource datasource = null;
         String url = connectionProp.getProperty("jdbc.url");
         String jndiDatasourceName = connectionProp.getProperty("datasource.jndi");
         jndiDatasourceName = StringUtils.isBlank(jndiDatasourceName) ? "jdbc/smpDatasource" : jndiDatasourceName;
 
-        if (url != null) {
+        if (!StringUtils.isBlank(url)) {
+            LOG.info( "Connect to {}.", url);
             DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
             driverManagerDataSource.setDriverClassName(connectionProp.getProperty("jdbc.driver"));
             driverManagerDataSource.setUrl(url);
@@ -265,12 +300,14 @@ public class PropertiesConfig {
             driverManagerDataSource.setPassword(connectionProp.getProperty("jdbc.password"));
             datasource = driverManagerDataSource;
         } else {
+            LOG.info( "Use JNDI {} to connect to database.", jndiDatasourceName);
             JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean();
             dataSource.setJndiName(jndiDatasourceName);
             try {
                 dataSource.afterPropertiesSet();
             } catch (IllegalArgumentException | NamingException e) {
                 // rethrow
+                LOG.error( "Error occurred while retriving datasource whith JNDI {}. Is datasource configured in server!", jndiDatasourceName);
                 throw new SMPRuntimeException(INTERNAL_ERROR, e, "Error occurred while retrieving datasource: " + jndiDatasourceName, e.getMessage());
             }
             datasource = (DataSource) dataSource.getObject();
@@ -279,14 +316,17 @@ public class PropertiesConfig {
     }
 
     protected Properties getFileProperties() {
+        LOG.info( "Start read file properties from '/smp.config.properties'");
         InputStream is = PropertiesConfig.class.getResourceAsStream("/smp.config.properties");
         if (is == null) {
+            LOG.info( "File '/smp.config.properties' not found in classpath, read '/config.properties'");
             is = PropertiesConfig.class.getResourceAsStream("/config.properties");
         }
         Properties connectionProp = new Properties();
         try {
             connectionProp.load(is);
         } catch (IOException e) {
+            LOG.error( "IOException occurred while reading properties", e);
             throw new SMPRuntimeException(INTERNAL_ERROR, e, "Error occurred  while reading properties.", e.getMessage());
         }
         return connectionProp;
@@ -312,7 +352,7 @@ public class PropertiesConfig {
     }
 
     private static class DatabaseProperties extends Properties {
-
+        SMPLogger LOG = SMPLoggerFactory.getLogger(PropertiesConfig.class);
         private static final long serialVersionUID = 1L;
 
         public DatabaseProperties(EntityManager em) {
@@ -321,6 +361,9 @@ public class PropertiesConfig {
             List<DBConfiguration> lst = tq.getResultList();
             for (DBConfiguration dc : lst) {
                 if(dc.getValue()!=null) {
+
+                    LOG.info("Set property: '{}' value: '{}'",dc.getProperty(),
+                            dc.getProperty().toLowerCase().contains("password")?"******": dc.getValue());
                     setProperty(dc.getProperty(), dc.getValue());
                 }
             }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java
index 8ad2afa91..0d79da20d 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java
@@ -30,12 +30,15 @@ public class ApplicationResource {
     @Autowired
     private Environment env;
 
-    @Value("${Artifact-Name}")
-    private String artifactName;
-    @Value("${Artifact-Version}")
-    private String artifactVersion;
-    @Value("${Build-Time}")
-    private String buildTime;
+    @Value("${smp.artifact.name:eDelivery SMP}")
+    String artifactName;
+    @Value("${smp.artifact.version:}")
+    String artifactVersion;
+    @Value("${smp.artifact.build.time:}")
+    String buildTime;
+
+    @Value("${bdmsl.integration.enabled}")
+    boolean smlIntegrationEnabled;
 
 
     @RequestMapping(method = RequestMethod.GET, path = "name")
@@ -49,7 +52,16 @@ public class ApplicationResource {
     }
 
     @RequestMapping(method = RequestMethod.GET, path = "info")
-    public SmpInfoRO getDisplayVersion() {
+    public SmpInfoRO getApplicationInfo() {
+        SmpInfoRO info = new SmpInfoRO();
+        info.setVersion(getDisplayVersion());
+        info.setSmlIntegrationOn(smlIntegrationEnabled);
+        info.setContextPath(getRootContext());
+        return info;
+    }
+
+
+    public String getDisplayVersion() {
         StringBuilder display = new StringBuilder();
         display.append(artifactName);
         display.append(" Version [");
@@ -57,12 +69,6 @@ public class ApplicationResource {
         display.append("] Build-Time [");
         display.append(buildTime + "|" + TimeZone.getDefault().getDisplayName());
         display.append("]");
-
-        SmpInfoRO info = new SmpInfoRO();
-        info.setVersion(display.toString());
-        return info;
+        return display.toString();
     }
-
-
-
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
index e94afe48d..848123274 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
@@ -3,22 +3,34 @@ package eu.europa.ec.edelivery.smp.ui;
 
 import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationToken;
 import eu.europa.ec.edelivery.smp.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
 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.KeystoreImportResult;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.services.DomainService;
 import eu.europa.ec.edelivery.smp.services.ui.UIDomainService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.annotation.Secured;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.PostConstruct;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 
 /**
  * @author Joze Rihtarsic
@@ -34,6 +46,9 @@ public class DomainResource {
     @Autowired
     private UIDomainService uiDomainService;
 
+    @Autowired
+    private DomainService domainService;
+
     @PostConstruct
     protected void init() {
 
@@ -69,4 +84,27 @@ public class DomainResource {
         dres.getListIds().addAll(query);
         return uiDomainService.validateDeleteRequest(dres);
     }
+
+    @PostMapping(value = "/{id}/smlregister/{domaincode}")
+    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
+    public void registerDomain(@PathVariable("id") Long id,
+                                               @PathVariable("domaincode") String domaincode
+                                               ) {
+        LOG.info("SML register domain code: {}, user id {}", domaincode, id);
+        // try to open keystore
+        DBDomain dbDomain =  domainService.getDomain(domaincode);
+        domainService.registerDomainAndParticipants(dbDomain);
+    }
+
+
+    @PostMapping(value = "/{id}/smlunregister/{domaincode}")
+    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
+    public void unregisterDomainAndParticiants(@PathVariable("id") Long id,
+                                               @PathVariable("domaincode") String domaincode
+    ) {
+        LOG.info("SML unregister domain code: {}, user id {}", domaincode, id);
+        // try to open keystore
+        DBDomain dbDomain =  domainService.getDomain(domaincode);
+        domainService.unregisterDomainAndParticipantsFromSml(dbDomain);
+    }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/KeystoreResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/KeystoreResource.java
index 69d0ca212..b04798e15 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/KeystoreResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/KeystoreResource.java
@@ -96,7 +96,7 @@ public class KeystoreResource {
 
     @DeleteMapping(value = "/{id}/delete/{alias}", produces = {"application/json"})
     @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public KeystoreImportResult uploadKeystore(@PathVariable("id") Long id,
+    public KeystoreImportResult deleteCertificate(@PathVariable("id") Long id,
                                                @PathVariable("alias") String alias) {
         LOG.info("Remove alias by user id {}, alias {}.", id, alias);
         KeystoreImportResult keystoreImportResult = new KeystoreImportResult();
diff --git a/smp-webapp/src/main/resources/application.properties b/smp-webapp/src/main/resources/application.properties
new file mode 100644
index 000000000..61b502b9d
--- /dev/null
+++ b/smp-webapp/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+smp.artifact.name=eDelivery SMP
+smp.artifact.version=${project.version}
+smp.artifact.build.time=${buildtimestamp}
\ No newline at end of file
diff --git a/smp-webapp/src/main/resources/config.properties b/smp-webapp/src/main/resources/config.properties
index 544058456..d0ec01682 100644
--- a/smp-webapp/src/main/resources/config.properties
+++ b/smp-webapp/src/main/resources/config.properties
@@ -16,10 +16,6 @@
 # Authentication with Blue Coat means that all HTTP requests having 'Client-Cert' header will be authenticated
 # as username placed in the header.
 # Never expose SMP to the WEB without properly configured reverse-proxy and active blue coat.
-Artifact-Name= eDelivery SMP
-Artifact-Version= 4.1.0-SNAPSHOT
-Build-Time= 22/10/2018
-
 authentication.blueCoat.enabled=false
 
 ## Only set to false in PRODUCTION mode. This variable is used to clear the context path of the SMP
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/config/PropertiesTestConfig.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/config/PropertiesTestConfig.java
index f3164d344..0b7319c94 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/config/PropertiesTestConfig.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/config/PropertiesTestConfig.java
@@ -13,7 +13,10 @@
 
 package eu.europa.ec.edelivery.smp.config;
 
-import org.springframework.context.annotation.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.annotation.PropertySources;
 import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
 
 import java.nio.file.Path;
@@ -25,7 +28,8 @@ import java.util.Properties;
  */
 @Configuration
 @PropertySources({
-        @PropertySource(value = "classpath:config.properties", ignoreResourceNotFound = true)
+        @PropertySource(value = "classpath:config.properties", ignoreResourceNotFound = true),
+        @PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true)
 })
 public class PropertiesTestConfig {
 
@@ -33,7 +37,7 @@ public class PropertiesTestConfig {
 
     @Bean
     public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
-        Path resourceDirectory = Paths.get("src", "test", "resources",  "keystores");
+        Path resourceDirectory = Paths.get("src", "test", "resources", "keystores");
         String path = resourceDirectory.toFile().getAbsolutePath();
 
         PropertySourcesPlaceholderConfigurer propertiesConfig = new PropertySourcesPlaceholderConfigurer();
@@ -41,16 +45,16 @@ public class PropertiesTestConfig {
         Properties localProps = new Properties();
         localProps.setProperty("jdbc.driverClassName", "org.h2.Driver");
         localProps.setProperty("jdbc.url", "jdbc:h2:file:./target/myDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE");
-        localProps.setProperty( "jdbc.user", "smp");
-        localProps.setProperty( "jdbc.pass", "smp");
-        localProps.setProperty( "spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.H2Dialect");
-        localProps.setProperty( "spring.jpa.generate-ddl", "true");
-        localProps.setProperty( "spring.jpa.properties.hibernate.hbm2ddl.auto", "create");
+        localProps.setProperty("jdbc.user", "smp");
+        localProps.setProperty("jdbc.pass", "smp");
+        localProps.setProperty("spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.H2Dialect");
+        localProps.setProperty("spring.jpa.generate-ddl", "true");
+        localProps.setProperty("spring.jpa.properties.hibernate.hbm2ddl.auto", "create");
 
         localProps.setProperty("configuration.dir", path);
-        localProps.setProperty( "encryption.key.filename","encryptionKey.key");
-        localProps.setProperty( "smp.keystore.password", "FarFJE2WUfY39SVRTFOqSg==");
-        localProps.setProperty( "smp.keystore.filename", "smp-keystore_multiple_domains.jks");
+        localProps.setProperty("encryption.key.filename", "encryptionKey.key");
+        localProps.setProperty("smp.keystore.password", "FarFJE2WUfY39SVRTFOqSg==");
+        localProps.setProperty("smp.keystore.filename", "smp-keystore_multiple_domains.jks");
         propertiesConfig.setProperties(localProps);
         propertiesConfig.setLocalOverride(true);
 
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ApplicationResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ApplicationResourceTest.java
index e6f2449a9..0586aa7cf 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ApplicationResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ApplicationResourceTest.java
@@ -1,9 +1,11 @@
 package eu.europa.ec.edelivery.smp.ui;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import eu.europa.ec.edelivery.smp.config.PropertiesTestConfig;
 import eu.europa.ec.edelivery.smp.config.SmpAppConfig;
 import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
 import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
+import eu.europa.ec.edelivery.smp.data.ui.SmpInfoRO;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -11,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.mock.web.MockServletContext;
 import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
 import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.jdbc.Sql;
 import org.springframework.test.context.jdbc.SqlConfig;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -24,10 +27,9 @@ import org.springframework.web.context.WebApplicationContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 
@@ -41,14 +43,25 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 @Sql("classpath:/cleanup-database.sql")
 @Sql("classpath:/webapp_integration_test_data.sql")
 @SqlConfig(encoding = "UTF-8")
+@TestPropertySource(properties = {
+        "smp.artifact.name=TestApplicationSmpName",
+        "smp.artifact.version=TestApplicationVersion",
+        "smp.artifact.build.time=2018-11-27 00:00:00",
+        "bdmsl.integration.enabled=true"})
+
 public class ApplicationResourceTest {
-    private static final String PATH="/ui/rest/application";
+    private static final String PATH = "/ui/rest/application";
 
     @Autowired
     private WebApplicationContext webAppContext;
 
+    @Autowired
+    private ApplicationResource applicationResource;
+
+
     private MockMvc mvc;
     private static final RequestPostProcessor ADMIN_CREDENTIALS = httpBasic("smp_admin", "test123");
+
     @Before
     public void setup() {
         mvc = MockMvcBuilders.webAppContextSetup(webAppContext)
@@ -56,7 +69,6 @@ public class ApplicationResourceTest {
                 .build();
 
 
-
         initServletContext();
     }
 
@@ -74,9 +86,10 @@ public class ApplicationResourceTest {
                 .getResponse()
                 .getContentAsString();
 
-        assertEquals("eDelivery SMP", value);
+        assertEquals("TestApplicationSmpName", value);
 
     }
+
     @Test
     public void getRootContext() throws Exception {
         String value = mvc.perform(get(PATH + "/rootContext"))
@@ -89,13 +102,24 @@ public class ApplicationResourceTest {
     }
 
     @Test
-    public void getDisplayVersion() throws Exception {
+    public void getDisplayName() throws Exception {
+        String value = applicationResource.getDisplayVersion();
+        assertEquals("TestApplicationSmpName Version [TestApplicationVersion] Build-Time [2018-11-27 00:00:00|Central European Time]", value);
+    }
+
+    @Test
+    public void getApplicationInfoTest() throws Exception {
         String value = mvc.perform(get(PATH + "/info"))
                 .andExpect(status().isOk())
                 .andReturn()
                 .getResponse()
                 .getContentAsString();
+        ObjectMapper mapper = new ObjectMapper();
+        SmpInfoRO info = mapper.readValue(value, SmpInfoRO.class);
 
-        assertEquals("{\"version\":\"eDelivery SMP Version [4.1.0-SNAPSHOT] Build-Time [22/10/2018|Central European Time]\"}", value);
+        assertEquals("TestApplicationSmpName Version [TestApplicationVersion] Build-Time [2018-11-27 00:00:00|Central European Time]", info.getVersion());
+        assertEquals(true, info.isSmlIntegrationOn());
+        assertEquals("/", info.getContextPath());
     }
+
 }
\ No newline at end of file
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/KeystoreResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/KeystoreResourceTest.java
new file mode 100644
index 000000000..8e5bdc2da
--- /dev/null
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/KeystoreResourceTest.java
@@ -0,0 +1,91 @@
+package eu.europa.ec.edelivery.smp.ui;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import eu.europa.ec.edelivery.smp.config.PropertiesTestConfig;
+import eu.europa.ec.edelivery.smp.config.SmpAppConfig;
+import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
+import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
+import eu.europa.ec.edelivery.smp.data.ui.SmpInfoRO;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.jdbc.SqlConfig;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.RequestPostProcessor;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.ContextLoaderListener;
+import org.springframework.web.context.WebApplicationContext;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {
+        PropertiesTestConfig.class,
+        SmpAppConfig.class,
+        SmpWebAppConfig.class,
+        SpringSecurityConfig.class})
+@WebAppConfiguration
+@Sql("classpath:/cleanup-database.sql")
+@Sql("classpath:/webapp_integration_test_data.sql")
+@SqlConfig(encoding = "UTF-8")
+@TestPropertySource(properties = {
+        "smp.artifact.name=TestApplicationSmpName",
+        "smp.artifact.version=TestApplicationVersion",
+        "smp.artifact.build.time=2018-11-27 00:00:00",
+        "bdmsl.integration.enabled=true"})
+
+public class KeystoreResourceTest {
+    private static final String PATH = "/ui/rest/application";
+
+    @Autowired
+    private WebApplicationContext webAppContext;
+
+
+
+
+    private MockMvc mvc;
+    private static final RequestPostProcessor ADMIN_CREDENTIALS = httpBasic("smp_admin", "test123");
+
+    @Before
+    public void setup() {
+        mvc = MockMvcBuilders.webAppContextSetup(webAppContext)
+                .apply(SecurityMockMvcConfigurers.springSecurity())
+                .build();
+
+
+        initServletContext();
+    }
+
+    private void initServletContext() {
+        MockServletContext sc = new MockServletContext("");
+        ServletContextListener listener = new ContextLoaderListener(webAppContext);
+        ServletContextEvent event = new ServletContextEvent(sc);
+    }
+
+    @Test
+    public void getKeyCertificateList() {
+    }
+
+    @Test
+    public void uploadKeystore() {
+    }
+
+
+
+}
\ No newline at end of file
-- 
GitLab