kitodo-production icon indicating copy to clipboard operation
kitodo-production copied to clipboard

Creating processes using the Active MQ interface

Open matthias-ronge opened this issue 1 year ago • 9 comments

You can use this function to create processes using the Active MQ interface. Examples:

Without a catalog (all data is passed):

import java.util.*;
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Main {
    public static void main(String[] args) { try {

        // Serververbindung
        Connection connection = new ActiveMQConnectionFactory("tcp://localhost:61616").createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue("KitodoProduction.CreateNewProcesses.Queue");
        MessageProducer producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        // Daten
        String processTitle = "TestAMQ";

        MapMessage message = session.createMapMessage();
        message.setString("id", processTitle); // "Betreff" (für Logging)

        message.setInt("project", 1); // Projekt-ID
        message.setInt("template", 3); // Produktionsvorlagen-ID
        message.setString("title", processTitle); // Vorgangstitel
        // message.setInt("parent", 14); // Elternvorgang

        Map<String, Object> metadata = new HashMap<>();
        metadata.put("docType", "Monograph"); // DocType

        List<String> collections = Arrays.asList("Drucke", "Varia.Drucke"); // Kollektionen
        metadata.put("singleDigCollection", collections);

        Map<String, Object> author = new HashMap<>(); // Metadatengruppe
        author.put("RoleCode", "aut");
        author.put("FirstName", "Max");
        author.put("LastName", "Mustermann");
        metadata.put("Person", author);

        message.setObject("metadata", metadata);

        // Daten senden
        producer.send(message);

        // Ende
        session.close();
        connection.close();

    } catch (Exception e) { e.printStackTrace(); }}
}

Or, use a catalog import:

import java.util.*;
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Main {
    public static void main(String[] args) { try {

        // Serververbindung
        Connection connection = new ActiveMQConnectionFactory("tcp://localhost:61616").createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue("KitodoProduction.CreateNewProcesses.Queue");
        MessageProducer producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        // Daten
        String katKey = "1752355024";

        MapMessage message = session.createMapMessage();
        message.setString("id", katKey); // "Betreff" (für Logging)

        message.setInt("project", 1); // Projekt-ID
        message.setInt("template", 3); // Produktionsvorlagen-ID

        // Import-Einstellungen
        Map<String, Object> import1 = new HashMap<>();
        import1.put("importconfiguration", 1);
        import1.put("value", katKey);

        message.setObject("import", Arrays.asList(import1));

        // Daten senden
        producer.send(message);

        // Ende
        session.close();
        connection.close();

    } catch (Exception e) { e.printStackTrace(); }}
}

matthias-ronge avatar Aug 13 '24 13:08 matthias-ronge

Metadata groups are supported. See also in the “send class” above:

Map<String, Object> author = new HashMap<>();
author.put("RoleCode", "aut");
author.put("FirstName", "Max");
author.put("LastName", "Mustermann");
metadata.put("Person", author);

matthias-ronge avatar Aug 13 '24 15:08 matthias-ronge

We have already tested this branch several times and it works well for us so far.

@solth what would be needed for this to be merged?

aetherfaerber avatar Sep 23 '24 12:09 aetherfaerber

@solth what would be needed for this to be merged?

For starters, there are conflicts that need to be resolved before this pull request can be merged. Additionally, it is a draft, so it seems @matthias-ronge is still working on it and hasn't deemed it ready for review, yet, himself.

solth avatar Sep 23 '24 14:09 solth

I must limit my previous statement to some extent.

We had tested creating processes by importing metadata froam a catalog. It works fine. We have now tested creating a process and passing its metadata vie ActiveMQ and have not been able to get it to work. We used the code given above but the only metadata field that was not empty aftewards was DocType. Of course we adapted the example to include only metadata fields that we have defined in our ruleset. Could this be caused by our ruleset or does the functionality not work properly?

Also @matthias-ronge could you please comment on the previous statement? Is this a draft or a real PR? Can you add documentation and resolve the merge conflicts?

aetherfaerber avatar Sep 27 '24 13:09 aetherfaerber

I had initially set the pull request as a draft to see if it would be sufficient to all your testings as well. Then I forgot to change it.

I will resolve the merge conflicts and I will take a closer look to the metadata, to see if this is a bug in the program or in the example code. Expect my reply soon.

