From d7d6077c4cd9c99186c6be6fa420b113a0652094 Mon Sep 17 00:00:00 2001
From: Pawel GUTOWSKI <Pawel.GUTOWSKI@ext.ec.europa.eu>
Date: Thu, 18 Jan 2018 14:59:30 +0100
Subject: [PATCH] EDELIVERY-1871 EDELIVERY-1893 Updated DB schema for
 multitenancy, added handling of multiple domains

---
 smp-server-library/database/create-Mysql.sql  | 66 +++++++++++++-
 smp-server-library/database/create-Oracle.sql |  5 +-
 .../integration_tests_initial_data.sql        | 29 -------
 .../mysql-3.0_4.0.sql                         | 77 ++++++++++++++++
 .../oracle_3.0_to_4.0.sql                     |  3 +-
 .../ec/edelivery/smp/data/dao/DomainDao.java  | 47 ++++++++++
 .../smp/data/model/CommonColumnsLengths.java  |  1 +
 .../ec/edelivery/smp/data/model/DBDomain.java | 87 +++++++++++++++++++
 .../smp/data/model/DBServiceGroup.java        | 18 +++-
 .../exceptions/WrongInputFieldException.java  | 26 ++++++
 .../smp/services/ServiceGroupService.java     | 31 ++++++-
 ...actServiceGroupServiceIntegrationTest.java | 66 ++++++++++++++
 ...ServiceMultipleDomainsIntegrationTest.java | 78 +++++++++++++++++
 ...upServiceSingleDomainIntegrationTest.java} | 56 ++++--------
 .../ServiceMetadataIntegrationTest.java       |  2 +-
 ...integration_multiple_domains_test_data.sql |  2 +
 .../controllers/ServiceGroupController.java   |  3 +-
 .../error/ErrorMappingControllerAdvice.java   |  6 ++
 .../webapp_integration_test_data.sql          | 26 ++++++
 19 files changed, 549 insertions(+), 80 deletions(-)
 delete mode 100644 smp-server-library/database/integration_tests_initial_data.sql
 create mode 100644 smp-server-library/database/migration from 3.0.x to 4.0.0/mysql-3.0_4.0.sql
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
 create mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/WrongInputFieldException.java
 create mode 100644 smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceGroupServiceIntegrationTest.java
 create mode 100644 smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java
 rename smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/{ServiceGroupServiceIntegrationTest.java => ServiceGroupServiceSingleDomainIntegrationTest.java} (69%)
 create mode 100644 smp-server-library/src/test/resources/service_integration_multiple_domains_test_data.sql

diff --git a/smp-server-library/database/create-Mysql.sql b/smp-server-library/database/create-Mysql.sql
index bbb9f1818..0895b396b 100644
--- a/smp-server-library/database/create-Mysql.sql
+++ b/smp-server-library/database/create-Mysql.sql
@@ -9,6 +9,27 @@
 -- 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.
 
