Merge branch 'master' of ssh://git.eclipse.org:29418/openk-usermodules/org.eclipse.openk-usermodules.elogbook into DEVELOP_BE
diff --git a/db/oracle/UpdateTo2.0.0FromDB_1.0.0/01_migrate_from_2.0.0_to_2.0.1.sql b/db/oracle/UpdateTo2.0.0FromDB_1.0.0/01_migrate_from_2.0.0_to_2.0.1.sql
new file mode 100644
index 0000000..bc6fc20
--- /dev/null
+++ b/db/oracle/UpdateTo2.0.0FromDB_1.0.0/01_migrate_from_2.0.0_to_2.0.1.sql
@@ -0,0 +1 @@
+ALTER TABLE TBL_NOTIFICATION add "RESPONSIBILITY_FORWARDING_UUID" RAW(16);
diff --git a/db/postgreSQL/UpdateTo2.0.0FromDB_1.0.0/01_migrate_from_2.0.0_to_2.0.1.sql b/db/postgreSQL/UpdateTo2.0.0FromDB_1.0.0/01_migrate_from_2.0.0_to_2.0.1.sql
new file mode 100644
index 0000000..b2db146
--- /dev/null
+++ b/db/postgreSQL/UpdateTo2.0.0FromDB_1.0.0/01_migrate_from_2.0.0_to_2.0.1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE tbl_notification add responsibility_forwarding_uuid uuid;
+
diff --git a/pom.xml b/pom.xml
index 8516e68..922f92b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,7 +27,7 @@
         <maven.test.skip>false</maven.test.skip>
         <jacoco-maven-plugin.version>0.7.9</jacoco-maven-plugin.version>
         <sonar-maven-plugin.version>3.0.2</sonar-maven-plugin.version>
-        <!--<javax.mail.version>3.0.2</javax.mail.version>-->
+        <hibernate-annotations.version>3.5.6-Final</hibernate-annotations.version>
     </properties>
     <dependencies>
         <dependency>
@@ -129,6 +129,11 @@
             <version>2.5.4</version>
         </dependency>
         <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-annotations</artifactId>
+            <version>${hibernate-annotations.version}</version>
+        </dependency>
+        <dependency>
             <groupId>com.auth0</groupId>
             <artifactId>java-jwt</artifactId>
             <version>3.2.0</version>
diff --git a/src/main/java/org/eclipse/openk/elogbook/common/BackendConfig.java b/src/main/java/org/eclipse/openk/elogbook/common/BackendConfig.java
index 45c640a..78a05da 100644
--- a/src/main/java/org/eclipse/openk/elogbook/common/BackendConfig.java
+++ b/src/main/java/org/eclipse/openk/elogbook/common/BackendConfig.java
@@ -38,6 +38,11 @@
   private boolean enableEmailPresenceCheckJob;
   private boolean isOnlySendSameDayReminderEmail;
 
+  private String cronSyncContacts;
+  private boolean enableContactSyncJob;
+  private String contactServiceTechUser;
+  private String contactServiceTechUserPwd;
+
   private static BackendConfig instance;
 
   private BackendConfig() {
@@ -128,6 +133,22 @@
   public boolean isOnlySendSameDayReminderEmail() {
     return isOnlySendSameDayReminderEmail;
   }
+
+  public String getCronSyncContacts() {
+    return cronSyncContacts;
+  }
+
+  public boolean isEnableContactSyncJob() {
+    return enableContactSyncJob;
+  }
+
+  public String getContactServiceTechUser() {
+    return contactServiceTechUser;
+  }
+
+  public String getContactServiceTechUserPwd() {
+    return contactServiceTechUserPwd;
+  }
 }
 
 
diff --git a/src/main/java/org/eclipse/openk/elogbook/common/mapper/NotificationMapper.java b/src/main/java/org/eclipse/openk/elogbook/common/mapper/NotificationMapper.java
index 92d6b02..8ac4d64 100644
--- a/src/main/java/org/eclipse/openk/elogbook/common/mapper/NotificationMapper.java
+++ b/src/main/java/org/eclipse/openk/elogbook/common/mapper/NotificationMapper.java
@@ -11,13 +11,6 @@
 */
 package org.eclipse.openk.elogbook.common.mapper;
 
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.eclipse.openk.elogbook.persistence.dao.RefBranchDao;
 import org.eclipse.openk.elogbook.persistence.dao.RefGridTerritoryDao;
 import org.eclipse.openk.elogbook.persistence.dao.RefNotificationPriorityDao;
@@ -30,6 +23,13 @@
 import org.eclipse.openk.elogbook.persistence.model.TblNotification;
 import org.eclipse.openk.elogbook.viewmodel.Notification;
 
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 public class NotificationMapper {
     private Map<Integer, RefNotificationStatus> refStatusMap;
     private Map<Integer, RefNotificationPriority> refPriorityMap;
@@ -77,6 +77,7 @@
         trg.setRefGridTerritory(refGridTerritoryMap.get(vmNot.getFkRefGridTerritory()));
         trg.setAdminFlag(vmNot.isAdminFlag());
         trg.setType(vmNot.getType());
+        trg.setResponsibilityForwardingUuid(vmNot.getResponsibilityForwardingUuid());
         return trg;
     }
 
