Skip to content

Commit

Permalink
#137 introduced ProcessInstance.version; enforce it on checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
teosarca committed Feb 16, 2017
1 parent 58a25fb commit f31d0f0
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.metas.ui.web.exceptions;

import org.adempiere.exceptions.AdempiereException;

/*
* #%L
* metasfresh-webui-api
* %%
* Copyright (C) 2017 metas GmbH
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/

@SuppressWarnings("serial")
public class InvalidDocumentVersionException extends AdempiereException
{
public InvalidDocumentVersionException(final int expectedVersion, final int actualVersion)
{
super("Invalid version, expected " + expectedVersion + " but it was " + actualVersion);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ public final class ProcessInstance
@Lazy
private IDocumentViewsRepository documentViewsRepo;

private final ProcessDescriptor processDescriptor;
private final DocumentId adPInstanceId;
private int version = 1;

private final ProcessDescriptor processDescriptor;
private final Document parameters;

private boolean executed = false;
Expand Down Expand Up @@ -114,8 +116,10 @@ private ProcessInstance(final ProcessInstance from, final CopyMode copyMode)
// Adempiere.autowire(this);
documentViewsRepo = from.documentViewsRepo;

processDescriptor = from.processDescriptor;
adPInstanceId = from.adPInstanceId;
version = from.version;

processDescriptor = from.processDescriptor;
parameters = from.parameters.copy(copyMode);

executed = from.executed;
Expand All @@ -128,6 +132,7 @@ public String toString()
return MoreObjects.toStringHelper(this)
.omitNullValues()
.add("AD_PInstance_ID", adPInstanceId)
.add("version", version)
.add("executed", "executed")
.add("executionResult", executionResult)
.add("processDescriptor", processDescriptor)
Expand All @@ -150,6 +155,16 @@ public DocumentId getAD_PInstance_ID()
return adPInstanceId;
}

/* package */int getVersion()
{
return version;
}

/* package */void setVersion(final int version)
{
this.version = version;
}

public Document getParametersDocument()
{
return parameters;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.metas.ui.web.process;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.adempiere.exceptions.AdempiereException;
import org.adempiere.util.Services;
Expand All @@ -19,6 +20,7 @@
import de.metas.process.IADPInstanceDAO;
import de.metas.process.ProcessDefaultParametersUpdater;
import de.metas.process.ProcessInfo;
import de.metas.ui.web.exceptions.InvalidDocumentVersionException;
import de.metas.ui.web.process.descriptor.ProcessDescriptor;
import de.metas.ui.web.process.descriptor.ProcessDescriptorsFactory;
import de.metas.ui.web.process.descriptor.ProcessParametersRepository;
Expand Down Expand Up @@ -58,6 +60,7 @@ public class ProcessInstancesRepository
private ProcessDescriptorsFactory processDescriptorFactory;

private final LoadingCache<DocumentId, ProcessInstance> processInstances = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.removalListener(new RemovalListener<DocumentId, ProcessInstance>()
{
@Override
Expand All @@ -72,6 +75,7 @@ public void onRemoval(final RemovalNotification<DocumentId, ProcessInstance> not
public void cacheReset()
{
processInstances.invalidateAll();
processInstances.cleanUp();
}

public ProcessDescriptor getProcessDescriptor(final int adProcessId)
Expand All @@ -82,7 +86,34 @@ public ProcessDescriptor getProcessDescriptor(final int adProcessId)
public void checkin(final ProcessInstance processInstance)
{
processInstance.saveIfValidAndHasChanges(false); // throwEx=false
processInstances.put(processInstance.getAD_PInstance_ID(), processInstance.copy(CopyMode.CheckInReadonly));

final int versionCurrentExpected = processInstance.getVersion();
final int version = versionCurrentExpected + 1;
final ProcessInstance processInstanceCopy = processInstance.copy(CopyMode.CheckInReadonly);
processInstanceCopy.setVersion(version);
final DocumentId adPInstanceId = processInstance.getAD_PInstance_ID();

// NOTE: because Cache does not have a compute() method, we have to synchronize this block.
synchronized (processInstanceCopy)
{
// Get current process instance.
final ProcessInstance processInstanceCurrent = processInstances.getIfPresent(adPInstanceId);

// Make sure we are not overriding a different document version than the one that was checked out.
if (processInstanceCurrent != null)
{
if (processInstanceCurrent.getVersion() != versionCurrentExpected)
{
throw new InvalidDocumentVersionException(versionCurrentExpected, processInstanceCurrent.getVersion());
}
}

// Actually put the new document
processInstances.put(adPInstanceId, processInstanceCopy);

// Update version of the document that was given as parameter.
processInstance.setVersion(version);
}
}

public ProcessInstance createNewProcessInstance(final ProcessInfo processInfo)
Expand Down Expand Up @@ -158,10 +189,10 @@ public ProcessInstance getProcessInstanceForReading(final int pinstanceIdAsInt)

public ProcessInstance getProcessInstanceForWriting(final int pinstanceIdAsInt)
{
final DocumentId documentId = DocumentId.of(pinstanceIdAsInt);
try
{
return processInstances.get(DocumentId.of(pinstanceIdAsInt))
.copy(CopyMode.CheckOutWritable);
return processInstances.get(documentId).copy(CopyMode.CheckOutWritable);
}
catch (final UncheckedExecutionException | ExecutionException e)
{
Expand Down

0 comments on commit f31d0f0

Please sign in to comment.