From a50dd692231b5967528bc1a10c4594e1085ca5e5 Mon Sep 17 00:00:00 2001
From: Christos Tranoris <tranoris@ece.upatras.gr>
Date: Sun, 12 Jan 2025 13:19:38 +0200
Subject: [PATCH] fixes for addressing issue #63

---
 .../tmf/ri639/repo/ResourceRepository.java    |   5 +-
 .../reposervices/ResourceRepoService.java     |  29 ++-
 .../tmf/sim638/repo/ServiceRepository.java    |   5 +-
 .../sim638/service/ServiceRepoService.java    |  24 +-
 .../so641/repo/ServiceOrderRepository.java    |   5 +-
 .../reposervices/ServiceOrderRepoService.java |  22 +-
 src/main/resources/application.yml            |   2 +-
 .../api/ResourceInventoryIntegrationTest.java | 222 ++++++++++++++++--
 .../api/sim638/ServiceRepoServiceTest.java    |  25 ++
 .../ri639/ResourceRepoServiceTest.java        |   5 +-
 10 files changed, 274 insertions(+), 70 deletions(-)

diff --git a/src/main/java/org/etsi/osl/tmf/ri639/repo/ResourceRepository.java b/src/main/java/org/etsi/osl/tmf/ri639/repo/ResourceRepository.java
index 86de40b..446a04c 100644
--- a/src/main/java/org/etsi/osl/tmf/ri639/repo/ResourceRepository.java
+++ b/src/main/java/org/etsi/osl/tmf/ri639/repo/ResourceRepository.java
@@ -22,15 +22,14 @@ package org.etsi.osl.tmf.ri639.repo;
 import java.util.List;
 import java.util.Optional;
 import org.etsi.osl.tmf.ri639.model.Resource;
+import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.CrudRepository;
-import org.springframework.data.repository.PagingAndSortingRepository;
 import org.springframework.stereotype.Repository;
 
 
 
 @Repository
