From 7723405024be4d3a52f3dde3de2cf75e7cfb73c8 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Wed, 21 Feb 2018 17:15:15 -0500 Subject: [PATCH 1/4] Fix #859 - Remove unused import on com.sun.prism --- .../entity/ResourceIndexedSearchParamCoords.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java index daf9b0e7ae7..c6cd2d437c1 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamCoords.java @@ -20,24 +20,15 @@ package ca.uhn.fhir.jpa.entity; * #L% */ -import javax.persistence.Column; -import javax.persistence.Embeddable; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Index; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - import ca.uhn.fhir.model.api.IQueryParameterType; -import com.sun.prism.image.Coords; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.hibernate.search.annotations.Field; +import javax.persistence.*; + //@formatter:off @Embeddable @Entity From 3b2930f8e9a04e524fb731c20604461a4aa81d69 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Fri, 23 Feb 2018 15:24:20 -0500 Subject: [PATCH 2/4] Prevent a crash in testpage overlay when deleting a resource --- .../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 25 ++-- .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 32 ++--- .../uhn/fhir/jpa/entity/BaseHasResource.java | 1 + .../email/JavaMailEmailSender.java | 8 +- .../main/java/ca/uhn/fhir/to/Controller.java | 128 ++++++++++-------- src/changes/changes.xml | 4 + 6 files changed, 109 insertions(+), 89 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index 3a0fbe4b642..bb3ce1e6ec1 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -82,10 +82,11 @@ import java.util.Map.Entry; import static org.apache.commons.lang3.StringUtils.*; +@SuppressWarnings("WeakerAccess") public abstract class BaseHapiFhirDao implements IDao { - public static final long INDEX_STATUS_INDEXED = Long.valueOf(1L); - public static final long INDEX_STATUS_INDEXING_FAILED = Long.valueOf(2L); + public static final long INDEX_STATUS_INDEXED = 1L; + public static final long INDEX_STATUS_INDEXING_FAILED = 2L; public static final String NS_JPA_PROFILE = "https://github.com/jamesagnew/hapi-fhir/ns/jpa/profile"; public static final String OO_SEVERITY_ERROR = "error"; public static final String OO_SEVERITY_INFO = "information"; @@ -379,7 +380,7 @@ public abstract class BaseHapiFhirDao implements IDao { } else { ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, nextId, theUpdateTime); if (theLinks.add(resourceLink)) { - ourLog.info("Indexing remote resource reference URL: {}", nextId); + ourLog.debug("Indexing remote resource reference URL: {}", nextId); } continue; } @@ -417,7 +418,7 @@ public abstract class BaseHapiFhirDao implements IDao { IBaseResource newResource = missingResourceDef.newInstance(); newResource.setId(resName + "/" + id); IFhirResourceDao placeholderResourceDao = (IFhirResourceDao) getDao(newResource.getClass()); - ourLog.info("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue()); + ourLog.debug("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue()); valueOf = placeholderResourceDao.update(newResource).getEntity().getId(); } else { throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit); @@ -673,7 +674,7 @@ public abstract class BaseHapiFhirDao implements IDao { @SuppressWarnings("unchecked") public IFhirResourceDao getDao(Class theType) { if (myResourceTypeToDao == null) { - Map, IFhirResourceDao> theResourceTypeToDao = new HashMap, IFhirResourceDao>(); + Map, IFhirResourceDao> theResourceTypeToDao = new HashMap<>(); for (IFhirResourceDao next : myResourceDaos) { theResourceTypeToDao.put(next.getResourceType(), next); } @@ -1549,7 +1550,7 @@ public abstract class BaseHapiFhirDao implements IDao { } Long next = matches.iterator().next(); String newId = translatePidIdToForcedId(resourceTypeString, next); - ourLog.info("Replacing inline match URL[{}] with ID[{}}", nextId.getValue(), newId); + ourLog.debug("Replacing inline match URL[{}] with ID[{}}", nextId.getValue(), newId); nextRef.setReference(newId); } } @@ -1615,7 +1616,7 @@ public abstract class BaseHapiFhirDao implements IDao { } if (!changed.isChanged() && !theForceUpdate && myConfig.isSuppressUpdatesWithNoChange()) { - ourLog.info("Resource {} has not changed", theEntity.getIdDt().toUnqualified().getValue()); + ourLog.debug("Resource {} has not changed", theEntity.getIdDt().toUnqualified().getValue()); if (theResource != null) { populateResourceIdFromEntity(theEntity, theResource); } @@ -1657,7 +1658,7 @@ public abstract class BaseHapiFhirDao implements IDao { historyEntry.setEncoding(changed.getEncoding()); historyEntry.setResource(changed.getResource()); - ourLog.info("Saving history entry {}", historyEntry.getIdDt()); + ourLog.debug("Saving history entry {}", historyEntry.getIdDt()); myResourceHistoryTableDao.save(historyEntry); } @@ -1765,7 +1766,7 @@ public abstract class BaseHapiFhirDao implements IDao { // Store composite string uniques if (getConfig().isUniqueIndexesEnabled()) { for (ResourceIndexedCompositeStringUnique next : removeCommon(existingCompositeStringUniques, compositeStringUniques)) { - ourLog.info("Removing unique index: {}", next); + ourLog.debug("Removing unique index: {}", next); myEntityManager.remove(next); theEntity.getParamsCompositeStringUnique().remove(next); } @@ -1776,7 +1777,7 @@ public abstract class BaseHapiFhirDao implements IDao { throw new PreconditionFailedException("Can not create resource of type " + theEntity.getResourceType() + " as it would create a duplicate index matching query: " + next.getIndexString() + " (existing index belongs to " + existing.getResource().getIdDt().toUnqualifiedVersionless().getValue() + ")"); } } - ourLog.info("Persisting unique index: {}", next); + ourLog.debug("Persisting unique index: {}", next); myEntityManager.persist(next); } } @@ -1821,7 +1822,7 @@ public abstract class BaseHapiFhirDao implements IDao { if (nextChildDef instanceof RuntimeChildResourceDefinition) { RuntimeChildResourceDefinition nextChildDefRes = (RuntimeChildResourceDefinition) nextChildDef; - Set validTypes = new HashSet(); + Set validTypes = new HashSet<>(); boolean allowAny = false; for (Class nextValidType : nextChildDefRes.getResourceTypes()) { if (nextValidType.isInterface()) { @@ -2147,7 +2148,7 @@ public abstract class BaseHapiFhirDao implements IDao { } if (forcedId.isEmpty() == false) { - List retVal = new ArrayList(forcedId.size()); + List retVal = new ArrayList<>(forcedId.size()); for (ForcedId next : forcedId) { retVal.add(next.getResourcePid()); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 9c26432e15c..4aa6732ec02 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -127,7 +127,7 @@ public abstract class BaseHapiFhirResourceDao extends B } } - ourLog.info("Processed addTag {}/{} on {} in {}ms", theScheme, theTerm, theId, w.getMillisAndRestart()); + ourLog.debug("Processed addTag {}/{} on {} in {}ms", theScheme, theTerm, theId, w.getMillisAndRestart()); } @Override @@ -273,7 +273,7 @@ public abstract class BaseHapiFhirResourceDao extends B validateDeleteConflictsEmptyOrThrowException(deleteConflicts); - ourLog.info("Processed delete on {} in {}ms", theId.getValue(), w.getMillisAndRestart()); + ourLog.debug("Processed delete on {} in {}ms", theId.getValue(), w.getMillisAndRestart()); return retVal; } @@ -350,7 +350,7 @@ public abstract class BaseHapiFhirResourceDao extends B OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code); } - ourLog.info("Processed delete on {} (matched {} resource(s)) in {}ms", theUrl, deletedResources.size(), w.getMillis()); + ourLog.debug("Processed delete on {} (matched {} resource(s)) in {}ms", theUrl, deletedResources.size(), w.getMillis()); DeleteMethodOutcome retVal = new DeleteMethodOutcome(); retVal.setDeletedEntities(deletedResources); @@ -462,7 +462,7 @@ public abstract class BaseHapiFhirResourceDao extends B String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart()); outcome.setOperationOutcome(createInfoOperationOutcome(msg)); - ourLog.info(msg); + ourLog.debug(msg); return outcome; } @@ -530,7 +530,7 @@ public abstract class BaseHapiFhirResourceDao extends B StopWatch w = new StopWatch(); TagList tags = super.getTags(myResourceType, null); - ourLog.info("Processed getTags on {} in {}ms", myResourceName, w.getMillisAndRestart()); + ourLog.debug("Processed getTags on {} in {}ms", myResourceName, w.getMillisAndRestart()); return tags; } @@ -557,7 +557,7 @@ public abstract class BaseHapiFhirResourceDao extends B StopWatch w = new StopWatch(); TagList retVal = super.getTags(myResourceType, theResourceId); - ourLog.info("Processed getTags on {} in {}ms", theResourceId, w.getMillisAndRestart()); + ourLog.debug("Processed getTags on {} in {}ms", theResourceId, w.getMillisAndRestart()); return retVal; } @@ -569,7 +569,7 @@ public abstract class BaseHapiFhirResourceDao extends B StopWatch w = new StopWatch(); IBundleProvider retVal = super.history(myResourceName, null, theSince, theUntil); - ourLog.info("Processed history on {} in {}ms", myResourceName, w.getMillisAndRestart()); + ourLog.debug("Processed history on {} in {}ms", myResourceName, w.getMillisAndRestart()); return retVal; } @@ -586,7 +586,7 @@ public abstract class BaseHapiFhirResourceDao extends B IBundleProvider retVal = super.history(myResourceName, entity.getId(), theSince, theUntil); - ourLog.info("Processed history on {} in {}ms", id, w.getMillisAndRestart()); + ourLog.debug("Processed history on {} in {}ms", id, w.getMillisAndRestart()); return retVal; } @@ -622,7 +622,7 @@ public abstract class BaseHapiFhirResourceDao extends B if (myDaoConfig.isMarkResourcesForReindexingUponSearchParameterChange()) { if (isNotBlank(theExpression)) { final String resourceType = theExpression.substring(0, theExpression.indexOf('.')); - ourLog.info("Marking all resources of type {} for reindexing due to updated search parameter with path: {}", resourceType, theExpression); + ourLog.debug("Marking all resources of type {} for reindexing due to updated search parameter with path: {}", resourceType, theExpression); TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); @@ -633,7 +633,7 @@ public abstract class BaseHapiFhirResourceDao extends B } }); - ourLog.info("Marked {} resources for reindexing", updatedCount); + ourLog.debug("Marked {} resources for reindexing", updatedCount); } } @@ -665,7 +665,7 @@ public abstract class BaseHapiFhirResourceDao extends B doMetaAdd(theMetaAdd, history); } - ourLog.info("Processed metaAddOperation on {} in {}ms", new Object[]{theResourceId, w.getMillisAndRestart()}); + ourLog.debug("Processed metaAddOperation on {} in {}ms", new Object[]{theResourceId, w.getMillisAndRestart()}); @SuppressWarnings("unchecked") MT retVal = (MT) metaGetOperation(theMetaAdd.getClass(), theResourceId, theRequestDetails); @@ -699,7 +699,7 @@ public abstract class BaseHapiFhirResourceDao extends B myEntityManager.flush(); - ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[]{theResourceId.getValue(), w.getMillisAndRestart()}); + ourLog.debug("Processed metaDeleteOperation on {} in {}ms", new Object[]{theResourceId.getValue(), w.getMillisAndRestart()}); @SuppressWarnings("unchecked") MT retVal = (MT) metaGetOperation(theMetaDel.getClass(), theResourceId, theRequestDetails); @@ -864,7 +864,7 @@ public abstract class BaseHapiFhirResourceDao extends B throw new ResourceGoneException("Resource was deleted at " + deleted.getValueAsString()); } - ourLog.info("Processed read on {} in {}ms", theId.getValue(), w.getMillisAndRestart()); + ourLog.debug("Processed read on {} in {}ms", theId.getValue(), w.getMillisAndRestart()); return retVal; } @@ -968,7 +968,7 @@ public abstract class BaseHapiFhirResourceDao extends B myEntityManager.merge(entity); - ourLog.info("Processed remove tag {}/{} on {} in {}ms", theScheme, theTerm, theId.getValue(), w.getMillisAndRestart()); + ourLog.debug("Processed remove tag {}/{} on {} in {}ms", theScheme, theTerm, theId.getValue(), w.getMillisAndRestart()); } @Transactional(propagation = Propagation.SUPPORTS) @@ -1282,7 +1282,7 @@ public abstract class BaseHapiFhirResourceDao extends B String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart()); outcome.setOperationOutcome(createInfoOperationOutcome(msg)); - ourLog.info(msg); + ourLog.debug(msg); return outcome; } @@ -1339,7 +1339,7 @@ public abstract class BaseHapiFhirResourceDao extends B } if (myDaoConfig.isEnforceReferentialIntegrityOnDelete() == false && !theForValidate) { - ourLog.info("Deleting {} resource dependencies which can no longer be satisfied", resultList.size()); + ourLog.debug("Deleting {} resource dependencies which can no longer be satisfied", resultList.size()); myResourceLinkDao.delete(resultList); return; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseHasResource.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseHasResource.java index a3f69dc64c3..c185e45e751 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseHasResource.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseHasResource.java @@ -36,6 +36,7 @@ public abstract class BaseHasResource { @Temporal(TemporalType.TIMESTAMP) private Date myDeleted; + // TODO: move to resource history table @Column(name = "RES_VERSION", nullable = true, length = 7) @Enumerated(EnumType.STRING) @OptimisticLock(excluded = true) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/email/JavaMailEmailSender.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/email/JavaMailEmailSender.java index 0ef87197a5a..8daf3a375e2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/email/JavaMailEmailSender.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/email/JavaMailEmailSender.java @@ -95,7 +95,6 @@ public class JavaMailEmailSender implements IEmailSender { @Override public void send(EmailDetails theDetails) { String subscriptionId = theDetails.getSubscription().toUnqualifiedVersionless().getValue(); - ourLog.info("Sending email for subscription {} to recipients: {}", subscriptionId, theDetails.getTo()); StopWatch sw = new StopWatch(); StringTemplateResolver templateResolver = new StringTemplateResolver(); @@ -116,15 +115,18 @@ public class JavaMailEmailSender implements IEmailSender { MimeMessage email = mySender.createMimeMessage(); + String from = trim(theDetails.getFrom()); + ourLog.info("Sending email for subscription {} from [{}] to recipients: [{}]", subscriptionId, from, theDetails.getTo()); + try { - email.setFrom(trim(theDetails.getFrom())); + email.setFrom(from); email.setRecipients(Message.RecipientType.TO, toTrimmedCommaSeparatedString(theDetails.getTo())); email.setSubject(subject); email.setText(body); email.setSentDate(new Date()); email.addHeader("X-FHIR-Subscription", subscriptionId); } catch (MessagingException e) { - throw new InternalErrorException("Failed to create email messaage", e); + throw new InternalErrorException("Failed to create email message", e); } mySender.send(email); diff --git a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java index bddc2103bff..54f95e22e24 100644 --- a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java +++ b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/Controller.java @@ -96,27 +96,29 @@ public class Controller extends BaseController { } @RequestMapping(value = { "/delete" }) - public String actionDelete(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) { - addCommonParams(theReq, theRequest, theModel); + public String actionDelete(HttpServletRequest theServletRequest, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) { + addCommonParams(theServletRequest, theRequest, theModel); CaptureInterceptor interceptor = new CaptureInterceptor(); - GenericClient client = theRequest.newClient(theReq, getContext(theRequest), myConfig, interceptor); + GenericClient client = theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor); RuntimeResourceDefinition def; try { - def = getResourceType(theRequest, theReq); + def = getResourceType(theRequest, theServletRequest); } catch (ServletException e) { + populateModelForResource(theServletRequest, theRequest, theModel); theModel.put("errorMsg", toDisplayError(e.toString(), e)); return "resource"; } - String id = StringUtils.defaultString(theReq.getParameter("resource-delete-id")); + String id = StringUtils.defaultString(theServletRequest.getParameter("resource-delete-id")); if (StringUtils.isBlank(id)) { + populateModelForResource(theServletRequest, theRequest, theModel); theModel.put("errorMsg", toDisplayError("No ID specified", null)); return "resource"; } - ResultType returnsResource = ResultType.BUNDLE; + ResultType returnsResource = ResultType.RESOURCE; String outcomeDescription = "Delete Resource"; long start = System.currentTimeMillis(); @@ -192,27 +194,29 @@ public class Controller extends BaseController { } @RequestMapping(value = { "/read" }) - public String actionRead(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) { - addCommonParams(theReq, theRequest, theModel); + public String actionRead(HttpServletRequest theServletRequest, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) { + addCommonParams(theServletRequest, theRequest, theModel); CaptureInterceptor interceptor = new CaptureInterceptor(); - GenericClient client = theRequest.newClient(theReq, getContext(theRequest), myConfig, interceptor); + GenericClient client = theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor); RuntimeResourceDefinition def; try { - def = getResourceType(theRequest, theReq); + def = getResourceType(theRequest, theServletRequest); } catch (ServletException e) { + populateModelForResource(theServletRequest, theRequest, theModel); theModel.put("errorMsg", toDisplayError(e.toString(), e)); return "resource"; } - String id = StringUtils.defaultString(theReq.getParameter("id")); + String id = StringUtils.defaultString(theServletRequest.getParameter("id")); if (StringUtils.isBlank(id)) { + populateModelForResource(theServletRequest, theRequest, theModel); theModel.put("errorMsg", toDisplayError("No ID specified", null)); return "resource"; } ResultType returnsResource = ResultType.RESOURCE; - String versionId = StringUtils.defaultString(theReq.getParameter("vid")); + String versionId = StringUtils.defaultString(theServletRequest.getParameter("vid")); String outcomeDescription; if (StringUtils.isBlank(versionId)) { versionId = null; @@ -242,45 +246,18 @@ public class Controller extends BaseController { @RequestMapping({ "/resource" }) public String actionResource(HttpServletRequest theServletRequest, final ResourceRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) { - IBaseResource conformance = addCommonParams(theServletRequest, theRequest, theModel); - - CaptureInterceptor interceptor = new CaptureInterceptor(); - GenericClient client = theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor); String resourceName = theRequest.getResource(); - RuntimeResourceDefinition def = getContext(theRequest).getResourceDefinition(theRequest.getResource()); - TreeSet includes = new TreeSet(); - TreeSet revIncludes = new TreeSet(); - TreeSet sortParams = new TreeSet(); - boolean haveSearchParams = false; - List> queryIncludes = new ArrayList>(); - - switch (theRequest.getFhirVersion(myConfig)) { - case DSTU2: - haveSearchParams = extractSearchParamsDstu2(conformance, resourceName, includes, revIncludes, sortParams, haveSearchParams, queryIncludes); - break; - case DSTU3: - haveSearchParams = extractSearchParamsDstu3CapabilityStatement(conformance, resourceName, includes, revIncludes, sortParams, haveSearchParams, queryIncludes); - break; - case R4: - haveSearchParams = extractSearchParamsR4CapabilityStatement(conformance, resourceName, includes, revIncludes, sortParams, haveSearchParams, queryIncludes); - break; - default: - throw new IllegalStateException("Unknown FHIR version: " + theRequest.getFhirVersion(myConfig)); - } - - theModel.put("includes", includes); - theModel.put("revincludes", revIncludes); - theModel.put("queries", Collections.emptyList()); // TODO: remove this, it does nothing - theModel.put("haveSearchParams", haveSearchParams); - theModel.put("queryIncludes", queryIncludes); - theModel.put("sortParams", sortParams); + populateModelForResource(theServletRequest, theRequest, theModel); if (isNotBlank(theRequest.getUpdateId())) { String updateId = theRequest.getUpdateId(); String updateVid = defaultIfEmpty(theRequest.getUpdateVid(), null); - IBaseResource updateResource = (IBaseResource) client.read(def.getImplementingClass(), new IdDt(resourceName, updateId, updateVid)); + CaptureInterceptor interceptor = new CaptureInterceptor(); + GenericClient client = theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor); + RuntimeResourceDefinition def = getContext(theRequest).getResourceDefinition(theRequest.getResource()); + IBaseResource updateResource = client.read(def.getImplementingClass(), new IdDt(resourceName, updateId, updateVid)); String updateResourceString = theRequest.newParser(getContext(theRequest)).setPrettyPrint(true).encodeResourceToString(updateResource); theModel.put("updateResource", updateResourceString); theModel.put("updateResourceId", updateId); @@ -291,10 +268,43 @@ public class Controller extends BaseController { return "resource"; } + private void populateModelForResource(HttpServletRequest theServletRequest, HomeRequest theRequest, ModelMap theModel) { + IBaseResource conformance = addCommonParams(theServletRequest, theRequest, theModel); + + String resourceName = theRequest.getResource(); + + TreeSet includes = new TreeSet<>(); + TreeSet revIncludes = new TreeSet<>(); + TreeSet sortParams = new TreeSet<>(); + boolean haveSearchParams = false; + List> queryIncludes = new ArrayList<>(); + + switch (theRequest.getFhirVersion(myConfig)) { + case DSTU2: + haveSearchParams = extractSearchParamsDstu2(conformance, resourceName, includes, revIncludes, sortParams, haveSearchParams, queryIncludes); + break; + case DSTU3: + haveSearchParams = extractSearchParamsDstu3CapabilityStatement(conformance, resourceName, includes, revIncludes, sortParams, haveSearchParams, queryIncludes); + break; + case R4: + haveSearchParams = extractSearchParamsR4CapabilityStatement(conformance, resourceName, includes, revIncludes, sortParams, haveSearchParams, queryIncludes); + break; + default: + throw new IllegalStateException("Unknown FHIR version: " + theRequest.getFhirVersion(myConfig)); + } + + theModel.put("includes", includes); + theModel.put("revincludes", revIncludes); + theModel.put("queries", Collections.emptyList()); // TODO: remove this, it does nothing + theModel.put("haveSearchParams", haveSearchParams); + theModel.put("queryIncludes", queryIncludes); + theModel.put("sortParams", sortParams); + } + @SuppressWarnings("unchecked") @RequestMapping(value = { "/search" }) - public String actionSearch(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) throws IOException { - addCommonParams(theReq, theRequest, theModel); + public String actionSearch(HttpServletRequest theServletRequest, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel) throws IOException { + addCommonParams(theServletRequest, theRequest, theModel); StringWriter clientCodeJsonStringWriter = new StringWriter(); JsonWriter clientCodeJsonWriter = new JsonWriter(clientCodeJsonStringWriter); @@ -305,19 +315,20 @@ public class Controller extends BaseController { clientCodeJsonWriter.value((String) theModel.get("base")); CaptureInterceptor interceptor = new CaptureInterceptor(); - GenericClient client = theRequest.newClient(theReq, getContext(theRequest), myConfig, interceptor); + GenericClient client = theRequest.newClient(theServletRequest, getContext(theRequest), myConfig, interceptor); IUntypedQuery search = client.search(); IQuery query; - if (isNotBlank(theReq.getParameter("resource"))) { + if (isNotBlank(theServletRequest.getParameter("resource"))) { try { - query = search.forResource((Class) getResourceType(theRequest, theReq).getImplementingClass()); + query = search.forResource(getResourceType(theRequest, theServletRequest).getImplementingClass()); } catch (ServletException e) { + populateModelForResource(theServletRequest, theRequest, theModel); theModel.put("errorMsg", toDisplayError(e.toString(), e)); return "resource"; } clientCodeJsonWriter.name("resource"); - clientCodeJsonWriter.value(theReq.getParameter("resource")); + clientCodeJsonWriter.value(theServletRequest.getParameter("resource")); } else { query = search.forAllResources(); clientCodeJsonWriter.name("resource"); @@ -349,7 +360,7 @@ public class Controller extends BaseController { paramIdx++; String paramIdxString = Integer.toString(paramIdx); - boolean shouldContinue = handleSearchParam(paramIdxString, theReq, query, clientCodeJsonWriter); + boolean shouldContinue = handleSearchParam(paramIdxString, theServletRequest, query, clientCodeJsonWriter); if (!shouldContinue) { break; } @@ -358,7 +369,7 @@ public class Controller extends BaseController { clientCodeJsonWriter.name("includes"); clientCodeJsonWriter.beginArray(); - String[] incValues = theReq.getParameterValues(Constants.PARAM_INCLUDE); + String[] incValues = theServletRequest.getParameterValues(Constants.PARAM_INCLUDE); if (incValues != null) { for (String next : incValues) { if (isNotBlank(next)) { @@ -371,7 +382,7 @@ public class Controller extends BaseController { clientCodeJsonWriter.name("revincludes"); clientCodeJsonWriter.beginArray(); - String[] revIncValues = theReq.getParameterValues(Constants.PARAM_REVINCLUDE); + String[] revIncValues = theServletRequest.getParameterValues(Constants.PARAM_REVINCLUDE); if (revIncValues != null) { for (String next : revIncValues) { if (isNotBlank(next)) { @@ -382,9 +393,10 @@ public class Controller extends BaseController { } clientCodeJsonWriter.endArray(); - String limit = theReq.getParameter("resource-search-limit"); + String limit = theServletRequest.getParameter("resource-search-limit"); if (isNotBlank(limit)) { if (!limit.matches("[0-9]+")) { + populateModelForResource(theServletRequest, theRequest, theModel); theModel.put("errorMsg", toDisplayError("Search limit must be a numeric value.", null)); return "resource"; } @@ -397,13 +409,13 @@ public class Controller extends BaseController { clientCodeJsonWriter.nullValue(); } - String[] sort = theReq.getParameterValues("sort_by"); + String[] sort = theServletRequest.getParameterValues("sort_by"); if (sort != null) { for (String next : sort) { if (isBlank(next)) { continue; } - String direction = theReq.getParameter("sort_direction"); + String direction = theServletRequest.getParameter("sort_direction"); if ("asc".equals(direction)) { query.sort().ascending(new StringClientParam(next)); } else if ("desc".equals(direction)) { @@ -505,7 +517,7 @@ public class Controller extends BaseController { Class type = null; // def.getImplementingClass(); if ("history-type".equals(theMethod)) { RuntimeResourceDefinition def = getContext(theRequest).getResourceDefinition(theRequest.getResource()); - type = (Class) def.getImplementingClass(); + type = def.getImplementingClass(); } String body = validate ? theReq.getParameter("resource-validate-body") : theReq.getParameter("resource-create-body"); @@ -588,7 +600,7 @@ public class Controller extends BaseController { Class type = null; // def.getImplementingClass(); if ("history-type".equals(theMethod)) { RuntimeResourceDefinition def = getContext(theRequest).getResourceDefinition(theRequest.getResource()); - type = (Class) def.getImplementingClass(); + type = def.getImplementingClass(); id = StringUtils.defaultString(theReq.getParameter("resource-history-id")); } diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c09699b15df..23ba44523ed 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -150,6 +150,10 @@ elements of type "Reference". Thanks to GitHub user @t4deon for supplying a testcase! + + Deleting a resource from the testpage overlay resulted in an error page after + clicking "delete", even though the delete succeeded. + From 6e479512206c7512808d14fc38dbf43f6b74d0f6 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Sat, 24 Feb 2018 10:57:32 -0500 Subject: [PATCH 3/4] Remove unneccesary log lines and clean up some documentation --- .../uhn/fhir/parser/IParserErrorHandler.java | 6 ++--- .../java/ca/uhn/fhir/parser/JsonParser.java | 2 +- .../ca/uhn/fhir/parser/ParseLocation.java | 12 ++++++--- .../java/ca/uhn/fhir/parser/ParserState.java | 2 +- .../uhn/fhir/cli/ValidationDataUploader.java | 27 ++++++++++--------- src/changes/changes.xml | 4 +++ 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java index 485311e5736..f7562c95b92 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParserErrorHandler.java @@ -55,7 +55,7 @@ public interface IParserErrorHandler { void incorrectJsonType(IParseLocation theLocation, String theElementName, ValueType theExpectedValueType, ScalarType theExpectedScalarType, ValueType theFoundValueType, ScalarType theFoundScalarType); /** - * The parser detected an atttribute value that was invalid (such as: empty "" values are not permitted) + * The parser detected an attribute value that was invalid (such as: empty "" values are not permitted) * * @param theLocation * The location in the document. Note that this may be null as the ParseLocation feature is experimental. Use with caution, as the API may change. @@ -70,7 +70,7 @@ public interface IParserErrorHandler { * * @param theLocation * The location in the document. Note that this may be null as the ParseLocation feature is experimental. Use with caution, as the API may change. - * @param theReference The actual invalid reference (e.g. "#3") + * @param theElementName The missing element name * @since 2.1 */ void missingRequiredElement(IParseLocation theLocation, String theElementName); @@ -123,7 +123,7 @@ public interface IParserErrorHandler { * type which will currently always be set to null. This interface is included here so that * locations can be added to the API in a future release without changing the API. */ - public interface IParseLocation { + interface IParseLocation { /** * Returns the name of the parent element (the element containing the element currently being parsed) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index b8fff2e30d4..d56aff6e5d2 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -1033,7 +1033,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { } else { parentElementName = "extension"; } - getErrorHandler().missingRequiredElement(new ParseLocation(parentElementName), "url"); + getErrorHandler().missingRequiredElement(new ParseLocation().setParentElementName(parentElementName), "url"); url = null; } else { url = getExtensionUrl(jsonElement.getAsString()); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParseLocation.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParseLocation.java index 8df9a37aa96..b493edc0bd1 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParseLocation.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParseLocation.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.parser; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -29,9 +29,8 @@ class ParseLocation implements IParseLocation { /** * Constructor */ - public ParseLocation(String theParentElementName) { + public ParseLocation() { super(); - myParentElementName = theParentElementName; } @Override @@ -39,4 +38,9 @@ class ParseLocation implements IParseLocation { return myParentElementName; } + public ParseLocation setParentElementName(String theParentElementName) { + myParentElementName = theParentElementName; + return this; + } + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java index b4c6d6db00f..6f4c5d02ad6 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java @@ -806,7 +806,7 @@ class ParserState { @SuppressWarnings("unchecked") List securityLabels = (List) myMap.get(ResourceMetadataKeyEnum.SECURITY_LABELS); if (securityLabels == null) { - securityLabels = new ArrayList(); + securityLabels = new ArrayList<>(); myMap.put(ResourceMetadataKeyEnum.SECURITY_LABELS, securityLabels); } IBase securityLabel = myContext.getVersion().newCodingDt(); diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java index 5025b098918..74d0b28d5fc 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; import ca.uhn.fhir.model.dstu2.resource.StructureDefinition; import ca.uhn.fhir.model.dstu2.resource.ValueSet; import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; @@ -163,7 +164,7 @@ public class ValidationDataUploader extends BaseCommand { ValueSet next = (ValueSet) i.getResource(); next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading ValueSet {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; @@ -182,7 +183,7 @@ public class ValidationDataUploader extends BaseCommand { ValueSet next = (ValueSet) i.getResource(); next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; @@ -200,7 +201,7 @@ public class ValidationDataUploader extends BaseCommand { ValueSet next = (ValueSet) i.getResource(); next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; } @@ -225,7 +226,7 @@ public class ValidationDataUploader extends BaseCommand { } next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); try { client.update().resource(next).execute(); } catch (Exception e) { @@ -268,12 +269,14 @@ public class ValidationDataUploader extends BaseCommand { int bytes = ctx.newXmlParser().encodeResourceToString(next).length(); - ourLog.info("Uploading ValueSet {}/{} : {} ({} bytes}", new Object[]{count, total, next.getIdElement().getValue(), bytes}); + ourLog.info("Uploading ValueSet {}/{} : {} ({} bytes}", new Object[] {count, total, next.getIdElement().getValue(), bytes}); try { IIdType id = client.update().resource(next).execute().getId(); ourLog.info(" - Got ID: {}", id.getValue()); } catch (UnprocessableEntityException e) { ourLog.warn("UnprocessableEntityException: " + e.toString()); + } catch (BaseServerResponseException e) { + ourLog.warn("Server responded HTTP " + e.getStatusCode() + ": " + e.toString()); } count++; } @@ -293,7 +296,7 @@ public class ValidationDataUploader extends BaseCommand { org.hl7.fhir.dstu3.model.Resource next = i.getResource(); next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); try { client.update().resource(next).execute(); } catch (Exception e) { @@ -318,7 +321,7 @@ public class ValidationDataUploader extends BaseCommand { } next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; } @@ -364,7 +367,7 @@ public class ValidationDataUploader extends BaseCommand { int bytes = theCtx.newXmlParser().encodeResourceToString(next).length(); - ourLog.info("Uploading ValueSet {}/{} : {} ({} bytes}", new Object[]{count, total, next.getIdElement().getValue(), bytes}); + ourLog.info("Uploading ValueSet {}/{} : {} ({} bytes}", new Object[] {count, total, next.getIdElement().getValue(), bytes}); try { IIdType id = client.update().resource(next).execute().getId(); ourLog.info(" - Got ID: {}", id.getValue()); @@ -388,7 +391,7 @@ public class ValidationDataUploader extends BaseCommand { org.hl7.fhir.r4.model.Resource next = i.getResource(); next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; @@ -410,7 +413,7 @@ public class ValidationDataUploader extends BaseCommand { } next.setId(next.getIdElement().toUnqualifiedVersionless()); - ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[]{count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading v2-tables ValueSet {}/{} : {}", new Object[] {count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; } @@ -470,7 +473,7 @@ public class ValidationDataUploader extends BaseCommand { continue; } - ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[]{name, count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[] {name, count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; @@ -518,7 +521,7 @@ public class ValidationDataUploader extends BaseCommand { continue; } - ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[]{name, count, total, next.getIdElement().getValue()}); + ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[] {name, count, total, next.getIdElement().getValue()}); client.update().resource(next).execute(); count++; diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 23ba44523ed..a70dfd42f3b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -154,6 +154,10 @@ Deleting a resource from the testpage overlay resulted in an error page after clicking "delete", even though the delete succeeded. + + A number of info level log lines have been reduced to debug level in the JPA server, in + order to reduce contention during heavy loads. + From 9757f58805d7b6fe86ff6cb0277727f525ceed12 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Sat, 24 Feb 2018 12:01:51 -0500 Subject: [PATCH 4/4] Improve tolerance of errors when uploading validation resources --- .../main/java/ca/uhn/fhir/cli/ValidationDataUploader.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java index 74d0b28d5fc..f57946927a1 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ValidationDataUploader.java @@ -522,7 +522,11 @@ public class ValidationDataUploader extends BaseCommand { } ourLog.info("Uploading {} StructureDefinition {}/{} : {}", new Object[] {name, count, total, next.getIdElement().getValue()}); - client.update().resource(next).execute(); + try { + client.update().resource(next).execute(); + } catch (BaseServerResponseException e) { + ourLog.warn("Server responded HTTP " + e.getStatusCode() + ": " + e.toString()); + } count++; }