Notification of GRSF update is now performed in one shot to avoid problems. The patch operation is performed at most 5 times in case of errors.
git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/user/gcube-ckan-datacatalog@139872 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
8e31ba287b
commit
a1874a714e
|
@ -85,7 +85,7 @@ public interface GcubeCkanDataCatalogService extends RemoteService {
|
|||
/**
|
||||
* Notify product update
|
||||
*/
|
||||
boolean notifyProductUpdate(ManageProductBean bean);
|
||||
String notifyProductUpdate(ManageProductBean bean);
|
||||
|
||||
/**
|
||||
* Get the product bean from the product identifier
|
||||
|
|
|
@ -91,7 +91,7 @@ public interface GcubeCkanDataCatalogServiceAsync {
|
|||
* Notify product update
|
||||
*/
|
||||
void notifyProductUpdate(ManageProductBean bean,
|
||||
AsyncCallback<Boolean> callback);
|
||||
AsyncCallback<String> callback);
|
||||
|
||||
void getProductBeanById(String identifier,
|
||||
AsyncCallback<ManageProductBean> callback);
|
||||
|
|
|
@ -186,18 +186,18 @@ public class ManageProductWidget extends Composite{
|
|||
bean.setAnnotation(new HTML(annotationArea.getText().trim()).getText());
|
||||
bean.setNewStatus(GRSFStatus.fromString(listBoxStatus.getSelectedItemText()));
|
||||
|
||||
service.notifyProductUpdate(bean, new AsyncCallback<Boolean>() {
|
||||
service.notifyProductUpdate(bean, new AsyncCallback<String>() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
public void onSuccess(String result) {
|
||||
|
||||
if(result){
|
||||
if(result == null){
|
||||
showInfo(STATUS_UPDATE_SUCCESS, AlertType.SUCCESS);
|
||||
confirmButton.removeFromParent();
|
||||
formUpdate.setVisible(false);
|
||||
|
||||
}else{
|
||||
showInfo(STATUS_UPDATE_ERROR, AlertType.ERROR);
|
||||
showInfo(STATUS_UPDATE_ERROR + "(" + result + ")", AlertType.ERROR);
|
||||
confirmButton.setEnabled(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -525,7 +525,7 @@ public class GcubeCkanDataCatalogServiceImpl extends RemoteServiceServlet implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean notifyProductUpdate(ManageProductBean bean) {
|
||||
public String notifyProductUpdate(ManageProductBean bean) {
|
||||
|
||||
logger.info("Creating notification for the bean " + bean + " to send to the knowledge base");
|
||||
try{
|
||||
|
@ -540,15 +540,12 @@ public class GcubeCkanDataCatalogServiceImpl extends RemoteServiceServlet implem
|
|||
baseUrl = GRSFNotificationService.discoverEndPoint(context);
|
||||
getThreadLocalRequest().getSession().setAttribute(keyPerContext, baseUrl);
|
||||
}
|
||||
String result = GRSFNotificationService.updateCatalogueRecord(baseUrl, bean, catalogue, SessionUtil.getCurrentUser(getThreadLocalRequest()).getUsername());
|
||||
|
||||
if(result == null)
|
||||
return true;
|
||||
return GRSFNotificationService.updateCatalogueRecord(baseUrl, bean, catalogue, SessionUtil.getCurrentUser(getThreadLocalRequest()).getUsername());
|
||||
|
||||
}catch(Exception e){
|
||||
logger.error("Unable to update the product.." + e.getMessage());
|
||||
return e.getMessage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.gcube.portlets.gcubeckan.gcubeckandatacatalog.server.manage;
|
|||
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
|
||||
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -13,6 +16,8 @@ import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
|
|||
import org.gcube.portlets.gcubeckan.gcubeckandatacatalog.shared.ManageProductBean;
|
||||
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
||||
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
||||
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -20,10 +25,15 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse;
|
||||
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpPost;
|
||||
import eu.trentorise.opendata.jackan.internal.org.apache.http.entity.ContentType;
|
||||
import eu.trentorise.opendata.jackan.internal.org.apache.http.entity.StringEntity;
|
||||
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient;
|
||||
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.HttpClientBuilder;
|
||||
import eu.trentorise.opendata.jackan.internal.org.apache.http.util.EntityUtils;
|
||||
import eu.trentorise.opendata.jackan.model.CkanDataset;
|
||||
import eu.trentorise.opendata.jackan.model.CkanGroup;
|
||||
import eu.trentorise.opendata.jackan.model.CkanPair;
|
||||
import eu.trentorise.opendata.jackan.model.CkanTag;
|
||||
|
||||
/**
|
||||
* Endpoint for sending update records information to GRSF KB
|
||||
|
@ -33,6 +43,10 @@ public class GRSFNotificationService {
|
|||
|
||||
private static Logger logger = LoggerFactory.getLogger(GRSFNotificationService.class);
|
||||
private static final String SERVICE_POST_METHOD = "/service/updater/post";
|
||||
private static final String ANNOTATION_KEY = "Annotation on update";
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
private static final String STATUS_CUSTOM_FIELD_KEY = "Status";
|
||||
private static final int MAX_TRIAL = 5;
|
||||
|
||||
// request post fields
|
||||
private static final String CATALOGUE_ID = "catalog_id";
|
||||
|
@ -145,13 +159,121 @@ public class GRSFNotificationService {
|
|||
"and error in the result bean is " + parsedJSON.get(ERROR));
|
||||
|
||||
// patch the catalogue product
|
||||
new PatchProductThread(catalogue, bean, username).start();
|
||||
return patchProduct(catalogue, bean, username);
|
||||
|
||||
}catch(Exception e){
|
||||
logger.error("Unable to update this record", e);
|
||||
logger.error("Unable to update this record" + e.getMessage());
|
||||
return e.getMessage();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the product
|
||||
* @param catalogue
|
||||
* @param bean
|
||||
* @param username
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static String patchProduct(DataCatalogue catalogue,
|
||||
ManageProductBean bean, String username) {
|
||||
|
||||
logger.info("Going to patch record in the catalogue with identifier " + bean.getCatalogueIdentifier() +
|
||||
" from user " + username);
|
||||
|
||||
String apiKey = catalogue.getApiKeyFromUsername(username);
|
||||
CkanDataset dataset = catalogue.getDataset(bean.getCatalogueIdentifier(), apiKey);
|
||||
String errorMessage = null;
|
||||
|
||||
for (int i = 0; i < MAX_TRIAL; i++) {
|
||||
|
||||
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){
|
||||
|
||||
JSONObject jsonRequest = new JSONObject();
|
||||
JSONArray tagsAsJson = new JSONArray();
|
||||
JSONArray groupsAsJson = new JSONArray();
|
||||
JSONArray customFieldsAsJson = new JSONArray();
|
||||
|
||||
// manage the custom fields
|
||||
List<CkanPair> extras = dataset.getExtras();
|
||||
for (CkanPair ckanPair : extras) {
|
||||
if(ckanPair.getKey().equals(STATUS_CUSTOM_FIELD_KEY) && ckanPair.getValue().equals(bean.getCurrentStatus().toString()))
|
||||
continue;
|
||||
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("key", ckanPair.getKey());
|
||||
obj.put("value", ckanPair.getValue());
|
||||
customFieldsAsJson.add(obj);
|
||||
}
|
||||
|
||||
// add the new one and the annotation message
|
||||
JSONObject newStatus = new JSONObject();
|
||||
newStatus.put(STATUS_CUSTOM_FIELD_KEY, bean.getNewStatus().toString());
|
||||
customFieldsAsJson.add(newStatus);
|
||||
|
||||
JSONObject newAnnotation = new JSONObject();
|
||||
newAnnotation.put(ANNOTATION_KEY, Arrays.asList("date: " + DATE_FORMAT.format(new Date())
|
||||
+ ", admin: " + new LiferayUserManager().getUserByUsername(username).getFullname()
|
||||
+ ", message: " + (bean.getAnnotation() != null ? bean.getAnnotation().replaceAll("\"", "") : "none")
|
||||
+ ", old status: " + bean.getCurrentStatus().toString()
|
||||
+ ", new status: " + bean.getNewStatus().toString()
|
||||
));
|
||||
customFieldsAsJson.add(newAnnotation);
|
||||
|
||||
// manage the tags
|
||||
List<CkanTag> tags = dataset.getTags();
|
||||
|
||||
for(CkanTag ckanTag : tags){
|
||||
if(!ckanTag.getName().equals(bean.getCurrentStatus().toString())){
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("vocabulary_id", ckanTag.getVocabularyId());
|
||||
obj.put("state", ckanTag.getState().toString());
|
||||
obj.put("display_name", ckanTag.getDisplayName());
|
||||
obj.put("id", ckanTag.getId());
|
||||
obj.put("name", ckanTag.getName());
|
||||
tagsAsJson.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
// add the new one
|
||||
JSONObject newTag = new JSONObject();
|
||||
newTag.put("name", bean.getNewStatus().toString());
|
||||
tagsAsJson.add(new JSONObject());
|
||||
|
||||
// manage the groups
|
||||
List<CkanGroup> groups = dataset.getGroups();
|
||||
for (CkanGroup ckanGroup : groups) {
|
||||
if(!ckanGroup.getName().equals("grsf" + "-" + bean.getCurrentStatus().toString().toLowerCase())){
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("name", ckanGroup.getName());
|
||||
groupsAsJson.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject newGroup = new JSONObject();
|
||||
newGroup.put("name", "grsf" + "-" + bean.getNewStatus().toString().toLowerCase());
|
||||
groupsAsJson.add(newGroup);
|
||||
|
||||
// perform the request
|
||||
jsonRequest.put("id", bean.getCatalogueIdentifier());
|
||||
jsonRequest.put("tags", tagsAsJson);
|
||||
jsonRequest.put("extras", customFieldsAsJson);
|
||||
jsonRequest.put("groups", groupsAsJson);
|
||||
|
||||
logger.debug("Request param is going to be " + jsonRequest);
|
||||
|
||||
if((errorMessage = catalogue.patchProductWithJSON(bean.getCatalogueIdentifier(), jsonRequest, apiKey)) == null){
|
||||
logger.info("Record patched ...");
|
||||
}else
|
||||
continue; // retry
|
||||
|
||||
}catch(Exception e){
|
||||
logger.error("Error while trying to patch grsf record (iteration " + i + " of " + MAX_TRIAL + ")" + e.getMessage());
|
||||
errorMessage = e.getMessage();
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
package org.gcube.portlets.gcubeckan.gcubeckandatacatalog.server.manage;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
|
||||
import org.gcube.portlets.gcubeckan.gcubeckandatacatalog.shared.ManageProductBean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Thread used to patch a ckan product.
|
||||
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
|
||||
*/
|
||||
public class PatchProductThread extends Thread{
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(PatchProductThread.class);
|
||||
private DataCatalogue catalogue;
|
||||
private ManageProductBean bean;
|
||||
private String username;
|
||||
private static final String ANNOTATION_KEY = "Annotation on Status update";
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
|
||||
private static final String STATUS_CUSTOM_FIELD_KEY = "Status";
|
||||
|
||||
/**
|
||||
* @param catalogue
|
||||
* @param bean
|
||||
*/
|
||||
public PatchProductThread(DataCatalogue catalogue, ManageProductBean bean, String username) {
|
||||
super();
|
||||
this.catalogue = catalogue;
|
||||
this.bean = bean;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
logger.info("Going to patch record in the catalogue with identifier " + bean.getCatalogueIdentifier() +
|
||||
" from user " + username);
|
||||
|
||||
String apiKey = catalogue.getApiKeyFromUsername(username);
|
||||
|
||||
// remove the "Status" field
|
||||
catalogue.removeCustomField(bean.getCatalogueIdentifier(), STATUS_CUSTOM_FIELD_KEY, bean.getCurrentStatus().toString(), apiKey);
|
||||
catalogue.removeTag(bean.getCatalogueIdentifier(), apiKey, bean.getCurrentStatus().toString());
|
||||
catalogue.removeDatasetFromGroup("grsf" + "-" + bean.getCurrentStatus().toString().toLowerCase(), bean.getCatalogueIdentifier(), apiKey);
|
||||
|
||||
Map<String, List<String>> statusMap = new HashMap<String, List<String>>();
|
||||
statusMap.put(STATUS_CUSTOM_FIELD_KEY, Arrays.asList(bean.getNewStatus().toString()));
|
||||
statusMap.put(ANNOTATION_KEY, Arrays.asList("date: " + DATE_FORMAT.format(new Date())
|
||||
+ ", admin: " + username
|
||||
+ ", annotation: " + (bean.getAnnotation() != null ? bean.getAnnotation().replaceAll("\"", "") : "none")
|
||||
+ ", new status: " + bean.getNewStatus().toString()
|
||||
+ ", old status: " + bean.getCurrentStatus().toString()
|
||||
));
|
||||
catalogue.patchProductCustomFields(bean.getCatalogueIdentifier(), apiKey, statusMap);
|
||||
catalogue.addTag(bean.getCatalogueIdentifier(), apiKey, bean.getNewStatus().toString());
|
||||
catalogue.assignDatasetToGroup("grsf" + "-" + bean.getNewStatus().toString().toLowerCase(), bean.getCatalogueIdentifier(), apiKey);
|
||||
logger.info("Record patched ...");
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@ package org.gcube.portlets.gcubeckan.gcubeckandatacatalog.shared.ex;
|
|||
|
||||
/**
|
||||
* This is thrown when the Manage product is pushed on a product that has
|
||||
* a Record Type field of Source.
|
||||
* a Record Type field of Source or none.
|
||||
* @author Costantino Perciante at ISTI-CNR
|
||||
* (costantino.perciante@isti.cnr.it)
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue