Skip to content

Commit

Permalink
Fix for protegeproject#769 - IllegalArgumentException: state should b…
Browse files Browse the repository at this point in the history
…e: writes is not an empty list upon savings Tags and Sharing Settings

- also workaround for com.mongodb.DuplicateKeyException: Write failed with error code 11000 and error message 'E11000 duplicate key error collection: webprotege.RoleAssignments index: userName_1_projectId_1
  • Loading branch information
wolfch-elsevier committed Jun 6, 2022
1 parent 2500943 commit 93cee38
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 29 deletions.
19 changes: 18 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,30 @@ target/
.classpath
.project
.settings/
**/.factorypath
out/

# https://www.jenv.be/
.java-version

logs/

velocity.log.*
*.log

dependency-reduced-pom.xml

.protegedata/
.protegedata/

# Package Files
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public interface TagRepository {

void saveTag(@Nonnull Tag tag);

void saveTags(@Nonnull Iterable<Tag> tags);
void saveTags(@Nonnull List<Tag> tags);

void deleteTag(@Nonnull TagId tagId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@
import org.semanticweb.owlapi.model.*;
import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl;

import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Provider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Matthew Horridge
* Stanford Center for Biomedical Informatics Research
Expand All @@ -27,6 +32,10 @@ public class ObjectMapperProvider implements Provider<ObjectMapper> {
@Nonnull
private final OWLDataFactory dataFactory;

private static Logger logger = LoggerFactory.getLogger(ObjectMapperProvider.class);

private static AtomicInteger mapperInstanceCount = new AtomicInteger();

@Inject
public ObjectMapperProvider() {
this.dataFactory = new OWLDataFactoryImpl();
Expand All @@ -35,6 +44,9 @@ public ObjectMapperProvider() {
@Override
public ObjectMapper get() {
ObjectMapper mapper = new ObjectMapper();
int instanceCount = mapperInstanceCount.incrementAndGet();
String msg = String.format("Instantiated another ObjectMappger#%08x, total: %d", mapper.hashCode(), instanceCount);
logger.info(msg);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setDefaultPrettyPrinter(new DefaultPrettyPrinter());
mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public ImmutableList<EntitySearchFilter> getSearchFilters(@Nonnull ProjectId pro
public void saveSearchFilters(@Nonnull ImmutableList<EntitySearchFilter> filters) {
try {
writeLock.lock();
if (filters.size() < 1)
return;
var writes = filters.stream()
.map(this::toMongoDocument)
.map(this::toReplaceOne)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
package edu.stanford.bmir.protege.web.server.sharing;

import static edu.stanford.bmir.protege.web.server.access.Subject.forAnySignedInUser;
import static edu.stanford.bmir.protege.web.server.access.Subject.forUser;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toMap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableSet;
import com.mongodb.DuplicateKeyException;

import edu.stanford.bmir.protege.web.server.access.AccessManager;
import edu.stanford.bmir.protege.web.server.access.ProjectResource;
import edu.stanford.bmir.protege.web.server.access.Subject;
Expand All @@ -12,16 +31,6 @@
import edu.stanford.bmir.protege.web.shared.sharing.SharingPermission;
import edu.stanford.bmir.protege.web.shared.sharing.SharingSetting;
import edu.stanford.bmir.protege.web.shared.user.UserId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.util.*;

import static edu.stanford.bmir.protege.web.server.access.Subject.forAnySignedInUser;
import static edu.stanford.bmir.protege.web.server.access.Subject.forUser;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toMap;

/**
* Matthew Horridge
Expand Down Expand Up @@ -66,12 +75,24 @@ public ProjectSharingSettings getProjectSharingSettings(ProjectId projectId) {

@Override
public void setProjectSharingSettings(ProjectSharingSettings settings) {
ProjectId projectId = settings.getProjectId();
ProjectResource projectResource = new ProjectResource(projectId);
ProjectId projectId = settings.getProjectId();
ProjectResource projectResource = new ProjectResource(projectId);

// Remove existing assignments
accessManager.getSubjectsWithAccessToResource(projectResource)
.forEach(subject -> accessManager.setAssignedRoles(subject, projectResource, Collections.emptySet()));
// Overwrite existing assignments with blank assignment
for (Subject subject : accessManager.getSubjectsWithAccessToResource(projectResource)) {
try {
logger.info("Subject: {}, resource: {}", subject, projectResource);
accessManager.setAssignedRoles(subject, projectResource, Collections.emptySet());
} catch (DuplicateKeyException e) {
// TODO: fix for intermittent 'E11000 duplicate key error collection:
// webprotege.RoleAssignments
// index: userName_1_projectId_1
// dup key: { userName: null, projectId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
// }'
String msg = String.format("Subject: %s, resource: %s", subject, projectResource);
logger.warn(msg, e);
}
}

Map<PersonId, SharingSetting> map = settings.getSharingSettings().stream()
.collect(toMap(SharingSetting::getPersonId, s -> s, (s1, s2) -> s1));
Expand All @@ -93,7 +114,7 @@ public void setProjectSharingSettings(ProjectSharingSettings settings) {
roles);
}
else {
logger.info("User in sharing setting not found. An email invitation needs to be sent");
logger.warn("User in sharing setting not found. An email invitation needs to be sent");
// TODO
// We need to send the user an email invitation
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public synchronized void saveTag(@Nonnull Tag tag) {
}

@Override
public synchronized void saveTags(@Nonnull Iterable<Tag> tags) {
public synchronized void saveTags(@Nonnull List<Tag> tags) {
delegate.saveTags(tags);
invalidate();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ private Document toDocument(@Nonnull Tag tag) {
return objectMapper.convertValue(tag, Document.class);
}

public void saveTags(@Nonnull Iterable<Tag> tags) {
public void saveTags(@Nonnull List<Tag> tags) {
writeLock.lock();
if (tags.size() < 1)
return;
try {
checkNotNull(tags);
Spliterator<Tag> spliterator = tags.spliterator();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
package edu.stanford.bmir.protege.web.server.api.resources;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;

import javax.annotation.Nonnull;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

import com.google.auto.factory.AutoFactory;
import com.google.auto.factory.Provided;
import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.stanford.bmir.protege.web.server.api.ActionExecutor;
import edu.stanford.bmir.protege.web.shared.crud.GetEntityCrudKitSettingsAction;
import edu.stanford.bmir.protege.web.shared.crud.IRIPrefixUpdateStrategy;
Expand All @@ -23,21 +39,14 @@
import edu.stanford.bmir.protege.web.shared.tag.TagData;
import edu.stanford.bmir.protege.web.shared.user.UserId;

import javax.annotation.Nonnull;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;

/**
* Matthew Horridge
* Stanford Center for Biomedical Informatics Research
* 2020-08-24
*/
public class ProjectSettingsResource {

protected static Logger logger = LoggerFactory.getLogger(ProjectSettingsResource.class);

@Nonnull
private final ProjectId projectId;
Expand Down Expand Up @@ -78,6 +87,16 @@ public Response getProjectSettings(@Context UserId userId) {
@POST
@Consumes(APPLICATION_JSON)
public Response setProjectSettings(@Context UserId userId, AllProjectSettings allProjectSettings) {
logger.info("Called setProjectSettings for projectId '{}'", this.projectId.getId());
try {
return _setProjectSettings(userId, allProjectSettings);
} catch (Exception e) {
logger.error("setProjectSettings failed", e);
throw e;
}
}

private Response _setProjectSettings(@Context UserId userId, AllProjectSettings allProjectSettings) {
var projectSettings = allProjectSettings.getProjectSettings().withProjectId(projectId);
actionExecutor.execute(new SetProjectSettingsAction(projectSettings), userId);

Expand Down

0 comments on commit 93cee38

Please sign in to comment.