Class ImportEntryProcessor
- java.lang.Object
-
- org.openbravo.service.importprocess.ImportEntryProcessor
-
- Direct Known Subclasses:
VariantChDescUpdateProcessor
@ApplicationScoped public abstract class ImportEntryProcessor extends Object
TheImportEntryProcessor
is responsible for importing/processingImportEntry
instances for a specific TypeOfData. TheImportEntryProcessor
is a singleton/applicationscoped, it implements a generic approach to make to make it possible to do import ofImportEntry
in parallel threads (ImportEntryProcessor.ImportEntryProcessRunnable
) if possible. It is important that a specific ImportEntry is assigned to the right processing thread to prevent for example deadlocks in the database. To make this possible a concept ofgetProcessSelectionKey(ImportEntry)
is used. The process selection key is a unique key derived from theImportEntry
which can be used to create/identify the thread which should process theImportEntry
. If no such thread exists a newImportEntryProcessor.ImportEntryProcessRunnable
is created. The exact type ofImportEntryProcessor.ImportEntryProcessRunnable
is determined by the extending subclass through thecreateImportEntryProcessRunnable()
method. For example if ImportEntry records of the same organization should be processed after each other (so not in parallel) to prevent DB deadlocks, this means that the records of the same organization should be assigned to the same thread object. So that they are indeed processed sequential and not in parallel. ThegetProcessSelectionKey(ImportEntry)
should in this case return theOrganization.getId()
so thatImportEntryProcessor.ImportEntryProcessRunnable
are keyed/registered using the organization. OtherImportEntry
records of the same organization are then processed by the same thread, always sequential, not parallel, preventing DB deadlocks. TheImportEntryManager
passes newImportEntry
records to the theImportEntryProcessor
by calling itshandleImportEntry(ImportEntry)
. TheImportEntryProcessor
then can decide how to handle thisImportEntry
, create a new thread or assign it to an existing thread (which is busy processing previous entries). This is all done in this generic class. An implementing subclass needs to implement thegetProcessSelectionKey(ImportEntry)
method. This method determines which/how the correctImportEntryProcessor.ImportEntryProcessRunnable
is chosen. The default/base implementation of theImportEntryProcessor.ImportEntryProcessRunnable
provides standard features related to caching ofOBContext
, error handling and transaction handling. Note: this implementation uses the executorService in theImportEntryManager
. Threads are started by using theExecutorService.submit(Runnable)
method, seeImportEntryManager.submitRunnable(Runnable)
. Any exceptions inside theRunnable.run()
method are swallowed and won't directly show up in the console. Therefore the default implementation in theImportEntryProcessor.ImportEntryProcessRunnable.run()
has different mechanisms to correctly log/record the error (in theImportEntry.getErrorinfo()
). Note: theImportEntryProcessor
should be aware that the sameImportEntry
can be passed multiple times to it. Also after theImportEntryProcessor
has already processed it. This can happen because of the parallel/multi-threaded approach followed here. So theImportEntryProcessor
and the implementation of theImportEntryProcessor.ImportEntryProcessRunnable
should correctly and robustly handle this case. The defaultImportEntryProcessor.ImportEntryProcessRunnable
implementation has mechanism to prevent double processing in some cases. Note: it is save for an ImportEntryProcessor to occasionally not process anImportEntry
. TheImportEntryManager
will offer theImportEntry
again in its next cycle. But it is quite important that this only happens if the order of the entries being processed is maintained or not relevant.- Author:
- mtaal
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
ImportEntryProcessor.ImportEntryProcessRunnable
The default implementation of the ImportEntryProcessRunnable.
-
Constructor Summary
Constructors Constructor Description ImportEntryProcessor()
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description protected boolean
assignEntryToThread(String key, ImportEntry importEntry)
Assigns an import entry to a processing thread besed on its type and key.protected abstract boolean
canHandleImportEntry(ImportEntry importEntryInformation)
Can be used by implementing subclass to check that the ImportEntry can be processed now.protected abstract ImportEntryProcessor.ImportEntryProcessRunnable
createImportEntryProcessRunnable()
Create a concrete subclass ofImportEntryProcessor.ImportEntryProcessRunnable
protected boolean
enableArchive()
Declares if the import entry will later on be archived after it has been processedprotected abstract String
getProcessSelectionKey(ImportEntry importEntry)
Based on theImportEntry
returns a key which uniquely identifies the thread which should process thisImportEntry
.boolean
handleImportEntry(ImportEntry importEntry)
Is called from theImportEntryManager
thread, passes in a new ImportEntry to process.void
shutdown()
Is called when the application context/tomcat stops, is called fromImportEntryManager.shutdown()
.String
toString()
-
-
-
Method Detail
-
shutdown
public void shutdown()
Is called when the application context/tomcat stops, is called fromImportEntryManager.shutdown()
.
-
handleImportEntry
public boolean handleImportEntry(ImportEntry importEntry)
Is called from theImportEntryManager
thread, passes in a new ImportEntry to process. Finds the Thread which can handle this entry, if none is found a new thread is created, if one is found then the ImportEntry is passed/given to it. If the processing of the entry does not happen fast enough then it can be that theImportEntry
is again offered to theImportEntryProcessor
through a call to this method. The implementation should be able to gracefully handle duplicate entries. Also the implementation should check if theImportEntry
was possibly already handled and ignore it then.- Returns:
- whether the importEntry has been assigned to a thread for it to be processed
-
assignEntryToThread
protected boolean assignEntryToThread(String key, ImportEntry importEntry)
Assigns an import entry to a processing thread besed on its type and key.- Returns:
- whether the import entry could be assigned to a thread
-
createImportEntryProcessRunnable
protected abstract ImportEntryProcessor.ImportEntryProcessRunnable createImportEntryProcessRunnable()
Create a concrete subclass ofImportEntryProcessor.ImportEntryProcessRunnable
-
canHandleImportEntry
protected abstract boolean canHandleImportEntry(ImportEntry importEntryInformation)
Can be used by implementing subclass to check that the ImportEntry can be processed now. In some cases other ImportEntries should be processed first. By returning false the ImportEntry is ignored for now. It will again be picked up in a next execution cycle of theImportEntryManager
thread and then offered again to thisImportEntryProcessor
to be processed.
-
getProcessSelectionKey
protected abstract String getProcessSelectionKey(ImportEntry importEntry)
Based on theImportEntry
returns a key which uniquely identifies the thread which should process thisImportEntry
. Can be used to place import entries which block/use the same records in the same import thread, in this way preventing DB (dead)locks.
-
enableArchive
protected boolean enableArchive()
Declares if the import entry will later on be archived after it has been processed
-
-