+CREATE TABLE smp_domain (
+  domainId              VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NOT NULL,
+  bdmslClientCertHeader VARCHAR(4000)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NULL,
+  bdmslClientCertAlias  VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NULL,
+  bdmslSmpId            VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NOT NULL,
+  signatureCertAlias    VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NULL,
+  PRIMARY KEY(domainId)
+)
+  ENGINE = InnoDB
+  DEFAULT CHARSET = utf8;
+
 
 CREATE TABLE smp_service_group (
   businessIdentifier       VARCHAR(256)
@@ -17,8 +38,14 @@ CREATE TABLE smp_service_group (
   businessIdentifierScheme VARCHAR(256)
                            CHARACTER SET utf8
                            COLLATE utf8_bin NOT NULL,
+  domainId                 VARCHAR(256)
+                           CHARACTER SET utf8
+                           COLLATE utf8_bin NOT NULL
+                           DEFAULT 'default',
   extension                TEXT             NULL DEFAULT NULL,
-  PRIMARY KEY (businessIdentifier, businessIdentifierScheme)
+  PRIMARY KEY (businessIdentifier, businessIdentifierScheme),
+  CONSTRAINT FK_srv_group_domain FOREIGN KEY (domainId)
+    REFERENCES smp_domain (domainId)
 )
   ENGINE = InnoDB
   DEFAULT CHARSET = utf8;
@@ -79,6 +106,8 @@ CREATE TABLE smp_ownership (
   DEFAULT CHARSET = utf8;
 
 
+
+
 DROP TRIGGER IF EXISTS smp_user_check_is_admin_value_before_insert;
 DROP TRIGGER IF EXISTS smp_user_check_is_admin_value_before_update;
 DELIMITER //
@@ -102,4 +131,37 @@ FOR EACH ROW
       SET MESSAGE_TEXT = '0 or 1 are the only allowed values for ISADMIN column';
     END IF;
   END //
-DELIMITER ;
\ No newline at end of file
+DELIMITER ;
+
+
+DROP TRIGGER IF EXISTS smp_domain_check_bdmsl_auth_before_insert;
+DROP TRIGGER IF EXISTS smp_domain_check_bdmsl_auth_before_update;
+DELIMITER //
+CREATE TRIGGER smp_domain_check_bdmsl_auth_before_insert
+BEFORE INSERT ON smp_domain
+FOR EACH ROW
+  BEGIN
+    IF ((NEW.bdmslClientCertAlias > '' OR NEW.bdmslClientCertAlias = null) AND (NEW.bdmslClientCertHeader > '' OR NEW.bdmslClientCertHeader = null))
+    THEN
+      SIGNAL SQLSTATE '99999'
+      SET MESSAGE_TEXT = 'Both BDMSL authentication ways cannot be switched ON at the same time: bdmslClientCertAlias and bdmslClientCertHeader';
+    END IF;
+  END //
+CREATE TRIGGER smp_domain_check_bdmsl_auth_before_update
+BEFORE UPDATE ON smp_domain
+FOR EACH ROW
+  BEGIN
+    IF ((NEW.bdmslClientCertAlias > '' OR NEW.bdmslClientCertAlias = null) AND (NEW.bdmslClientCertHeader > '' OR NEW.bdmslClientCertHeader = null))
+    THEN
+      SIGNAL SQLSTATE '99999'
+      SET MESSAGE_TEXT = 'Both BDMSL authentication ways cannot be switched ON at the same time: bdmslClientCertAlias and bdmslClientCertHeader';
+    END IF;
+  END //
+DELIMITER ;
+
+
+INSERT INTO smp_domain(domainId, bdmslSmpId) VALUES('default', 'DEFAULT-SMP-ID');
+-- default admin user with password "changeit"
+INSERT INTO smp_user(username, password, isadmin) VALUES ('smp_admin', '$2a$10$SZXMo7K/wA.ULWxH7uximOxeNk4mf3zU6nxJx/2VfKA19QlqwSpNO', '1');
+
+commit;
\ No newline at end of file
diff --git a/smp-server-library/database/create-Oracle.sql b/smp-server-library/database/create-Oracle.sql
index 0c5348155..581ed856c 100644
--- a/smp-server-library/database/create-Oracle.sql
+++ b/smp-server-library/database/create-Oracle.sql
@@ -14,6 +14,7 @@ CREATE TABLE smp_domain (
   domainId              VARCHAR(50),
   bdmslClientCertHeader VARCHAR(4000),
   bdmslClientCertAlias  VARCHAR(50),
+  bdmslSmpId            VARCHAR(50) NOT NULL,
   signatureCertAlias    VARCHAR(50),
   PRIMARY KEY(domainId),
   CONSTRAINT check_max_one_auth CHECK (
@@ -69,8 +70,8 @@ CREATE TABLE smp_ownership (
 );
 
 
-INSERT INTO smp_domain(domainId) VALUES('default');
---default admin user with password "changeit"
+INSERT INTO smp_domain(domainId, bdmslSmpId) VALUES('default', 'DEFAULT-SMP-ID');
+-- default admin user with password "changeit"
 INSERT INTO smp_user(username, password, isadmin) VALUES ('smp_admin', '$2a$10$SZXMo7K/wA.ULWxH7uximOxeNk4mf3zU6nxJx/2VfKA19QlqwSpNO', '1');
 
 commit;
\ No newline at end of file
diff --git a/smp-server-library/database/integration_tests_initial_data.sql b/smp-server-library/database/integration_tests_initial_data.sql
deleted file mode 100644
index c676f40de..000000000
--- a/smp-server-library/database/integration_tests_initial_data.sql
+++ /dev/null
@@ -1,29 +0,0 @@
---
--- Copyright 2017 European Commission | CEF eDelivery
---
--- Licensed under the EUPL, Version 1.1 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 at:
--- https://joinup.ec.europa.eu/software/page/eupl
--- or file: LICENCE-EUPL-v1.1.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.
-
-
--- Initial data only for integration tests.
-
-
-insert into smp_user (username, password, isadmin) values ('peppol_user', '$2a$10$.pqNZZ4fRDdNbLhNlnEYg.1/d4yAGpLDgeXpJFI0sw7.WtyKphFzu', 1);
-insert into smp_user (username, isadmin) values ('CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', 0);
-insert into smp_user (username, isadmin) values ('CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', 0);
-
-insert into smp_service_group(businessidentifier, businessidentifierscheme) values ('urn:australia:ncpb', 'ehealth-actorid-qns');
-insert into smp_service_group(businessidentifier, businessidentifierscheme) values ('urn:brazil:ncpb', 'ehealth-actorid-qns');
-
-insert into smp_ownership(username, businessidentifier, businessidentifierscheme) values ('CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', 'urn:australia:ncpb', 'ehealth-actorid-qns');
-insert into smp_ownership(username, businessidentifier, businessidentifierscheme) values ('CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', 'urn:brazil:ncpb', 'ehealth-actorid-qns');
-
-commit;
\ No newline at end of file
diff --git a/smp-server-library/database/migration from 3.0.x to 4.0.0/mysql-3.0_4.0.sql b/smp-server-library/database/migration from 3.0.x to 4.0.0/mysql-3.0_4.0.sql
new file mode 100644
index 000000000..b51f4bbaf
--- /dev/null
+++ b/smp-server-library/database/migration from 3.0.x to 4.0.0/mysql-3.0_4.0.sql	
@@ -0,0 +1,77 @@
+-- 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.
+
+
+CREATE TABLE smp_domain (
+  domainId              VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NOT NULL,
+  bdmslClientCertHeader VARCHAR(4000)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NULL,
+  bdmslClientCertAlias  VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NULL,
+  bdmslSmpId            VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NOT NULL,
+  signatureCertAlias    VARCHAR(256)
+                        CHARACTER SET utf8
+                        COLLATE utf8_bin NULL,
+  PRIMARY KEY(domainId)
+);
+
+
+INSERT INTO smp_domain(domainId, bdmslSmpId) VALUES('default', 'DEFAULT-SMP-ID');
+
+
+
+ALTER TABLE smp_service_group ADD
+  domainId  VARCHAR(256)
+            CHARACTER SET utf8
+            COLLATE utf8_bin NOT NULL
+            DEFAULT 'default';
+
+ALTER TABLE smp_service_group ADD
+  CONSTRAINT
+    FK_srv_group_domain FOREIGN KEY (domainId)
+    REFERENCES smp_domain (domainId);
+
+
+
+
+DROP TRIGGER IF EXISTS smp_domain_check_bdmsl_auth_before_insert;
+DROP TRIGGER IF EXISTS smp_domain_check_bdmsl_auth_before_update;
+DELIMITER //
+CREATE TRIGGER smp_domain_check_bdmsl_auth_before_insert
+BEFORE INSERT ON smp_domain
+FOR EACH ROW
+  BEGIN
+    IF ((NEW.bdmslClientCertAlias > '' OR NEW.bdmslClientCertAlias = null) AND (NEW.bdmslClientCertHeader > '' OR NEW.bdmslClientCertHeader = null))
+    THEN
+      SIGNAL SQLSTATE '99999'
+      SET MESSAGE_TEXT = 'Both BDMSL authentication ways cannot be switched ON at the same time: bdmslClientCertAlias and bdmslClientCertHeader';
+    END IF;
+  END //
+CREATE TRIGGER smp_domain_check_bdmsl_auth_before_update
+BEFORE UPDATE ON smp_domain
+FOR EACH ROW
+  BEGIN
+    IF ((NEW.bdmslClientCertAlias > '' OR NEW.bdmslClientCertAlias = null) AND (NEW.bdmslClientCertHeader > '' OR NEW.bdmslClientCertHeader = null))
+    THEN
+      SIGNAL SQLSTATE '99999'
+      SET MESSAGE_TEXT = 'Both BDMSL authentication ways cannot be switched ON at the same time: bdmslClientCertAlias and bdmslClientCertHeader';
+    END IF;
+  END //
+DELIMITER ;
+
+
+commit;
\ No newline at end of file
diff --git a/smp-server-library/database/migration from 3.0.x to 4.0.0/oracle_3.0_to_4.0.sql b/smp-server-library/database/migration from 3.0.x to 4.0.0/oracle_3.0_to_4.0.sql
index f7939f5dc..290fbc1f6 100644
--- a/smp-server-library/database/migration from 3.0.x to 4.0.0/oracle_3.0_to_4.0.sql	
+++ b/smp-server-library/database/migration from 3.0.x to 4.0.0/oracle_3.0_to_4.0.sql	
@@ -13,6 +13,7 @@ CREATE TABLE smp_domain (
   domainId              VARCHAR(50),
   bdmslClientCertHeader VARCHAR(4000),
   bdmslClientCertAlias  VARCHAR(50),
+  bdmslSmpId            VARCHAR(50) NOT NULL,
   signatureCertAlias    VARCHAR(50),
   PRIMARY KEY(domainId),
   CONSTRAINT check_max_one_auth CHECK (
@@ -20,7 +21,7 @@ CREATE TABLE smp_domain (
   )
 );
 
-INSERT INTO smp_domain(domainId) VALUES('default');
+INSERT INTO smp_domain(domainId, bdmslSmpId) VALUES('default', 'DEFAULT-SMP-ID');
 
 ALTER TABLE smp_service_group ADD (
   domainId  VARCHAR(50) DEFAULT 'default' NOT NULL
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
new file mode 100644
index 000000000..5bafa7c6a
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
@@ -0,0 +1,47 @@
+/*
+ * 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.dao;
+
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import org.springframework.stereotype.Repository;
+
+import javax.persistence.NoResultException;
+import javax.persistence.NonUniqueResultException;
+import javax.persistence.TypedQuery;
+import java.util.Optional;
+
+/**
+ * Created by gutowpa on 16/01/2018.
+ */
+@Repository
+public class DomainDao extends BaseDao<DBDomain> {
+
+    /**
+     * Returns the only single record from smp_domain table.
+     * Returns Optional.empty() if there is 0 or more than 1 records present.
+     *
+     * @return the only single record from smp_domain table
+     * @throws IllegalStateException if no domain is configured
+     */
+    public Optional<DBDomain> getTheOnlyDomain() {
+        try {
+            TypedQuery<DBDomain> query = em.createQuery("SELECT d FROM DBDomain d", DBDomain.class);
+            return Optional.of(query.getSingleResult());
+        } catch (NonUniqueResultException e) {
+            return Optional.empty();
+        } catch (NoResultException e) {
+            throw new IllegalStateException("No domain is created, at least one domain is mandatory");
+        }
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java
index f9f53ff99..09bb10e86 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java
@@ -17,6 +17,7 @@ package eu.europa.ec.edelivery.smp.data.model;
  * Created by gutowpa on 01/02/2017.
  */
 public class CommonColumnsLengths {
+    public static final int MAX_FREE_TEXT_LENGTH = 4000;
     public static final int MAX_IDENTIFIER_SCHEME_LENGTH = 100;
     public static final int MAX_IDENTIFIER_VALUE_LENGTH = 50;
     public static final int MAX_DOCUMENT_TYPE_IDENTIFIER_VALUE_LENGTH = 500;
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
new file mode 100644
index 000000000..f139fec9b
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
@@ -0,0 +1,87 @@
+/*
+ * 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.model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import java.io.Serializable;
+
+import static eu.europa.ec.edelivery.smp.data.model.CommonColumnsLengths.MAX_FREE_TEXT_LENGTH;
+import static eu.europa.ec.edelivery.smp.data.model.CommonColumnsLengths.MAX_IDENTIFIER_VALUE_LENGTH;
+
+/**
+ * Created by gutowpa on 16/01/2018.
+ */
+@Entity
+@Table(name = "smp_domain")
+public class DBDomain implements Serializable{
+
+    String domainId;
+    String bdmslClientCertHeader;
+    String bdmslClientCertAlias;
+    String bdmslSmpId;
+    String signatureCertAlias;
+
+    public DBDomain() {
+    }
+
+    @Id
+    @Column(name = "domainId", length = MAX_IDENTIFIER_VALUE_LENGTH)
+    public String getDomainId() {
+        return domainId;
+    }
+
+    @Column(name = "bdmslClientCertHeader", length = MAX_FREE_TEXT_LENGTH)
+    public String getBdmslClientCertHeader() {
+        return bdmslClientCertHeader;
+    }
+
+    @Column(name = "bdmslClientCertAlias", length = MAX_IDENTIFIER_VALUE_LENGTH)
+    public String getBdmslClientCertAlias() {
+        return bdmslClientCertAlias;
+    }
+
+    @Column(name = "bdmslSmpId", length = MAX_IDENTIFIER_VALUE_LENGTH, nullable = false)
+    public String getBdmslSmpId() {
+        return bdmslSmpId;
+    }
+
+    @Column(name = "signatureCertAlias", length = MAX_IDENTIFIER_VALUE_LENGTH)
+    public String getSignatureCertAlias() {
+        return signatureCertAlias;
+    }
+
+    public void setDomainId(String domainId) {
+        this.domainId = domainId;
+    }
+
+    public void setBdmslClientCertHeader(String bdmslClientCertHeader) {
+        this.bdmslClientCertHeader = bdmslClientCertHeader;
+    }
+
+    public void setBdmslClientCertAlias(String bdmslClientCertAlias) {
+        this.bdmslClientCertAlias = bdmslClientCertAlias;
+    }
+
+    public void setBdmslSmpId(String bdmslSmpId) {
+        this.bdmslSmpId = bdmslSmpId;
+    }
+
+    public void setSignatureCertAlias(String signatureCertAlias) {
+        this.signatureCertAlias = signatureCertAlias;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroup.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroup.java
index a564d67cb..ec29d8b10 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroup.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBServiceGroup.java
@@ -18,6 +18,9 @@ import java.io.Serializable;
 import java.util.HashSet;
 import java.util.Set;
 
+import static javax.persistence.FetchType.EAGER;
+import static javax.persistence.FetchType.LAZY;
+
 @Entity
 @Table(name = "smp_service_group")
 public class DBServiceGroup implements Serializable {
@@ -26,6 +29,7 @@ public class DBServiceGroup implements Serializable {
     private String extension;
     private Set<DBOwnership> ownerships = new HashSet<>();
     private Set<DBServiceMetadata> serviceMetadatas = new HashSet<DBServiceMetadata>();
+    private DBDomain domain;
 
     public DBServiceGroup() {
     }
@@ -56,16 +60,22 @@ public class DBServiceGroup implements Serializable {
         return extension;
     }
 
-    @OneToMany(fetch = FetchType.LAZY, mappedBy = "serviceGroup", cascade = CascadeType.ALL)
+    @OneToMany(fetch = LAZY, mappedBy = "serviceGroup", cascade = CascadeType.ALL)
     public Set<DBOwnership> getOwnerships() {
         return ownerships;
     }
 
-    @OneToMany(fetch = FetchType.LAZY, mappedBy = "serviceGroup", cascade = CascadeType.ALL)
+    @OneToMany(fetch = LAZY, mappedBy = "serviceGroup", cascade = CascadeType.ALL)
     public Set<DBServiceMetadata> getServiceMetadatas() {
         return serviceMetadatas;
     }
 
+    @ManyToOne(fetch = EAGER, optional = false)
+    @JoinColumn(name = "domainId", nullable = false)
+    public DBDomain getDomain() {
+        return domain;
+    }
+
     public void setId(final DBServiceGroupId serviceGroupId) {
         this.serviceGroupId = serviceGroupId;
     }
@@ -81,4 +91,8 @@ public class DBServiceGroup implements Serializable {
     public void setServiceMetadatas(final Set<DBServiceMetadata> serviceMetadatas) {
         this.serviceMetadatas = serviceMetadatas;
     }
+
+    public void setDomain(final DBDomain domain) {
+        this.domain = domain;
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/WrongInputFieldException.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/WrongInputFieldException.java
new file mode 100644
index 000000000..2251dcb94
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/WrongInputFieldException.java
@@ -0,0 +1,26 @@
+/*
+ * 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.exceptions;
+
+/**
+ * Input field provided by user has wrong value.
+ *
+ * Created by gutowpa on 17/01/2018.
+ */
+public class WrongInputFieldException extends RuntimeException{
+
+    public WrongInputFieldException(String msg){
+        super(msg);
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java
index 88056ded2..c8da53166 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java
@@ -15,12 +15,15 @@ package eu.europa.ec.edelivery.smp.services;
 
 import eu.europa.ec.edelivery.smp.conversion.CaseSensitivityNormalizer;
 import eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter;
+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.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.model.*;
 import eu.europa.ec.edelivery.smp.exceptions.NotFoundException;
 import eu.europa.ec.edelivery.smp.exceptions.UnknownUserException;
+import eu.europa.ec.edelivery.smp.exceptions.WrongInputFieldException;
 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.oasis_open.docs.bdxr.ns.smp._2016._05.ServiceGroup;
 import org.slf4j.Logger;
@@ -30,10 +33,12 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.HashSet;
+import java.util.Optional;
 
 import static eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter.toDbModel;
 import static eu.europa.ec.smp.api.Identifiers.asString;
 import static java.util.Arrays.asList;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
 
 /**
  * Created by gutowpa on 14/11/2017.
@@ -52,9 +57,13 @@ public class ServiceGroupService {
     @Autowired
     private UserDao userDao;
 
+    @Autowired
+    private DomainDao domainDao;
+
     @Autowired
     private SmlConnector smlConnector;
 
+
     public ServiceGroup getServiceGroup(ParticipantIdentifierType serviceGroupId) {
         ParticipantIdentifierType normalizedServiceGroupId = caseSensitivityNormalizer.normalize(serviceGroupId);
 
@@ -66,7 +75,7 @@ public class ServiceGroupService {
     }
 
     @Transactional
-    public boolean saveServiceGroup(ServiceGroup serviceGroup, String newOwnerName) {
+    public boolean saveServiceGroup(ServiceGroup serviceGroup, String domain, String newOwnerName) {
         ServiceGroup normalizedServiceGroup = normalizeIdentifierCaseSensitivity(serviceGroup);
         ParticipantIdentifierType normalizedParticipantId = normalizedServiceGroup.getParticipantIdentifier();
 
@@ -80,6 +89,7 @@ public class ServiceGroupService {
         String extensions = ServiceGroupConverter.extractExtensionsPayload(normalizedServiceGroup);
 
         if (dbServiceGroup != null) {
+            blockPotentialDomainChange(dbServiceGroup, domain);
             dbServiceGroup.setExtension(extensions);
             serviceGroupDao.save(dbServiceGroup);
             return false;
@@ -87,6 +97,7 @@ public class ServiceGroupService {
             //Save ServiceGroup
             dbServiceGroup = new DBServiceGroup(new DBServiceGroupId(normalizedParticipantId.getScheme(), normalizedParticipantId.getValue()));
             dbServiceGroup.setExtension(extensions);
+            dbServiceGroup.setDomain(findDomain(domain));
 
             // Save the ownership information
             DBOwnershipId dbOwnershipID = new DBOwnershipId(newOwnerName, normalizedParticipantId.getScheme(), normalizedParticipantId.getValue());
@@ -99,6 +110,24 @@ public class ServiceGroupService {
         }
     }
 
+    private DBDomain findDomain(String domain) {
+        if (isNotBlank(domain)) {
+            return domainDao.find(domain);
+        }
+        Optional<DBDomain> dbDomain = domainDao.getTheOnlyDomain();
+        if (dbDomain.isPresent()) {
+            return dbDomain.get();
+        }
+        throw new WrongInputFieldException("SMP is configured to use multiple domains, but no Domain is specified in request. Please specify Domain in request.");
+    }
+
+
+    private void blockPotentialDomainChange(DBServiceGroup dbServiceGroup, String domain) {
+        if (isNotBlank(domain) && !domain.equalsIgnoreCase(dbServiceGroup.getDomain().getDomainId())) {
+            throw new WrongInputFieldException("The same SarviceGroup cannot exist under 2 different domains. ServiceGroup cannot be switched between domains. Remove domain parameter from request if you want to update existing ServiceGroup.");
+        }
+    }
+
     private ServiceGroup normalizeIdentifierCaseSensitivity(ServiceGroup serviceGroup) {
         final ServiceGroup sg = new ServiceGroup();
         sg.setParticipantIdentifier(caseSensitivityNormalizer.normalize(serviceGroup.getParticipantIdentifier()));
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceGroupServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceGroupServiceIntegrationTest.java
new file mode 100644
index 000000000..a83098001
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceGroupServiceIntegrationTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017 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.services;
+
+import eu.europa.ec.edelivery.smp.config.SmpServicesTestConfig;
+import eu.europa.ec.edelivery.smp.data.dao.OwnershipDao;
+import eu.europa.ec.edelivery.smp.data.dao.ServiceGroupDao;
+import org.junit.runner.RunWith;
+import org.oasis_open.docs.bdxr.ns.smp._2016._05.ParticipantIdentifierType;
+import org.oasis_open.docs.bdxr.ns.smp._2016._05.ServiceGroup;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.io.IOException;
+
+import static eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter.unmarshal;
+import static eu.europa.ec.edelivery.smp.testutil.XmlTestUtils.loadDocumentAsString;
+import static eu.europa.ec.smp.api.Identifiers.asParticipantId;
+
+/**
+ * Created by gutowpa on 27/03/2017.
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {SmpServicesTestConfig.class})
+@Transactional
+@Rollback(true)
+abstract class AbstractServiceGroupServiceIntegrationTest {
+
+    protected static final String SERVICE_GROUP_XML_PATH = "/eu/europa/ec/edelivery/smp/services/ServiceGroupPoland.xml";
+    protected static final ParticipantIdentifierType SERVICE_GROUP_ID = asParticipantId("participant-scheme-qns::urn:poland:ncpb");
+    public static final String ADMIN_USERNAME = "test_admin";
+
+    @PersistenceContext
+    protected EntityManager em;
+
+    @Autowired
+    protected ServiceGroupDao serviceGroupDao;
+
+    @Autowired
+    protected OwnershipDao ownershipDao;
+
+    @Autowired
+    protected ServiceGroupService serviceGroupService;
+
+    protected ServiceGroup saveServiceGroup() throws IOException {
+        ServiceGroup inServiceGroup = unmarshal(loadDocumentAsString(SERVICE_GROUP_XML_PATH));
+        serviceGroupService.saveServiceGroup(inServiceGroup, null, ADMIN_USERNAME);
+        return inServiceGroup;
+    }
+}
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java
new file mode 100644
index 000000000..7289efeeb
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.services;
+
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.DBServiceGroup;
+import eu.europa.ec.edelivery.smp.exceptions.WrongInputFieldException;
+import org.junit.Test;
+import org.oasis_open.docs.bdxr.ns.smp._2016._05.ServiceGroup;
+import org.springframework.test.context.jdbc.Sql;
+
+import java.io.IOException;
+
+import static eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter.toDbModel;
+import static eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter.unmarshal;
+import static eu.europa.ec.edelivery.smp.testutil.XmlTestUtils.loadDocumentAsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.util.StringUtils.isEmpty;
+
+/**
+ * Created by gutowpa on 18/01/2018.
+ */
+@Sql({"classpath:/service_integration_test_data.sql",
+        "classpath:/service_integration_multiple_domains_test_data.sql"})
+public class ServiceGroupServiceMultipleDomainsIntegrationTest extends AbstractServiceGroupServiceIntegrationTest {
+
+    private static final String SECOND_DOMAIN_ID = "second_domain";
+    private static final String SECOND_DOMAIN_CERT_HEADER = "client-cert-header-value";
+    private static final String SECOND_DOMAIN_SIGNING_ALIAS = "signature-alias";
+    private static final String SECOND_DOMAIN_SMP_ID = "SECOND-SMP-ID";
+
+    @Test(expected = WrongInputFieldException.class)
+    public void explictlySpecifiedDomainIsRequiredWhenSavingInMultipleDomainConfiguration() throws IOException {
+        saveServiceGroup();
+    }
+
+    @Test
+    public void saveAndReadPositiveScenarioForMultipleDomain() throws IOException {
+        // given
+        ServiceGroup inServiceGroup = unmarshal(loadDocumentAsString(SERVICE_GROUP_XML_PATH));
+        serviceGroupService.saveServiceGroup(inServiceGroup, SECOND_DOMAIN_ID, ADMIN_USERNAME);
+
+        // when
+        DBServiceGroup dbServiceGroup = serviceGroupDao.find(toDbModel(SERVICE_GROUP_ID));
+
+        // then
+        DBDomain dbDomain = dbServiceGroup.getDomain();
+        assertEquals(SECOND_DOMAIN_ID, dbDomain.getDomainId());
+        assertEquals(SECOND_DOMAIN_CERT_HEADER, dbDomain.getBdmslClientCertHeader());
+        assertEquals(SECOND_DOMAIN_SIGNING_ALIAS, dbDomain.getSignatureCertAlias());
+        assertEquals(SECOND_DOMAIN_SMP_ID, dbDomain.getBdmslSmpId());
+        assertTrue(isEmpty(dbDomain.getBdmslClientCertAlias()));
+    }
+
+    @Test(expected = WrongInputFieldException.class)
+    public void changingDomainOfExistingServiceGroupIsNotAllowed() throws Throwable {
+        //given
+        saveServiceGroup();
+        ServiceGroup newServiceGroup = unmarshal(loadDocumentAsString(SERVICE_GROUP_XML_PATH));
+
+        //when-then
+        serviceGroupService.saveServiceGroup(newServiceGroup, SECOND_DOMAIN_ID, ADMIN_USERNAME);
+    }
+
+
+}
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceSingleDomainIntegrationTest.java
similarity index 69%
rename from smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceIntegrationTest.java
rename to smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceSingleDomainIntegrationTest.java
index 589253981..6b98bbb43 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceSingleDomainIntegrationTest.java
@@ -1,7 +1,7 @@
 /*
- * Copyright 2017 European Commission | CEF eDelivery
+ * 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");
+ * 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
@@ -13,28 +13,17 @@
 
 package eu.europa.ec.edelivery.smp.services;
 
-import eu.europa.ec.edelivery.smp.data.dao.OwnershipDao;
-import eu.europa.ec.edelivery.smp.data.dao.ServiceGroupDao;
 import eu.europa.ec.edelivery.smp.data.model.DBOwnership;
 import eu.europa.ec.edelivery.smp.data.model.DBOwnershipId;
 import eu.europa.ec.edelivery.smp.data.model.DBServiceGroup;
 import eu.europa.ec.edelivery.smp.exceptions.NotFoundException;
-import eu.europa.ec.edelivery.smp.config.SmpServicesTestConfig;
+import eu.europa.ec.edelivery.smp.exceptions.WrongInputFieldException;
 import org.junit.Test;
-import org.junit.runner.RunWith;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.ExtensionType;
-import org.oasis_open.docs.bdxr.ns.smp._2016._05.ParticipantIdentifierType;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.ServiceGroup;
 import org.oasis_open.docs.bdxr.ns.smp._2016._05.ServiceMetadataReferenceType;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.annotation.Rollback;
-import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.jdbc.Sql;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.transaction.annotation.Transactional;
 
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
 import javax.xml.bind.JAXBException;
 import java.io.IOException;
 import java.util.List;
@@ -47,30 +36,10 @@ import static eu.europa.ec.smp.api.Identifiers.asParticipantId;
 import static org.junit.Assert.*;
 
 /**
- * Created by gutowpa on 27/03/2017.
+ * Created by gutowpa on 17/01/2018.
  */
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {SmpServicesTestConfig.class})
-@Transactional
-@Rollback(true)
 @Sql("classpath:/service_integration_test_data.sql")
-public class ServiceGroupServiceIntegrationTest {
-
-    private static final String SERVICE_GROUP_XML_PATH = "/eu/europa/ec/edelivery/smp/services/ServiceGroupPoland.xml";
-    private static final ParticipantIdentifierType SERVICE_GROUP_ID = asParticipantId("participant-scheme-qns::urn:poland:ncpb");
-    public static final String ADMIN_USERNAME = "test_admin";
-
-    @PersistenceContext
-    EntityManager em;
-
-    @Autowired
-    ServiceGroupDao serviceGroupDao;
-
-    @Autowired
-    OwnershipDao ownershipDao;
-
-    @Autowired
-    private ServiceGroupService serviceGroupService;
+public class ServiceGroupServiceSingleDomainIntegrationTest extends AbstractServiceGroupServiceIntegrationTest {
 
     @Test
     public void makeSureServiceGroupDoesNotExistAlready(){
@@ -130,7 +99,7 @@ public class ServiceGroupServiceIntegrationTest {
         newServiceGroup.getExtensions().add(newExtension);
 
         //when
-        serviceGroupService.saveServiceGroup(newServiceGroup, ADMIN_USERNAME);
+        serviceGroupService.saveServiceGroup(newServiceGroup, null, ADMIN_USERNAME);
         ServiceGroup resultServiceGroup = serviceGroupService.getServiceGroup(SERVICE_GROUP_ID);
 
         //then
@@ -152,9 +121,14 @@ public class ServiceGroupServiceIntegrationTest {
         assertEquals(0, serviceMetadataReferences.size());
     }
 
-    private ServiceGroup saveServiceGroup() throws IOException {
-        ServiceGroup inServiceGroup = unmarshal(loadDocumentAsString(SERVICE_GROUP_XML_PATH));
-        serviceGroupService.saveServiceGroup(inServiceGroup, ADMIN_USERNAME);
-        return inServiceGroup;
+    @Test(expected = WrongInputFieldException.class)
+    public void savingUnderNotExistingDomainIsNotAllowed() throws Throwable {
+        //given
+        saveServiceGroup();
+        ServiceGroup newServiceGroup = unmarshal(loadDocumentAsString(SERVICE_GROUP_XML_PATH));
+
+        //when-then
+        serviceGroupService.saveServiceGroup(newServiceGroup,"NOT-EXISITING-DOMAIN", ADMIN_USERNAME);
     }
+
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java
index 6574b16d2..f7ecca5f4 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceMetadataIntegrationTest.java
@@ -78,7 +78,7 @@ public class ServiceMetadataIntegrationTest {
     @Before
     public void before() throws IOException {
         ServiceGroup inServiceGroup = ServiceGroupConverter.unmarshal(loadDocumentAsString(SERVICE_GROUP_XML_PATH));
-        serviceGroupService.saveServiceGroup(inServiceGroup, ADMIN_USERNAME);
+        serviceGroupService.saveServiceGroup(inServiceGroup, null, ADMIN_USERNAME);
     }
 
     @Test
diff --git a/smp-server-library/src/test/resources/service_integration_multiple_domains_test_data.sql b/smp-server-library/src/test/resources/service_integration_multiple_domains_test_data.sql
new file mode 100644
index 000000000..471278f79
--- /dev/null
+++ b/smp-server-library/src/test/resources/service_integration_multiple_domains_test_data.sql
@@ -0,0 +1,2 @@
+INSERT INTO smp_domain(domainId, bdmslClientCertHeader, bdmslClientCertAlias, bdmslSmpId, signatureCertAlias) VALUES('second_domain', 'client-cert-header-value', '', 'SECOND-SMP-ID', 'signature-alias');
+INSERT INTO smp_domain(domainId, bdmslClientCertHeader, bdmslClientCertAlias, bdmslSmpId, signatureCertAlias) VALUES('third_domain', '', 'client-keystore-alias-key', 'THIRD-SMP-ID', 'signature-alias');
\ No newline at end of file
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
index 46d59d9e3..6cc311744 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
@@ -81,6 +81,7 @@ public class ServiceGroupController {
     public ResponseEntity saveServiceGroup(
             @PathVariable String serviceGroupId,
             @RequestHeader(name = "ServiceGroup-Owner", required = false) String serviceGroupOwner,
+            @RequestHeader(name = "Domain", required = false) String domain,
             @RequestBody String body) throws XmlInvalidAgainstSchemaException {
 
         log.info("PUT ServiceGroup: {}\n{}", serviceGroupId, body);
@@ -92,7 +93,7 @@ public class ServiceGroupController {
 
         // Service action
         String newOwnerName = isNotBlank(serviceGroupOwner) ? serviceGroupOwner : SecurityContextHolder.getContext().getAuthentication().getName();
-        boolean newServiceGroupCreated = serviceGroupService.saveServiceGroup(serviceGroup, newOwnerName);
+        boolean newServiceGroupCreated = serviceGroupService.saveServiceGroup(serviceGroup, domain, newOwnerName);
 
         log.info("Finished PUT ServiceGroup: {}", serviceGroupId);
 
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdvice.java
index 2d52497ce..3fdc1bcaa 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdvice.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdvice.java
@@ -16,6 +16,7 @@ package eu.europa.ec.edelivery.smp.error;
 import ec.services.smp._1.ErrorResponse;
 import eu.europa.ec.edelivery.smp.exceptions.NotFoundException;
 import eu.europa.ec.edelivery.smp.exceptions.UnknownUserException;
+import eu.europa.ec.edelivery.smp.exceptions.WrongInputFieldException;
 import eu.europa.ec.edelivery.smp.exceptions.XmlParsingException;
 import eu.europa.ec.edelivery.smp.error.exceptions.BadRequestException;
 import eu.europa.ec.smp.api.exceptions.MalformedIdentifierException;
@@ -61,6 +62,11 @@ public class ErrorMappingControllerAdvice {
         return buildAndWarn(BAD_REQUEST, FORMAT_ERROR, ex.getMessage(), ex);
     }
 
+    @ExceptionHandler(WrongInputFieldException.class)
+    public ResponseEntity handleWrongInputFieldException(WrongInputFieldException ex) {
+        return buildAndWarn(BAD_REQUEST, WRONG_FIELD, ex.getMessage(), ex);
+    }
+
     @ExceptionHandler(NotFoundException.class)
     public ResponseEntity handleNotFoundException(NotFoundException ex) {
         return buildAndWarn(NOT_FOUND, ErrorBusinessCode.NOT_FOUND, ex.getMessage(), ex);
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 bf74a2882..2dd916f2d 100644
--- a/smp-webapp/src/test/resources/webapp_integration_test_data.sql
+++ b/smp-webapp/src/test/resources/webapp_integration_test_data.sql
@@ -1,4 +1,30 @@
+--
+-- Copyright 2017 European Commission | CEF eDelivery
+--
+-- Licensed under the EUPL, Version 1.1 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 at:
+-- https://joinup.ec.europa.eu/software/page/eupl
+-- or file: LICENCE-EUPL-v1.1.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.
+
+
 insert into smp_user(username, password, isadmin) values ('test_admin',                                '$2a$06$k.Q/6anG4Eq/nNTZ0C1UIuAKxpr6ra5oaMkMSrlESIyA5jKEsUdyS', 1);
 insert into smp_user(username, password, isadmin) values ('test_user_hashed_pass',                     '$2a$06$k.Q/6anG4Eq/nNTZ0C1UIuAKxpr6ra5oaMkMSrlESIyA5jKEsUdyS', 0);
 insert into smp_user(username, password, isadmin) values ('test_user_clear_pass',                      'gutek123',                                                     0);
 insert into smp_user(username, password, isadmin) values ('CN=comon name,O=org,C=BE:0000000000000066', '',                                                             0);
+insert into smp_user (username, isadmin) values ('CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', 0);
+insert into smp_user (username, isadmin) values ('CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', 0);
+
+insert into smp_service_group(businessidentifier, businessidentifierscheme) values ('urn:australia:ncpb', 'ehealth-actorid-qns');
+insert into smp_service_group(businessidentifier, businessidentifierscheme) values ('urn:brazil:ncpb', 'ehealth-actorid-qns');
+
+insert into smp_ownership(username, businessidentifier, businessidentifierscheme) values ('CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', 'urn:australia:ncpb', 'ehealth-actorid-qns');
+insert into smp_ownership(username, businessidentifier, businessidentifierscheme) values ('CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', 'urn:brazil:ncpb', 'ehealth-actorid-qns');
+
+
+
-- 
GitLab