diff --git a/iparapheur-core/src/main/java/coop/libriciel/service/CreerDossierService.java b/iparapheur-core/src/main/java/coop/libriciel/service/CreerDossierService.java index c0219335ada4ba01ac13631db4a87bd808196610..d5e65945909ea6980b5ef849afc2f74408e0d9ec 100644 --- a/iparapheur-core/src/main/java/coop/libriciel/service/CreerDossierService.java +++ b/iparapheur-core/src/main/java/coop/libriciel/service/CreerDossierService.java @@ -34,13 +34,10 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringEscapeUtils; import org.apache.log4j.Level; import org.dom4j.DocumentException; -import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.json.JSONStringer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.dao.ConcurrencyFailureException; -import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; import org.springframework.stereotype.Service; import javax.transaction.SystemException; @@ -51,7 +48,6 @@ import java.text.Normalizer; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; -import java.util.concurrent.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -104,11 +100,6 @@ public class CreerDossierService { @Autowired private SignatureService signatureService; - //Executeur de tâches, géré par spring - private ConcurrentTaskExecutor taskExecutor; - - private List<String> idsCreatingList = Collections.synchronizedList(new ArrayList<>()); - @Value("${parapheur.ws.creerdossier.autoselectsigformat.ifunsigned.pdf:pades}") private String sigformatifunsignedpdf; @Value("${parapheur.ws.creerdossier.autoselectsigformat.ifunsigned:pkcs7}") @@ -119,33 +110,6 @@ public class CreerDossierService { */ protected void init() { log.setLevel(Level.INFO); - int threadPool = 1; - //Initialisation du taskExecutor avec les paramètres passés en fichier de configuration - if (taskExecutor == null) { - /* Low priority ThreadFactory */ - ThreadFactory threadFactory = new ThreadFactory() { - private static final String PH_JOB_PREFIX = "IP_Create_Doc_Queue"; - private int jobId = 1; - - @Override - public Thread newThread(@NotNull Runnable runnable) { - Thread nt = new Thread(runnable); - nt.setPriority(Thread.MIN_PRIORITY); - nt.setName(PH_JOB_PREFIX + "-" + jobId); - jobId++; - nt.setDaemon(true); - return nt; - } - }; - - ThreadPoolExecutor executor = new ThreadPoolExecutor(threadPool, - threadPool, - 0L, - TimeUnit.MILLISECONDS, - new LinkedBlockingQueue<>(), - threadFactory); - taskExecutor = new ConcurrentTaskExecutor(executor); - } } public CreerDossierResponse doCreateFile(CreerDossierRequest request) { @@ -159,27 +123,40 @@ public class CreerDossierService { msg.setMessage("Requete incomplete."); msg.setSeverite("FATAL"); - boolean idAddedToList = false; - - if(request.getDossierID() != null && !request.getDossierID().trim().isEmpty()) { - if(!idsCreatingList.contains(request.getDossierID())) { - idsCreatingList.add(request.getDossierID()); - idAddedToList = true; - } else { - Exception e = new Exception("Le nom de dossier est déjà présent dans le Parapheur: dossierID = " + request.getDossierID().trim()); - - log.error(e.getMessage()); - return this.handleException(e); - } - } - - // Do all verifications in a transaction for reader only - UserTransaction tx = transactionService.getNonPropagatingUserTransaction(true); + // Do all verifications in a transaction + UserTransaction tx = transactionService.getUserTransaction(false); try { tx.begin(); + // Vérification de la requete this.checkAndBuildRequest(request, model); + // Création du dossier + this.createDossier(request, model); + + AuthenticationUtil.setRunAsUser(model.getUsername()); + authenticationComponent.setCurrentUser(model.getUsername()); + + // Définition de la typologie et document principal + this.setTypologyAndContents(request, model); + + // Gestion des documents supplémentaires + if (request.getDocumentsSupplementaires() != null) { + log.debug(model.getLoggerPrefix() + " - Gestion des documents supplémentaires..."); + this.handleDocsSupp(request, model); + } + // Gestion des documents annexes + if (request.getDocumentsAnnexes() != null) { + log.debug(model.getLoggerPrefix() + " - Gestion des annexes..."); + this.handleDocsAnnexes(request, model); + } + // Envoi du dossier dans le circuit + log.debug(model.getLoggerPrefix() + " - Envoi du document dans le circuit de validation..."); + + // Gestion de l'ordre des documents + if(model.getOrdreDocuments()!=null && !model.getOrdreDocuments().isEmpty()) { + dossierService.setOrderDocuments(model.getDossier(), model.getOrdreDocuments()); + } tx.commit(); } catch (Exception e) { @@ -189,144 +166,86 @@ public class CreerDossierService { log.error("Erreur lors du rollback de la vérification de la requête", e1); } log.error(e.getMessage(), e); - if(idAddedToList) { - idsCreatingList.remove(request.getDossierID()); - } return this.handleException(e); } - log.debug(model.getLoggerPrefix() + " - Verification de requête OK"); + // Envoi du dossier dans le workflow + this.sendFileInWorkflow(request, model); - RetryingTransactionHelper rtx = transactionService.getRetryingTransactionHelper(); - rtx.setMaxRetries(10); - boolean finalIdAddedToList = idAddedToList; - rtx.doInTransaction(() -> { - try { - Map<QName, Serializable> properties = this.defineProperties(model); - - log.debug(model.getLoggerPrefix() + " - Creation de dossier..."); - // ------------------------------------- Création dossier - model.setDossier(dossierService.createDossier(model.getParapheur(), properties)); - dossierService.setDossierPropertiesWithAuditTrail(model.getDossier(), model.getParapheur(), properties, true); - model.setId((String) nodeService.getProperty(model.getDossier(), ContentModel.PROP_NAME)); - nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_DOSSIER_ORIGINE_WS, null); - - log.debug(model.getLoggerPrefix() + " - Creation de dossier OK"); - - msg.setCodeRetour("OK"); - msg.setMessage("Dossier " + model.getTitle() + " soumis dans le circuit"); - msg.setSeverite("INFO"); - - res.setMessageRetour(msg); - // Retro-compatibilité - Pour les connecteurs n'utilisant pas les dernières versions du WSDL, comprenant le champ "DossierID" - // Pour information - Ce champ a été ajouté en 2013 - if(!finalIdAddedToList) { - res.setDossierID(model.getId()); - } - }catch (Throwable are) { - are.printStackTrace(); - throw new ConcurrencyFailureException(are.getMessage()); - } - return null; - }); + msg.setCodeRetour("OK"); + msg.setMessage("Dossier " + model.getTitle() + " soumis dans le circuit"); + msg.setSeverite("INFO"); - if(idAddedToList) { - idsCreatingList.remove(request.getDossierID()); - } + res.setMessageRetour(msg); + res.setDossierID(model.getId()); - if(model.getDossier() != null && nodeService.exists(model.getDossier())) { - log.info(model.getLoggerPrefix() + " - Lancement du async..."); - taskExecutor.execute(() -> { - AuthenticationUtil.setRunAsUser(model.getUsername()); - authenticationComponent.setCurrentUser(model.getUsername()); + return res; + } - RetryingTransactionHelper rtxx = transactionService.getRetryingTransactionHelper(); - rtxx.setMaxRetries(10); - rtxx.doInTransaction(() -> { - try { - log.debug(model.getLoggerPrefix() + " - Préparation du circuit..."); - // This define the final workflow to the folder - typesService.getWorkflow(model.getDossier(), model.getType(), model.getSousType(), model.getScriptCustomProperties()); + private void setTypologyAndContents(CreerDossierRequest request, CreerDossieModel model) throws IOException { + log.debug(model.getLoggerPrefix() + " - Préparation du circuit..."); + // This defines the final workflow to the folder + typesService.getWorkflow(model.getDossier(), model.getType(), model.getSousType(), model.getScriptCustomProperties()); - log.debug(model.getLoggerPrefix() + " - Préparation multidoc..."); - this.prepareMultidoc(request, model); + log.debug(model.getLoggerPrefix() + " - Préparation multidoc..."); + this.prepareMultidoc(request, model); - log.debug(model.getLoggerPrefix() + " - Définition du circuit..."); - this.setWorkflow(request, model); + log.debug(model.getLoggerPrefix() + " - Définition du circuit..."); + this.setWorkflow(request, model); - log.debug(model.getLoggerPrefix() + " - Gestion des aspects de typologie..."); - if (model.getProtocole() != null && model.getProtocole().equalsIgnoreCase("HELIOS")) { - if (typesService.isTdtAuto(model.getType(), model.getSousType())) { - nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_ETAPE_TDT_AUTO, null); - } - } - if (request.getXPathPourSignatureXML() != null) { - model.getTypageProps().put(ParapheurModel.PROP_XPATH_SIGNATURE, request.getXPathPourSignatureXML()); - } - nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_TYPAGE_METIER, model.getTypageProps()); + log.debug(model.getLoggerPrefix() + " - Gestion des aspects de typologie..."); + if (model.getProtocole() != null && model.getProtocole().equalsIgnoreCase("HELIOS")) { + if (typesService.isTdtAuto(model.getType(), model.getSousType())) { + nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_ETAPE_TDT_AUTO, null); + } + } + if (request.getXPathPourSignatureXML() != null) { + model.getTypageProps().put(ParapheurModel.PROP_XPATH_SIGNATURE, request.getXPathPourSignatureXML()); + } + nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_TYPAGE_METIER, model.getTypageProps()); - log.debug(model.getLoggerPrefix() + " - Métadonnées personalisées..."); - if (!model.getCustomProperties().isEmpty()) { - nodeService.addAspect(model.getDossier(), QName.createQName("cu:customMetadata", namespaceService), model.getCustomProperties()); - } + log.debug(model.getLoggerPrefix() + " - Métadonnées personalisées..."); + if (!model.getCustomProperties().isEmpty()) { + nodeService.addAspect(model.getDossier(), QName.createQName("cu:customMetadata", namespaceService), model.getCustomProperties()); + } - log.debug(model.getLoggerPrefix() + " - Définition des annotations..."); - // ------------------- Annotations (publique + privee) - if (request.getAnnotationPublique() != null) { - parapheurService.setAnnotationPublique(model.getDossier(), request.getAnnotationPublique()); - } - if (request.getAnnotationPrivee() != null) { - parapheurService.setAnnotationPrivee(model.getDossier(), request.getAnnotationPrivee()); - } + log.debug(model.getLoggerPrefix() + " - Définition des annotations..."); + // ------------------- Annotations (publique + privee) + if (request.getAnnotationPublique() != null) { + parapheurService.setAnnotationPublique(model.getDossier(), request.getAnnotationPublique()); + } + if (request.getAnnotationPrivee() != null) { + parapheurService.setAnnotationPrivee(model.getDossier(), request.getAnnotationPrivee()); + } - log.debug(model.getLoggerPrefix() + " - Définition du contenu..."); - this.setContent(request, model); - this.setVisuel(request, model); + log.debug(model.getLoggerPrefix() + " - Définition du contenu..."); + this.setContent(request, model); + this.setVisuel(request, model); - log.debug(model.getLoggerPrefix() + " - Définition de signature détachée..."); - this.setSignatureDetachee(request, model); + log.debug(model.getLoggerPrefix() + " - Définition de signature détachée..."); + this.setSignatureDetachee(request, model); - log.debug(model.getLoggerPrefix() + " - Finalisation de la création..."); - //redéfinition de la propriété, obligatoire sinon non pris en compte - nodeService.setProperty(model.getDossier(), ParapheurModel.PROP_RECUPERABLE, Boolean.TRUE); + log.debug(model.getLoggerPrefix() + " - Finalisation de la création..."); + //redéfinition de la propriété, obligatoire sinon non pris en compte + nodeService.setProperty(model.getDossier(), ParapheurModel.PROP_RECUPERABLE, Boolean.TRUE); - // Cachet serveur automatique ? - if (typesService.isCachetAuto(model.getType(), model.getSousType())) { - nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_ETAPE_CACHET_AUTO, null); - } - } catch (Throwable are) { - //are.printStackTrace(); - throw new ConcurrencyFailureException(are.getMessage()); - } - return null; - }); + // Cachet serveur automatique ? + if (typesService.isCachetAuto(model.getType(), model.getSousType())) { + nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_ETAPE_CACHET_AUTO, null); + } + } - log.debug(model.getLoggerPrefix() + " - Création de dossier terminée"); + private void createDossier(CreerDossierRequest request, CreerDossieModel model) throws ParseException { + Map<QName, Serializable> properties = this.defineProperties(model); - // Passer à la suite uniquement si l'étape de création de dossier s'est bien passée, cà d code retour OK et noeud existant - if (msg.getCodeRetour().equals("OK") && model.getDossier() != null && nodeService.exists(model.getDossier())) { - // Gestion des documents supplémentaires - if (request.getDocumentsSupplementaires() != null) { - log.debug(model.getLoggerPrefix() + " - Gestion des documents supplémentaires..."); - this.handleDocsSupp(request, model); - } - // Gestion des documents annexes - if (request.getDocumentsAnnexes() != null) { - log.debug(model.getLoggerPrefix() + " - Gestion des annexes..."); - this.handleDocsAnnexes(request, model); - } - // Envoi du dossier dans le circuit - log.debug(model.getLoggerPrefix() + " - Envoi du document dans le circuit de validation..."); - - // Gestion de l'ordre des documents - this.handleDocumentOrder(model); - - this.sendFileInWorkflow(request, model); - } - }); - } + log.debug(model.getLoggerPrefix() + " - Creation de dossier..."); + // ------------------------------------- Création dossier + model.setDossier(dossierService.createDossier(model.getParapheur(), properties)); + dossierService.setDossierPropertiesWithAuditTrail(model.getDossier(), model.getParapheur(), properties, true); + model.setId((String) nodeService.getProperty(model.getDossier(), ContentModel.PROP_NAME)); + nodeService.addAspect(model.getDossier(), ParapheurModel.ASPECT_DOSSIER_ORIGINE_WS, null); - return res; + log.debug(model.getLoggerPrefix() + " - Creation de dossier OK"); } private void checkAndBuildRequest(CreerDossierRequest request, CreerDossieModel model) throws Exception { @@ -485,21 +404,7 @@ public class CreerDossierService { leDoc.setNom(Normalizer.normalize(nom, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "")); model.getDocNames().put(nom, nom); - UserTransaction tx = transactionService.getNonPropagatingUserTransaction(false); - - try { - tx.begin(); - this.handleDocAnnexes(leDoc, model); - tx.commit(); - } catch(Throwable e) { - e.printStackTrace(); - try { - tx.rollback(); - } catch(Throwable e1) { - e1.printStackTrace(); - } - } - + this.handleDocAnnexes(leDoc, model); } else { if (log.isEnabledFor(Level.ERROR)) { log.error(model.getLoggerPrefix() + "doc annexe invalide, donc non ajouté au dossier."); @@ -508,25 +413,6 @@ public class CreerDossierService { } } - private void handleDocumentOrder(CreerDossieModel model) { - if(model.getOrdreDocuments()!=null && !model.getOrdreDocuments().isEmpty()) { - log.debug("Gestion de l'ordre des documents"); - UserTransaction tx = transactionService.getNonPropagatingUserTransaction(false); - try { - tx.begin(); - dossierService.setOrderDocuments(model.getDossier(), model.getOrdreDocuments()); - tx.commit(); - } catch(Throwable e) { - log.error("Erreur lors de la gestion des documents", e); - try { - tx.rollback(); - } catch(Throwable e1) { - log.error("erreur lors du rollback dans [handleDocumentOrder]", e1); - } - } - } - } - private void checkDocAnnexes(CreerDossierRequest request) throws DocumentException { if (request.getDocumentsAnnexes() != null) { this.checkListTypeAnnexe(request.getDocumentsAnnexes(), false); @@ -602,22 +488,7 @@ public class CreerDossierService { } model.getDocNames().put(nom, nom); - UserTransaction tx = transactionService.getNonPropagatingUserTransaction(false); - - try { - tx.begin(); - this.handleDocSupp(leDoc, model); - tx.commit(); - } catch(Throwable e) { - e.printStackTrace(); - try { - tx.rollback(); - } catch(Throwable e1) { - e1.printStackTrace(); - } - } - - + this.handleDocSupp(leDoc, model); if (leDoc.getSignature() != null) { // signature, optionnel String leSigType = leDoc.getSignature().getContentType();