diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java index 5bce84346f0b17a77ded48a3faef0aba222b0d3a..7b9d127353d70d4cbf77116543130dd0a2fefd05 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java @@ -81,6 +81,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPersonDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleTypeDAO; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.ServiceConversationsThreadContext; import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSServiceConversational; @@ -1454,6 +1455,8 @@ public class ETLService extends AbstractCommonServer<IETLLIMSService> implements injectPerson(sessionForEntityOperation, userId); } + ServiceConversationsThreadContext.setProgressListener(progressListener); + long spacesCreated = createSpaces(sessionForEntityOperation, operationDetails, progressListener); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/ServiceConversationsThreadContext.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/ServiceConversationsThreadContext.java new file mode 100644 index 0000000000000000000000000000000000000000..55c292fd19ecf40030421790133c563f0dfc97c6 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/ServiceConversationsThreadContext.java @@ -0,0 +1,63 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.server.dataaccess; + +import ch.systemsx.cisd.common.conversation.IProgressListener; + +/** + * The class contains the logic for communication beetween Hibernate interceptors, which should send + * service conversation updates, and parts of applications that use service conversations, but don't + * have acces to the Hibernate objects. + * <p> + * It lets the owner of service conversation store the information about it in the thread local + * variable, from which the interceptor can later read it. + * + * @author Jakub Straszewski + */ +public class ServiceConversationsThreadContext +{ + private static ThreadLocal<IProgressListener> progressListener; + + static + { + progressListener = new ThreadLocal<IProgressListener>(); + } + + /** + * Store progress listener in a thread local context + */ + public static void setProgressListener(IProgressListener listener) + { + progressListener.set(listener); + } + + /** + * Remove information about progress listener from the thread local context. + */ + public static void unsetProgressListener() + { + progressListener.remove(); + } + + /** + * Read the progress listener from the thread local context + */ + public static IProgressListener getProgressListener() + { + return progressListener.get(); + } +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityValidationInterceptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityValidationInterceptor.java index 61ea338acfd85dc6b2435081c5d2d78c122c25a2..3e2d6e7100abb4693d5a55ed619756ae0f221895 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityValidationInterceptor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityValidationInterceptor.java @@ -27,8 +27,10 @@ import org.hibernate.Interceptor; import org.hibernate.Transaction; import org.hibernate.type.Type; +import ch.systemsx.cisd.common.conversation.IProgressListener; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.ServiceConversationsThreadContext; import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.DynamicPropertyEvaluator; import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.IDynamicPropertyEvaluator; import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.EntityAdaptorFactory; @@ -61,6 +63,10 @@ public class EntityValidationInterceptor extends EmptyInterceptor implements this.callback = callback; this.daoFactory = daoFactory; initializeLists(); + + totalEntitiesToValidateCount = 0; + + entitiesValidatedCount = 0; } IHibernateTransactionManagerCallback callback; @@ -80,10 +86,25 @@ public class EntityValidationInterceptor extends EmptyInterceptor implements Queue<IEntityInformationWithPropertiesHolder> entitiesToValidate; + /** + * WE get information about progress listener, form the caller of updates. Luckily the + * onFlushDirty and onSave hooks are executed in the same thread as the caller. + * <p> + * The beforeTransactionCompletionHook is called in the separate thread, therefore we persist + * progress listener in a designated variable + */ + IProgressListener progressListener; + + int totalEntitiesToValidateCount; + + int entitiesValidatedCount; + @Override public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { + updateListener(); + if (entity instanceof IEntityInformationWithPropertiesHolder) { newEntity((IEntityInformationWithPropertiesHolder) entity); @@ -91,10 +112,17 @@ public class EntityValidationInterceptor extends EmptyInterceptor implements return false; } + private void updateListener() + { + progressListener = ServiceConversationsThreadContext.getProgressListener(); + } + @Override public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { + updateListener(); + if (entity instanceof IEntityInformationWithPropertiesHolder) { modifiedEntity((IEntityInformationWithPropertiesHolder) entity); @@ -143,15 +171,18 @@ public class EntityValidationInterceptor extends EmptyInterceptor implements IEntityInformationWithPropertiesHolder entity, boolean isNewEntity) { String result = null; - try { + if (progressListener != null) + { + progressListener.update("Validation of entities", totalEntitiesToValidateCount, + entitiesValidatedCount); + } result = calculate(script, entity, isNewEntity); } catch (Throwable e) { callback.rollbackTransaction(tx, "Validation of " + entityDescription(entity) + " resulted in error. " + e.getMessage()); - e.printStackTrace(); } if (result != null) { @@ -181,11 +212,13 @@ public class EntityValidationInterceptor extends EmptyInterceptor implements private void newEntity(IEntityInformationWithPropertiesHolder entity) { + totalEntitiesToValidateCount++; newEntities.add(entity); } private void validatedEntity(IEntityInformationWithPropertiesHolder entity) { + entitiesValidatedCount++; validatedEntities.add(entity); } @@ -193,6 +226,7 @@ public class EntityValidationInterceptor extends EmptyInterceptor implements { if (false == newEntities.contains(entity)) { + totalEntitiesToValidateCount++; modifiedEntities.add(entity); } } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java index f85a688cb42d983d16fccb8d4d14284e57998f68..dd54d0782305191097a6ef6007e07969d766ad56 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java @@ -139,7 +139,7 @@ public final class EntityTypeDAOTest extends AbstractDAOTest public final void testListMaterialTypes() { final IEntityTypeDAO entityTypeDAO = daoFactory.getEntityTypeDAO(EntityKind.MATERIAL); - assertEquals(8, entityTypeDAO.listEntityTypes().size()); + assertEquals(9, entityTypeDAO.listEntityTypes().size()); } @Test(dependsOnMethods = "testListMaterialTypes") diff --git a/openbis/sourceTest/sql/postgresql/120/039=material_type_property_types.tsv b/openbis/sourceTest/sql/postgresql/120/039=material_type_property_types.tsv index 14be4e6c44c2018df78bdf3a60534b92ea743867..e9fe833436e993e5bf31e0f0b61f72b73c7262db 100644 --- a/openbis/sourceTest/sql/postgresql/120/039=material_type_property_types.tsv +++ b/openbis/sourceTest/sql/postgresql/120/039=material_type_property_types.tsv @@ -16,3 +16,5 @@ 22 6 15 f f 2008-11-05 09:18:32.512+01 2 \N 2 \N t 23 8 1 t t 2008-11-05 09:18:32.512+01 2 \N 1 \N t 24 8 26 f f 2012-03-13 09:18:32.512+01 2 \N 2 \N t +25 9 2 t t 2008-11-05 09:18:00.622+01 1 \N 1 \N t +26 9 1 f t 2008-11-05 09:18:00.622+01 1 \N 2 \N t \ No newline at end of file diff --git a/openbis/sourceTest/sql/postgresql/120/040=material_types.tsv b/openbis/sourceTest/sql/postgresql/120/040=material_types.tsv index 5365c9e6141e2ba3a0453ef7e63b8dff257df7d6..ad2b89ce5a917b824c0a1ead8def050d823904b4 100644 --- a/openbis/sourceTest/sql/postgresql/120/040=material_types.tsv +++ b/openbis/sourceTest/sql/postgresql/120/040=material_types.tsv @@ -1,8 +1,9 @@ 1 VIRUS Virus 1 2009-03-23 15:34:44.462776+01 \N 2 CELL_LINE Cell Line or Cell Culture. The growing of cells under controlled conditions. 1 2009-03-23 15:34:44.462776+01 \N 3 GENE Gene 1 2009-03-23 15:34:44.462776+01 \N -5 CONTROL Control of a control layout 1 2009-03-23 15:34:44.462776+01 \N +5 CONTROL Control of a control layout 1 2009-03-23 15:34:44.462776+01 5 6 BACTERIUM Bacterium 1 2009-03-23 15:34:44.462776+01 \N 7 COMPOUND Compound 1 2009-03-23 15:34:44.462776+01 \N 4 SIRNA Oligo nucleotide 1 2009-03-23 15:34:44.462776+01 \N 8 SELF_REF Self Referencing Material 1 2012-03-13 15:34:44.462776+01 \N +9 SLOW_GENE Slowly validating material 1 2009-03-23 15:34:44.462776+01 10 diff --git a/openbis/sourceTest/sql/postgresql/120/057=scripts.tsv b/openbis/sourceTest/sql/postgresql/120/057=scripts.tsv index 86b1ac13a3eea129a32570ae90a731aa3a2b22d0..f5337aa5e81fabbab1ae6dea35b88b6c11130637 100644 --- a/openbis/sourceTest/sql/postgresql/120/057=scripts.tsv +++ b/openbis/sourceTest/sql/postgresql/120/057=scripts.tsv @@ -7,3 +7,4 @@ 7 1 validateUpdateFAIL \N def validate(entity, isNew):\n if (not isNew):\n return "Cannot update this entity"\n 2010-10-27 15:16:48.994831+02 2 \N ENTITY_VALIDATION 8 1 validateChildren \N def validate(entity, isNew):\n for childRelation in entity.entityPE().getChildRelationships():\n requestValidation(childRelation.getChildSample()) 2010-10-27 15:16:48.994831+02 2 \N ENTITY_VALIDATION 9 1 code_date \N "%s %s" % (entity.code(), str(currentDate().getTime())) 2010-10-27 15:16:48.994831+02 2 \N DYNAMIC_PROPERTY +10 1 waitOK \N import time;\ndef validate(entity, isNew):\n time.sleep(1);\n 2010-10-27 15:16:48.994831+02 2 \N ENTITY_VALIDATION