matthias-ronge avatar Oct 02 '24 06:10 matthias-ronge

I will resolve the merge conflicts and I will take a closer look to the metadata, to see if this is a bug in the program or in the example code. Expect my reply soon.

Thank you for looking into it. FWIW, here is the sample code we used, adapted to our ruleset:

import java.util.*;
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Main {
    public static void main(String[] args) { try {

        // Serververbindung
        Connection connection = new ActiveMQConnectionFactory("tcp://localhost:61616").createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue("KitodoProduction.CreateNewProcesses.Queue");
        MessageProducer producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

        // Daten
        String processTitle = "TestAMQ9";

        MapMessage message = session.createMapMessage();
        message.setString("id", processTitle); // "Betreff" (für Logging)

        message.setInt("project", 2); // Projekt-ID
        message.setInt("template", 1); // Produktionsvorlagen-ID
        message.setString("title", processTitle); // Vorgangstitel

        Map<String, Object> metadata = new HashMap<>();
        metadata.put("document_type", "ThematicFile");
        metadata.put("delivery", "Lieferung42"); 
        metadata.put("archiveName", "archive42"); 
        metadata.put("ArcinsysID", "iid42");
        metadata.put("stockID", "stock42");
        metadata.put("stockUnitID", "stockunit42");
        metadata.put("unitID", "unit42");

        message.setObject("metadata", metadata);

        // Daten senden
        producer.send(message);

        // Ende
        session.close();
        connection.close();

    } catch (Exception e) { e.printStackTrace(); }}
}

The created process has no metadata besides the doctype.

aetherfaerber avatar Oct 02 '24 07:10 aetherfaerber

I was able to reproduce the error. The code forgot to specify the location of the metadata storage, so when saving, it didn't know where to put it, and discarded it. I have now fixed that; the metadata is currently always stored in dmdSec, others are not yet possible.

matthias-ronge avatar Oct 02 '24 10:10 matthias-ronge

@aetherfaerber would you or a colleague of yours be willing and confident to review this pull request? That includes checking the code as well as testing the functionality (which you already did, if I am not mistaken).

solth avatar Oct 08 '24 14:10 solth

@aetherfaerber would you or a colleague of yours be willing and confident to review this pull request? That includes checking the code as well as testing the functionality (which you already did, if I am not mistaken).

Yes, we already tested the functionality and can also confirm that the fix to the problem I reported earlier works well. Everything works as expected.

While investigating the error we already had a brief look at the code. We can also try to check it but are not sure what this should include. We can offer to go through it and check for unclear variable names, missing comments, possible unrelated changes and the like. An in-depth analysis on code architecture/efficiency/standards is probably out of our league here. What is expected?

Do the CQ-Pipelines in this repository already check for conformance to the guidelines at https://www.kitodo.org/fileadmin/groups/kitodo/Dokumente/Kitodo-EntwicklerLeitfaden_2017-06.pdf ?

aetherfaerber avatar Oct 15 '24 05:10 aetherfaerber

@aetherfaerber thank you very much for your review. And sorry I forgot to reply to your question earlier. Those are the correct, current coding guidelines you mentioned, even though they are quite old and long overdue for reevaluation.

solth avatar Nov 07 '24 08:11 solth

@BartChris does this pull request resolve #4837 for you?

solth avatar Nov 07 '24 09:11 solth

I agree with @BartChris that we should try to avoid code and method duplication as much as possible. Unfortunately, the various ways to import metadata into Kitodo has already resulted in quite some redundant code duplicates. I think we need a focused effort to consolidate all the different parts of the import code, but that should be dealt with in a separate project.

I also agree that it would be very helpful for external applications if the interface returned the ID of created processes to keep track of the Kitodo processes in the application and to have a way to reference the correct processes in subsequent interactions. I would propose, though, to see that as an incremental expansion of this first version of the function that can be implemented later.

However, the absence of tests is a problem. Since we want this function in Kitodo 3.8 I would agree to merge the PR as it's functionality has been tested and is working, but @matthias-ronge should supply tests via a separate pull request at a later stage.

solth avatar Nov 14 '24 09:11 solth

Even this new way must be documented in the developers part of the wiki which is not done yet. The latest changes of the ActiveMQ part in the wiki are missing which must be avoided as no one could use it.

henning-gerhardt avatar Nov 14 '24 14:11 henning-gerhardt