Java Automation Client used from multiple threads

Hi,

I have made a tool to bulk import files in Nuxeo through Automation.

If I allow more than one Thread to be executed, I ocasionally get this error:

java.lang.RuntimeException: Cannot execute {Authorization=Basic QWRtaW5pc3RyYXRvcjpBZG1pbmlzdHJhdG9y, Accept=application/json+nxentity, */*, Content-Type=application/json+nxrequest}
    at org.nuxeo.ecm.automation.client.jaxrs.impl.HttpConnector.execute(HttpConnector.java:88)
    at org.nuxeo.ecm.automation.client.jaxrs.spi.ConnectorHandler.execute(ConnectorHandler.java:30)
    at org.nuxeo.ecm.automation.client.jaxrs.spi.DefaultSession.execute(DefaultSession.java:94)
    at org.nuxeo.ecm.automation.client.jaxrs.spi.DefaultOperationRequest.execute(DefaultOperationRequest.java:155)
    at Transfer$1.run(Transfer.java:81)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Caused by: java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
    at org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:218)
    at org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(SingleClientConnManager.java:192)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:391)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
    at org.nuxeo.ecm.automation.client.jaxrs.impl.HttpConnector.execute(HttpConnector.java:97)
    at org.nuxeo.ecm.automation.client.jaxrs.impl.HttpConnector.execute(HttpConnector.java:84)
    ... 7 more

The code is like this:

    private static Map<String, String> writtenFiles;
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd # HH:mm:ss");
private static Session session;

public static void main(String[] args) throws Exception {
    if (args.length >= 0)
        prop.load(new FileInputStream(args[0]));
    HttpAutomationClient client = new HttpAutomationClient(String.format("http://%s/nuxeo/site/automation", serverName()));
    session = client.getSession("Administrator", "Administrator");
    writtenFiles.put(fileSystemPath(), ((Document) session.newRequest(DocumentService.FetchDocument).set("value", documentPath()).execute()).getId());
    createSynchronizationTask(new File(fileSystemPath()));
}

private static void createSynchronizationTask(final File file) {
    threadPoolExecutor.execute(new Runnable() {
        @Override
        public void run() {
            try {
                log(String.format("%s |||  Processing %s", simpleDateFormat.format(new Date()), file.getPath()));
                String fileName = file.getName();
                IdRef parentDocument = new IdRef(writtenFiles.get(file.getParent()));

                PropertyMap props = new PropertyMap();
                if (file.isDirectory()) {
                    if (writtenFiles.get(file.getPath()) == null) {
                        props.set("dc:title", fileName);
                        Document createdFolder = (Document) session.newRequest(DocumentService.CreateDocument).setInput(parentDocument)
                                .set("type", folderType()).set("name", fileName)
                                .set("properties", props).execute();
                        logExecution(file, createdFolder);
                    }
                    for (File child : filesFirst(file)) {
                        createSynchronizationTask(child);
                    }
                } else {
                    if (writtenFiles.get(file.getPath()) == null) {
                        props.set("dc:title", fileName);
                        props.set("file:filename", file.getName());
                        Document document = (Document) session.newRequest(DocumentService.CreateDocument)
                                .setInput(parentDocument).set("type", documentType()).set("name", fileName).set("properties", props).execute();

                        FileBlob fb = new FileBlob(file);
                        try {
                            session.newRequest("Blob.Attach").setHeader(Constants.HEADER_NX_VOIDOP, "true").setInput(fb).set("document", document).execute();
                            logExecution(file, document);
                        } catch (Exception e) {
                            log(e);
                        }
                    }
                }
            } catch (Exception e) {
                log(e);
                logFileError(file, e.getMessage());
            }
        }
    });
}

Any guidance on how I should use the Java Automation Client from multiple threads? Thank you.

0 votes

0 answers

2758 views

ANSWER