Identifier | 88589 |
Address | Water Road 675 Apartment 62 Freetown Sierra Leone |
Date of birth | 11 November 2018 |
Identifier | 88589 |
Address | Water Road 675 Apartment 62 Freetown Sierra Leone |
Date of birth | 11 November 2018 |
true
if the enqueue can be made, false
if there
- * are still messages inside the queue.
+ * @throws AlreadyQueuedException thrown if there are still messages inside the queue.
*/
- boolean enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String fhirResourceId, @Nonnull String requestId );
+ void enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String fhirResourceId, @Nonnull String requestId ) throws AlreadyQueuedException;
/**
* Tries to dequeue the entity with the specified IDs. If the entity does not
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomQueuedRemoteSubscriptionRequestRepository.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomQueuedRemoteSubscriptionRequestRepository.java
index 0d50e7fe..b79bb08d 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomQueuedRemoteSubscriptionRequestRepository.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/CustomQueuedRemoteSubscriptionRequestRepository.java
@@ -49,10 +49,9 @@ public interface CustomQueuedRemoteSubscriptionRequestRepository
* @param subscriptionResourceId the ID of the subscription resource for which a
* message should be enqueued.
* @param requestId the ID of the current request.
- * @return true
if the enqueue can be made, false
if there
- * are still messages inside the queue.
+ * @throws AlreadyQueuedException thrown if there are still messages inside the queue.
*/
- boolean enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String requestId );
+ void enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String requestId ) throws AlreadyQueuedException;
/**
* Tries to dequeue the entity with the specified ID. If the entity does not
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteFhirResourceRepositoryImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteFhirResourceRepositoryImpl.java
index 2f95535c..2adef87b 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteFhirResourceRepositoryImpl.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteFhirResourceRepositoryImpl.java
@@ -29,13 +29,20 @@
*/
import org.dhis2.fhir.adapter.fhir.data.model.QueuedRemoteSubscriptionRequest;
+import org.dhis2.fhir.adapter.fhir.data.repository.AlreadyQueuedException;
import org.dhis2.fhir.adapter.fhir.data.repository.CustomQueuedRemoteFhirResourceRepository;
import org.dhis2.fhir.adapter.fhir.data.repository.IgnoredSubscriptionResourceException;
-import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.query.NativeQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.support.DataAccessUtils;
+import org.springframework.dao.support.PersistenceExceptionTranslator;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.annotation.Nonnull;
import javax.persistence.EntityManager;
@@ -45,6 +52,8 @@
import java.time.Instant;
import java.util.UUID;
+import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW;
+
/**
* Implementation of {@link CustomQueuedRemoteFhirResourceRepository}.
*
@@ -57,18 +66,25 @@ public class CustomQueuedRemoteFhirResourceRepositoryImpl implements CustomQueue
@PersistenceContext
private EntityManager entityManager;
- public CustomQueuedRemoteFhirResourceRepositoryImpl( @Nonnull EntityManager entityManager )
+ private PlatformTransactionManager platformTransactionManager;
+
+ private PersistenceExceptionTranslator persistenceExceptionTranslator;
+
+ public CustomQueuedRemoteFhirResourceRepositoryImpl( @Nonnull EntityManager entityManager,
+ @Nonnull PlatformTransactionManager platformTransactionManager, @Nonnull @Qualifier( "&entityManagerFactory" ) PersistenceExceptionTranslator persistenceExceptionTranslator )
{
this.entityManager = entityManager;
+ this.platformTransactionManager = platformTransactionManager;
+ this.persistenceExceptionTranslator = persistenceExceptionTranslator;
}
- @Transactional
+ @Transactional( rollbackFor = AlreadyQueuedException.class )
@Override
@SuppressWarnings( "unchecked" )
- public boolean enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String fhirResourceId, @Nonnull String requestId )
+ public void enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String fhirResourceId, @Nonnull String requestId ) throws AlreadyQueuedException
{
final Query query = entityManager.createNativeQuery( "INSERT INTO fhir_queued_remote_resource(remote_subscription_resource_id,fhir_resource_id,request_id,queued_at) " +
- "VALUES (:subscriptionResourceId,:fhirResourceId,:requestId,:queuedAt) ON CONFLICT ON CONSTRAINT fhir_queued_remote_resource_pk DO NOTHING RETURNING request_id" )
+ "VALUES (:subscriptionResourceId,:fhirResourceId,:requestId,:queuedAt)" )
.setParameter( "subscriptionResourceId", subscriptionResourceId ).setParameter( "fhirResourceId", fhirResourceId )
.setParameter( "requestId", requestId ).setParameter( "queuedAt", Instant.now() );
// avoid invalidation of complete 2nd level cache
@@ -76,31 +92,76 @@ public boolean enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String fh
try
{
- return query.getResultList().stream().anyMatch( requestId::equals );
+ query.executeUpdate();
}
catch ( PersistenceException e )
{
- if ( e.getCause() instanceof ConstraintViolationException )
+ final RuntimeException runtimeException = DataAccessUtils.translateIfNecessary( e, persistenceExceptionTranslator );
+ if ( runtimeException instanceof DataIntegrityViolationException )
{
- logger.error( "Could not process enqueue request for subscription resource {} and FHIR resource {} due to constraint violation: {}",
- subscriptionResourceId, fhirResourceId, e.getCause().getMessage() );
- throw new IgnoredSubscriptionResourceException( "Subscription resource " + subscriptionResourceId + " does no longer exist.", e );
+ final DataIntegrityViolationException dataIntegrityViolationException =
+ (DataIntegrityViolationException) runtimeException;
+ if ( SqlExceptionUtils.isUniqueKeyViolation( dataIntegrityViolationException.getMostSpecificCause() ) )
+ {
+ throw new AlreadyQueuedException();
+ }
+ if ( SqlExceptionUtils.isForeignKeyViolation( dataIntegrityViolationException.getMostSpecificCause() ) )
+ {
+ logger.error( "Could not process enqueue request for subscription resource {} and FHIR resource {} due to constraint violation: {}",
+ subscriptionResourceId, fhirResourceId, e.getCause().getMessage() );
+ throw new IgnoredSubscriptionResourceException( "Subscription resource " + subscriptionResourceId + " does no longer exist.", e );
+ }
}
- throw e;
+ throw runtimeException;
}
}
- @Transactional
@Override
public boolean dequeued( @Nonnull UUID subscriptionResourceId, @Nonnull String fhirResourceId )
{
// First an enqueue must be tried. There may still be a pending not committed enqueue.
// This must be deleted. The pending enqueue will block this enqueue until it has been committed.
- enqueue( subscriptionResourceId, fhirResourceId, "?" );
+ TransactionStatus transactionStatus = platformTransactionManager
+ .getTransaction( new DefaultTransactionDefinition( PROPAGATION_REQUIRES_NEW ) );
+ try
+ {
+ enqueue( subscriptionResourceId, fhirResourceId, "?" );
+ }
+ catch ( AlreadyQueuedException e )
+ {
+ // can be ignored
+ }
+ finally
+ {
+ if ( transactionStatus.isRollbackOnly() )
+ {
+ platformTransactionManager.rollback( transactionStatus );
+ }
+ else
+ {
+ platformTransactionManager.commit( transactionStatus );
+ }
+ }
- final Query query = entityManager.createQuery( "DELETE FROM QueuedRemoteFhirResource " +
- "WHERE id.remoteSubscriptionResource.id=:subscriptionResourceId AND id.fhirResourceId=:fhirResourceId" )
- .setParameter( "subscriptionResourceId", subscriptionResourceId ).setParameter( "fhirResourceId", fhirResourceId );
- return (query.executeUpdate() > 0);
+ transactionStatus = platformTransactionManager
+ .getTransaction( new DefaultTransactionDefinition() );
+ try
+ {
+ final Query query = entityManager.createQuery( "DELETE FROM QueuedRemoteFhirResource " +
+ "WHERE id.remoteSubscriptionResource.id=:subscriptionResourceId AND id.fhirResourceId=:fhirResourceId" )
+ .setParameter( "subscriptionResourceId", subscriptionResourceId ).setParameter( "fhirResourceId", fhirResourceId );
+ return (query.executeUpdate() > 0);
+ }
+ finally
+ {
+ if ( transactionStatus.isRollbackOnly() )
+ {
+ platformTransactionManager.rollback( transactionStatus );
+ }
+ else
+ {
+ platformTransactionManager.commit( transactionStatus );
+ }
+ }
}
}
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteSubscriptionRequestRepositoryImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteSubscriptionRequestRepositoryImpl.java
index afb33517..2fab3a65 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteSubscriptionRequestRepositoryImpl.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/CustomQueuedRemoteSubscriptionRequestRepositoryImpl.java
@@ -29,13 +29,20 @@
*/
import org.dhis2.fhir.adapter.fhir.data.model.QueuedRemoteSubscriptionRequest;
+import org.dhis2.fhir.adapter.fhir.data.repository.AlreadyQueuedException;
import org.dhis2.fhir.adapter.fhir.data.repository.CustomQueuedRemoteSubscriptionRequestRepository;
import org.dhis2.fhir.adapter.fhir.data.repository.IgnoredSubscriptionResourceException;
-import org.hibernate.exception.ConstraintViolationException;
import org.hibernate.query.NativeQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.support.DataAccessUtils;
+import org.springframework.dao.support.PersistenceExceptionTranslator;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.annotation.Nonnull;
import javax.persistence.EntityManager;
@@ -45,6 +52,8 @@
import java.time.Instant;
import java.util.UUID;
+import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW;
+
/**
* Implementation of {@link CustomQueuedRemoteSubscriptionRequestRepository}.
*
@@ -57,48 +66,100 @@ public class CustomQueuedRemoteSubscriptionRequestRepositoryImpl implements Cust
@PersistenceContext
private EntityManager entityManager;
- public CustomQueuedRemoteSubscriptionRequestRepositoryImpl( @Nonnull EntityManager entityManager )
+ private PlatformTransactionManager platformTransactionManager;
+
+ private PersistenceExceptionTranslator persistenceExceptionTranslator;
+
+ public CustomQueuedRemoteSubscriptionRequestRepositoryImpl( @Nonnull EntityManager entityManager,
+ @Nonnull PlatformTransactionManager platformTransactionManager, @Nonnull @Qualifier( "&entityManagerFactory" ) PersistenceExceptionTranslator persistenceExceptionTranslator )
{
this.entityManager = entityManager;
+ this.platformTransactionManager = platformTransactionManager;
+ this.persistenceExceptionTranslator = persistenceExceptionTranslator;
}
- @Transactional
+ @Transactional( rollbackFor = AlreadyQueuedException.class )
@Override
@SuppressWarnings( "unchecked" )
- public boolean enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String requestId )
+ public void enqueue( @Nonnull UUID subscriptionResourceId, @Nonnull String requestId ) throws AlreadyQueuedException
{
- final Query query = entityManager.createNativeQuery( "INSERT INTO fhir_queued_remote_subscription_request(id,request_id,queued_at) " +
- "VALUES (:id,:requestId,:queuedAt) ON CONFLICT ON CONSTRAINT fhir_queued_remote_subscription_request_pk DO NOTHING RETURNING request_id" )
+ final Query query = entityManager.createNativeQuery( "INSERT INTO fhir_queued_remote_subscription_request" +
+ "(id,request_id,queued_at) VALUES (:id,:requestId,:queuedAt)" )
.setParameter( "id", subscriptionResourceId ).setParameter( "requestId", requestId ).setParameter( "queuedAt", Instant.now() );
// avoid invalidation of complete 2nd level cache
query.unwrap( NativeQuery.class ).addSynchronizedEntityClass( QueuedRemoteSubscriptionRequest.class );
try
{
- return query.getResultList().stream().anyMatch( requestId::equals );
+ query.executeUpdate();
}
catch ( PersistenceException e )
{
- if ( e.getCause() instanceof ConstraintViolationException )
+ final RuntimeException runtimeException = DataAccessUtils.translateIfNecessary( e, persistenceExceptionTranslator );
+ if ( runtimeException instanceof DataIntegrityViolationException )
{
- logger.error( "Could not process enqueue request for subscription resource {} due to constraint violation: {}",
- subscriptionResourceId, e.getCause().getMessage() );
- throw new IgnoredSubscriptionResourceException( "Subscription resource " + subscriptionResourceId + " does no longer exist.", e );
+ final DataIntegrityViolationException dataIntegrityViolationException =
+ (DataIntegrityViolationException) runtimeException;
+ if ( SqlExceptionUtils.isUniqueKeyViolation( dataIntegrityViolationException.getMostSpecificCause() ) )
+ {
+ throw new AlreadyQueuedException();
+ }
+ if ( SqlExceptionUtils.isForeignKeyViolation( dataIntegrityViolationException.getMostSpecificCause() ) )
+ {
+ logger.error( "Could not process enqueue request for subscription resource {} due to constraint violation: {}",
+ subscriptionResourceId, e.getCause().getMessage() );
+ throw new IgnoredSubscriptionResourceException( "Subscription resource " + subscriptionResourceId + " does no longer exist.", e );
+ }
}
- throw e;
+ throw runtimeException;
}
}
- @Transactional
@Override
public boolean dequeued( @Nonnull UUID subscriptionResourceId )
{
// First an enqueue must be tried. There may still be a pending not committed enqueue.
// This must be deleted. The pending enqueue will block this enqueue until it has been committed.
- enqueue( subscriptionResourceId, "?" );
+ TransactionStatus transactionStatus = platformTransactionManager
+ .getTransaction( new DefaultTransactionDefinition( PROPAGATION_REQUIRES_NEW ) );
+ try
+ {
+ enqueue( subscriptionResourceId, "?" );
+ }
+ catch ( AlreadyQueuedException e )
+ {
+ // can be ignored
+ }
+ finally
+ {
+ if ( transactionStatus.isRollbackOnly() )
+ {
+ platformTransactionManager.rollback( transactionStatus );
+ }
+ else
+ {
+ platformTransactionManager.commit( transactionStatus );
+ }
+ }
- final Query query = entityManager.createQuery( "DELETE FROM QueuedRemoteSubscriptionRequest WHERE id=:id" )
- .setParameter( "id", subscriptionResourceId );
- return (query.executeUpdate() > 0);
+ transactionStatus = platformTransactionManager
+ .getTransaction( new DefaultTransactionDefinition() );
+ try
+ {
+ final Query query = entityManager.createQuery( "DELETE FROM QueuedRemoteSubscriptionRequest WHERE id=:id" )
+ .setParameter( "id", subscriptionResourceId );
+ return (query.executeUpdate() > 0);
+ }
+ finally
+ {
+ if ( transactionStatus.isRollbackOnly() )
+ {
+ platformTransactionManager.rollback( transactionStatus );
+ }
+ else
+ {
+ platformTransactionManager.commit( transactionStatus );
+ }
+ }
}
}
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/SqlExceptionUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/SqlExceptionUtils.java
new file mode 100644
index 00000000..ead861e0
--- /dev/null
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/data/repository/impl/SqlExceptionUtils.java
@@ -0,0 +1,75 @@
+package org.dhis2.fhir.adapter.fhir.data.repository.impl;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import javax.annotation.Nullable;
+import java.sql.SQLException;
+
+/**
+ * Utility class for handling SQL exception types.
+ *
+ * @author volsch
+ */
+public abstract class SqlExceptionUtils
+{
+ protected static final String UNIQUE_KEY_VIOLATION_ERROR_CODE = "23505";
+
+ protected static final String FOREIGN_KEY_VIOLATION_ERROR_CODE = "23503";
+
+ public static boolean isUniqueKeyViolation( @Nullable Throwable exception )
+ {
+ if ( exception == null )
+ {
+ return false;
+ }
+ if ( !(exception instanceof SQLException) )
+ {
+ return false;
+ }
+ return UNIQUE_KEY_VIOLATION_ERROR_CODE.equals( ((SQLException) exception).getSQLState() );
+ }
+
+ public static boolean isForeignKeyViolation( @Nullable Throwable exception )
+ {
+ if ( exception == null )
+ {
+ return false;
+ }
+ if ( !(exception instanceof SQLException) )
+ {
+ return false;
+ }
+ return FOREIGN_KEY_VIOLATION_ERROR_CODE.equals( ((SQLException) exception).getSQLState() );
+ }
+
+ private SqlExceptionUtils()
+ {
+ super();
+ }
+}
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java
index 45be74e5..20bac03e 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java
@@ -228,7 +228,7 @@ public void setTransformInScript( ExecutableScript transformInScript )
this.transformInScript = transformInScript;
}
- @Column( name = "contained_allowed", nullable = false )
+ @Column( name = "contained_allowed", nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE NOT NULL" )
public boolean isContainedAllowed()
{
return containedAllowed;
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ExecutableScriptArg.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ExecutableScriptArg.java
index a01de593..c03805e8 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ExecutableScriptArg.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ExecutableScriptArg.java
@@ -122,7 +122,7 @@ public void setArgument( ScriptArg argument )
}
@Basic
- @Column( name = "enabled", nullable = false )
+ @Column( name = "enabled", nullable = false, columnDefinition = "BOOLEAN DEFAULT TRUE NOT NULL" )
public boolean isEnabled()
{
return enabled;
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/MappedTrackedEntity.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/MappedTrackedEntity.java
index 05b14b56..8178b9c5 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/MappedTrackedEntity.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/MappedTrackedEntity.java
@@ -96,7 +96,7 @@ public void setDescription( String description )
}
@Basic
- @Column( name = "enabled" )
+ @Column( name = "enabled", nullable = false, columnDefinition = "BOOLEAN DEFAULT TRUE NOT NULL" )
public boolean isEnabled()
{
return enabled;
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptArg.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptArg.java
index 77593824..4f534cd7 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptArg.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptArg.java
@@ -125,7 +125,7 @@ public void setMandatory( boolean mandatory )
}
@Basic
- @Column( name = "array_value", nullable = false )
+ @Column( name = "array_value", nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE NOT NULL" )
public boolean isArray()
{
return array;
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java
index e519c627..7d514a32 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/System.java
@@ -103,7 +103,7 @@ public void setSystemUri( String systemUri )
}
@Basic
- @Column( name = "enabled", nullable = false )
+ @Column( name = "enabled", nullable = false, columnDefinition = "BOOLEAN DEFAULT TRUE NOT NULL" )
public boolean isEnabled()
{
return enabled;
@@ -127,7 +127,7 @@ public void setDescription( String description )
}
@Basic
- @Column( name = "description_protected", nullable = false, updatable = false )
+ @Column( name = "description_protected", nullable = false, updatable = false, columnDefinition = "BOOLEAN DEFAULT FALSE NOT NULL" )
public boolean isDescriptionProtected()
{
return descriptionProtected;
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/VersionedBaseMetadata.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/VersionedBaseMetadata.java
index bd15da1f..54192177 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/VersionedBaseMetadata.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/VersionedBaseMetadata.java
@@ -76,7 +76,7 @@ public void setId( UUID id )
}
@Version
- @Column( name = "version", nullable = false )
+ @Column( name = "version", nullable = false, columnDefinition = "BIGINT DEFAULT 0 NOT NULL" )
public Long getVersion()
{
return version;
@@ -88,7 +88,7 @@ public void setVersion( Long version )
}
@Basic
- @Column( name = "created_at", nullable = false, updatable = false )
+ @Column( name = "created_at", nullable = false, updatable = false, columnDefinition = "TIMESTAMP(3) WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP() NOT NULL" )
public Instant getCreatedAt()
{
return createdAt;
@@ -112,7 +112,7 @@ public void setLastUpdatedBy( String lastUpdatedBy )
}
@Basic
- @Column( name = "last_updated_at", nullable = false )
+ @Column( name = "last_updated_at", nullable = false, columnDefinition = "TIMESTAMP(3) WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP() NOT NULL" )
@LastModifiedDate
public Instant getLastUpdatedAt()
{
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/remote/impl/RemoteRestHookProcessorImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/remote/impl/RemoteRestHookProcessorImpl.java
index 7135919b..afe4c4ba 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/remote/impl/RemoteRestHookProcessorImpl.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/remote/impl/RemoteRestHookProcessorImpl.java
@@ -30,6 +30,7 @@
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.dhis2.fhir.adapter.fhir.data.model.ProcessedRemoteFhirResource;
+import org.dhis2.fhir.adapter.fhir.data.repository.AlreadyQueuedException;
import org.dhis2.fhir.adapter.fhir.data.repository.IgnoredSubscriptionResourceException;
import org.dhis2.fhir.adapter.fhir.data.repository.ProcessedRemoteFhirResourceRepository;
import org.dhis2.fhir.adapter.fhir.data.repository.QueuedRemoteFhirResourceRepository;
@@ -50,8 +51,12 @@
import org.springframework.jms.core.JmsTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.annotation.Nonnull;
import java.time.Instant;
@@ -90,6 +95,8 @@ public class RemoteRestHookProcessorImpl implements RemoteRestHookProcessor
private final Map