Merge "Issue #2191 Registry federation synchronization and garbage collection" into development

Former-commit-id: 4e3f429e5aebec59e5c15c8bea062cc62e599cc6
This commit is contained in:
Richard Peter 2013-08-02 14:44:16 -05:00 committed by Gerrit Code Review
commit e692cc245b
29 changed files with 1289 additions and 180 deletions

View file

@ -13,7 +13,8 @@ Export-Package: com.raytheon.uf.common.registry,
com.raytheon.uf.common.registry.ebxml.slots,
com.raytheon.uf.common.registry.handler,
com.raytheon.uf.common.registry.services,
com.raytheon.uf.common.registry.services.rest
com.raytheon.uf.common.registry.services.rest,
com.raytheon.uf.common.registry.services.rest.response
Require-Bundle: org.apache.commons.codec;bundle-version="1.4.0",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.util;bundle-version="1.12.1174",

View file

@ -33,6 +33,7 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.raytheon.uf.common.registry.constants.RegistryAvailability;
import com.raytheon.uf.common.registry.services.rest.IRegistryAvailableRestService;
import com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService;
import com.raytheon.uf.common.registry.services.rest.IRegistryObjectsRestService;
import com.raytheon.uf.common.registry.services.rest.IRepositoryItemsRestService;
import com.raytheon.uf.common.serialization.SerializationUtil;
@ -50,6 +51,7 @@ import com.raytheon.uf.common.status.UFStatus;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 5/21/2013 2022 bphillip Initial implementation
* 7/29/2013 2191 bphillip Implemented registry data access service
* </pre>
*
* @author bphillip
@ -87,6 +89,16 @@ public class RegistryRESTServices {
}
});
/** Map of known registry data access services */
private static LoadingCache<String, IRegistryDataAccessService> registryDataAccessServiceMap = CacheBuilder
.newBuilder().expireAfterAccess(1, TimeUnit.HOURS)
.build(new CacheLoader<String, IRegistryDataAccessService>() {
public IRegistryDataAccessService load(String key) {
return JAXRSClientFactory.create(key,
IRegistryDataAccessService.class);
}
});
/**
* The logger
*/
@ -99,11 +111,9 @@ public class RegistryRESTServices {
* @param baseURL
* The base URL of the registry
* @return The service implementation
* @throws RegistryServiceException
* If an invalid URL is provided
*/
public static IRegistryObjectsRestService getRegistryObjectService(
String baseURL) throws RegistryServiceException {
String baseURL) {
try {
return registryObjectServiceMap.get(baseURL);
} catch (ExecutionException e) {
@ -124,8 +134,6 @@ public class RegistryRESTServices {
* @return The object
* @throws JAXBException
* If errors occur while serializing the object
* @throws RegistryServiceException
* If an invalid URL is provided
*/
public static <T extends RegistryObjectType> T getRegistryObject(
Class<T> expectedType, String baseURL, String objectId)
@ -140,11 +148,9 @@ public class RegistryRESTServices {
* @param baseURL
* The base URL of the registry
* @return The service implementation
* @throws RegistryServiceException
* If an invalid URL is provided
*/
public static IRepositoryItemsRestService getRepositoryItemService(
String baseURL) throws RegistryServiceException {
String baseURL) {
try {
return repositoryItemServiceMap.get(baseURL);
} catch (ExecutionException e) {
@ -161,11 +167,9 @@ public class RegistryRESTServices {
* @param repositoryItemId
* The id of the object
* @return The repository item
* @throws RegistryServiceException
* If an invalid URL is provided
*/
public static byte[] getRepositoryItem(String baseURL,
String repositoryItemId) throws RegistryServiceException {
String repositoryItemId) {
return getRepositoryItemService(baseURL).getRepositoryItem(
repositoryItemId);
}
@ -176,11 +180,9 @@ public class RegistryRESTServices {
* @param baseURL
* The base URL of the registry
* @return THe registry available service implementation
* @throws RegistryServiceException
* If an invalid URL is provided
*/
public static IRegistryAvailableRestService getRegistryAvailableService(
String baseURL) throws RegistryServiceException {
String baseURL) {
try {
return registryAvailabilityServiceMap.get(baseURL);
} catch (ExecutionException e) {
@ -204,8 +206,25 @@ public class RegistryRESTServices {
} catch (Throwable t) {
statusHandler.error(
"Registry at [" + baseURL + "] not available: ",
t.getLocalizedMessage());
t.getMessage());
return false;
}
}
/**
* Gets the data access service for the specified registry URL
*
* @param baseURL
* The baseURL of the registry
* @return The data access service for the specified registry URL
*/
public static IRegistryDataAccessService getRegistryDataAccessService(
String baseURL) {
try {
return registryDataAccessServiceMap.get(baseURL);
} catch (ExecutionException e) {
throw new RegistryServiceException(
"Error getting Registry Availability Rest Service", e);
}
}
}

View file

@ -0,0 +1,71 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.registry.services.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import com.raytheon.uf.common.registry.RegistryException;
import com.raytheon.uf.common.registry.services.rest.response.RestCollectionResponse;
/**
*
* REST service interface for various registry data access methods
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
public interface IRegistryDataAccessService {
/**
* Gets the ids of registry objects of the given object type
*
* @param objectType
* The object type to get ids for
* @return List of ids for registry objects of the given type
*/
@GET
@Path("/rest/dataAccess/getRegistryObjectIds/{objectType}")
public RestCollectionResponse<String> getRegistryObjectIdsOfType(
@PathParam("objectType") String objectType);
/**
* Removes any subscriptions for the given site
*
* @param siteId
* The site to remove the subscriptions for
* @throws RegistryException
* If errors occur while removing the subscriptions
*/
@GET
@Path("/rest/dataAccess/removeSubscriptionsFor/{siteId}")
public void removeSubscriptionsForSite(@PathParam("siteId") String siteId)
throws RegistryException;
}

View file

@ -0,0 +1,50 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.registry.services.rest.response;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.serialization.ISerializableObject;
/**
*
* A response from a registry REST service call
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
@XmlRootElement
public interface IRestResponse<OBJECT_TYPE extends Object> extends
ISerializableObject {
public OBJECT_TYPE getPayload();
public void setPayload(OBJECT_TYPE payload);
}

View file

@ -0,0 +1,67 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.registry.services.rest.response;
import java.util.Collection;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
*
* Response object for returning a collection from a REST service
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
@XmlRootElement
public class RestCollectionResponse<COLLECTION_TYPE extends Object> implements
IRestResponse<Collection<COLLECTION_TYPE>> {
@XmlElements({ @XmlElement(name = "item") })
private Collection<COLLECTION_TYPE> set;
public RestCollectionResponse() {
}
@Override
@XmlTransient
public Collection<COLLECTION_TYPE> getPayload() {
return set;
}
@Override
public void setPayload(Collection<COLLECTION_TYPE> payload) {
this.set = payload;
}
}

View file

@ -46,6 +46,7 @@ import org.hibernate.usertype.UserType;
* ------------ ---------- ----------- --------------------------
* Feb 21, 2012 #184 bphillip Initial creation
* 4/9/2013 1802 bphillip Added null check
* 7/29/2013 2191 bphillip Fixed equals method
*
* </pre>
*
@ -77,7 +78,11 @@ public class XMLGregorianCalendarType implements UserType {
public boolean equals(Object x, Object y) throws HibernateException {
if (x instanceof XMLGregorianCalendar
&& y instanceof XMLGregorianCalendar) {
return x.equals(y);
try {
return x.equals(y);
} catch (ClassCastException e) {
return y.equals(x);
}
} else {
return false;
}

View file

@ -0,0 +1,84 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.database;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
/**
*
* Implementation of a runnable who's run method is encapsulated in a Hibernate
* transaction. This class is used for executing asynchronous actions that
* require a Hibernate transaction.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
public abstract class RunnableWithTransaction implements Runnable {
/** The Hibernate transaction template used to get a transaction */
private TransactionTemplate txTemplate;
/**
* Creates a new RunnableWithTransaction object
*/
public RunnableWithTransaction() {
}
/**
* Creates a new RunnableWithTransaction object
*
* @param txTemplate
* The transaction template to use
*/
public RunnableWithTransaction(TransactionTemplate txTemplate) {
this.txTemplate = txTemplate;
}
public void run() {
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
runWithTransaction();
}
});
}
/**
* This method is executed transactionally
*/
public abstract void runWithTransaction();
public void setTxTemplate(TransactionTemplate txTemplate) {
this.txTemplate = txTemplate;
}
}

View file

@ -16,4 +16,5 @@ Require-Bundle: com.raytheon.uf.common.registry.schemas.ebxml;bundle-version="1.
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
org.springframework;bundle-version="2.5.6",
com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.edex.core;bundle-version="1.12.1174"
com.raytheon.uf.edex.core;bundle-version="1.12.1174",
com.google.guava;bundle-version="1.0.0"

View file

@ -3,9 +3,17 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="FederatedRegistryMonitor" class="com.raytheon.uf.edex.datadelivery.registry.availability.FederatedRegistryMonitor">
<constructor-arg ref="metadataTxTemplate"/>
<constructor-arg ref="registryObjectDao"/>
</bean>
<bean id="RegistryReplicationManager" class="com.raytheon.uf.edex.datadelivery.registry.replication.RegistryReplicationManager">
<constructor-arg ref="ebxmlSubscriptionsEnabled"/>
<constructor-arg ref="replicationConfigFileName"/>
<constructor-arg ref="registryObjectDao"/>
<constructor-arg ref="FederatedRegistryMonitor"/>
<constructor-arg ref="metadataTxTemplate"/>
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

View file

@ -0,0 +1,130 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.datadelivery.registry.availability;
import java.util.Calendar;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.DateTimeValueType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SlotType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.VersionInfoType;
import org.springframework.transaction.support.TransactionTemplate;
import com.raytheon.uf.common.registry.constants.StatusTypes;
import com.raytheon.uf.common.registry.ebxml.RegistryUtil;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.database.RunnableWithTransaction;
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil;
/**
*
* Periodically writes a record to the database as long as this registry is
* connected to the federation. This class is primarily used to determine if,
* upon startup, this registry must synchronize with the federation to get the
* state of the registry up to date
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
public class FederatedRegistryMonitor extends RunnableWithTransaction {
/** The logger instance */
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(FederatedRegistryMonitor.class);
/** ID of the object to write to the registry */
private static final String REGISTRY_AVAILABLE_ID = "RegistryAvailability";
/** Data access object for registry objects */
private RegistryObjectDao registryObjectDao;
public FederatedRegistryMonitor() {
super();
}
public FederatedRegistryMonitor(TransactionTemplate txTemplate,
RegistryObjectDao registryObjectDao) {
super(txTemplate);
this.registryObjectDao = registryObjectDao;
}
public long getLastKnownUptime() {
RegistryObjectType regObj = registryObjectDao
.getById(REGISTRY_AVAILABLE_ID);
Calendar cal = null;
if (regObj == null) {
cal = TimeUtil.newCalendar();
cal.setTimeInMillis(0);
} else {
DateTimeValueType value = (DateTimeValueType) regObj.getSlotByName(
REGISTRY_AVAILABLE_ID).getSlotValue();
cal = value.getValue().toGregorianCalendar();
}
return cal.getTimeInMillis();
}
@Override
public void runWithTransaction() {
try {
RegistryObjectType regObj = registryObjectDao
.getById(REGISTRY_AVAILABLE_ID);
if (regObj == null) {
statusHandler
.info("Availability object not found in registry. Creating new entry.");
SlotType slot = new SlotType();
slot.setName(REGISTRY_AVAILABLE_ID);
DateTimeValueType value = new DateTimeValueType();
value.setDateTimeValue(EbxmlObjectUtil
.getCurrentTimeAsXMLGregorianCalendar());
slot.setSlotValue(value);
regObj = new RegistryObjectType();
regObj.setId(REGISTRY_AVAILABLE_ID);
regObj.setLid(REGISTRY_AVAILABLE_ID);
regObj.setOwner(RegistryUtil.DEFAULT_OWNER);
regObj.setVersionInfo(new VersionInfoType());
regObj.setStatus(StatusTypes.APPROVED);
regObj.getSlot().add(slot);
} else {
DateTimeValueType dateTime = (DateTimeValueType) regObj
.getSlotByName(REGISTRY_AVAILABLE_ID).getSlotValue();
dateTime.setDateTimeValue(EbxmlObjectUtil
.getCurrentTimeAsXMLGregorianCalendar());
}
registryObjectDao.createOrUpdate(regObj);
} catch (EbxmlRegistryException e) {
statusHandler.error("Error updating federated time!", e);
}
}
}

View file

@ -26,6 +26,7 @@ import java.util.List;
import javax.xml.bind.JAXBException;
import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.LifecycleManager;
import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.MsgRegistryException;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.AssociationType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.FederationType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.OrganizationType;
@ -38,6 +39,7 @@ import com.raytheon.uf.common.registry.constants.StatusTypes;
import com.raytheon.uf.common.registry.ebxml.RegistryUtil;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
import com.raytheon.uf.edex.registry.ebxml.init.RegistryInitializedListener;
/**
*
@ -50,12 +52,14 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 5/22/2013 1707 bphillip Initial implementation
* 7/29/2013 2191 bphillip Implemented registry sync for registries that have been down for an extended period of time
* </pre>
*
* @author bphillip
* @version 1
*/
public class NcfRegistryFederationManager extends RegistryFederationManager {
public class NcfRegistryFederationManager extends RegistryFederationManager
implements RegistryInitializedListener {
/**
* Creates a new NcfRegistryFederationManager
@ -103,7 +107,12 @@ public class NcfRegistryFederationManager extends RegistryFederationManager {
objects.add(primaryContact);
objects.add(federationAssociation);
submitObjects(objects);
replicationManager.submitRemoteSubscriptions(registry.getBaseURL());
replicationManager.submitRemoteSubscriptions(registry);
try {
replicationManager.checkDownTime();
} catch (MsgRegistryException e) {
throw new EbxmlRegistryException("Error checkint down time!", e);
}
} else {
statusHandler.info("Federation is disabled for this registry.");
}

View file

@ -21,6 +21,7 @@ package com.raytheon.uf.edex.datadelivery.registry.federation;
import java.io.File;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import javax.xml.bind.JAXBException;
@ -50,7 +51,6 @@ import com.raytheon.uf.edex.datadelivery.registry.replication.RegistryReplicatio
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryDao;
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
import com.raytheon.uf.edex.registry.ebxml.init.RegistryInitializedListener;
/**
*
@ -64,6 +64,7 @@ import com.raytheon.uf.edex.registry.ebxml.init.RegistryInitializedListener;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 5/22/2013 1707 bphillip Initial implementation
* 7/29/2013 2191 bphillip Implemented registry sync for registries that have been down for an extended period of time
* </pre>
*
* @author bphillip
@ -71,13 +72,18 @@ import com.raytheon.uf.edex.registry.ebxml.init.RegistryInitializedListener;
*/
@Service
@Transactional
public abstract class RegistryFederationManager implements
RegistryInitializedListener {
public abstract class RegistryFederationManager {
/** The logger instance */
protected static final IUFStatusHandler statusHandler = UFStatus
.getHandler(RegistryFederationManager.class);
/**
* The scheduler service used for registering this registry with the
* federation
*/
protected ScheduledExecutorService scheduler;
/** The federation identifier */
public static final String FEDERATION_ID = "Registry Federation";
@ -174,6 +180,7 @@ public abstract class RegistryFederationManager implements
+ " Federation Membership Association");
association.setLid(association.getId());
association.setObjectType(RegistryObjectTypes.ASSOCIATION);
association.setOwner(federationProperties.getSiteIdentifier());
association.setType(AssociationTypes.HAS_FEDERATION_MEMBER);
association.setStatus(StatusTypes.APPROVED);
association.setName(RegistryUtil.getInternationalString(registry

View file

@ -23,7 +23,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@ -44,9 +43,7 @@ import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SlotType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.StringValueType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.raytheon.uf.common.registry.constants.CanonicalQueryTypes;
@ -56,7 +53,9 @@ import com.raytheon.uf.common.registry.constants.QueryReturnTypes;
import com.raytheon.uf.common.registry.services.RegistryRESTServices;
import com.raytheon.uf.common.registry.services.RegistrySOAPServices;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.edex.database.RunnableWithTransaction;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
import com.raytheon.uf.edex.registry.ebxml.init.RegistryInitializedListener;
/**
*
@ -69,6 +68,7 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 5/22/2013 1707 bphillip Initial implementation
* 7/29/2013 2191 bphillip Implemented registry sync for registries that have been down for an extended period of time
* </pre>
*
* @author bphillip
@ -76,17 +76,12 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
*/
@Service
@Transactional
public class WfoRegistryFederationManager extends RegistryFederationManager {
public class WfoRegistryFederationManager extends RegistryFederationManager
implements RegistryInitializedListener {
/** The address of the NCF */
private String ncfAddress;
/**
* The scheduler service used for registering this registry with the
* federation
*/
private ScheduledExecutorService scheduler;
/** The transaction template used to manually handle transactions */
private TransactionTemplate txTemplate;
@ -173,7 +168,7 @@ public class WfoRegistryFederationManager extends RegistryFederationManager {
objects.add(federationAssociation);
submitObjects(objects);
replicationManager.setSubscriptionProcessingEnabled(true);
replicationManager.submitRemoteSubscriptions(registry.getBaseURL());
replicationManager.submitRemoteSubscriptions(registry);
}
protected FederationType getFederation() throws EbxmlRegistryException {
@ -222,7 +217,7 @@ public class WfoRegistryFederationManager extends RegistryFederationManager {
* @author bphillip
* @version 1
*/
private class RegisterWithFederationTask implements Runnable {
private class RegisterWithFederationTask extends RunnableWithTransaction {
/**
* Denotes if this task has successfully registered this registry with
@ -234,44 +229,39 @@ public class WfoRegistryFederationManager extends RegistryFederationManager {
* Creates a new RegisterwithFederationTask
*/
public RegisterWithFederationTask() {
super(txTemplate);
}
@Override
public void run() {
public void runWithTransaction() {
if (!success) {
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(
TransactionStatus status) {
try {
try {
if (RegistryRESTServices
.isRegistryAvailable(ncfAddress)) {
statusHandler
.info("NCF Registry is available. Attempting to join federation...");
} else {
statusHandler
.error("NCF is currently unreachable. Local registry is unable to join the federation at this time. Retrying in 10 seconds...");
replicationManager
.setSubscriptionProcessingEnabled(false);
success = false;
return;
}
registerWithFederation();
success = true;
} catch (EbxmlRegistryException e) {
statusHandler.error(
"Error registering with federation", e);
success = false;
}
} catch (Throwable e) {
throw new RuntimeException(
"Error initializing EBXML database!", e);
try {
try {
if (RegistryRESTServices
.isRegistryAvailable(ncfAddress)) {
statusHandler
.info("NCF Registry is available. Attempting to join federation...");
} else {
statusHandler
.error("NCF is currently unreachable. Local registry is unable to join the federation at this time. Retrying in 10 seconds...");
replicationManager
.setSubscriptionProcessingEnabled(false);
success = false;
return;
}
registerWithFederation();
replicationManager.checkDownTime();
success = true;
} catch (EbxmlRegistryException e) {
statusHandler.error(
"Error registering with federation", e);
success = false;
}
});
} catch (Throwable e) {
throw new RuntimeException(
"Error initializing EBXML database!", e);
}
}
}
}

View file

@ -0,0 +1,72 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.datadelivery.registry.replication;
import org.springframework.transaction.support.TransactionTemplate;
import com.raytheon.uf.edex.database.RunnableWithTransaction;
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
/**
*
* A task to remove an object from the registry asynchonously
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
public class RegistryRemoveTask extends RunnableWithTransaction {
/** Data Access object for registry objects */
private RegistryObjectDao dao;
/** The id of the registry object this task is removing */
private String idToRemove;
/**
* Creates a new AsyncRemove object
*
* @param txTemplate
* The Hibernate transaction template
* @param lcm
* The lifecycle manager
* @param idToRemove
* The ide of the registry object to remove
*/
public RegistryRemoveTask(TransactionTemplate txTemplate,
RegistryObjectDao dao, String idToRemove) {
super(txTemplate);
this.dao = dao;
}
@Override
public void runWithTransaction() {
dao.delete(dao.getById(idToRemove));
}
}

View file

@ -21,7 +21,12 @@ package com.raytheon.uf.edex.datadelivery.registry.replication;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
@ -35,17 +40,23 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;
import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.MsgRegistryException;
import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.Mode;
import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.SubmitObjectsRequest;
import oasis.names.tc.ebxml.regrep.xsd.query.v4.QueryRequest;
import oasis.names.tc.ebxml.regrep.xsd.query.v4.QueryResponse;
import oasis.names.tc.ebxml.regrep.xsd.query.v4.ResponseOptionType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.DeliveryInfoType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.QueryType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectListType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SlotType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.StringValueType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SubscriptionType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.VersionInfoType;
import org.springframework.transaction.support.TransactionTemplate;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
@ -57,6 +68,7 @@ import com.raytheon.uf.common.registry.constants.CanonicalQueryTypes;
import com.raytheon.uf.common.registry.constants.DeliveryMethodTypes;
import com.raytheon.uf.common.registry.constants.Namespaces;
import com.raytheon.uf.common.registry.constants.NotificationOptionTypes;
import com.raytheon.uf.common.registry.constants.QueryReturnTypes;
import com.raytheon.uf.common.registry.constants.RegistryObjectTypes;
import com.raytheon.uf.common.registry.constants.StatusTypes;
import com.raytheon.uf.common.registry.ebxml.RegistryUtil;
@ -66,7 +78,12 @@ import com.raytheon.uf.common.serialization.JAXBManager;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.CollectionUtil;
import com.raytheon.uf.edex.datadelivery.registry.availability.FederatedRegistryMonitor;
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
import com.raytheon.uf.edex.registry.ebxml.services.query.QueryConstants;
import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil;
/**
@ -81,6 +98,7 @@ import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil;
* ------------ ---------- ----------- --------------------------
* 4/24/2013 1675 bphillip Initial implementation
* 6/4/2013 1707 bphillip Changed to use new NotificationServer objects
* 7/29/2013 2191 bphillip Implemented registry sync for registries that have been down for an extended period of time
* </pre>
*
* @author bphillip
@ -92,12 +110,21 @@ public class RegistryReplicationManager {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(RegistryReplicationManager.class);
private FederatedRegistryMonitor federatedRegistryMonitor;
private static final long MAX_DOWN_TIME_DURATION = TimeUtil.MILLIS_PER_DAY
* 2 - TimeUtil.MILLIS_PER_HOUR;
/** Scheduler service for monitoring subscription submission tasks */
private ScheduledExecutorService scheduler;
/** The servers that we are subscribing to */
private NotificationServers servers;
private RegistryObjectDao dao;
private TransactionTemplate txTemplate;
/**
* The JAXBManager instance for marshalling/unmarshalling objects
*/
@ -127,10 +154,15 @@ public class RegistryReplicationManager {
* @throws SerializationException
*/
public RegistryReplicationManager(boolean subscriptionProcessingEnabled,
String notificationServerConfigFileName) throws JAXBException,
String notificationServerConfigFileName, RegistryObjectDao dao,
FederatedRegistryMonitor availabilityMonitor,
TransactionTemplate txTemplate) throws JAXBException,
SerializationException {
this.subscriptionProcessingEnabled = subscriptionProcessingEnabled;
this.replicationConfigFileName = notificationServerConfigFileName;
this.dao = dao;
this.txTemplate = txTemplate;
this.federatedRegistryMonitor = availabilityMonitor;
jaxbManager = new JAXBManager(NotificationServers.class,
SubscriptionType.class);
File notificationServerConfigFile = PathManagerFactory.getPathManager()
@ -147,6 +179,201 @@ public class RegistryReplicationManager {
scheduler = Executors.newSingleThreadScheduledExecutor();
}
/**
* Checks how long a registry has been down. If the registry has been down
* for over 2 days, the registry is synchronized with one of the federation
* members
*
* @throws MsgRegistryException
* If errors occur during registry synchronization
* @throws EbxmlRegistryException
* If errors occur during registry synchronization
*/
public void checkDownTime() throws MsgRegistryException,
EbxmlRegistryException {
long currentTime = TimeUtil.currentTimeMillis();
long lastKnownUp = federatedRegistryMonitor.getLasKnownUptime();
long downTime = currentTime - lastKnownUp;
statusHandler
.info("Registry has been down since: "
+ new Date(currentTime - downTime)
+ ". Checking if synchronization with the federation is necessary...");
// The registry has been down for ~2 days, this requires a
// synchronization of the
// data from the federation
if (currentTime - lastKnownUp > MAX_DOWN_TIME_DURATION) {
statusHandler
.warn("Registry has been down for ~2 days. Initiating federated data synchronization....");
List<NotificationHostConfiguration> notificationServers = servers
.getRegistryReplicationServers();
if (servers == null
|| CollectionUtil.isNullOrEmpty(servers
.getRegistryReplicationServers())) {
statusHandler
.warn("No servers configured for replication. Unable to synchronize data with federation!");
} else {
NotificationHostConfiguration registryToSyncFrom = null;
for (NotificationHostConfiguration config : notificationServers) {
statusHandler.info("Checking availability of registry at: "
+ config.getRegistryBaseURL());
if (RegistryRESTServices.isRegistryAvailable(config
.getRegistryBaseURL())) {
registryToSyncFrom = config;
break;
}
statusHandler.info("Registry at "
+ config.getRegistryBaseURL()
+ " is not available...");
}
// No available registry was found!
if (registryToSyncFrom == null) {
statusHandler
.warn("No available registries found! Registry data will not be synchronized with the federation!");
} else {
synchronizeRegistryWithFederation(registryToSyncFrom
.getRegistryBaseURL());
}
}
}
statusHandler.info("Starting federated uptime monitor...");
scheduler.scheduleAtFixedRate(federatedRegistryMonitor, 0, 1,
TimeUnit.MINUTES);
}
private void synchronizeRegistryWithFederation(String remoteRegistryUrl)
throws MsgRegistryException, EbxmlRegistryException {
ExecutorService executor = Executors.newFixedThreadPool(25);
for (String objectType : objectTypes) {
Set<String> localIds = new HashSet<String>();
Set<String> remoteIds = new HashSet<String>();
statusHandler
.info("Getting registry object Ids from local registry...");
Collection<String> response = RegistryRESTServices
.getRegistryDataAccessService(
RegistryUtil.LOCAL_REGISTRY_ADDRESS)
.getRegistryObjectIdsOfType(objectType).getPayload();
if (response != null) {
localIds.addAll(response);
}
statusHandler.info(localIds.size() + " objects of type "
+ objectType + " present in local registry.");
statusHandler.info("Getting registry object Ids from "
+ remoteRegistryUrl + "...");
response = RegistryRESTServices
.getRegistryDataAccessService(remoteRegistryUrl)
.getRegistryObjectIdsOfType(objectType).getPayload();
if (response != null) {
remoteIds.addAll(response);
}
statusHandler.info(remoteIds.size() + " objects of type "
+ objectType + " present on registry at "
+ remoteRegistryUrl);
statusHandler.info("Synchronizing objects of type " + objectType
+ "...");
/*
* Iterate through local objects and compare them with the remote
* object inventory to determine if they need to be updated or
* deleted locally
*/
for (String localId : localIds) {
if (remoteIds.contains(localId)) {
RegistryObjectType objectToSubmit;
try {
objectToSubmit = getRemoteObject(remoteRegistryUrl,
localId);
} catch (Exception e) {
statusHandler.error("Error getting remote object: "
+ localId, e);
continue;
}
objectToSubmit.addSlot(EbxmlObjectUtil.HOME_SLOT_NAME,
remoteRegistryUrl);
RegistrySubmitTask submitTask = new RegistrySubmitTask(
txTemplate, dao, objectToSubmit, remoteRegistryUrl);
executor.submit(submitTask);
} else {
RegistryRemoveTask removeTask = new RegistryRemoveTask(
txTemplate, dao, localId);
executor.submit(removeTask);
}
}
/*
* Iterate through the remote objects to see if there are any
* objects on the remote registry that do not exist local. If found,
* retrieve them and add them to the local registry
*/
for (String remoteId : remoteIds) {
if (!localIds.contains(remoteId)) {
RegistryObjectType objectToSubmit;
try {
objectToSubmit = getRemoteObject(remoteRegistryUrl,
remoteId);
} catch (Exception e) {
statusHandler.error("Error getting remote object: "
+ remoteId, e);
continue;
}
objectToSubmit.addSlot(EbxmlObjectUtil.HOME_SLOT_NAME,
remoteRegistryUrl);
RegistrySubmitTask submitTask = new RegistrySubmitTask(
txTemplate, dao, objectToSubmit, remoteRegistryUrl);
executor.submit(submitTask);
}
}
}
// Wait for all threads to complete
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
statusHandler
.error("Registry synchronization using ["
+ remoteRegistryUrl
+ "] did not complete successfully!", e);
throw new EbxmlRegistryException(
"Task executor did not shutdown properly!", e);
}
statusHandler.info("Registry synchronization using ["
+ remoteRegistryUrl + "] completed successfully!");
}
private RegistryObjectType getRemoteObject(String remoteRegistryUrl,
String objectId) throws Exception {
final QueryType queryType = new QueryType();
queryType.setQueryDefinition(CanonicalQueryTypes.GET_OBJECT_BY_ID);
Set<SlotType> slots = new HashSet<SlotType>();
final SlotType slot = new SlotType();
slot.setName(QueryConstants.ID);
final StringValueType slotValue = new StringValueType();
slotValue.setStringValue(objectId);
slot.setSlotValue(slotValue);
slots.add(slot);
queryType.setSlot(slots);
QueryRequest queryRequest = new QueryRequest();
queryRequest.setResponseOption(new ResponseOptionType(
QueryReturnTypes.REGISTRY_OBJECT, true));
queryRequest.setFederated(false);
queryRequest.setQuery(queryType);
QueryResponse response = RegistrySOAPServices.getQueryServiceForHost(
remoteRegistryUrl).executeQuery(queryRequest);
if (!CollectionUtil.isNullOrEmpty(response.getRegistryObjects())) {
return response.getRegistryObjects().get(0);
} else {
throw new EbxmlRegistryException("Object " + objectId
+ " not found on remote server!");
}
}
/**
* Static method only used during the Spring container to inject the object
* types to subscribe to for registry replication
@ -166,7 +393,7 @@ public class RegistryReplicationManager {
* @param baseURL
* The url of the registry to send the subscriptions to
*/
public void submitRemoteSubscriptions(String baseURL) {
public void submitRemoteSubscriptions(RegistryType registry) {
if (subscriptionProcessingEnabled) {
statusHandler.info("Registry Replication is enabled.");
@ -187,7 +414,7 @@ public class RegistryReplicationManager {
statusHandler
.info("Submitting subscriptions to registry replication servers...");
for (NotificationHostConfiguration config : replicationRegistries) {
scheduleSubscriptionSubmission(config, baseURL);
scheduleSubscriptionSubmission(config, registry);
}
}
}
@ -201,9 +428,9 @@ public class RegistryReplicationManager {
* The url of the registry to submit the subscriptions to
*/
private void scheduleSubscriptionSubmission(
NotificationHostConfiguration config, String baseURL) {
NotificationHostConfiguration config, RegistryType registry) {
final SubmitSubscriptionTask submitSubscriptionTask = new SubmitSubscriptionTask(
config, baseURL);
config, registry);
final ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(
submitSubscriptionTask, 0, 10, TimeUnit.SECONDS);
scheduler.schedule(new Runnable() {
@ -227,7 +454,7 @@ public class RegistryReplicationManager {
* replication subscriptions to
*/
private void submitSubscriptionsToHost(
NotificationHostConfiguration config, String localRegistryBaseURL) {
NotificationHostConfiguration config, RegistryType localRegistry) {
statusHandler
.info("Generating registry replication subscriptions for registry at ["
+ config.getRegistrySiteName()
@ -239,7 +466,7 @@ public class RegistryReplicationManager {
SubscriptionType subscription;
try {
subscription = createSubscription(config.getRegistryBaseURL(),
objectType, localRegistryBaseURL);
objectType, localRegistry);
} catch (Exception e) {
throw new RegistryException("Error creating subscription", e);
}
@ -267,10 +494,10 @@ public class RegistryReplicationManager {
* If errors occur while creating the subscription object
*/
private SubscriptionType createSubscription(String host, String objectType,
String localRegistryBaseURL) throws Exception {
RegistryType registry) throws Exception {
// Set normal registry object fields
String subscriptionDetail = "Replication Subscription for ["
+ objectType + "] objects for server [" + localRegistryBaseURL
+ objectType + "] objects for server [" + registry.getBaseURL()
+ "]";
SubscriptionType sub = new SubscriptionType();
sub.setId(subscriptionDetail);
@ -283,7 +510,7 @@ public class RegistryReplicationManager {
version.setVersionName("1");
version.setUserVersionName("1");
sub.setVersionInfo(version);
sub.setOwner("Subscription Owner");
sub.setOwner(registry.getOwner());
sub.setStatus(StatusTypes.APPROVED);
sub.setStartTime(EbxmlObjectUtil.getTimeAsXMLGregorianCalendar(0));
@ -304,7 +531,7 @@ public class RegistryReplicationManager {
String endpointType = DeliveryMethodTypes.SOAP;
W3CEndpointReferenceBuilder builder = new W3CEndpointReferenceBuilder();
builder.address(RegistrySOAPServices.getNotificationListenerServiceUrl(
localRegistryBaseURL).toString());
registry.getBaseURL()).toString());
W3CEndpointReference ref = builder.build();
DOMResult dom = new DOMResult();
ref.writeTo(dom);
@ -355,8 +582,8 @@ public class RegistryReplicationManager {
/** The server configuration */
private NotificationHostConfiguration config;
/** The base URL of the remote registry */
private String baseURL;
/** The remote registry */
private RegistryType registry;
/**
* Creates a new SubmitSubscriptionTask
@ -367,15 +594,16 @@ public class RegistryReplicationManager {
* The base URL of the remote registry
*/
public SubmitSubscriptionTask(NotificationHostConfiguration config,
String baseURL) {
RegistryType registry) {
this.config = config;
this.baseURL = baseURL;
this.registry = registry;
}
@Override
public void run() {
if (!success) {
String remoteRegistryBaseURL = config.getRegistryBaseURL();
final String remoteRegistryBaseURL = config
.getRegistryBaseURL();
statusHandler.info("Checking if remote registry at ["
+ remoteRegistryBaseURL + "] is available...");
@ -390,7 +618,25 @@ public class RegistryReplicationManager {
return;
}
try {
submitSubscriptionsToHost(config, baseURL);
statusHandler
.info("Removing remote subscriptions prior to submission of new subscriptions");
RegistryRESTServices.getRegistryDataAccessService(
config.getRegistryBaseURL())
.removeSubscriptionsForSite(registry.getOwner());
submitSubscriptionsToHost(config, registry);
/*
* Adds a hook to remove the subscriptions from the remote
* server when this server shuts down
*/
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
RegistryRESTServices.getRegistryDataAccessService(
remoteRegistryBaseURL)
.removeSubscriptionsForSite(
registry.getOwner());
}
});
success = true;
} catch (Exception e) {
statusHandler

View file

@ -0,0 +1,76 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.datadelivery.registry.replication;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectType;
import org.springframework.transaction.support.TransactionTemplate;
import com.raytheon.uf.edex.database.RunnableWithTransaction;
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil;
/**
*
* A task to submit an object to the registry asynchonously
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
public class RegistrySubmitTask extends RunnableWithTransaction {
/** The Registry Object data access object */
private RegistryObjectDao dao;
/** The id of the registry object this task is submitting */
private RegistryObjectType objectToSubmit;
public RegistrySubmitTask(TransactionTemplate txTemplate,
RegistryObjectDao dao, RegistryObjectType objectToSubmit,
String retrievedFrom) {
super(txTemplate);
this.dao = dao;
this.objectToSubmit = objectToSubmit;
if (this.objectToSubmit.getSlotByName(EbxmlObjectUtil.HOME_SLOT_NAME) == null) {
this.objectToSubmit.addSlot(EbxmlObjectUtil.HOME_SLOT_NAME,
retrievedFrom);
}
}
@Override
public void runWithTransaction() {
RegistryObjectType existingObject = dao.getById(objectToSubmit.getId());
if (existingObject == null) {
dao.create(objectToSubmit);
} else {
dao.merge(objectToSubmit, existingObject);
}
}
}

View file

@ -1 +1,2 @@
com.raytheon.uf.edex.registry.ebxml.services.query.adhoc.AdhocQueryExpression
com.raytheon.uf.edex.registry.ebxml.services.query.adhoc.AdhocQueryExpression
com.raytheon.uf.edex.registry.ebxml.services.rest.RestResponse

View file

@ -37,6 +37,7 @@
class="com.raytheon.uf.edex.registry.ebxml.services.RegistryGarbageCollector">
<constructor-arg ref="slotTypeDao" />
<constructor-arg ref="AuditableEventTypeDao" />
<constructor-arg ref="metadataTxTemplate"/>
</bean>
</beans>

View file

@ -69,6 +69,11 @@
<property name="partyDao" ref="partyDao" />
<property name="webUtil" ref="RegistryWebUtil" />
</bean>
<bean id="registryDataAccessService" class="com.raytheon.uf.edex.registry.ebxml.services.rest.RegistryDataAccessService">
<property name="registryObjectDao" ref="registryObjectDao"/>
<property name="lcm" ref="lcmServiceImpl"/>
</bean>
<bean id="registryAvailabilityService"
class="com.raytheon.uf.edex.registry.ebxml.services.rest.RegistryAvailableRestService" />

View file

@ -1,5 +1,5 @@
# The period which registry subscriptions are processed
ebxml-subscription-process.cron=0+0/1+*+*+*+?
ebxml-garbage-collect-process.cron=0/30+*+*+*+*+?
ebxml-garbage-collect-process.cron=0/1+*+*+*+*+?
# Master switch enabling email transmission
ebxml-email.enabled=false

View file

@ -61,6 +61,7 @@ import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil;
* 4/9/2013 1802 bphillip Removed exception catching
* Apr 17, 2013 1914 djohnson Use strategy for subscription processing.
* May 02, 2013 1910 djohnson Broke out registry subscription notification to a service class.
* 7/29/2013 2191 bphillip Changed method to get expired events
*
* </pre>
*
@ -94,9 +95,6 @@ public class AuditableEventTypeDao extends
/** Cutoff parameter for the query to get the expired events */
private static final String GET_EXPIRED_EVENTS_QUERY_CUTOFF_PARAMETER = "cutoff";
/** Batch size for the query to get expired events */
private static final int GET_EXPIRED_EVENTS_QUERY_BATCH_SIZE = 2500;
/** Query to get Expired AuditableEvents */
private static final String GET_EXPIRED_EVENTS_QUERY = "FROM AuditableEventType event where event.timestamp < :"
+ GET_EXPIRED_EVENTS_QUERY_CUTOFF_PARAMETER;
@ -115,25 +113,20 @@ public class AuditableEventTypeDao extends
}
/**
* Deletes auditable events older than 48 hrs old
* Gets auditable events older than 48 hrs old
*
* @throws EbxmlRegistryException
* If errors occur purging auditable events
*/
@Transactional(propagation = Propagation.REQUIRED)
public void deleteExpiredEvents() throws EbxmlRegistryException {
public List<AuditableEventType> getExpiredEvents(int limit)
throws EbxmlRegistryException {
Calendar cutoffTime = TimeUtil.newGmtCalendar();
cutoffTime.add(Calendar.HOUR_OF_DAY, -AUDITABLE_EVENT_RETENTION_TIME);
List<AuditableEventType> expiredEvents = this.executeHQLQuery(
GET_EXPIRED_EVENTS_QUERY, GET_EXPIRED_EVENTS_QUERY_BATCH_SIZE,
return this.executeHQLQuery(GET_EXPIRED_EVENTS_QUERY, limit,
GET_EXPIRED_EVENTS_QUERY_CUTOFF_PARAMETER, EbxmlObjectUtil
.getTimeAsXMLGregorianCalendar(cutoffTime
.getTimeInMillis()));
if (!expiredEvents.isEmpty()) {
statusHandler.info("Deleting " + expiredEvents.size()
+ " Auditable Events prior to: " + cutoffTime.getTime());
this.template.deleteAll(expiredEvents);
}
}
/**

View file

@ -23,7 +23,6 @@ import java.util.List;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectType;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
/**
@ -38,6 +37,7 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
* 3/13/2013 1082 bphillip Initial creation
* 4/9/2013 1802 bphillip Removed exception catching
* 6/4/2013 2022 bphillip Added delete objects of type method
* 7/29/2013 2191 bphillip Added new methods to support registry synchronization
*
* </pre>
*
@ -48,25 +48,31 @@ public class RegistryObjectDao extends
RegistryObjectTypeDao<RegistryObjectType> {
/** Delete object type parameterized statement */
private static final String DELETE_OBJECT_TYPE = "DELETE RegistryObjectType regObj where regObj.objectType=:objectType";
private static final String GET_IDS_BY_OBJECT_TYPE = "SELECT regObj.id FROM RegistryObjectType regObj WHERE regObj.objectType=:objectType";
public RegistryObjectDao() {
}
/**
* Deletes objects of a specific type from the registry
* Gets the object ids of objects of the given object type
*
* @param objectType
* The object type to delete
* @throws DataAccessLayerException
* If errors occur on the delete
* The object type to get the ids for
* @return The list of object ids of objects of the given type
*/
public void deleteObjectsOfType(String objectType)
throws DataAccessLayerException {
int objectsDeleted = this.executeHQLStatement(DELETE_OBJECT_TYPE,
"objectType", objectType);
statusHandler.info(objectsDeleted + " objects of type " + objectType
+ " deleted from registry");
public List<String> getRegistryObjectIdsOfType(String objectType) {
return this.executeHQLQuery(GET_IDS_BY_OBJECT_TYPE, "objectType",
objectType);
}
/**
* Deletes a persistent object
*
* @param obj
* The persistent object to delete
*/
public void deleteWithoutMerge(RegistryObjectType obj) {
this.template.delete(obj);
}
/**

View file

@ -23,9 +23,6 @@ import java.util.List;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SlotType;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.raytheon.uf.edex.database.dao.SessionManagedDao;
/**
@ -39,6 +36,7 @@ import com.raytheon.uf.edex.database.dao.SessionManagedDao;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/11/2013 1707 bphillip Initial implementation
* 7/29/2013 2191 bphillip Modified method to get orphaned slots
* </pre>
*
* @author bphillip
@ -71,35 +69,34 @@ public class SlotTypeDao extends SessionManagedDao<Integer, SlotType> {
+ "select child_slot_key from ebxml.emailaddress_slot "
+ "UNION "
+ "select child_slot_key from ebxml.postaladdress_slot "
+ ")";
/** Keys parameter for the query to get the orphaned slot objects */
private static final String GET_BY_ID_QUERY_KEYS_PARAMETER = "keys";
/** Result batch size for the query to get the orphaned slot objects */
private static final int GET_BY_ID_QUERY_BATCH_SIZE = 1000;
private static final String GET_BY_ID_QUERY = "FROM SlotType slot where slot.key in (:"
+ GET_BY_ID_QUERY_KEYS_PARAMETER + ")";
+ ") limit %s";
@Override
protected Class<SlotType> getEntityClass() {
return SlotType.class;
}
/**
* Gets orphaned slot ids
*
* @param limit
* The maximum number of results to return
* @return List of orphaned ids of size limit
*/
@SuppressWarnings("unchecked")
@Transactional(propagation = Propagation.REQUIRED)
public void deleteOrphanedSlots() {
List<Integer> orphanedSlotIds = this.getSessionFactory()
.getCurrentSession().createSQLQuery(ORPHANED_SLOT_QUERY).list();
if (!orphanedSlotIds.isEmpty()) {
public List<Integer> getOrphanedSlotIds(int limit) {
return this
.getSessionFactory()
.getCurrentSession()
.createSQLQuery(
String.format(ORPHANED_SLOT_QUERY,
String.valueOf(limit))).list();
}
List<SlotType> slots = this.executeHQLQuery(GET_BY_ID_QUERY,
GET_BY_ID_QUERY_BATCH_SIZE, GET_BY_ID_QUERY_KEYS_PARAMETER,
orphanedSlotIds);
statusHandler.info("Removing " + orphanedSlotIds.size()
+ " orphaned slots...");
this.deleteAll(slots);
public void deleteBySlotId(Integer id) {
SlotType slot = this.getById(id);
if (slot != null) {
this.template.delete(slot);
}
}
}

View file

@ -19,8 +19,22 @@
**/
package com.raytheon.uf.edex.registry.ebxml.services;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.AuditableEventType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.database.RunnableWithTransaction;
import com.raytheon.uf.edex.registry.ebxml.dao.AuditableEventTypeDao;
import com.raytheon.uf.edex.registry.ebxml.dao.SlotTypeDao;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
@ -38,27 +52,48 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/11/2013 1707 bphillip Initial implementation
* 7/29/2013 2191 bphillip Added executors to remove orphaned slots and expired events
* </pre>
*
* @author bphillip
* @version 1
*/
@Service
@Transactional
public class RegistryGarbageCollector {
/** The logger instance */
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(RegistryGarbageCollector.class);
/** Sentinel to denote if the garbage collection is currently running */
private AtomicBoolean running = new AtomicBoolean(false);
/** The executor service to remove orphaned slots */
private ThreadPoolExecutor orphanedSlotExecutor;
/** The executor service to remove expired events */
private ThreadPoolExecutor expiredEventExecutor;
/** The transaction template to use for asynchronous tasks */
private TransactionTemplate txTemplate;
/** Data access object for SlotType */
private SlotTypeDao slotDao;
/** Data access object for AuditableEventType */
private AuditableEventTypeDao eventDao;
private static final int QUEUE_MAX_SIZE = 500;
/**
* Creates a new GarbageCollector object
*/
public RegistryGarbageCollector() {
orphanedSlotExecutor = new ThreadPoolExecutor(1, 3, 1L,
TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(250));
expiredEventExecutor = new ThreadPoolExecutor(1, 3, 1L,
TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(250));
}
/**
@ -70,24 +105,119 @@ public class RegistryGarbageCollector {
* The auditable event dao to use
*/
public RegistryGarbageCollector(SlotTypeDao slotDao,
AuditableEventTypeDao eventDao) {
AuditableEventTypeDao eventDao, TransactionTemplate txTemplate) {
this();
this.slotDao = slotDao;
this.eventDao = eventDao;
this.txTemplate = txTemplate;
}
/**
* Cleans up the registry by removing unused and/or orphaned objects
*/
public void gc() throws EbxmlRegistryException {
public void gc() {
if (!running.compareAndSet(false, true)) {
return;
}
try {
eventDao.deleteExpiredEvents();
slotDao.deleteOrphanedSlots();
purgeOrphanedSlots();
purgeExpiredEvents();
} catch (EbxmlRegistryException e) {
statusHandler.error("Error purging auditable events!", e);
} finally {
running.set(false);
}
}
/**
* Purges orphaned slots in the registry
*/
private void purgeOrphanedSlots() {
/*
* Determines how many more orphaned slots can be added to the queue
* based on the existing queue size
*/
int limit = QUEUE_MAX_SIZE - orphanedSlotExecutor.getQueue().size();
if (limit > QUEUE_MAX_SIZE * .25) {
List<Integer> orphanedSlotIds = slotDao.getOrphanedSlotIds(limit);
for (Integer slotId : orphanedSlotIds) {
try {
orphanedSlotExecutor.submit(new RemoveOrphanedSlot(
txTemplate, slotId));
} catch (RejectedExecutionException e) {
// Could not add more to the queue since it is full
}
}
}
}
/**
* Purges expired events older than 2 days
*
* @throws EbxmlRegistryException
* If errors occur while enqueuing events to be deleted
*/
private void purgeExpiredEvents() throws EbxmlRegistryException {
int limit = QUEUE_MAX_SIZE - expiredEventExecutor.getQueue().size();
if (limit > QUEUE_MAX_SIZE * .25) {
List<AuditableEventType> expiredEvents = eventDao
.getExpiredEvents(limit);
for (AuditableEventType event : expiredEvents) {
try {
expiredEventExecutor.submit(new RemoveExpiredEvent(
txTemplate, event));
} catch (RejectedExecutionException e) {
// Could not add more to the queue since it is full
}
}
}
}
/**
* Task to remove orphaned slots that is run asynchronously
*
* @author bphillip
*
*/
private class RemoveOrphanedSlot extends RunnableWithTransaction {
/** The id of the orphaned slot to be removed by this task */
private Integer slotId;
public RemoveOrphanedSlot(TransactionTemplate txTemplate, Integer slotId) {
super(txTemplate);
this.slotId = slotId;
}
@Override
public void runWithTransaction() {
slotDao.deleteBySlotId(slotId);
}
}
/**
* Task to remove expired auditable eventss
*
* @author bphillip
*
*/
private class RemoveExpiredEvent extends RunnableWithTransaction {
/** The event to be removed */
private AuditableEventType event;
public RemoveExpiredEvent(TransactionTemplate txTemplate,
AuditableEventType event) {
super(txTemplate);
this.event = event;
}
@Override
public void runWithTransaction() {
eventDao.delete(event);
}
}
}

View file

@ -40,7 +40,6 @@ import oasis.names.tc.ebxml.regrep.xsd.query.v4.ResponseOptionType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.AssociationType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ClassificationNodeType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ClassificationSchemeType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ExtensibleObjectType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ObjectRefType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.QueryType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.RegistryObjectType;
@ -329,7 +328,8 @@ public class LifecycleManagerImpl implements LifecycleManager {
statusHandler
.info("Client has selected to check object references before submitting objects.");
ValidateObjectsRequest validateObjectsRequest = new ValidateObjectsRequest();
validateObjectsRequest.setOriginalObjects(request.getRegistryObjectList());
validateObjectsRequest.setOriginalObjects(request
.getRegistryObjectList());
// Uses the validation service directly, not going through the
// web-service client interface
@ -338,8 +338,10 @@ public class LifecycleManagerImpl implements LifecycleManager {
EbxmlObjectUtil.spiObjectFactory
.createValidateObjectsResponse());
final List<RegistryExceptionType> validationExceptions = validationResponse.getException();
final List<RegistryExceptionType> responseExceptions = response.getException();
final List<RegistryExceptionType> validationExceptions = validationResponse
.getException();
final List<RegistryExceptionType> responseExceptions = response
.getException();
if (!validationExceptions.isEmpty()) {
// Only care about unresolved references
@ -636,7 +638,7 @@ public class LifecycleManagerImpl implements LifecycleManager {
}
private void checkReplica(SubmitObjectsRequest request,
ExtensibleObjectType object1, ExtensibleObjectType object2)
RegistryObjectType object1, RegistryObjectType object2)
throws MsgRegistryException {
boolean fromNotification = request
.getSlotValue(EbxmlObjectUtil.HOME_SLOT_NAME) != null;
@ -645,7 +647,11 @@ public class LifecycleManagerImpl implements LifecycleManager {
String object2Home = object2
.getSlotValue(EbxmlObjectUtil.HOME_SLOT_NAME);
if (object1.getOwner().equals(object2.getOwner())) {
return;
}
if (fromNotification) {
if (object1Home != null && object2Home == null) {
throw EbxmlExceptionUtil.createMsgRegistryException(
"Cannot overwrite local object with replica",

View file

@ -44,7 +44,6 @@ import com.raytheon.uf.common.registry.constants.StatusTypes;
import com.raytheon.uf.common.registry.ebxml.RegistryUtil;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.registry.ebxml.dao.AuditableEventTypeDao;
import com.raytheon.uf.edex.registry.ebxml.dao.NotificationTypeDao;
import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException;
@ -164,39 +163,32 @@ public class RegistryNotificationManager {
subscription, objectsOfInterest);
if (!eventsOfInterest.isEmpty()) {
try {
for (NotificationListenerWrapper listener : listeners) {
int subListCount = eventsOfInterest.size() / SIZE_LIMIT;
int lastListSize = eventsOfInterest.size() % SIZE_LIMIT;
for (int i = 0; i < subListCount; i++) {
NotificationType notification = getNotification(
subscription, listener.address,
objectsOfInterest, eventsOfInterest.subList(
SIZE_LIMIT * i, SIZE_LIMIT * i
+ SIZE_LIMIT));
if (!notification.getEvent().isEmpty()) {
sendNotification(listener, notification,
listener.address);
}
for (NotificationListenerWrapper listener : listeners) {
int subListCount = eventsOfInterest.size() / SIZE_LIMIT;
int lastListSize = eventsOfInterest.size() % SIZE_LIMIT;
for (int i = 0; i < subListCount; i++) {
NotificationType notification = getNotification(
subscription,
listener.address,
objectsOfInterest,
eventsOfInterest.subList(SIZE_LIMIT * i, SIZE_LIMIT
* i + SIZE_LIMIT));
if (!notification.getEvent().isEmpty()) {
sendNotification(listener, notification,
listener.address);
}
if (lastListSize > 0) {
NotificationType notification = getNotification(
subscription,
listener.address,
objectsOfInterest,
eventsOfInterest.subList(SIZE_LIMIT
* subListCount, SIZE_LIMIT
* subListCount + lastListSize));
if (!notification.getEvent().isEmpty()) {
sendNotification(listener, notification,
listener.address);
}
}
}
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Unable to determine notification destinations.", e);
if (lastListSize > 0) {
NotificationType notification = getNotification(
subscription, listener.address, objectsOfInterest,
eventsOfInterest.subList(SIZE_LIMIT * subListCount,
SIZE_LIMIT * subListCount + lastListSize));
if (!notification.getEvent().isEmpty()) {
sendNotification(listener, notification,
listener.address);
}
}
}
}
}

View file

@ -310,11 +310,7 @@ public class RegistrySubscriptionManager implements
if (subscriptionShouldRun(sub)) {
try {
processSubscription(subNotificationListener);
} catch (EbxmlRegistryException e) {
statusHandler.error(
"Errors occurred while processing subscription ["
+ sub.getId() + "]", e);
} catch (MsgRegistryException e) {
} catch (Throwable e) {
statusHandler.error(
"Errors occurred while processing subscription ["
+ sub.getId() + "]", e);

View file

@ -0,0 +1,145 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.registry.ebxml.services.rest;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.LifecycleManager;
import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.RemoveObjectsRequest;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.DeliveryInfoType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ObjectRefListType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ObjectRefType;
import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SubscriptionType;
import oasis.names.tc.ebxml.regrep.xsd.rs.v4.RegistryResponseStatus;
import oasis.names.tc.ebxml.regrep.xsd.rs.v4.RegistryResponseType;
import org.springframework.transaction.annotation.Transactional;
import com.raytheon.uf.common.registry.RegistryException;
import com.raytheon.uf.common.registry.services.rest.IRegistryDataAccessService;
import com.raytheon.uf.common.registry.services.rest.response.RestCollectionResponse;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.registry.ebxml.dao.RegistryObjectDao;
/**
*
* Implementation of the registry data access service interface
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 7/29/2013 2191 bphillip Initial implementation
* </pre>
*
* @author bphillip
* @version 1
*/
@Transactional
public class RegistryDataAccessService implements IRegistryDataAccessService {
/** The logger */
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(RegistryDataAccessService.class);
/** Data access object for registry objects */
private RegistryObjectDao registryObjectDao;
/** Lifecyclemanager */
private LifecycleManager lcm;
@GET
@Path("/rest/dataAccess/getRegistryObjectIds/{objectType}")
public RestCollectionResponse<String> getRegistryObjectIdsOfType(
@PathParam("objectType") String objectType) {
statusHandler.info("Getting registry object ids of type [" + objectType
+ "]...");
RestCollectionResponse<String> response = new RestCollectionResponse<String>();
response.setPayload(registryObjectDao
.getRegistryObjectIdsOfType(objectType));
return response;
}
@GET
@Path("/rest/dataAccess/removeSubscriptionsFor/{siteId}")
public void removeSubscriptionsForSite(@PathParam("siteId") String siteId) {
statusHandler.info("Removing subscriptions for: " + siteId);
List<SubscriptionType> subscriptions = registryObjectDao
.executeHQLQuery(
"from SubscriptionType sub where sub.owner=:siteId",
"siteId", siteId);
if (subscriptions.isEmpty()) {
statusHandler.info("No subscriptions present for site: " + siteId);
} else {
List<Integer> deliveryInfoKeys = new ArrayList<Integer>();
ObjectRefListType refList = new ObjectRefListType();
for (SubscriptionType sub : subscriptions) {
refList.getObjectRef().add(new ObjectRefType(sub.getId()));
for (DeliveryInfoType deliveryInfo : sub.getDeliveryInfo()) {
deliveryInfoKeys.add(deliveryInfo.getKey());
}
}
RemoveObjectsRequest removeRequest = new RemoveObjectsRequest();
removeRequest.setId("Remote subscription removal request for "
+ siteId);
removeRequest.setComment("Removal of remote subscriptions for "
+ siteId);
removeRequest.setObjectRefList(refList);
try {
RegistryResponseType response = lcm
.removeObjects(removeRequest);
if (response.getStatus().equals(RegistryResponseStatus.SUCCESS)) {
registryObjectDao
.executeHQLStatement(
"DELETE FROM DeliveryInfoType deliveryInfo where deliveryInfo.key in (:keys)",
"keys", deliveryInfoKeys);
statusHandler
.info("Successfully removed subscriptions for site "
+ siteId);
} else {
statusHandler
.info("Failed to remove subscriptions for site "
+ siteId);
}
} catch (Exception e) {
throw new RegistryException(
"Error removing subscriptions for site " + siteId, e);
}
}
}
public void setRegistryObjectDao(RegistryObjectDao registryObjectDao) {
this.registryObjectDao = registryObjectDao;
}
public void setLcm(LifecycleManager lcm) {
this.lcm = lcm;
}
}

View file

@ -88,6 +88,7 @@
<!-- REST Service Definitions -->
<jaxrs:server id="registryRestServices" address="/">
<jaxrs:serviceBeans>
<ref bean="registryDataAccessService"/>
<ref bean="registryAvailabilityService" />
<ref bean="registryObjectsRestService" />
<ref bean="repositoryObjectsRestService" />