Add skeleton for the $process-message operation in JPA erver

This commit is contained in:
James Agnew 2018-07-12 17:52:24 -04:00
parent e992043a22
commit 03e7b018a6
22 changed files with 2045 additions and 1568 deletions

View File

@ -1103,7 +1103,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
@SuppressWarnings("unchecked")
@Override
public Object execute() {
if (myOperationName != null && myOperationName.equals(Constants.EXTOP_PROCESS_MESSAGE)) {
if (myOperationName != null && myOperationName.equals(Constants.EXTOP_PROCESS_MESSAGE) && myMsgBundle != null) {
Map<String, List<String>> urlParams = new LinkedHashMap<String, List<String>>();
// Set Url parameter Async and Response-Url
if (myIsAsync != null) {

View File

@ -57,17 +57,6 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
private IIdType myForceResourceId;
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, Map<String, List<String>> theParams, String... theUrlPath) {
super(theContext);
myResource = theResource;
myUrlPath = StringUtils.join(theUrlPath, '/');
myResources = null;
myContents = null;
myParams = theParams;
myBundleType = null;
}
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, String theUrlPath) {
super(theContext);
myResource = theResource;
@ -105,17 +94,6 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
myBundleType = null;
}
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, Map<String, List<String>> theParams, String... theUrlPath) {
super(theContext);
myResource = null;
myUrlPath = StringUtils.join(theUrlPath, '/');
myResources = null;
myContents = theContents;
myParams = theParams;
myBundleType = null;
}
@Override
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) throws DataFormatException {
StringBuilder url = new StringBuilder();

View File

@ -0,0 +1,38 @@
package ca.uhn.fhir.jpa.dao;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.model.dstu2.resource.MessageHeader;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import org.hl7.fhir.instance.model.api.IBaseBundle;
public class FhirResourceDaoMessageHeaderDstu2 extends FhirResourceDaoDstu2<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
@Override
public IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
}
public static IBaseBundle throwProcessMessageNotImplemented() {
throw new NotImplementedOperationException("This operation is not yet implemented on this server");
}
}

View File

@ -0,0 +1,31 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public interface IFhirResourceDaoMessageHeader<T extends IBaseResource> extends IFhirResourceDao<T> {
IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage);
}

View File

@ -0,0 +1,36 @@
package ca.uhn.fhir.jpa.dao.dstu3;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.dstu3.model.MessageHeader;
import org.hl7.fhir.instance.model.api.IBaseBundle;
public class FhirResourceDaoMessageHeaderDstu3 extends FhirResourceDaoDstu3<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
@Override
public IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
}
}

View File

@ -0,0 +1,36 @@
package ca.uhn.fhir.jpa.dao.r4;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.r4.model.MessageHeader;
public class FhirResourceDaoMessageHeaderR4 extends FhirResourceDaoR4<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
@Override
public IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
}
}

View File