@@ -126,6 +127,7 @@
         }
 		not.getAdminFlag(tblNot.isAdminFlag());
 		not.setType(tblNot.getType());
+		not.setResponsibilityForwardingUuid(tblNot.getResponsibilityForwardingUuid());
 		return not;
     }
 
diff --git a/src/main/java/org/eclipse/openk/elogbook/common/mapper/ResponsibilityMapper.java b/src/main/java/org/eclipse/openk/elogbook/common/mapper/ResponsibilityMapper.java
index 8ebfb2a..af40cb8 100644
--- a/src/main/java/org/eclipse/openk/elogbook/common/mapper/ResponsibilityMapper.java
+++ b/src/main/java/org/eclipse/openk/elogbook/common/mapper/ResponsibilityMapper.java
@@ -11,11 +11,6 @@
 */
 package org.eclipse.openk.elogbook.common.mapper;
 
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
 import org.apache.log4j.Logger;
 import org.eclipse.openk.elogbook.common.Globals;
 import org.eclipse.openk.elogbook.exceptions.BtbGone;
@@ -23,14 +18,17 @@
 import org.eclipse.openk.elogbook.viewmodel.Responsibility;
 import org.eclipse.openk.elogbook.viewmodel.TerritoryResponsibility;
 
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
 public class ResponsibilityMapper {
 
   private static final Logger LOGGER = Logger.getLogger(ResponsibilityMapper.class.getName());
   public enum PROCESS_MODE {PLAN, CONFIRM, FETCH}
 
-  public ResponsibilityMapper() { }
-
-
   public Responsibility mapToVModelForContainer(TblResponsibility tblResponsibility) {
 
          Responsibility responsibility = new Responsibility();
diff --git a/src/main/java/org/eclipse/openk/elogbook/common/timer/ContactSyncJob.java b/src/main/java/org/eclipse/openk/elogbook/common/timer/ContactSyncJob.java
new file mode 100644
index 0000000..81a35e3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/elogbook/common/timer/ContactSyncJob.java
@@ -0,0 +1,27 @@
+package org.eclipse.openk.elogbook.common.timer;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.elogbook.controller.BackendControllerUser;
+import org.eclipse.openk.elogbook.exceptions.BtbException;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+public class ContactSyncJob implements Job {
+
+    private static final Logger LOGGER = Logger.getLogger(ContactSyncJob.class.getName());
+
+    @Override
+    public void execute(JobExecutionContext arg0) throws JobExecutionException {
+        LOGGER.debug("Quartz: ContactSyncJob called");
+
+        try {
+            new BackendControllerUser().synchronizeContacts();
+        } catch (BtbException btbException) {
+            LOGGER.error("Error in synchronizeContacts");
+        }
+        LOGGER.debug("Quartz: ContactSyncJob finished");
+
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/elogbook/common/timer/InitContactSyncJobServlet.java b/src/main/java/org/eclipse/openk/elogbook/common/timer/InitContactSyncJobServlet.java
new file mode 100644
index 0000000..06f2ffd
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/elogbook/common/timer/InitContactSyncJobServlet.java
@@ -0,0 +1,50 @@
+package org.eclipse.openk.elogbook.common.timer;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.elogbook.common.BackendConfig;
+import org.quartz.CronScheduleBuilder;
+import org.quartz.JobBuilder;
+import org.quartz.JobDetail;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.Trigger;
+import org.quartz.TriggerBuilder;
+import org.quartz.impl.StdSchedulerFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+public class InitContactSyncJobServlet extends HttpServlet {
+
+    private static final long serialVersionUID = -7802116179801471578L;
+
+    private static final Logger LOGGER = Logger.getLogger(InitContactSyncJobServlet.class.getName());
+
+    @Override
+    public void init() throws ServletException {
+        String cronExpression = BackendConfig.getInstance().getCronSyncContacts();
+        boolean isJobEnabled = BackendConfig.getInstance().isEnableContactSyncJob();
+        if (isJobEnabled) {
+            LOGGER.info("Init timer: 'Check contact sync job' triggered with cronExpression: " + cronExpression);
+
+            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("CheckContactSyncTrigger", "CheckContactSyncTriggerGroup1")
+                    .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).build();
+
+            Scheduler scheduler;
+
+            try {
+                JobDetail contactSyncJob = JobBuilder.newJob(ContactSyncJob.class)
+                        .withIdentity("contactSyncJob", "contactSyncJobGroup").build();
+                scheduler = new StdSchedulerFactory().getScheduler();
+                scheduler.start();
+                scheduler.scheduleJob(contactSyncJob, trigger);
+            } catch (SchedulerException e) {
+                LOGGER.error("SchedulerException caught", e);
+            }
+        } else {
+            LOGGER.info("'Check contact sync job' is disabled");
+        }
+
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerNotificationFile.java b/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerNotificationFile.java
index 00f2a35..daab585 100644
--- a/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerNotificationFile.java
+++ b/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerNotificationFile.java
@@ -11,9 +11,14 @@
 */
 package org.eclipse.openk.elogbook.controller;
 
+import org.apache.commons.io.FilenameUtils;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.elogbook.common.BackendConfig;
+import org.eclipse.openk.elogbook.exceptions.BtbInternalServerError;
+import org.eclipse.openk.elogbook.viewmodel.NotificationFile;
+
 import java.io.File;
 import java.io.IOException;
-import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -23,11 +28,6 @@
 import java.nio.file.attribute.UserPrincipal;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.log4j.Logger;
-import org.eclipse.openk.elogbook.common.BackendConfig;
-import org.eclipse.openk.elogbook.exceptions.BtbInternalServerError;
-import org.eclipse.openk.elogbook.viewmodel.NotificationFile;
 
 public class BackendControllerNotificationFile {
 
@@ -113,7 +113,7 @@
 			throws IOException {
 		if (listOfFiles != null) {
 
-			//TODO 17.01.2019 "Leitsystem" is beeing updated and we are waiting for more information to continue here and adjust the import process
+			// 17.01.2019 "Leitsystem" is beeing updated and we are waiting for more information to continue here and adjust the import process
 			// see also BackendControllerNotificationFile_ImportFilenameAdjusted (reiss)
 
 			for (File file : listOfFiles) {
diff --git a/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerUser.java b/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerUser.java
index 8686316..38c675a 100644
--- a/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerUser.java
+++ b/src/main/java/org/eclipse/openk/elogbook/controller/BackendControllerUser.java
@@ -13,6 +13,7 @@
 package org.eclipse.openk.elogbook.controller;
 
 import org.apache.log4j.Logger;
+import org.eclipse.openk.elogbook.auth2.model.JwtToken;
 import org.eclipse.openk.elogbook.auth2.model.KeyCloakUser;
 import org.eclipse.openk.elogbook.auth2.util.JwtHelper;
 import org.eclipse.openk.elogbook.common.BackendConfig;
@@ -29,6 +30,7 @@
 import org.eclipse.openk.elogbook.persistence.model.TblUserSettings;
 import org.eclipse.openk.elogbook.viewmodel.LoginCredentials;
 import org.eclipse.openk.elogbook.viewmodel.UserAuthentication;
+import org.eclipse.openk.elogbook.viewmodel.contactbasedata.ContactTupel;
 
 import javax.persistence.EntityManager;
 import java.util.List;
@@ -55,6 +57,17 @@
 		return userAuthenticationList;
 	}
 
+	public String portalLogin(String user, String pwd) throws BtbException {
+		LOGGER.debug("portalLogin is called");
+		String credentials = "{ \"userName\": \""+user+"\", \"password\": \""+pwd+"\"}";
+		RestServiceWrapper restServiceWrapper = new RestServiceWrapper(BackendConfig.getInstance().getPortalBaseURL(), false);
+		String url = "login";
+		JwtToken jwt = JsonGeneratorBase.getGson().fromJson( restServiceWrapper.performPostRequest(url, "", credentials), JwtToken.class );
+
+		return jwt.getAccessToken();
+
+	}
+
 	public UserAuthentication authenticate(String credentials) throws BtbException {
 		LOGGER.debug("authenticate() is called");
 
@@ -85,16 +98,15 @@
 		return ret;
 	}
 
-	public List<String> getUserSuggestionsFromContactdatabase(String token) throws BtbException {
+	public List<ContactTupel> getUserSuggestionsFromContactdatabase(String token) throws BtbException {
 		LOGGER.debug("getUserSuggestionsFromContactdatabase() is called");
-		List<String> userContacts = ContactBaseDataManager.getInstance().getUserContacts(token);
+		List<ContactTupel> userContacts = ContactBaseDataManager.getInstance().getUserContacts(token);
 		LOGGER.debug("getUserSuggestionsFromContactdatabase() is finished");
 		return userContacts;
 	}
 
 	public void sentTestMail() throws BtbException {
 		LOGGER.debug("sentTestMail() is called");
-		//EmailService.getInstance().senTestMail();
 		EmailService.getInstance().sendPresenceCheckReminderMail();
 		LOGGER.debug("sentTestMail() is finished");
 	}
@@ -112,6 +124,20 @@
 
 	}
 
+
+	public void synchronizeContacts() throws BtbException {
+		LOGGER.debug("synchronizeContacts() is called");
+
+		try {
+			ContactBaseDataManager.getInstance().synchronizeContacts(portalLogin(
+					BackendConfig.getInstance().getContactServiceTechUser(),
+					BackendConfig.getInstance().getContactServiceTechUserPwd()
+			));
+		} finally {
+			LOGGER.debug("synchronizeContacts() is finished");
+		}
+
+	}
 	public String getUserSettings( String modUser ) throws BtbInternalServerError {
 		LOGGER.debug("getUserSettings() is called");
 		EntityManager emOrg = EntityHelper.getEMF().createEntityManager();
diff --git a/src/main/java/org/eclipse/openk/elogbook/controller/ContactBaseDataManager.java b/src/main/java/org/eclipse/openk/elogbook/controller/ContactBaseDataManager.java
index 4005527..ec45f29 100644
--- a/src/main/java/org/eclipse/openk/elogbook/controller/ContactBaseDataManager.java
+++ b/src/main/java/org/eclipse/openk/elogbook/controller/ContactBaseDataManager.java
@@ -12,17 +12,27 @@
 package org.eclipse.openk.elogbook.controller;
 
 
+import org.apache.log4j.Logger;
 import org.eclipse.openk.elogbook.common.BackendConfig;
 import org.eclipse.openk.elogbook.common.JsonGeneratorBase;
 import org.eclipse.openk.elogbook.communication.RestServiceWrapper;
 import org.eclipse.openk.elogbook.exceptions.BtbException;
+import org.eclipse.openk.elogbook.persistence.dao.AutoCloseEntityManager;
+import org.eclipse.openk.elogbook.persistence.dao.EntityHelper;
+import org.eclipse.openk.elogbook.persistence.dao.TblNotificationDao;
+import org.eclipse.openk.elogbook.viewmodel.contactbasedata.ContactTupel;
 import org.eclipse.openk.elogbook.viewmodel.contactbasedata.VwDetailedContact;
 import org.eclipse.openk.elogbook.viewmodel.contactbasedata.VwDetailedContactPage;
 
-import java.util.ArrayList;
+import javax.persistence.EntityManager;
 import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
 
 public class ContactBaseDataManager {
+    private static final Logger LOGGER = Logger.getLogger(ContactBaseDataManager.class.getName());
+
 
     private static final ContactBaseDataManager INSTANCE = new ContactBaseDataManager();
 
@@ -33,21 +43,43 @@
         return INSTANCE;
     }
 
-    public List<String> getUserContacts(String token) throws BtbException {
-        List<String> returnList = new ArrayList();
+    public List<ContactTupel> getUserContacts(String token) throws BtbException {
         RestServiceWrapper restServiceWrapper = new RestServiceWrapper(BackendConfig.getInstance().getContactBaseDataApiUrl(), false);
         String response = restServiceWrapper.performGetRequest("contacts?size=2000",token);
         VwDetailedContactPage vwDetailedContactPage = JsonGeneratorBase.getGson().fromJson(response,
                 VwDetailedContactPage.class);
-        List<VwDetailedContact> content = vwDetailedContactPage.getContent();
-        for (VwDetailedContact vwDetailedContact : content) {
-            String userName = vwDetailedContact.getName();
-            if (userName != null) {
-                userName = userName.replace("," ,"");
-            }
-            returnList.add(userName);
+        return vwDetailedContactPage.getContent().stream().map(this::mapFromViewObj ).collect(Collectors.toList());
+    }
+
+    public void synchronizeContacts(String token) {
+        LOGGER.debug("synchronizeContacts is called");
+        EntityManager emOrg = EntityHelper.getEMF().createEntityManager();
+        try (AutoCloseEntityManager em = new AutoCloseEntityManager(emOrg)) {
+            em.getTransaction().begin();
+            TblNotificationDao notifDao = new TblNotificationDao(em);
+            Map<UUID, String> uuid2NameMap = getUserContacts(token).stream().collect(Collectors.toMap(ContactTupel::getContactUuid, ContactTupel::getContactName));
+            notifDao.getDistinctResponsibilityForwardingUuid()
+                        .forEach( contactUuid -> notifDao.updateResponsibilityForwardingByContactUuid( contactUuid, uuid2NameMap.getOrDefault(contactUuid, "/gelöscht/")));
+            em.getTransaction().commit();
+
+        } catch (BtbException btbException) {
+            LOGGER.error("error in synchronizeContacts", btbException);
+        } finally {
+            LOGGER.debug("synchronizeContacts is finished");
         }
-        return returnList;
+    }
+
+
+    private ContactTupel mapFromViewObj( VwDetailedContact vwDetailedContact ) {
+        String userName = vwDetailedContact.getName();
+        if (userName != null) {
+            userName = userName.replace("," ,"");
+        }
+        ContactTupel ct = new ContactTupel();
+        ct.setContactName(userName);
+        ct.setContactUuid(vwDetailedContact.getUuid());
+        return ct;
+
     }
 
 }
diff --git a/src/main/java/org/eclipse/openk/elogbook/controller/ControllerImplementations.java b/src/main/java/org/eclipse/openk/elogbook/controller/ControllerImplementations.java
index 32c9882..b7ba24b 100644
--- a/src/main/java/org/eclipse/openk/elogbook/controller/ControllerImplementations.java
+++ b/src/main/java/org/eclipse/openk/elogbook/controller/ControllerImplementations.java
@@ -31,6 +31,7 @@
 import org.eclipse.openk.elogbook.viewmodel.TerritoryResponsibility;
 import org.eclipse.openk.elogbook.viewmodel.UserAuthentication;
 import org.eclipse.openk.elogbook.viewmodel.VersionInfo;
+import org.eclipse.openk.elogbook.viewmodel.contactbasedata.ContactTupel;
 
 import javax.ws.rs.core.Response;
 import java.util.List;
@@ -573,13 +574,30 @@
 
 		@Override
 		public Response invoke() throws BtbException {
-//			List<String> userSuggestionsList = backendControllerUser.getAssignedUserSuggestions();
-			List<String> userSuggestionsList = backendControllerUser.getUserSuggestionsFromContactdatabase(this.token);
+			List<ContactTupel> userSuggestionsList = backendControllerUser.getUserSuggestionsFromContactdatabase(this.token);
 			return ResponseBuilderWrapper.INSTANCE
 					.buildOKResponse(JsonGeneratorBase.getGson().toJson(userSuggestionsList));
 		}
 	}
 
+
+	public static class SynchronizeContacts extends BackendInvokable {
+
+		private BackendControllerUser backendControllerUser;
+		private String token;
+
+		public SynchronizeContacts(BackendControllerUser backendControllerUser, String token) {
+			this.backendControllerUser = backendControllerUser;
+			this.token = token;
+		}
+
+		@Override
+		public Response invoke() throws BtbException {
+			backendControllerUser.synchronizeContacts();
+			return ResponseBuilderWrapper.INSTANCE
+					.buildOKResponse(JsonGeneratorBase.getGson().toJson(Globals.OK_STRING));
+		}
+	}
 	public static class GetTestMail extends BackendInvokable {
 
 		private BackendControllerUser backendControllerUser;
diff --git a/src/main/java/org/eclipse/openk/elogbook/controller/ResponseBuilderWrapper.java b/src/main/java/org/eclipse/openk/elogbook/controller/ResponseBuilderWrapper.java
index 1745e1e..46e5143 100644
--- a/src/main/java/org/eclipse/openk/elogbook/controller/ResponseBuilderWrapper.java
+++ b/src/main/java/org/eclipse/openk/elogbook/controller/ResponseBuilderWrapper.java
@@ -17,7 +17,7 @@
 import org.eclipse.openk.elogbook.exceptions.BtbInternalServerError;
 
 import javax.ws.rs.core.Response;
-import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 
 public enum ResponseBuilderWrapper {
     INSTANCE;
@@ -42,11 +42,7 @@
     }
 
     private byte[] jsonStringToBytes( String jsonString ) throws BtbInternalServerError {
-        try {
-            return jsonString.getBytes("UTF-8");
-        } catch (UnsupportedEncodingException e) {
-            throw new BtbInternalServerError("Unexpected Error", e);
-        }
+        return jsonString.getBytes(StandardCharsets.UTF_8);
     }
 
     public Response buildOKResponse(String jsonString) throws BtbException {
diff --git a/src/main/java/org/eclipse/openk/elogbook/controller/TokenManager.java b/src/main/java/org/eclipse/openk/elogbook/controller/TokenManager.java
index c62a51c..63f8fa7 100644
--- a/src/main/java/org/eclipse/openk/elogbook/controller/TokenManager.java
+++ b/src/main/java/org/eclipse/openk/elogbook/controller/TokenManager.java
@@ -50,11 +50,11 @@
         if (jwtPayload != null && secureType == SecureType.NORMAL && !(jwtPayload.getRealmAccess()
             .isInRole(Globals.KEYCLOAK_ROLE_NORMALUSER) || jwtPayload.getRealmAccess()
             .isInRole(Globals.KEYCLOAK_ROLE_SUPERUSER))){
-            LOGGER.warn("Security level not sufficent ");
+            LOGGER.warn("Security level not sufficent.");
             throw new BtbForbidden("insufficent rights");
         } else if (jwtPayload != null && secureType == BaseWebService.SecureType.HIGH &&
             !jwtPayload.getRealmAccess().isInRole(Globals.KEYCLOAK_ROLE_SUPERUSER)){
-            LOGGER.warn("Security level not sufficent ");
+            LOGGER.warn("Security level not sufficent!");
             throw new BtbForbidden("insufficent rights");
         }
     }
diff --git a/src/main/java/org/eclipse/openk/elogbook/email/Email.java b/src/main/java/org/eclipse/openk/elogbook/email/Email.java
index 68dd459..e8a145b 100644
--- a/src/main/java/org/eclipse/openk/elogbook/email/Email.java
+++ b/src/main/java/org/eclipse/openk/elogbook/email/Email.java
@@ -25,7 +25,6 @@
 import jakarta.mail.internet.MimeMultipart;
 import org.apache.log4j.Logger;
 
-import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
diff --git a/src/main/java/org/eclipse/openk/elogbook/persistence/dao/TblNotificationDao.java b/src/main/java/org/eclipse/openk/elogbook/persistence/dao/TblNotificationDao.java
index d8bf720..9685cbb 100644
--- a/src/main/java/org/eclipse/openk/elogbook/persistence/dao/TblNotificationDao.java
+++ b/src/main/java/org/eclipse/openk/elogbook/persistence/dao/TblNotificationDao.java
@@ -11,11 +11,6 @@
 */
 package org.eclipse.openk.elogbook.persistence.dao;
 
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.List;
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
 import org.eclipse.openk.elogbook.common.NotificationStatus;
 import org.eclipse.openk.elogbook.exceptions.BtbException;
 import org.eclipse.openk.elogbook.exceptions.BtbInternalServerError;
@@ -29,6 +24,13 @@
 import org.eclipse.openk.elogbook.viewmodel.NotificationSearchFilter;
 import org.eclipse.openk.elogbook.viewmodel.ReminderSearchFilter;
 
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
 public class TblNotificationDao extends GenericDaoJpa<TblNotification, Integer> {
 	private static final String VIEW_ACTIVE_NOTIFICATION = EntityHelper.instance().makeIdentifier("VIEW_ACTIVE_NOTIFICATION");
 	private static final String FK_REF_NOTIFICATION_STATUS = EntityHelper.instance().makeIdentifier("fk_ref_notification_status");
@@ -36,6 +38,7 @@
 	private static final String INCIDENT_ID = EntityHelper.instance().makeIdentifier("incident_id");
 	private static final String VERSION = EntityHelper.instance().makeIdentifier("version");
 	private static final String RESPONSIBILITY_FORWARDING = EntityHelper.instance().makeIdentifier("responsibility_forwarding");
+	private static final String RESPONSIBILITY_FORW_UUID = EntityHelper.instance().makeIdentifier("responsibility_forwarding_uuid");
 
 
 
@@ -189,6 +192,31 @@
 		}
 	}
 
+	public List<UUID> getDistinctResponsibilityForwardingUuid() throws BtbInternalServerError {
+		try {
+			String selectString = "select distinct "+RESPONSIBILITY_FORW_UUID+" from "+TBL_NOTIFICATION+" n where n.responsibility_forwarding_uuid is not null";
+			Query q = getEM().createNativeQuery(selectString);
+			return q.getResultList();
+
+		} catch (Exception t) {
+			LOGGER.error(t);
+			throw new BtbInternalServerError("Error loading distict responsibility forwarding uuid");
+		}
+	}
+
+	public void updateResponsibilityForwardingByContactUuid( UUID contactUuid, String contactName ) {
+		try {
+			String selectString = "update "+TBL_NOTIFICATION+" set "+RESPONSIBILITY_FORWARDING+" = ? where "+RESPONSIBILITY_FORW_UUID+" = ?";
+			Query q = getEM().createNativeQuery(selectString);
+			q.setParameter(2, contactUuid);
+			q.setParameter(1, contactName);
+			q.executeUpdate();
+
+		} catch (Exception t) {
+			LOGGER.error(t);
+		}
+	}
+
 
 	/**
 	 * Create and execute the query to get a collection of notifications.
diff --git a/src/main/java/org/eclipse/openk/elogbook/persistence/model/AbstractNotification.java b/src/main/java/org/eclipse/openk/elogbook/persistence/model/AbstractNotification.java
index 2944de0..5dde8c6 100644
--- a/src/main/java/org/eclipse/openk/elogbook/persistence/model/AbstractNotification.java
+++ b/src/main/java/org/eclipse/openk/elogbook/persistence/model/AbstractNotification.java
@@ -11,9 +11,21 @@
 */
 package org.eclipse.openk.elogbook.persistence.model;
 
-import javax.persistence.*;
+import org.eclipse.openk.elogbook.persistence.util.UUIDConverter;
+import org.eclipse.persistence.annotations.Convert;
+import org.eclipse.persistence.annotations.Converter;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.SequenceGenerator;
 import java.io.Serializable;
 import java.sql.Timestamp;
+import java.util.UUID;
 
 
 /**
@@ -72,6 +84,11 @@
 	@Column(name="responsibility_forwarding")
 	private String responsibilityForwarding;
 
+	@Column(name="responsibility_forwarding_uuid")
+	@Converter(converterClass= UUIDConverter.class, name="responsibility_forwarding_uuid")
+	@Convert("responsibility_forwarding_uuid")
+	private UUID responsibilityForwardingUuid;
+
 	@Column(name="version")
 	private Integer version;
 	
@@ -279,4 +296,12 @@
 	public void setType(String type) {
 		this.type = type;
 	}
+
+	public UUID getResponsibilityForwardingUuid() {
+		return responsibilityForwardingUuid;
+	}
+
+	public void setResponsibilityForwardingUuid(UUID responsibilityForwardingUuid) {
+		this.responsibilityForwardingUuid = responsibilityForwardingUuid;
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/elogbook/persistence/util/UUIDConverter.java b/src/main/java/org/eclipse/openk/elogbook/persistence/util/UUIDConverter.java
new file mode 100644
index 0000000..c39247c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/elogbook/persistence/util/UUIDConverter.java
@@ -0,0 +1,67 @@
+package org.eclipse.openk.elogbook.persistence.util;
+
+import org.eclipse.persistence.internal.helper.DatabaseField;
+import org.eclipse.persistence.mappings.DatabaseMapping;
+import org.eclipse.persistence.mappings.OneToOneMapping;
+import org.eclipse.persistence.sessions.Session;
+
+import java.sql.Types;
+import java.text.MessageFormat;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class UUIDConverter implements org.eclipse.persistence.mappings.converters.Converter
+{
+    private static final Logger LOG = Logger.getLogger(UUIDConverter.class.getName());
+
+    @Override
+    public UUID convertObjectValueToDataValue(Object objectValue, Session session)
+    {
+        return (UUID) objectValue;
+    }
+
+    @Override
+    public UUID convertDataValueToObjectValue(Object dataValue, Session session)
+    {
+        return (UUID) dataValue;
+    }
+
+    @Override
+    public boolean isMutable()
+    {
+        return false;
+    }
+
+    @Override
+    public void initialize(DatabaseMapping mapping, Session session)
+    {
+        DatabaseField field = mapping.getField();
+        field.setSqlType(Types.OTHER);
+        field.setTypeName("java.util.UUID");
+        field.setColumnDefinition("UUID");
+
+
+        if (LOG.isLoggable(Level.FINE))
+            LOG.log(Level.FINE, MessageFormat.format("Setting local field {0} to be a UUID", field) );
+
+        // Find the bi-directional references other objects have to this field, and update them to be uuid too
+        for (DatabaseMapping m : mapping.getDescriptor().getMappings())
+        {
+            if (m instanceof OneToOneMapping)
+            {
+                OneToOneMapping oneToOneMapping = (OneToOneMapping) m;
+
+                DatabaseField relationshipField = oneToOneMapping.getSourceToTargetKeyFields().get(field);
+                if (relationshipField != null)
+                {
+                    relationshipField.setSqlType(Types.OTHER);
+                    relationshipField.setColumnDefinition("UUID");
+                    relationshipField.setTypeName("java.util.UUID");
+                    if (LOG.isLoggable(Level.FINE))
+                        LOG.log(Level.FINE, MessageFormat.format("Setting foreign key field {0} to be a UUID", relationshipField));
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/elogbook/rest/BackendRestService.java b/src/main/java/org/eclipse/openk/elogbook/rest/BackendRestService.java
index 7f9b029..b0b694e 100644
--- a/src/main/java/org/eclipse/openk/elogbook/rest/BackendRestService.java
+++ b/src/main/java/org/eclipse/openk/elogbook/rest/BackendRestService.java
@@ -325,6 +325,15 @@
 				new ControllerImplementations.GetUserSuggestions(new BackendControllerUser(), token));
 	}
 
+
+	@GET
+	@Path("/synchronizeContacts")
+	@Produces("application/json")
+	public Response synchronizeContacts(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String token) {
+		return invoke(token, SecureType.NORMAL,
+				new ControllerImplementations.SynchronizeContacts(new BackendControllerUser(), token));
+	}
+
 	@GET
 	@Path("/testmail")
 	@Produces("application/json")
diff --git a/src/main/java/org/eclipse/openk/elogbook/viewmodel/Notification.java b/src/main/java/org/eclipse/openk/elogbook/viewmodel/Notification.java
index 02c8177..0a29961 100644
--- a/src/main/java/org/eclipse/openk/elogbook/viewmodel/Notification.java
+++ b/src/main/java/org/eclipse/openk/elogbook/viewmodel/Notification.java
@@ -13,6 +13,7 @@
 
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 
 public class Notification {
 
@@ -28,6 +29,7 @@
     private String freeText;
     private String freeTextExtended;
     private String responsibilityForwarding;
+    private UUID responsibilityForwardingUuid;
     private String responsibilityControlPoint;
     private Date reminderDate;
     private Date futureDate;
@@ -255,4 +257,12 @@
     public void setType(String type) {
         this.type = type;
     }
+
+    public UUID getResponsibilityForwardingUuid() {
+        return responsibilityForwardingUuid;
+    }
+
+    public void setResponsibilityForwardingUuid(UUID responsibilityForwardingUuid) {
+        this.responsibilityForwardingUuid = responsibilityForwardingUuid;
+    }
 }
diff --git a/src/main/java/org/eclipse/openk/elogbook/viewmodel/contactbasedata/ContactTupel.java b/src/main/java/org/eclipse/openk/elogbook/viewmodel/contactbasedata/ContactTupel.java
new file mode 100644
index 0000000..63d22eb
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/elogbook/viewmodel/contactbasedata/ContactTupel.java
@@ -0,0 +1,24 @@
+package org.eclipse.openk.elogbook.viewmodel.contactbasedata;
+
+import java.util.UUID;
+
+public class ContactTupel {
+    private String contactName;
+    private UUID contactUuid;
+
+    public String getContactName() {
+        return contactName;
+    }
+
+    public void setContactName(String contactName) {
+        this.contactName = contactName;
+    }
+
+    public UUID getContactUuid() {
+        return contactUuid;
+    }
+
+    public void setContactUuid(UUID contactUuid) {
+        this.contactUuid = contactUuid;
+    }
+}
diff --git a/src/main/resources/backendConfigDevLocal.json b/src/main/resources/backendConfigDevLocal.json
index feea975..f0de1af 100644
--- a/src/main/resources/backendConfigDevLocal.json
+++ b/src/main/resources/backendConfigDevLocal.json
@@ -18,5 +18,12 @@
   "isOnlySendSameDayReminderEmail": true,
 
   "cronEmailPresenceCheck": "30 0 16 * * ?",
-  "enableEmailPresenceCheckJob": true
+  "enableEmailPresenceCheckJob": true,
+
+  "_cronSyncContacts": "0 0 1 * * ?",
+  "cronSyncContacts": "* 0/1 * * * ?",
+  "enableContactSyncJob": true,
+  "contactServiceTechUser": "admin",
+  "contactServiceTechUserPwd": "admin"
+
 }
diff --git a/src/main/resources/backendConfigDevServer.json b/src/main/resources/backendConfigDevServer.json
index d17a708..6d8031c 100644
--- a/src/main/resources/backendConfigDevServer.json
+++ b/src/main/resources/backendConfigDevServer.json
@@ -18,6 +18,12 @@
   "isOnlySendSameDayReminderEmail": true,
 
   "_cronEmailPresenceCheck": "30 0 16 * * ?",
-  "cronEmailPresenceCheck": "0 */1 * * * ?",
-  "enableEmailPresenceCheckJob": true
+  "cronEmailPresenceCheck": "0 0/1 * * * ?",
+  "enableEmailPresenceCheckJob": true,
+
+  "_cronSyncContacts": "0 0 1 * * ?",
+  "cronSyncContacts": "0 0/1 * * * ?",
+  "enableContactSyncJob": true,
+  "contactServiceTechUser": "admin",
+  "contactServiceTechUserPwd": "admin"
 }
diff --git a/src/main/resources/backendConfigProduction.json b/src/main/resources/backendConfigProduction.json
index f2d242f..b5bc551 100644
--- a/src/main/resources/backendConfigProduction.json
+++ b/src/main/resources/backendConfigProduction.json
@@ -16,5 +16,11 @@
 
   "_cronEmailPresenceCheck": "30 0 16 * * ?",
   "cronEmailPresenceCheck": "0 */2 * * * ?",
-  "enableEmailPresenceCheckJob": true
+  "enableEmailPresenceCheckJob": true,
+
+  "cronSyncContacts": "0 0 1 * * ?",
+  "enableContactSyncJob": true,
+  "contactServiceTechUser": "admin",
+  "contactServiceTechUserPwd": "admin"
+
 }
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index d8a0ce9..99fd8b3 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -73,5 +73,9 @@
         <load-on-startup>3</load-on-startup>
     </servlet>
 
-
+    <servlet>
+        <servlet-name>InitContactSyncJobServlet</servlet-name>
+        <servlet-class>org.eclipse.openk.elogbook.common.timer.InitContactSyncJobServlet</servlet-class>
+        <load-on-startup>4</load-on-startup>
+    </servlet>
 </web-app>
diff --git a/src/test/java/org/eclipse/openk/elogbook/controller/ControllerImplementationsTest.java b/src/test/java/org/eclipse/openk/elogbook/controller/ControllerImplementationsTest.java
index 57dfa37..5087479 100644
--- a/src/test/java/org/eclipse/openk/elogbook/controller/ControllerImplementationsTest.java
+++ b/src/test/java/org/eclipse/openk/elogbook/controller/ControllerImplementationsTest.java
@@ -369,7 +369,7 @@
     public void testGetAssignedUserSuggestions() throws BtbException {
         List<String> assignedUserSuggestionsList = new LinkedList<>();
 
-        ControllerImplementations.GetUserSuggestions controllerImpl = new ControllerImplementations.GetUserSuggestions(beMockUser, "fakeToken");
+        ControllerImplementations.SynchronizeContacts controllerImpl = new ControllerImplementations.SynchronizeContacts(beMockUser, "fakeToken");
         expect(beMockUser.getAssignedUserSuggestions()).andReturn(assignedUserSuggestionsList);
          PowerMock.replay(beMockUser);