-public interface ResourceRepository extends  CrudRepository<Resource, Long>, PagingAndSortingRepository<Resource, Long> {
+public interface ResourceRepository extends  JpaRepository<Resource, Long> {
 
 	
 	Optional<Resource> findByUuid(String id);
diff --git a/src/main/java/org/etsi/osl/tmf/ri639/reposervices/ResourceRepoService.java b/src/main/java/org/etsi/osl/tmf/ri639/reposervices/ResourceRepoService.java
index e3f0f4c..3f645f4 100644
--- a/src/main/java/org/etsi/osl/tmf/ri639/reposervices/ResourceRepoService.java
+++ b/src/main/java/org/etsi/osl/tmf/ri639/reposervices/ResourceRepoService.java
@@ -67,6 +67,7 @@ import org.hibernate.SessionFactory;
 import org.hibernate.Transaction;
 import org.hibernate.transform.ResultTransformer;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import jakarta.persistence.EntityManagerFactory;
 import jakarta.validation.Valid;
@@ -199,7 +200,7 @@ public class ResourceRepoService {
     return (List<Resource>) this.resourceRepo.findByRolename(name);
   }
 
-
+  @Transactional
   public Resource addResource(@Valid ResourceCreate resource) {
     logger.info("Will add Resource: " + resource.getName());
 
@@ -272,7 +273,7 @@ public class ResourceRepoService {
     noteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC));
     s.addNoteItem(noteItem);
 
-    s = this.resourceRepo.save(s);
+    s = this.resourceRepo.saveAndFlush(s);
 
     raiseResourceCreateNotification(s);
     return s;
@@ -448,7 +449,7 @@ public class ResourceRepoService {
     }
 
 
-    resource = this.resourceRepo.save(resource);
+    resource = this.resourceRepo.saveAndFlush(resource);
     
     if (resourceCharacteristicChanged) {
       raiseResourceAttributeValueChangeEventNotification(resource);
@@ -458,6 +459,7 @@ public class ResourceRepoService {
     return resource;
   }
 
+  @Transactional
   public String getResourceEagerAsString(String id) throws JsonProcessingException {
     Resource s = this.getResourceEager(id);
     ObjectMapper mapper = new ObjectMapper();
@@ -467,11 +469,13 @@ public class ResourceRepoService {
     return res;
   }
 
+
+  @Transactional
   public Resource getResourceEager(String id) {
-    Session session = sessionFactory.openSession();
-    Transaction tx = session.beginTransaction();
+    
     Resource s = null;
-    try {
+    try(Session session = sessionFactory.openSession()) {
+      Transaction tx = session.beginTransaction();
       s = (Resource) session.get(Resource.class, id);
       if (s == null) {
         return this.findByUuid(id);// last resort
@@ -487,15 +491,15 @@ public class ResourceRepoService {
 
 
       tx.commit();
-    } finally {
-      session.close();
+    } catch (Exception e) {
+      e.printStackTrace();
     }
 
     return s;
   }
 
 
-  @Transactional
+  @Transactional(propagation = Propagation.REQUIRES_NEW)
   private void raiseResourceCreateNotification(Resource so) {
     ResourceCreateNotification n = new ResourceCreateNotification();
     ResourceCreateEvent event = new ResourceCreateEvent();
@@ -505,7 +509,7 @@ public class ResourceRepoService {
 
   }
 
-  @Transactional
+  @Transactional(propagation = Propagation.REQUIRES_NEW)
   private void raiseResourceAttributeValueChangeEventNotification(Resource so) {
     ResourceAttributeValueChangeNotification n = new ResourceAttributeValueChangeNotification();
     ResourceAttributeValueChangeEvent event = new ResourceAttributeValueChangeEvent();
@@ -516,8 +520,8 @@ public class ResourceRepoService {
   }
   
   
-  
-  @Transactional
+
+  @Transactional(propagation = Propagation.REQUIRES_NEW)
   private void raiseResourceStateChangeEventNotification(Resource so) {
     ResourceStateChangeNotification n = new ResourceStateChangeNotification();
     ResourceStateChangeEvent event = new ResourceStateChangeEvent();
@@ -554,6 +558,7 @@ public class ResourceRepoService {
     return result;
   }
 
+  @Transactional
   public Void deleteByUuid(String id) {
     Optional<Resource> optionalCat = this.resourceRepo.findByUuid(id);
     Resource s = optionalCat.get();
diff --git a/src/main/java/org/etsi/osl/tmf/sim638/repo/ServiceRepository.java b/src/main/java/org/etsi/osl/tmf/sim638/repo/ServiceRepository.java
index bd2cbf0..8c92037 100644
--- a/src/main/java/org/etsi/osl/tmf/sim638/repo/ServiceRepository.java
+++ b/src/main/java/org/etsi/osl/tmf/sim638/repo/ServiceRepository.java
@@ -22,15 +22,14 @@ package org.etsi.osl.tmf.sim638.repo;
 import java.util.List;
 import java.util.Optional;
 import org.etsi.osl.tmf.sim638.model.Service;
+import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.CrudRepository;
-import org.springframework.data.repository.PagingAndSortingRepository;
 import org.springframework.stereotype.Repository;
 
 
 
 @Repository
-public interface ServiceRepository extends CrudRepository<Service, Long>,  PagingAndSortingRepository<Service, Long> {
+public interface ServiceRepository extends JpaRepository<Service, Long> {
 
 	
 	Optional<Service> findByUuid(String id);
diff --git a/src/main/java/org/etsi/osl/tmf/sim638/service/ServiceRepoService.java b/src/main/java/org/etsi/osl/tmf/sim638/service/ServiceRepoService.java
index 62d067a..01b5b31 100644
--- a/src/main/java/org/etsi/osl/tmf/sim638/service/ServiceRepoService.java
+++ b/src/main/java/org/etsi/osl/tmf/sim638/service/ServiceRepoService.java
@@ -78,6 +78,7 @@ import org.hibernate.SessionFactory;
 import org.hibernate.Transaction;
 import org.hibernate.transform.ResultTransformer;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import org.etsi.osl.model.nfv.DeploymentDescriptor;
 import org.etsi.osl.model.nfv.DeploymentDescriptorVxFInstanceInfo;
@@ -340,7 +341,7 @@ public class ServiceRepoService {
 		noteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC) );
 		s.addNoteItem(noteItem);		
 		
-		s = this.serviceRepo.save( s );
+		s = this.serviceRepo.saveAndFlush( s );
 
 		raiseServiceCreateNotification(s);
 		return s;
@@ -621,7 +622,7 @@ public class ServiceRepoService {
 		}
 
 		
-		service = this.serviceRepo.save( service );
+		service = this.serviceRepo.saveAndFlush( service );
 		
 
 		
@@ -867,14 +868,14 @@ public class ServiceRepoService {
 	}
 
 
+    @Transactional
 	public Service getServiceEager(String id) {
 		if ( id == null || id.equals("")) {
 			return null;
 		}
-		Session session = sessionFactory.openSession();
-		Transaction tx = session.beginTransaction();
 		Service s = null;
-		try {
+		try (Session session = sessionFactory.openSession()) {
+	        Transaction tx = session.beginTransaction();
 			s = (Service) session.get(Service.class, id);
 			if (s == null) {
 				return this.findByUuid(id);// last resort
@@ -891,15 +892,16 @@ public class ServiceRepoService {
 			Hibernate.initialize(s.getPlace()  );
 			
 			tx.commit();
-		} finally {
-			session.close();
-		}
+		} catch (Exception e) {
+	        e.printStackTrace();
+	      }
+
 		
 		return s;
 	}
 	
 
-	@Transactional
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
 	private void raiseServiceCreateNotification(Service so) {
 		ServiceCreateNotification n = new ServiceCreateNotification();
 		ServiceCreateEvent event = new ServiceCreateEvent();
@@ -909,7 +911,7 @@ public class ServiceRepoService {
 		
 	}
 
-	@Transactional
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
 	private void raiseServiceStateChangedNotification(Service so) {
 		ServiceStateChangeNotification n = new ServiceStateChangeNotification();
 		ServiceStateChangeEvent event = new ServiceStateChangeEvent();
@@ -919,7 +921,7 @@ public class ServiceRepoService {
 		
 	}
 
-	@Transactional
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
 	private void raiseServiceAttributeValueChangedNotification(Service so) {
 		ServiceAttributeValueChangeNotification n = new ServiceAttributeValueChangeNotification();
 		ServiceAttributeValueChangeEvent event = new ServiceAttributeValueChangeEvent();
diff --git a/src/main/java/org/etsi/osl/tmf/so641/repo/ServiceOrderRepository.java b/src/main/java/org/etsi/osl/tmf/so641/repo/ServiceOrderRepository.java
index 3279fad..c717e06 100644
--- a/src/main/java/org/etsi/osl/tmf/so641/repo/ServiceOrderRepository.java
+++ b/src/main/java/org/etsi/osl/tmf/so641/repo/ServiceOrderRepository.java
@@ -24,14 +24,13 @@ import java.util.Optional;
 import org.etsi.osl.tmf.common.model.UserPartRoleType;
 import org.etsi.osl.tmf.so641.model.ServiceOrder;
 import org.etsi.osl.tmf.so641.model.ServiceOrderStateType;
+import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.CrudRepository;
-import org.springframework.data.repository.PagingAndSortingRepository;
 import org.springframework.stereotype.Repository;
 
 
 @Repository
-public interface ServiceOrderRepository extends CrudRepository<ServiceOrder, Long>, PagingAndSortingRepository<ServiceOrder, Long> {
+public interface ServiceOrderRepository extends JpaRepository<ServiceOrder, Long> {
 
 
 	Optional<ServiceOrder> findByUuid(String id);
diff --git a/src/main/java/org/etsi/osl/tmf/so641/reposervices/ServiceOrderRepoService.java b/src/main/java/org/etsi/osl/tmf/so641/reposervices/ServiceOrderRepoService.java
index 64f6604..4c44519 100644
--- a/src/main/java/org/etsi/osl/tmf/so641/reposervices/ServiceOrderRepoService.java
+++ b/src/main/java/org/etsi/osl/tmf/so641/reposervices/ServiceOrderRepoService.java
@@ -59,6 +59,7 @@ import org.hibernate.query.Query;
 import org.hibernate.transform.ResultTransformer;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import jakarta.persistence.EntityManagerFactory;
 import jakarta.persistence.TemporalType;
@@ -365,7 +366,7 @@ public class ServiceOrderRepoService {
 		noteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC) );
 		so.addNoteItem(noteItem);
 
-		so = this.serviceOrderRepo.save(so);
+		so = this.serviceOrderRepo.saveAndFlush(so);
 		
 		if (allAcknowledged) { //in the case were order items are automatically acknowledged
 			so.setState( ServiceOrderStateType.ACKNOWLEDGED );
@@ -376,7 +377,7 @@ public class ServiceOrderRepoService {
 			noteItem.setDate(OffsetDateTime.now(ZoneOffset.UTC) );
 			so.addNoteItem(noteItem);
 			
-			so = this.serviceOrderRepo.save(so);
+			so = this.serviceOrderRepo.saveAndFlush(so);
 		}
 		
 		raiseSOCreateNotification(so);
@@ -658,13 +659,14 @@ public class ServiceOrderRepoService {
 
 		
 
-		so = this.serviceOrderRepo.save(so);
+		so = this.serviceOrderRepo.saveAndFlush(so);
 		if (stateChanged) {
 			raiseSOStateChangedNotification(so);			
 		} else {
 			raiseSOAttributeValueChangedNotification(so);
 		}
 		
+
 		return so;
 	}
 
@@ -737,12 +739,11 @@ public class ServiceOrderRepoService {
 		return res;
 	}
 
+	@Transactional
 	public ServiceOrder getServiceORderEager(String id) {
 
-		Session session = sessionFactory.openSession();
-		Transaction tx = session.beginTransaction();
-		
-		try {
+		try( Session session = sessionFactory.openSession() ) {
+	        Transaction tx = session.beginTransaction();
 			ServiceOrder s = null;
 			try {
 				s = (ServiceOrder) session.get(ServiceOrder.class, id);
@@ -770,13 +771,12 @@ public class ServiceOrderRepoService {
 			// TODO: handle exception
 		}
 
-		session.close();
 		return null;
 		
 		
 	}
 
-	@Transactional
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
 	private void raiseSOCreateNotification(ServiceOrder so) {
 		ServiceOrderCreateNotification n = new ServiceOrderCreateNotification();
 		ServiceOrderCreateEvent event = new ServiceOrderCreateEvent();
@@ -786,7 +786,7 @@ public class ServiceOrderRepoService {
 		
 	}
 
-	@Transactional
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
 	private void raiseSOStateChangedNotification(ServiceOrder so) {
 		ServiceOrderStateChangeNotification n = new ServiceOrderStateChangeNotification();
 		ServiceOrderStateChangeEvent event = new ServiceOrderStateChangeEvent();
@@ -797,7 +797,7 @@ public class ServiceOrderRepoService {
 		
 	}
 
-	@Transactional
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
 	private void raiseSOAttributeValueChangedNotification(ServiceOrder so) {
 		ServiceOrderAttributeValueChangeNotification n = new ServiceOrderAttributeValueChangeNotification();
 		ServiceOrderAttributeValueChangeEvent event = new ServiceOrderAttributeValueChangeEvent();
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 894408a..3722fa8 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -53,7 +53,7 @@ spring:
        idleTimeout: 20000
        idle-timeout: 20000
        connectionTimeout: 40000
-       leakDetectionThreshold: 30000
+       leakDetectionThreshold: 40000
        
        
   jpa:
diff --git a/src/test/java/org/etsi/osl/services/api/ResourceInventoryIntegrationTest.java b/src/test/java/org/etsi/osl/services/api/ResourceInventoryIntegrationTest.java
index fd6989e..9e8f625 100644
--- a/src/test/java/org/etsi/osl/services/api/ResourceInventoryIntegrationTest.java
+++ b/src/test/java/org/etsi/osl/services/api/ResourceInventoryIntegrationTest.java
@@ -330,33 +330,207 @@ public class ResourceInventoryIntegrationTest {
 		assertThat( responseRes2.getResourceRelationship().size()  ).isEqualTo( 0 );
 		
 
-		resUpd.addResourceRelationshipItem( rri  );
 		
-		responseResUpd = mvc.perform(MockMvcRequestBuilders
-				.patch("/resourceInventoryManagement/v4/resource/" + responseRsc.getId() )
-	            .with( SecurityMockMvcRequestPostProcessors.csrf())
-				.contentType(MediaType.APPLICATION_JSON)
-				.content( JsonUtils.toJson( resUpd ) ))
-			    .andExpect(status().isOk())
-			    .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
-	    	    .andExpect(status().isOk())
-	    	    .andReturn().getResponse().getContentAsString();
-		logger.info("testServiceOrderUpdate = " + responseResUpd);
-		responseRes2 = JsonUtils.toJsonObj(responseResUpd,  LogicalResource.class);
-		
-
-		assertThat( resourceRepoService.findAll().size() ).isEqualTo( 2 );
-
-		assertThat( responseRes2.getEndOperatingDate() ).isNotNull();
-		assertThat( responseRes2.getNote().size()  ).isEqualTo( 5 );
-		assertThat( responseRes2.getResourceCharacteristic().size()  ).isEqualTo( 2 );
-		assertThat( responseRes2.getResourceCharacteristicByName( "ConfigStatus" ).getValue().getValue()  ).isEqualTo( "RUNNING" )  ;
-		assertThat( responseRes2.getResourceCharacteristicByName( "DeploymentRequestID" ).getValue().getValue()  ).isEqualTo( "007a008" )  ;
-		assertThat( responseRes2.getResourceSpecification().getId()  ).isNotNull();
-		assertThat( responseRes2.getResourceSpecification().getName()  ).isNotNull();
-		assertThat( responseRes2.getResourceRelationship().size()  ).isEqualTo( 1 );
 		
 	}
+	
+	
+	@WithMockUser(username="osadmin", roles = {"USER","ADMIN"})
+    @Test
+    public void testResourceCreateAndUpdate2() throws UnsupportedEncodingException, IOException, Exception {
+    
+        /**
+         * first add 2 specs
+         */
+
+        File sspec = new File( "src/test/resources/testResourceSpec.json" );
+        InputStream in = new FileInputStream( sspec );
+        String sspectext = IOUtils.toString(in, "UTF-8");
+
+        
+        ResourceSpecificationCreate sspeccr1 = JsonUtils.toJsonObj( sspectext,  ResourceSpecificationCreate.class);
+        sspeccr1.setName("Spec1");
+        ResourceSpecification responsesSpec1 = createResourceSpec( sspeccr1);
+
+        //res 2 is an RFS
+        ResourceSpecificationCreate sspeccr2 = JsonUtils.toJsonObj( sspectext,  ResourceSpecificationCreate.class);
+        sspeccr2.setName("Spec2");
+
+        sspeccr2.addResourceSpecificationRelationshipWith( responsesSpec1 );        
+        LogicalResourceSpecification responsesSpec2 = (LogicalResourceSpecification) createResourceSpec( sspeccr2 );
+        /**
+         * add them as bundle
+         */
+
+        ResourceSpecificationCreate sspeccr3 = JsonUtils.toJsonObj( sspectext,  ResourceSpecificationCreate.class);
+        sspeccr3.setName("BundleExampleSpec");
+        sspeccr3.isBundle(true);
+        sspeccr3.addResourceSpecificationRelationshipWith( responsesSpec1 );
+        sspeccr3.addResourceSpecificationRelationshipWith( responsesSpec2 );        
+        ResourceSpecification responsesSpec3 = createResourceSpec( sspeccr3);
+        
+        ResourceCreate aResource = new ResourceCreate();
+        aResource.setName("aNew Resource parent");
+        aResource.setCategory("Experimentation");
+        aResource.setDescription("Experimentation Descr");
+        aResource.setStartOperatingDate( OffsetDateTime.now(ZoneOffset.UTC ).toString() );
+        aResource.setEndOperatingDate( OffsetDateTime.now(ZoneOffset.UTC ).toString() );
+        
+        
+        
+        Note noteItem = new Note();
+        noteItem.text("test note");
+        aResource.addNoteItem(noteItem);
+        
+        Characteristic resCharacteristicItem = new Characteristic();
+        
+        resCharacteristicItem.setName( "ConfigStatus" );
+        resCharacteristicItem.setValue( new Any("NONE"));
+        aResource.addResourceCharacteristicItem(resCharacteristicItem);
+        
+        ResourceSpecificationRef aServiceSpecificationRef = new ResourceSpecificationRef();
+        aServiceSpecificationRef.setId(responsesSpec3.getId() );
+        aServiceSpecificationRef.setName(responsesSpec3.getName());
+        
+        aResource.setResourceSpecification( aServiceSpecificationRef );
+        //create a first resoruce that will be added to the next one as ref
+        String responseResource = mvc.perform(MockMvcRequestBuilders.post("/resourceInventoryManagement/v4/resource")
+                .with( SecurityMockMvcRequestPostProcessors.csrf())
+                .contentType(MediaType.APPLICATION_JSON)
+                .content( JsonUtils.toJson( aResource ) ))
+                .andExpect(status().isOk())
+                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk())
+                .andReturn().getResponse().getContentAsString();
+        logger.info("responseResource = " + responseResource);
+        Resource responseRsc = JsonUtils.toJsonObj( responseResource,  LogicalResource.class);
+        
+
+        aResource.setName("aNew Resource");
+        
+        ResourceRelationship rri = new ResourceRelationship();
+        rri.setRelationshipType("PARENT");
+        ResourceRef rrref = new ResourceRef();
+        rrref.setName( responseRsc.getName() );
+        rrref.setId( responseRsc.getId() );
+        rri.setResource( rrref );
+        aResource.addResourceRelationshipItem( rri  );
+
+        logger.info("aService JSON = " + JsonUtils.toJsonString( aResource ));
+        
+        responseResource = mvc.perform(MockMvcRequestBuilders.post("/resourceInventoryManagement/v4/resource")
+                .with( SecurityMockMvcRequestPostProcessors.csrf())
+                .contentType(MediaType.APPLICATION_JSON)
+                .content( JsonUtils.toJson( aResource ) ))
+                .andExpect(status().isOk())
+                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk())
+                .andReturn().getResponse().getContentAsString();
+        logger.info("responseResource = " + responseResource);
+         responseRsc = JsonUtils.toJsonObj( responseResource,  LogicalResource.class);
+        
+        
+        logger.info("testService = " + JsonUtils.toJsonString( responseRsc ));
+        
+
+        assertThat( responseRsc.getCategory()  ).isEqualTo( "Experimentation" );
+        assertThat( responseRsc.getDescription()  ).isEqualTo( "Experimentation Descr" );
+        assertThat( responseRsc.getStartOperatingDate() ).isNotNull();
+        assertThat( responseRsc.getEndOperatingDate() ).isNotNull();
+        assertThat( responseRsc.getResourceCharacteristic().size()  ).isEqualTo( 1 );
+        assertThat( responseRsc.getResourceCharacteristicByName( "ConfigStatus" ) ).isNotNull();
+        assertThat( responseRsc.getResourceCharacteristicByName( "ConfigStatus" ).getValue().getValue()  ).isEqualTo( "NONE" )  ;
+        assertThat( responseRsc.getResourceSpecification().getId()  ).isNotNull();
+        assertThat( responseRsc.getResourceSpecification().getName()  ).isNotNull();
+        assertThat( responseRsc.getResourceRelationship().size()  ).isEqualTo( 1 );
+        
+
+        assertThat( responseRsc.getNote().size()  ).isEqualTo( 2 );
+        
+        boolean userPartyRoleexists = false;
+        for (RelatedParty r : responseRsc.getRelatedParty()) {
+            if ( r.getName().equals( "osadmin" ) && r.getRole().equals( UserPartRoleType.REQUESTER.toString() )) {
+                userPartyRoleexists = true;
+            }
+        }
+        
+        assertThat(userPartyRoleexists  ).isTrue() ;
+
+        assertThat( resourceRepoService.findAll().size() ).isEqualTo( 2 );
+        
+        
+        ResourceUpdate resUpd = new ResourceUpdate();
+        resUpd.setEndOperatingDate( OffsetDateTime.now(ZoneOffset.UTC ).toString()  );
+        responseRsc.getNote().stream().forEach(n -> resUpd.addNoteItem(n));
+        Note en = new Note();
+        en.text("test note2");
+        en.setDate( OffsetDateTime.now(ZoneOffset.UTC).toString() );
+        resUpd.addNoteItem(en);     
+
+        for (Characteristic c : responseRsc.getResourceCharacteristic()) {
+            if (c.getName().equals( "ConfigStatus" )) {
+                c.setValue( new Any("RUNNING"));
+            }
+            resUpd.addResourceCharacteristicItem(c);
+        }
+        resUpd.setOperationalState( ResourceOperationalStateType.ENABLE );
+        resCharacteristicItem = new Characteristic();       
+        resCharacteristicItem.setName( "DeploymentRequestID" );
+        resCharacteristicItem.setValue( new Any("007a008"));
+        resUpd.addResourceCharacteristicItem(resCharacteristicItem);
+        resUpd.setResourceRelationship( new ArrayList<>());
+        
+        
+       
+        
+
+        String responseResUpd = mvc.perform(MockMvcRequestBuilders
+                .get("/resourceInventoryManagement/v4/resource/" + responseRsc.getId() )
+                .with( SecurityMockMvcRequestPostProcessors.csrf())
+                .contentType(MediaType.APPLICATION_JSON)
+                .content( JsonUtils.toJson( resUpd ) ))
+                .andExpect(status().isOk())
+                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk())
+                .andReturn().getResponse().getContentAsString();
+        logger.info("testServiceOrderUpdate = " + responseResUpd);
+        LogicalResource responseRes2 = JsonUtils.toJsonObj(responseResUpd,  LogicalResource.class);
+        
+
+        assertThat( resourceRepoService.findAll().size() ).isEqualTo( 2 );
+
+        assertThat( responseRes2.getEndOperatingDate() ).isNotNull();
+        assertThat( responseRes2.getNote().size()  ).isEqualTo( 2 );
+        assertThat( responseRes2.getResourceCharacteristic().size()  ).isEqualTo( 1 );
+        
+
+        resUpd.addResourceRelationshipItem( rri  );
+        
+        responseResUpd = mvc.perform(MockMvcRequestBuilders
+                .patch("/resourceInventoryManagement/v4/resource/" + responseRsc.getId() )
+                .with( SecurityMockMvcRequestPostProcessors.csrf())
+                .contentType(MediaType.APPLICATION_JSON)
+                .content( JsonUtils.toJson( resUpd ) ))
+                .andExpect(status().isOk())
+                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk())
+                .andReturn().getResponse().getContentAsString();
+        logger.info("testServiceOrderUpdate = " + responseResUpd);
+        responseRes2 = JsonUtils.toJsonObj(responseResUpd,  LogicalResource.class);
+        
+
+        assertThat( resourceRepoService.findAll().size() ).isEqualTo( 2 );
+
+        assertThat( responseRes2.getEndOperatingDate() ).isNotNull();
+        assertThat( responseRes2.getNote().size()  ).isEqualTo( 4 );
+        assertThat( responseRes2.getResourceCharacteristic().size()  ).isEqualTo( 2 );
+        assertThat( responseRes2.getResourceCharacteristicByName( "ConfigStatus" ).getValue().getValue()  ).isEqualTo( "RUNNING" )  ;
+        assertThat( responseRes2.getResourceCharacteristicByName( "DeploymentRequestID" ).getValue().getValue()  ).isEqualTo( "007a008" )  ;
+        assertThat( responseRes2.getResourceSpecification().getId()  ).isNotNull();
+        assertThat( responseRes2.getResourceSpecification().getName()  ).isNotNull();
+        assertThat( responseRes2.getResourceRelationship().size()  ).isEqualTo( 1 );
+        
+    }
 		
 	
 	private ResourceSpecification createResourceSpec(ResourceSpecificationUpdate sspeccr1) throws Exception{
diff --git a/src/test/java/org/etsi/osl/services/api/sim638/ServiceRepoServiceTest.java b/src/test/java/org/etsi/osl/services/api/sim638/ServiceRepoServiceTest.java
index 9150fb1..d433726 100644
--- a/src/test/java/org/etsi/osl/services/api/sim638/ServiceRepoServiceTest.java
+++ b/src/test/java/org/etsi/osl/services/api/sim638/ServiceRepoServiceTest.java
@@ -52,6 +52,11 @@ import java.util.Set;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.CoreMatchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
@@ -103,6 +108,26 @@ public class ServiceRepoServiceTest {
         }
         assertThat( idExists ).isTrue();
     }
+    
+
+    @Test
+    public void testAddService() {
+      // When
+      ServiceCreate s = new ServiceCreate();
+      s.setDescription("A Service for ");
+      s.setServiceDate(OffsetDateTime.now(ZoneOffset.UTC).toString());
+      s.hasStarted(false);
+      s.setIsServiceEnabled(false);
+      s.setName("Servicename");
+      s.setStartMode("0");
+
+      Service result = serviceRepoService.addService(s);
+
+      // Then
+      assertNotNull(result);
+      assertEquals("Servicename", result.getName());
+      
+    }
 
     // AlarmManagementIntegrationTest.testAlarmCreateAndUpdateRoutes:224 » CamelExecution Exception occurred during execution on the exchange: Exchange[0054D8F070E6449-0000000000000001]
     // PartyManagementIntegrationTest.addOrganization:246 » JDBCConnection Unable to acquire JDBC Connection [HikariPool-1 - Connection is not available, request timed out after 30000ms.]
diff --git a/src/test/java/org/etsi/osl/services/reposervices/ri639/ResourceRepoServiceTest.java b/src/test/java/org/etsi/osl/services/reposervices/ri639/ResourceRepoServiceTest.java
index 8100820..84fe0e8 100644
--- a/src/test/java/org/etsi/osl/services/reposervices/ri639/ResourceRepoServiceTest.java
+++ b/src/test/java/org/etsi/osl/services/reposervices/ri639/ResourceRepoServiceTest.java
@@ -117,6 +117,7 @@ public class ResourceRepoServiceTest {
     public void setupBefore() {
         when(resourceRepo.findByUuid(anyString())).thenReturn(Optional.of(resource));
         when(resourceRepo.save(any(Resource.class))).thenReturn(resource);
+        when(resourceRepo.saveAndFlush(any(Resource.class))).thenReturn(resource);
         doReturn(resource).when(resourceRepoService).getResourceEager(anyString());
     }
 
@@ -174,7 +175,7 @@ public class ResourceRepoServiceTest {
         // Then
         assertNotNull(result);
         assertEquals("test_resource", result.getName());
-        verify(resourceRepo, times(1)).save(any(Resource.class));
+        verify(resourceRepo, times(1)).saveAndFlush(any(Resource.class));
     }
 
     /**
@@ -210,7 +211,7 @@ public class ResourceRepoServiceTest {
         assertEquals(ResourceStatusType.AVAILABLE, updatedResource.getResourceStatus());
         assertEquals("2.0", updatedResource.getResourceVersion());
         
-        verify(resourceRepo, times(1)).save(any(Resource.class));
+        verify(resourceRepo, times(1)).saveAndFlush(any(Resource.class));
     }
 
     /**
-- 
GitLab