@ -187,7 +187,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
*/
@Override
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<>();
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
for (RuntimeSearchParam nextSpDef : searchParams) {
@ -290,7 +290,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
*/
@Override
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<>();
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
for (RuntimeSearchParam nextSpDef : searchParams) {
@ -354,7 +354,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
*/
@Override
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<>();
String resourceName = getContext().getResourceDefinition(theResource).getName();
@ -397,7 +397,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
addSearchTerm(theEntity, retVal, nextSpName, searchTerm);
} else {
if (nextObject instanceof HumanName) {
ArrayList<StringType> allNames = new ArrayList<StringType>();
ArrayList<StringType> allNames = new ArrayList<>();
HumanName nextHumanName = (HumanName) nextObject;
if (isNotBlank(nextHumanName.getFamily())) {
allNames.add(nextHumanName.getFamilyElement());
@ -407,7 +407,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
}
} else if (nextObject instanceof Address) {
ArrayList<StringType> allNames = new ArrayList<StringType>();
ArrayList<StringType> allNames = new ArrayList<>();
Address nextAddress = (Address) nextObject;
allNames.addAll(nextAddress.getLine());
allNames.add(nextAddress.getCityElement());
@ -573,7 +573,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
assert systems.size() == codes.size() : "Systems contains " + systems + ", codes contains: " + codes;
Set<Pair<String, String>> haveValues = new HashSet<Pair<String, String>>();
Set<Pair<String, String>> haveValues = new HashSet<>();
for (int i = 0; i < systems.size(); i++) {
String system = systems.get(i);
String code = codes.get(i);
@ -608,7 +608,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
@Override
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<ResourceIndexedSearchParamUri>();
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<>();
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
for (RuntimeSearchParam nextSpDef : searchParams) {
@ -690,7 +690,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
IWorkerContext worker = new org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext(getContext(), myValidationSupport);
FHIRPathEngine fp = new FHIRPathEngine(worker);
List<Object> values = new ArrayList<Object>();
List<Object> values = new ArrayList<>();
try {
String[] nextPathsSplit = SPLIT.split(thePaths);
for (String nextPath : nextPathsSplit) {
@ -717,7 +717,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
@Override
public List<PathAndRef> extractResourceLinks(IBaseResource theResource, RuntimeSearchParam theNextSpDef) {
ArrayList<PathAndRef> retVal = new ArrayList<PathAndRef>();
ArrayList<PathAndRef> retVal = new ArrayList<>();
String[] nextPathsSplit = SPLIT.split(theNextSpDef.getPath());
for (String path : nextPathsSplit) {

View File

@ -24,16 +24,19 @@ import org.hibernate.annotations.ColumnDefault;
import javax.persistence.*;
//@formatter:off
@Entity()
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = {
@UniqueConstraint(name = "IDX_FORCEDID_RESID", columnNames = {"RESOURCE_PID"}),
@UniqueConstraint(name = "IDX_FORCEDID_TYPE_RESID", columnNames = {"RESOURCE_TYPE", "RESOURCE_PID"}),
@UniqueConstraint(name = "IDX_FORCEDID_TYPE_FID", columnNames = {"RESOURCE_TYPE", "FORCED_ID"})
}, indexes = {
@Index(name = "IDX_FORCEDID_TYPE_FORCEDID", columnList = "RESOURCE_TYPE,FORCED_ID"),
/*
* NB: We previously had indexes named
* - IDX_FORCEDID_TYPE_FORCEDID
* - IDX_FORCEDID_TYPE_RESID
* so don't reuse these names
*/
})
//@formatter:on
public class ForcedId {
public static final int MAX_FORCED_ID_LENGTH = 100;

View File

@ -0,0 +1,61 @@
package ca.uhn.fhir.jpa.provider;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.MessageHeader;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import javax.servlet.http.HttpServletRequest;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public class BaseJpaResourceProviderMessageHeaderDstu2 extends JpaResourceProviderDstu2<MessageHeader> {
/**
* /MessageHeader/$process-message
*/
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
public IBaseBundle processMessage(
HttpServletRequest theServletRequest,
RequestDetails theRequestDetails,
@OperationParam(name = "content", min = 1, max = 1)
@Description(formalDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
Bundle theMessageToProcess
) {
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoMessageHeader<MessageHeader>) getDao()).messageHeaderProcessMessage(theRequestDetails, theMessageToProcess);
} finally {
endRequest(theServletRequest);
}
}
}

View File

@ -0,0 +1,61 @@
package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.MessageHeader;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import javax.servlet.http.HttpServletRequest;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public class BaseJpaResourceProviderMessageHeaderDstu3 extends JpaResourceProviderDstu3<MessageHeader> {
/**
* /MessageHeader/$process-message
*/
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
public IBaseBundle processMessage(
HttpServletRequest theServletRequest,
RequestDetails theRequestDetails,
@OperationParam(name = "content", min = 1, max = 1)
@Description(formalDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
Bundle theMessageToProcess
) {
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoMessageHeader<MessageHeader>) getDao()).messageHeaderProcessMessage(theRequestDetails, theMessageToProcess);
} finally {
endRequest(theServletRequest);
}
}
}

View File

@ -0,0 +1,61 @@
package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.MessageHeader;
import javax.servlet.http.HttpServletRequest;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public class BaseJpaResourceProviderMessageHeaderR4 extends JpaResourceProviderR4<MessageHeader> {
/**
* /MessageHeader/$process-message
*/
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
public IBaseBundle processMessage(
HttpServletRequest theServletRequest,
RequestDetails theRequestDetails,
@OperationParam(name = "content", min = 1, max = 1)
@Description(formalDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
Bundle theMessageToProcess
) {
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoMessageHeader<MessageHeader>) getDao()).messageHeaderProcessMessage(theRequestDetails, theMessageToProcess);
} finally {
endRequest(theServletRequest);
}
}
}

View File

@ -150,6 +150,11 @@ public class JpaConstants {
*/
public static final String OPERATION_EVERYTHING = "$everything";
/**
* Operation name for the $process-message operation
*/
public static final String OPERATION_PROCESS_MESSAGE = "$process-message";
/**
* Operation name for the $meta-delete operation
*/

View File

@ -25,7 +25,11 @@ import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.util.TestUtil;
import org.springframework.test.context.TestPropertySource;
@TestPropertySource(properties = {
"scheduling_disabled=true"
})
public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UpdateTest.class);
@ -35,6 +39,35 @@ public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
}
@Test
public void testOneRowPerUpdate(){
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
QueryCountHolder.clear();
Patient p = new Patient();
p.getPhotoFirstRep().setCreationElement(new DateTimeType("2011")); // non-indexed field
IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
assertEquals(2, QueryCountHolder.getGrandTotal().getInsert());
runInTransaction(()->{
assertEquals(1, myResourceTableDao.count());
assertEquals(1, myResourceHistoryTableDao.count());
});
QueryCountHolder.clear();
p = new Patient();
p.setId(id);
p.getPhotoFirstRep().setCreationElement(new DateTimeType("2012")); // non-indexed field
myPatientDao.update(p).getId().toUnqualifiedVersionless();
assertEquals(2, QueryCountHolder.getGrandTotal().getInsert());
runInTransaction(()->{
assertEquals(1, myResourceTableDao.count());
assertEquals(2, myResourceHistoryTableDao.count());
});
}
@Test
public void testCreateAndUpdateWithoutRequest() {
String methodName = "testUpdateByUrl";

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.provider;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
@ -20,10 +21,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.TestUtil;
@ -87,11 +85,11 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
mySearchCoordinatorSvcRaw = AopTestUtils.getTargetObject(mySearchCoordinatorSvc);
}
private void checkParamMissing(String paramName) throws IOException, ClientProtocolException {
private void checkParamMissing(String paramName) throws IOException {
HttpGet get = new HttpGet(ourServerBase + "/Observation?" + paramName + ":missing=false");
CloseableHttpResponse resp = ourHttpClient.execute(get);
IOUtils.closeQuietly(resp.getEntity().getContent());
assertEquals(200, resp.getStatusLine().getStatusCode());
try (CloseableHttpResponse resp = ourHttpClient.execute(get)) {
assertEquals(200, resp.getStatusLine().getStatusCode());
}
}
/**
@ -186,7 +184,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testCountParam() throws Exception {
public void testCountParam() {
// NB this does not get used- The paging provider has its own limits built in
myDaoConfig.setHardSearchLimit(100);
@ -224,7 +222,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
* See #438
*/
@Test
public void testCreateAndUpdateBinary() throws ClientProtocolException, Exception {
public void testCreateAndUpdateBinary() throws Exception {
byte[] arr = {1, 21, 74, 123, -44};
Binary binary = new Binary();
binary.setContent(arr);
@ -289,7 +287,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testCreateQuestionnaireResponseWithValidation() throws IOException {
public void testCreateQuestionnaireResponseWithValidation() {
ValueSet options = new ValueSet();
options.getCodeSystem().setSystem("urn:system").addConcept().setCode("code0");
IIdType optId = ourClient.create().resource(options).execute().getId();
@ -419,6 +417,27 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testCreateResourceWithNumericId() throws IOException {
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(responseString);
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)",
oo.getIssue().get(0).getDiagnostics());
} finally {
response.getEntity().getContent().close();
response.close();
}
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
@ -445,28 +464,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
// }
@Test
public void testCreateResourceWithNumericId() throws IOException {
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(responseString);
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)",
oo.getIssue().get(0).getDiagnostics());
} finally {
response.getEntity().getContent().close();
response.close();
}
}
@Test
public void testCreateWithForcedId() throws IOException {
public void testCreateWithForcedId() {
String methodName = "testCreateWithForcedId";
Patient p = new Patient();
@ -628,7 +626,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
* Based on email from Rene Spronk
*/
@Test
public void testDeleteResourceConditional2() throws IOException, Exception {
public void testDeleteResourceConditional2() throws Exception {
String methodName = "testDeleteResourceConditional2";
Patient pt = new Patient();
@ -695,7 +693,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
* See issue #52
*/
@Test
public void testDiagnosticOrderResources() throws Exception {
public void testDiagnosticOrderResources() {
IGenericClient client = ourClient;
int initialSize = client
@ -787,7 +785,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testEverythingEncounterInstance() throws Exception {
public void testEverythingEncounterInstance() {
String methodName = "testEverythingEncounterInstance";
Organization org1parent = new Organization();
@ -851,7 +849,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testEverythingEncounterType() throws Exception {
public void testEverythingEncounterType() {
String methodName = "testEverythingEncounterInstance";
Organization org1parent = new Organization();
@ -951,7 +949,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
List<IIdType> actual;
StringAndListParam param;
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] {ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart()});
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart());
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
@ -974,7 +972,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
* See #147
*/
@Test
public void testEverythingPatientDoesntRepeatPatient() throws Exception {
public void testEverythingPatientDoesntRepeatPatient() {
ca.uhn.fhir.model.dstu2.resource.Bundle b;
b = myFhirCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
@ -1033,7 +1031,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
* Test for #226
*/
@Test
public void testEverythingPatientIncludesBackReferences() throws Exception {
public void testEverythingPatientIncludesBackReferences() {
String methodName = "testEverythingIncludesBackReferences";
Medication med = new Medication();
@ -1060,7 +1058,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
* See #148
*/
@Test
public void testEverythingPatientIncludesCondition() throws Exception {
public void testEverythingPatientIncludesCondition() {
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
Patient p = new Patient();
p.setId("1");
@ -1092,7 +1090,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testEverythingPatientOperation() throws Exception {
public void testEverythingPatientOperation() {
String methodName = "testEverythingOperation";
Organization org1parent = new Organization();
@ -1137,7 +1135,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testEverythingPatientType() throws Exception {
public void testEverythingPatientType() {
String methodName = "testEverythingPatientType";
Organization o1 = new Organization();
@ -1451,7 +1449,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testMetaOperations() throws Exception {
public void testMetaOperations() {
String methodName = "testMetaOperations";
Patient pt = new Patient();
@ -1488,7 +1486,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testPagingOverEverythingSet() throws InterruptedException {
Patient p = new Patient();
@ -1543,7 +1540,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testPagingOverEverythingSetWithNoPagingProvider() throws InterruptedException {
public void testPagingOverEverythingSetWithNoPagingProvider() {
ourRestServer.setPagingProvider(null);
Patient p = new Patient();
@ -1576,11 +1573,30 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testProcessMessage() {
Bundle bundle = new Bundle();
bundle.setType(BundleTypeEnum.MESSAGE);
Parameters parameters = new Parameters();
parameters.addParameter()
.setName("content")
.setResource(bundle);
try {
ourClient.operation().onType(MessageHeader.class).named(JpaConstants.OPERATION_PROCESS_MESSAGE).withParameters(parameters).execute();
fail();
} catch (NotImplementedOperationException e) {
assertThat(e.getMessage(), containsString("This operation is not yet implemented on this server"));
}
}
/**
* Test for issue #60
*/
@Test
public void testReadAllInstancesOfType() throws Exception {
public void testReadAllInstancesOfType() {
Patient pat;
pat = new Patient();
@ -1960,7 +1976,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
private void testSearchReturnsResults(String search) throws IOException, ClientProtocolException {
private void testSearchReturnsResults(String search) throws IOException {
int matches;
HttpGet get = new HttpGet(ourServerBase + search);
CloseableHttpResponse response = ourHttpClient.execute(get);
@ -2001,7 +2017,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testSearchWithInclude() throws Exception {
public void testSearchWithInclude() {
Organization org = new Organization();
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
IdDt orgId = (IdDt) ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
@ -2029,7 +2045,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test(expected = InvalidRequestException.class)
public void testSearchWithInvalidSort() throws Exception {
public void testSearchWithInvalidSort() {
Observation o = new Observation();
o.getCode().setText("testSearchWithInvalidSort");
myObservationDao.create(o, mySrd);
@ -2042,7 +2058,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testSearchWithMissing() throws Exception {
public void testSearchWithMissing() {
ourLog.info("Starting testSearchWithMissing");
String methodName = "testSearchWithMissing";
@ -2286,7 +2302,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
* Test for issue #60
*/
@Test
public void testStoreUtf8Characters() throws Exception {
public void testStoreUtf8Characters() {
Organization org = new Organization();
org.setName("測試醫院");
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
@ -2340,7 +2356,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testUpdateInvalidUrl() throws IOException, Exception {
public void testUpdateInvalidUrl() throws Exception {
String methodName = "testUpdateInvalidReference";
Patient pt = new Patient();
@ -2362,7 +2378,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
public void testUpdateRejectsInvalidTypes() {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
@ -2467,7 +2483,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
@Test
public void testUpdateResourceWithPrefer() throws IOException, Exception {
public void testUpdateResourceWithPrefer() throws Exception {
String methodName = "testUpdateResourceWithPrefer";
Patient pt = new Patient();
@ -2680,7 +2696,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
Patient patient = new Patient();
patient.addName().addGiven("James" + StringUtils.leftPad("James", 1000000, 'A'));
;
patient.setBirthDate(new DateDt("2011-02-02"));
Parameters input = new Parameters();

View File

@ -1,46 +1,68 @@
package ca.uhn.fhir.jpa.provider.dstu3;
import static org.junit.Assert.*;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.Composition;
import org.hl7.fhir.dstu3.model.MessageHeader;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.Test;
import ca.uhn.fhir.util.TestUtil;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.*;
public class ResourceProviderDstu3BundleTest extends BaseResourceProviderDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3BundleTest.class);
/**
* See #401
*/
@Test
public void testBundlePreservesFullUrl() {
Bundle bundle = new Bundle();
bundle.setType(BundleType.DOCUMENT);
Composition composition = new Composition();
composition.setTitle("Visit Summary");
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
IIdType id = ourClient.create().resource(bundle).execute().getId();
Bundle retBundle = ourClient.read().resource(Bundle.class).withId(id).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
}
@Test
public void testProcessMessage() {
Bundle bundle = new Bundle();
bundle.setType(Bundle.BundleType.MESSAGE);
Parameters parameters = new Parameters();
parameters.addParameter()
.setName("content")
.setResource(bundle);
try {
ourClient.operation().onType(MessageHeader.class).named(JpaConstants.OPERATION_PROCESS_MESSAGE).withParameters(parameters).execute();
fail();
} catch (NotImplementedOperationException e) {
assertThat(e.getMessage(), containsString("This operation is not yet implemented on this server"));
}
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
/**
* See #401
*/
@Test
public void testBundlePreservesFullUrl() throws Exception {
Bundle bundle = new Bundle();
bundle.setType(BundleType.DOCUMENT);
Composition composition = new Composition();
composition.setTitle("Visit Summary");
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
IIdType id = ourClient.create().resource(bundle).execute().getId();
Bundle retBundle = ourClient.read().resource(Bundle.class).withId(id).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
}
}

View File

@ -1,46 +1,68 @@
package ca.uhn.fhir.jpa.provider.r4;
import static org.junit.Assert.*;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.r4.model.MessageHeader;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Composition;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Parameters;
import org.junit.AfterClass;
import org.junit.Test;
import ca.uhn.fhir.util.TestUtil;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.*;
public class ResourceProviderR4BundleTest extends BaseResourceProviderR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4BundleTest.class);
/**
* See #401
*/
@Test
public void testBundlePreservesFullUrl() {
Bundle bundle = new Bundle();
bundle.setType(BundleType.DOCUMENT);
Composition composition = new Composition();
composition.setTitle("Visit Summary");
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
IIdType id = myClient.create().resource(bundle).execute().getId();
Bundle retBundle = myClient.read().resource(Bundle.class).withId(id).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
}
@Test
public void testProcessMessage() {
Bundle bundle = new Bundle();
bundle.setType(BundleType.MESSAGE);
Parameters parameters = new Parameters();
parameters.addParameter()
.setName("content")
.setResource(bundle);
try {
myClient.operation().onType(MessageHeader.class).named(JpaConstants.OPERATION_PROCESS_MESSAGE).withParameters(parameters).execute();
fail();
} catch (NotImplementedOperationException e) {
assertThat(e.getMessage(), containsString("This operation is not yet implemented on this server"));
}
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
/**
* See #401
*/
@Test
public void testBundlePreservesFullUrl() throws Exception {
Bundle bundle = new Bundle();
bundle.setType(BundleType.DOCUMENT);
Composition composition = new Composition();
composition.setTitle("Visit Summary");
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
IIdType id = myClient.create().resource(bundle).execute().getId();
Bundle retBundle = myClient.read().resource(Bundle.class).withId(id).execute();
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
}
}

View File

@ -137,6 +137,39 @@ drop table cdr_xact_log_step cascade constraints;
drop table cdr_xact_log cascade constraints;
drop table hfj_history_tag cascade;
drop table hfj_forced_id cascade;
drop table hfj_res_link cascade;
drop table hfj_spidx_coords cascade;
drop table hfj_spidx_date cascade;
drop table hfj_spidx_number cascade;
drop table hfj_spidx_quantity cascade;
drop table hfj_spidx_string cascade;
drop table hfj_spidx_token cascade;
drop table hfj_spidx_uri cascade;
drop table hfj_res_tag cascade;
drop table hfj_search_result cascade;
drop table hfj_search_include cascade;
drop table hfj_search cascade;
drop table hfj_res_param_present cascade;
drop table hfj_idx_cmp_string_uniq cascade;
drop table hfj_subscription_stats cascade;
drop table trm_concept_property cascade;
drop table trm_concept_pc_link cascade;
drop table trm_concept cascade;
drop table trm_codesystem_ver cascade;
drop table trm_codesystem cascade;
DROP TABLE hfj_resource cascade;
DROP TABLE hfj_res_ver cascade;
drop table hfj_search_parm cascade;
drop table hfj_tag_def cascade;
drop index IDX_FORCEDID_TYPE_FORCEDID;
alter table hfj_forced_id drop constraint idx_forcedid_type_resid;
Upgrading
drop index IDX_SP_STRING;
create index IDX_SP_STRING_HASH_NRM;
@ -153,6 +186,7 @@ drop index IDX_SP_QUANTITY;
create index IDX_SP_QUANTITY_HASH;
create index IDX_SP_QUANTITY_HASH_UN;
drop index IDX_FORCEDID_TYPE_FORCEDID;
alter table hfj_forced_id drop constraint idx_forcedid_type_resid;
create index IDX_FORCEDID_TYPE_FID;
drop index IDX_SP_NUMBER;
create index IDX_SP_NUMBER_HASH_VAL;

View File

@ -958,6 +958,8 @@ public class ClientR4Test {
}
@Test
public void testSearchWithStringIncludes() throws Exception {

View File

@ -22,7 +22,7 @@ import ca.uhn.fhir.rest.api.SortSpec;
public class ${className}ResourceProvider extends
## We have specialized base classes for RPs that handle certain resource types. These
## RPs implement type specific operations
#if ( $version != 'dstu' && (${className} == 'Encounter' || ${className} == 'Patient' || ${className} == 'ValueSet' || ${className} == 'QuestionnaireAnswers' || ${className} == 'CodeSystem' || ($version != 'dstu2' && ${className} == 'ConceptMap')))
#if ( $version != 'dstu' && (${className} == 'Encounter' || ${className} == 'Patient' || ${className} == 'ValueSet' || ${className} == 'QuestionnaireAnswers' || ${className} == 'CodeSystem' || ($version != 'dstu2' && ${className} == 'ConceptMap') || ${className} == 'MessageHeader'))
BaseJpaResourceProvider${className}${versionCapitalized}
#else
JpaResourceProvider${versionCapitalized}<${className}>

View File

@ -62,7 +62,7 @@ public abstract class BaseJavaConfig${versionCapitalized} extends ca.uhn.fhir.jp
IFhirResourceDaoConceptMap<org.hl7.fhir.dstu3.model.ConceptMap>
#elseif ( ${versionCapitalized} == 'R4' && ${res.name} == 'ConceptMap' )
IFhirResourceDaoConceptMap<org.hl7.fhir.r4.model.ConceptMap>
#elseif ( ${versionCapitalized} != 'Dstu1' && ( ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'SearchParameter'))
#elseif ( ${versionCapitalized} != 'Dstu1' && ( ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'SearchParameter' || ${res.name} == 'MessageHeader'))
IFhirResourceDao${res.name}<${resourcePackage}.${res.declaringClassNameComplete}>
#else
IFhirResourceDao<${resourcePackage}.${res.declaringClassNameComplete}>
@ -72,7 +72,7 @@ public abstract class BaseJavaConfig${versionCapitalized} extends ca.uhn.fhir.jp
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
#elseif ( ${versionCapitalized} == 'R4' && ${res.name} == 'ConceptMap' )
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
#elseif ( ${versionCapitalized} != 'Dstu1' && ( ${res.name} == 'Bundle' || ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'ValueSet' || ${res.name} == 'QuestionnaireResponse' || ${res.name} == 'SearchParameter' || ${res.name} == 'CodeSystem'))
#elseif ( ${res.name} == 'Bundle' || ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'ValueSet' || ${res.name} == 'QuestionnaireResponse' || ${res.name} == 'SearchParameter' || ${res.name} == 'CodeSystem' || ${res.name} == 'MessageHeader')
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
#else
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${versionCapitalized}<${resourcePackage}.${res.declaringClassNameComplete}> retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${versionCapitalized}<${resourcePackage}.${res.declaringClassNameComplete}>();

View File

@ -138,6 +138,12 @@
A crash in the JPA server when performing a manual reindex of a deleted resource
was fixed.
</action>
<action type="fix">
Using the generic/fluent client, it is now possible to
invoke the $process-message method using a standard
client.operation() call. Previously this caused a strange
NullPointerException.
</action>
</release>
<release version="3.4.0" date="2018-05-28">
<action type="add">