@Async
    @Transactional
    public SamlMetadataProcessResult startCollectMetadata(Connection con, Map<String, String> map) {
        SamlMetadataProcessResult result = new SamlMetadataProcessResult(con.getId());
        EntitiesDescriptor descriptor;

        try {
            String metadataXML = getMetadataFromConnection(con);
            descriptor = convertMetadataXMLtoEntitiesDescriptor(metadataXML);
            String hash = getSignatureValue(descriptor.getSignature());

            Optional<SamlMetadataProcessResult> process = samlMetadataProcessResultRepository.findByConnectionIdAndHash(con.getId(), hash);

            if (process.isPresent()) return result;

            updateMetadata(descriptor, con, map, result);
            result.setMetadata(metadataXML);

            if (result.allEntriesSuccessful()) {
                result.setHash(hash);
            }
        } catch (InitializationException | ComponentInitializationException | UnmarshallingException | IOException | MetadataParseException e) {
            map.put("status", "failed");
            LOGGER.error("Failed to collect/parse metadata: {}", e.getMessage());
            result.addProcessError(e.getMessage(), "");
        }

        samlMetadataProcessResultRepository.saveAndFlush(result);

        return result;
    }
@Test
    public void startCollectMetadataValidTest() throws IOException {
        // Connection, service and certificate expected values from metadata/valid-valid-metadata.xml
        Connection connection = newConnection();
        Service service = newService();
        List<Certificate> certificates = getServiceCertificates();

        when(httpClientMock.execute(any(HttpGet.class))).thenReturn(httpResponseMock);
        when(httpResponseMock.getEntity()).thenReturn(httpEntityMock);
        when(httpEntityMock.getContent()).thenReturn(getClass().getClassLoader().getResourceAsStream("metadata/valid-metadata.xml"));
        when(serviceServiceMock.findAllowedServiceById(anyLong(), anyString())).thenReturn(service);

        // Map can be null if no errors occur
        SamlMetadataProcessResult result = metadataProcessorServiceMock.startCollectMetadata(connection, null);

        // Result
        assertEquals(3, result.getTotalUpdated());
        assertEquals(0, result.getTotalErrors());
        assertEquals(3, result.getTotalProcessed());
        assertEquals(0, result.getSamlMetadataProcessErrors().size());
        assertEquals(3, service.getCertificates().size());

        // Connection
        assertNotNull(result.getMetadata());
        assertEquals(CertificateType.SIGNING, connection.getCertificates().get(0).getCertType());

        // Service
        for (int i = 0; i<certificates.size(); i++) {
            assertEquals(certificates.get(i).getCachedCertificate(), service.getCertificates().get(i).getCachedCertificate());
            assertEquals(certificates.get(i).getFingerprint(), service.getCertificates().get(i).getFingerprint());
            assertEquals(certificates.get(i).getDistinguishedName(), service.getCertificates().get(i).getDistinguishedName());
            assertEquals(certificates.get(i).getActiveFrom(), service.getCertificates().get(i).getActiveFrom());
            assertEquals(certificates.get(i).getActiveUntil(), service.getCertificates().get(i).getActiveUntil());
            assertEquals(certificates.get(i).getCertType(), service.getCertificates().get(i).getCertType());
        }
    }