Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2015-10-19 20:22:11 -04:00
commit 9b5598e2ab
47 changed files with 3217 additions and 846 deletions

View File

@ -81,14 +81,24 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
@Override
public ValueSet expand(IIdType theId, String theFilter) {
ValueSet source = loadValueSetForExpansion(theId);
return expand(source, theFilter);
}
private ValueSet loadValueSetForExpansion(IIdType theId) {
if (theId.getValue().startsWith("http://hl7.org/fhir/")) {
org.hl7.fhir.instance.model.ValueSet valueSet = myValidationSupport.fetchResource(myRiCtx, org.hl7.fhir.instance.model.ValueSet.class, theId.getValue());
if (valueSet != null) {
return getContext().newJsonParser().parseResource(ValueSet.class, myRiCtx.newJsonParser().encodeResourceToString(valueSet));
}
}
BaseHasResource sourceEntity = readEntity(theId);
if (sourceEntity == null) {
throw new ResourceNotFoundException(theId);
}
ValueSet source = (ValueSet) toResource(sourceEntity, false);
return expand(source, theFilter);
return source;
}
@Override
@ -182,7 +192,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
if (!haveCodeableConcept && !haveCoding && !haveCode) {
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
}
if (!(haveCodeableConcept ^ haveCoding ^ haveCode)) {
if (!multiXor(haveCodeableConcept, haveCoding, haveCode)) {
throw new InvalidRequestException("$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
}
@ -199,11 +209,9 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
if (theCode == null || theCode.isEmpty()) {
throw new InvalidRequestException("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
}
Set<Long> ids = searchForIds(ValueSet.SP_CODE, new TokenParam(toStringOrNull(theSystem), theCode.getValue()));
valueSetIds = new ArrayList<IIdType>();
for (Long next : ids) {
valueSetIds.add(new IdDt("ValueSet", next));
}
String code = theCode.getValue();
String system = toStringOrNull(theSystem);
valueSetIds = findValueSetIdsContainingSystemAndCode(code, system);
}
for (IIdType nextId : valueSetIds) {
@ -223,6 +231,30 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
return new ValidateCodeResult(false, "Code not found", null);
}
private List<IIdType> findValueSetIdsContainingSystemAndCode(String theCode, String theSystem) {
if (theSystem != null && theSystem.startsWith("http://hl7.org/fhir/")) {
return Collections.singletonList((IIdType)new IdDt(theSystem));
}
List<IIdType> valueSetIds;
Set<Long> ids = searchForIds(ValueSet.SP_CODE, new TokenParam(theSystem, theCode));
valueSetIds = new ArrayList<IIdType>();
for (Long next : ids) {
valueSetIds.add(new IdDt("ValueSet", next));
}
return valueSetIds;
}
private static boolean multiXor(boolean... theValues) {
int count = 0;
for (int i = 0; i < theValues.length; i++) {
if (theValues[i]) {
count++;
}
}
return count == 1;
}
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
return thePrimitive != null ? thePrimitive.getValue() : null;
}
@ -259,4 +291,68 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
return null;
}
@Override
public ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.LookupCodeResult lookupCode(CodeDt theCode, UriDt theSystem, CodingDt theCoding) {
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
boolean haveCode = theCode != null && theCode.isEmpty() == false;
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
if (!haveCoding && !(haveSystem && haveCode)) {
throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
}
if (!multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
throw new InvalidRequestException("$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
}
String code;
String system;
if (haveCoding) {
code = theCoding.getCode();
system = theCoding.getSystem();
} else {
code = theCode.getValue();
system = theSystem.getValue();
}
List<IIdType> valueSetIds = findValueSetIdsContainingSystemAndCode(code, system);
for (IIdType nextId : valueSetIds) {
ValueSet expansion = expand(nextId, null);
List<ExpansionContains> contains = expansion.getExpansion().getContains();
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.LookupCodeResult result = lookup(contains, system, code);
if (result != null) {
return result;
}
}
LookupCodeResult retVal = new LookupCodeResult();
retVal.setFound(false);
retVal.setSearchedForCode(code);
retVal.setSearchedForSystem(system);
return retVal;
}
private ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.LookupCodeResult lookup(List<ExpansionContains> theContains, String theSystem, String theCode) {
for (ExpansionContains nextCode : theContains) {
String system = nextCode.getSystem();
String code = nextCode.getCode();
if (theSystem.equals(system) && theCode.equals(code)) {
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.LookupCodeResult retVal = new LookupCodeResult();
retVal.setSearchedForCode(code);
retVal.setSearchedForSystem(system);
retVal.setFound(true);
if (nextCode.getAbstract() != null) {
retVal.setCodeIsAbstract(nextCode.getAbstract().booleanValue());
}
retVal.setCodeDisplay(nextCode.getDisplay());
retVal.setCodeSystemVersion(nextCode.getVersion());
retVal.setCodeSystemDisplayName("Unknown"); // TODO: implement
return retVal;
}
}
return null;
}
}

View File

@ -38,8 +38,76 @@ public interface IFhirResourceDaoValueSet<T extends IBaseResource> extends IFhir
ValueSet expandByIdentifier(String theUri, String theFilter);
LookupCodeResult lookupCode(CodeDt theCode, UriDt theSystem, CodingDt theCoding);
ValidateCodeResult validateCode(UriDt theValueSetIdentifier, IIdType theId, CodeDt theCode, UriDt theSystem, StringDt theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept);
public class LookupCodeResult {
private String myCodeDisplay;
private boolean myCodeIsAbstract;
private String myCodeSystemDisplayName;
private String myCodeSystemVersion;
private boolean myFound;
private String mySearchedForCode;
private String mySearchedForSystem;
public String getCodeDisplay() {
return myCodeDisplay;
}
public String getCodeSystemDisplayName() {
return myCodeSystemDisplayName;
}
public String getCodeSystemVersion() {
return myCodeSystemVersion;
}
public String getSearchedForCode() {
return mySearchedForCode;
}
public String getSearchedForSystem() {
return mySearchedForSystem;
}
public boolean isCodeIsAbstract() {
return myCodeIsAbstract;
}
public boolean isFound() {
return myFound;
}
public void setCodeDisplay(String theCodeDisplay) {
myCodeDisplay = theCodeDisplay;
}
public void setCodeIsAbstract(boolean theCodeIsAbstract) {
myCodeIsAbstract = theCodeIsAbstract;
}
public void setCodeSystemDisplayName(String theCodeSystemDisplayName) {
myCodeSystemDisplayName = theCodeSystemDisplayName;
}
public void setCodeSystemVersion(String theCodeSystemVersion) {
myCodeSystemVersion = theCodeSystemVersion;
}
public void setFound(boolean theFound) {
myFound = theFound;
}
public void setSearchedForCode(String theSearchedForCode) {
mySearchedForCode = theSearchedForCode;
}
public void setSearchedForSystem(String theSearchedForSystem) {
mySearchedForSystem = theSearchedForSystem;
}
}
public class ValidateCodeResult {
private String myDisplay;
private String myMessage;

View File

@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.BooleanUtils;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.LookupCodeResult;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
@ -41,6 +42,7 @@ import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDstu2<ValueSet> {
@ -102,6 +104,42 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
return theFilter != null ? theFilter.getValue() : null;
}
//@formatter:off
@Operation(name = "$lookup", idempotent = true, returnParameters= {
@OperationParam(name="name", type=StringDt.class, min=1),
@OperationParam(name="version", type=StringDt.class, min=0),
@OperationParam(name="display", type=StringDt.class, min=1),
@OperationParam(name="abstract", type=BooleanDt.class, min=1),
})
public Parameters lookup(
HttpServletRequest theServletRequest,
@OperationParam(name="code", min=0, max=1) CodeDt theCode,
@OperationParam(name="system", min=0, max=1) UriDt theSystem,
@OperationParam(name="coding", min=0, max=1) CodingDt theCoding
) {
//@formatter:on
startRequest(theServletRequest);
try {
IFhirResourceDaoValueSet<ValueSet> dao = (IFhirResourceDaoValueSet<ValueSet>) getDao();
LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding);
if (result.isFound()==false) {
throw new ResourceNotFoundException("Unable to find code[" + result.getSearchedForCode() + "] in system[" + result.getSearchedForSystem() + "]");
}
Parameters retVal = new Parameters();
retVal.addParameter().setName("name").setValue(new StringDt(result.getCodeSystemDisplayName()));
if (isNotBlank(result.getCodeSystemVersion())) {
retVal.addParameter().setName("version").setValue(new StringDt(result.getCodeSystemVersion()));
}
retVal.addParameter().setName("display").setValue(new StringDt(result.getCodeDisplay()));
retVal.addParameter().setName("abstract").setValue(new BooleanDt(result.isCodeIsAbstract()));
return retVal;
} finally {
endRequest(theServletRequest);
}
}
//@formatter:off
@Operation(name = "$validate-code", idempotent = true, returnParameters= {
@OperationParam(name="result", type=BooleanDt.class, min=1),
@ -137,4 +175,6 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
endRequest(theServletRequest);
}
}
}

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
"
default-autowire="no" default-lazy-init="false">
<context:annotation-config />
<context:mbean-server />
<bean id="myPersistenceDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true">
<property name="url" value="jdbc:derby:memory:myUnitTestDB;create=true" />
</bean>
<bean id="myPersistenceDataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" lazy-init="true">
<!-- <property name="url" value="jdbc:hsqldb:mem:unit-testing-jpa"/> -->
<!-- <property name="url" value="jdbc:hsqldb:file:svcret.hsqldb" /> -->
<property name="url" value="jdbc:derby:memory:myUnitTestDB;create=true" />
<!--
<property name="username" value="sa" />
<property name="password" value="" />
-->
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myPersistenceDataSource" />
<!-- <property name="persistenceUnitName" value="FHIR_UT" /> -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" /> -->
<property name="databasePlatform" value="ca.uhn.fhir.jpa.util.HapiDerbyTenSevenDialect" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

View File

@ -1,21 +0,0 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<context:annotation-config />
<tx:annotation-driven transaction-manager="myTxManagerDstu2" />
<bean id="mySearchDaoDstu2" class="ca.uhn.fhir.jpa.dao.FhirSearchDao" />
</beans>

View File

@ -1,33 +0,0 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<context:annotation-config />
<websocket:handlers>
<websocket:mapping path="/websocket/dstu2" handler="mySubscriptionWebsocketHandler" />
</websocket:handlers>
<!--
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
-->
<bean id="mySubscriptionWebsocketHandler" class="org.springframework.web.socket.handler.PerConnectionWebSocketHandler">
<constructor-arg value="ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandler"/>
</bean>
<bean id="mySubscriptionSecurityInterceptor" class="ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptor"/>
<tx:annotation-driven transaction-manager="myTxManagerDstu2" />
</beans>

View File

@ -0,0 +1,8 @@
package ca.uhn.fhir.jpa.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DispatcherServletConfig {
//nothing
}

View File

@ -20,10 +20,13 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.DispatcherServlet;
import ca.uhn.fhir.jpa.config.DispatcherServletConfig;
import ca.uhn.fhir.jpa.config.TestDstu2Config;
import ca.uhn.fhir.jpa.dao.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;
@ -126,7 +129,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
// dispatcherServlet.setApplicationContext(webApplicationContext);
dispatcherServlet.setContextConfigLocation("classpath:/fhir-spring-subscription-config-dstu2.xml");
dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);
ServletHolder subsServletHolder = new ServletHolder();
subsServletHolder.setServlet(dispatcherServlet);
proxyHandler.addServlet(subsServletHolder, "/*");

View File

@ -1,7 +1,11 @@
package ca.uhn.fhir.jpa.provider;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Date;
@ -21,9 +25,10 @@ import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.config.TestDstu1Config;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
@ -60,7 +65,7 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
public class ResourceProviderDstu1Test extends BaseJpaTest {
private static ClassPathXmlApplicationContext ourAppCtx;
private static AnnotationConfigApplicationContext ourAppCtx;
private static IGenericClient ourClient;
private static DaoConfig ourDaoConfig;
private static FhirContext ourCtx = FhirContext.forDstu1();
@ -523,7 +528,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
ourServerBase = "http://localhost:" + port + "/fhir/context";
ourAppCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu1.xml", "fhir-jpabase-spring-test-config.xml");
ourAppCtx = new AnnotationConfigApplicationContext(TestDstu1Config.class);
ourDaoConfig = (DaoConfig) ourAppCtx.getBean(DaoConfig.class);

View File

@ -11,9 +11,11 @@ import java.io.IOException;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.transaction.annotation.Transactional;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.primitive.BooleanDt;
@ -36,7 +38,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
}
@Test
public void testValidateCodeOperationByCodeAndSystemBad() {
public void testValidateCodeOperationByCodeAndSystemInstance() {
//@formatter:off
Parameters respParam = ourClient
.operation()
@ -53,7 +55,146 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2
assertEquals(new BooleanDt(true), respParam.getParameter().get(0).getValue());
}
@Test
public void testValidateCodeOperationByCodeAndSystemType() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("validate-code")
.withParameter(Parameters.class, "code", new CodeDt("8450-9"))
.andParameter("system", new UriDt("http://loinc.org"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(new BooleanDt(true), respParam.getParameter().get(0).getValue());
}
@Test
public void testLookupOperationByCodeAndSystem() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeDt("8450-9"))
.andParameter("system", new UriDt("http://loinc.org"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue());
assertEquals("display", respParam.getParameter().get(1).getName());
assertEquals(new StringDt("Systolic blood pressure--expiration"), respParam.getParameter().get(1).getValue());
assertEquals("abstract", respParam.getParameter().get(2).getName());
assertEquals(new BooleanDt(false), respParam.getParameter().get(2).getValue());
}
@Test
@Ignore
public void testLookupOperationForBuiltInCode() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeDt("M"))
.andParameter("system", new UriDt("http://hl7.org/fhir/v3/MaritalStatus"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue());
assertEquals("display", respParam.getParameter().get(1).getName());
assertEquals(new StringDt("Married"), respParam.getParameter().get(1).getValue());
assertEquals("abstract", respParam.getParameter().get(2).getName());
assertEquals(new BooleanDt(false), respParam.getParameter().get(2).getValue());
}
@Test
public void testLookupOperationByCoding() {
//@formatter:off
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", "8450-9"))
.execute();
//@formatter:on
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue());
assertEquals("display", respParam.getParameter().get(1).getName());
assertEquals(new StringDt("Systolic blood pressure--expiration"), respParam.getParameter().get(1).getValue());
assertEquals("abstract", respParam.getParameter().get(2).getName());
assertEquals(new BooleanDt(false), respParam.getParameter().get(2).getValue());
}
@Test
public void testLookupOperationByInvalidCombination() {
//@formatter:off
try {
ourClient
.operation()
.onType(ValueSet.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", "8450-9"))
.andParameter("code", new CodeDt("8450-9"))
.andParameter("system", new UriDt("http://loinc.org"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $lookup can only validate (system AND code) OR (coding.system AND coding.code)", e.getMessage());
}
//@formatter:on
}
@Test
public void testLookupOperationByInvalidCombination2() {
//@formatter:off
try {
ourClient
.operation()
.onType(ValueSet.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", "8450-9"))
.andParameter("system", new UriDt("http://loinc.org"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $lookup can only validate (system AND code) OR (coding.system AND coding.code)", e.getMessage());
}
//@formatter:on
}
@Test
public void testLookupOperationByInvalidCombination3() {
//@formatter:off
try {
ourClient
.operation()
.onType(ValueSet.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", null))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: No code, coding, or codeableConcept provided to validate", e.getMessage());
}
//@formatter:on
}
@Test
public void testExpandById() throws IOException {

View File

@ -1,205 +0,0 @@
package ca.uhn.fhir.jpa.provider;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.valueset.AdministrativeGenderCodesEnum;
import ca.uhn.fhir.model.dstu2.resource.PaymentNotice;
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
public class ResourceProviderMultiVersionTest extends BaseJpaTest {
private static ClassPathXmlApplicationContext ourAppCtx;
private static IGenericClient ourClientDstu2;
private static Server ourServer;
private static IGenericClient ourClientDstu1;
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
ourAppCtx.stop();
}
@Test
public void testSubmitPatient() {
Patient p = new Patient();
p.addIdentifier("urn:MultiFhirVersionTest", "testSubmitPatient01");
p.addUndeclaredExtension(false, "http://foo#ext1", new StringDt("The value"));
p.getGender().setValueAsEnum(AdministrativeGenderCodesEnum.M);
IdDt id = (IdDt) ourClientDstu1.create().resource(p).execute().getId();
// Read back as DSTU1
Patient patDstu1 = ourClientDstu1.read(Patient.class, id);
assertEquals("testSubmitPatient01", p.getIdentifierFirstRep().getValue().getValue());
assertEquals(1, patDstu1.getUndeclaredExtensionsByUrl("http://foo#ext1").size());
assertEquals("M", patDstu1.getGender().getCodingFirstRep().getCode().getValue());
// Read back as DEV
ca.uhn.fhir.model.dstu2.resource.Patient patDstu2;
patDstu2 = ourClientDstu2.read(ca.uhn.fhir.model.dstu2.resource.Patient.class, id);
assertEquals("testSubmitPatient01", p.getIdentifierFirstRep().getValue().getValue());
assertEquals(1, patDstu2.getUndeclaredExtensionsByUrl("http://foo#ext1").size());
assertEquals(null, patDstu2.getGender());
// Search using new bundle format
Bundle bundle = ourClientDstu2.search().forResource(ca.uhn.fhir.model.dstu2.resource.Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:MultiFhirVersionTest", "testSubmitPatient01")).encodedJson().execute();
patDstu2 = (ca.uhn.fhir.model.dstu2.resource.Patient) bundle.getEntries().get(0).getResource();
assertEquals("testSubmitPatient01", p.getIdentifierFirstRep().getValue().getValue());
assertEquals(1, patDstu2.getUndeclaredExtensionsByUrl("http://foo#ext1").size());
assertEquals(null, patDstu2.getGender());
}
@Test
public void testSubmitPatientDstu2() {
ca.uhn.fhir.model.dstu2.resource.Patient p = new ca.uhn.fhir.model.dstu2.resource.Patient();
p.addIdentifier().setSystem("urn:MultiFhirVersionTest").setValue("testSubmitPatientDstu201");
p.addUndeclaredExtension(false, "http://foo#ext1", new StringDt("The value"));
p.setGender(AdministrativeGenderEnum.MALE);
IdDt id = (IdDt) ourClientDstu2.create().resource(p).execute().getId();
// Read back as DSTU1
Patient patDstu1 = ourClientDstu1.read(Patient.class, id);
assertEquals("testSubmitPatientDstu201", p.getIdentifierFirstRep().getValue());
assertEquals(1, patDstu1.getUndeclaredExtensionsByUrl("http://foo#ext1").size());
assertEquals(null, patDstu1.getGender().getCodingFirstRep().getCode().getValue());
// Read back as DEV
ca.uhn.fhir.model.dstu2.resource.Patient patDstu2;
patDstu2 = ourClientDstu2.read(ca.uhn.fhir.model.dstu2.resource.Patient.class, id);
assertEquals("testSubmitPatientDstu201", p.getIdentifierFirstRep().getValue());
assertEquals(1, patDstu2.getUndeclaredExtensionsByUrl("http://foo#ext1").size());
assertEquals("male", patDstu2.getGender());
// Search using new bundle format
Bundle bundle = ourClientDstu2.search().forResource(ca.uhn.fhir.model.dstu2.resource.Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:MultiFhirVersionTest", "testSubmitPatientDstu201")).encodedJson().execute();
patDstu2 = (ca.uhn.fhir.model.dstu2.resource.Patient) bundle.getEntries().get(0).getResource();
assertEquals("testSubmitPatientDstu201", p.getIdentifierFirstRep().getValue());
assertEquals(1, patDstu2.getUndeclaredExtensionsByUrl("http://foo#ext1").size());
assertEquals("male", patDstu2.getGender());
}
@SuppressWarnings("deprecation")
@Test
public void testUnknownResourceType() {
ca.uhn.fhir.model.dstu2.resource.Patient p = new ca.uhn.fhir.model.dstu2.resource.Patient();
p.addIdentifier().setSystem("urn:MultiFhirVersionTest").setValue("testUnknownResourceType01");
IdDt id = (IdDt) ourClientDstu2.create().resource(p).execute().getId();
PaymentNotice s = new PaymentNotice();
s.addIdentifier().setSystem("urn:MultiFhirVersionTest").setValue("testUnknownResourceType02");
ourClientDstu2.create().resource(s).execute().getId();
Bundle history = ourClientDstu2.history(null, id, null, null);
assertEquals(PaymentNotice.class, history.getEntries().get(0).getResource().getClass());
assertEquals(ca.uhn.fhir.model.dstu2.resource.Patient.class, history.getEntries().get(1).getResource().getClass());
history = ourClientDstu1.history(null, id, null, null);
assertEquals(ca.uhn.fhir.model.dstu.resource.Patient.class, history.getEntries().get(0).getResource().getClass());
history = ourClientDstu2.history().onServer().andReturnDstu1Bundle().execute();
assertEquals(PaymentNotice.class, history.getEntries().get(0).getResource().getClass());
assertEquals(ca.uhn.fhir.model.dstu2.resource.Patient.class, history.getEntries().get(1).getResource().getClass());
history = ourClientDstu1.history().onServer().andReturnDstu1Bundle().execute();
assertEquals(ca.uhn.fhir.model.dstu.resource.Patient.class, history.getEntries().get(0).getResource().getClass());
history = ourClientDstu1.history().onInstance(id).andReturnDstu1Bundle().execute();
assertEquals(ca.uhn.fhir.model.dstu.resource.Patient.class, history.getEntries().get(0).getResource().getClass());
}
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() throws Exception {
//@formatter:off
ourAppCtx = new ClassPathXmlApplicationContext(
"hapi-fhir-server-resourceproviders-dstu1.xml",
"hapi-fhir-server-resourceproviders-dstu2.xml",
"fhir-jpabase-spring-test-config.xml"
);
//@formatter:on
int port = RandomServerPortProvider.findFreePort();
ServletContextHandler proxyHandler = new ServletContextHandler();
proxyHandler.setContextPath("/");
ourServer = new Server(port);
/*
* DEV resources
*/
RestfulServer restServerDstu2 = new RestfulServer(ourAppCtx.getBean("myFhirContextDstu2", FhirContext.class));
List<IResourceProvider> rpsDstu2 = (List<IResourceProvider>) ourAppCtx.getBean("myResourceProvidersDstu2", List.class);
restServerDstu2.setResourceProviders(rpsDstu2);
JpaSystemProviderDstu2 systemProvDstu2 = (JpaSystemProviderDstu2) ourAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class);
restServerDstu2.setPlainProviders(systemProvDstu2);
ServletHolder servletHolder = new ServletHolder();
servletHolder.setServlet(restServerDstu2);
proxyHandler.addServlet(servletHolder, "/fhir/contextDstu2/*");
/*
* DSTU resources
*/
RestfulServer restServerDstu1 = new RestfulServer(ourAppCtx.getBean("myFhirContextDstu1", FhirContext.class));
List<IResourceProvider> rpsDstu1 = (List<IResourceProvider>) ourAppCtx.getBean("myResourceProvidersDstu1", List.class);
restServerDstu1.setResourceProviders(rpsDstu1);
JpaSystemProviderDstu1 systemProvDstu1 = (JpaSystemProviderDstu1) ourAppCtx.getBean("mySystemProviderDstu1", JpaSystemProviderDstu1.class);
restServerDstu1.setPlainProviders(systemProvDstu1);
servletHolder = new ServletHolder();
servletHolder.setServlet(restServerDstu1);
proxyHandler.addServlet(servletHolder, "/fhir/contextDstu1/*");
/*
* Start server
*/
ourServer.setHandler(proxyHandler);
ourServer.start();
/*
* DEV Client
*/
String serverBaseDstu2 = "http://localhost:" + port + "/fhir/contextDstu2";
FhirContext ctxDstu2 = ourAppCtx.getBean("myFhirContextDstu2", FhirContext.class);
ctxDstu2.getRestfulClientFactory().setSocketTimeout(600 * 1000);
ourClientDstu2 = ctxDstu2.newRestfulGenericClient(serverBaseDstu2);
ourClientDstu2.registerInterceptor(new LoggingInterceptor(true));
/*
* DSTU1 Client
*/
String serverBaseDstu1 = "http://localhost:" + port + "/fhir/contextDstu1";
FhirContext ctxDstu1 = ourAppCtx.getBean("myFhirContextDstu1", FhirContext.class);
ctxDstu1.getRestfulClientFactory().setSocketTimeout(600 * 1000);
ourClientDstu1 = ctxDstu1.newRestfulGenericClient(serverBaseDstu1);
ourClientDstu1.registerInterceptor(new LoggingInterceptor(true));
}
}

View File

@ -16,9 +16,11 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.config.TestDstu1Config;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.rp.dstu.ObservationResourceProvider;
@ -39,7 +41,7 @@ public class SystemProviderDstu1Test extends BaseJpaTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SystemProviderDstu1Test.class);
private static Server ourServer;
private static ClassPathXmlApplicationContext ourAppCtx;
private static AnnotationConfigApplicationContext ourAppCtx;
private static FhirContext ourCtx;
private static IGenericClient ourClient;
@ -72,7 +74,7 @@ public class SystemProviderDstu1Test extends BaseJpaTest {
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() throws Exception {
ourAppCtx = new ClassPathXmlApplicationContext("fhir-jpabase-spring-test-config.xml", "hapi-fhir-server-resourceproviders-dstu1.xml");
ourAppCtx = new AnnotationConfigApplicationContext(TestDstu1Config.class);
IFhirResourceDao<Patient> patientDao = (IFhirResourceDao<Patient>) ourAppCtx.getBean("myPatientDaoDstu1", IFhirResourceDao.class);
PatientResourceProvider patientRp = new PatientResourceProvider();

View File

@ -24,6 +24,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.config.TestDstu1Config;
import ca.uhn.fhir.jpa.config.TestDstu2Config;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;

View File

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="FHIR_UT" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- <class>ca.uhn.fhir.jpa.entity.PatientResourceTable</class> -->
<class>ca.uhn.fhir.jpa.entity.ForcedId</class>
<class>ca.uhn.fhir.jpa.entity.ResourceTable</class>
<class>ca.uhn.fhir.jpa.entity.ResourceHistoryTable</class>
<class>ca.uhn.fhir.jpa.entity.ResourceHistoryTag</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
<class>ca.uhn.fhir.jpa.entity.Search</class>
<class>ca.uhn.fhir.jpa.entity.SearchResult</class>
<class>ca.uhn.fhir.jpa.entity.SubscriptionTable</class>
<class>ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource</class>
<class>ca.uhn.fhir.jpa.entity.TagDefinition</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.jdbc.batch_size" value="0" />
<property name="hibernate.cache.use_minimal_puts" value="false" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
<property name="hibernate.cache.use_structured_entries" value="false" />
<property name="hibernate.search.default.directory_provider" value="filesystem"/>
<property name="hibernate.search.default.indexBase" value="./target/lucene_indexes"/>
<property name="hibernate.search.lucene_version" value="LUCENE_CURRENT" />
<!--
<property name="hibernate.ejb.naming_strategy" value="ca.uhn.fhir.jpa.util.CustomNamingStrategy" />
-->
<!--
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
-->
</properties>
</persistence-unit>
</persistence>

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
"
default-autowire="no" default-lazy-init="false">
<context:annotation-config />
<context:mbean-server />
<bean id="myDaoConfig" class="ca.uhn.fhir.jpa.dao.DaoConfig">
</bean>
<bean id="myPersistenceDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"></property>
<property name="url" value="jdbc:derby:memory:myUnitTestDB;create=true" />
<property name="username" value=""/>
<property name="password" value=""/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myPersistenceDataSource" />
<property name="persistenceUnitName" value="FHIR_UT" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" /> -->
<property name="databasePlatform" value="ca.uhn.fhir.jpa.util.HapiDerbyTenSevenDialect" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

View File

@ -61,6 +61,13 @@
<type>war</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>1.3-SNAPSHOT</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
<!-- HAPI-FHIR uses Logback for logging support. The logback library is included automatically by Maven as a part of the hapi-fhir-base dependency, but you also need to include a logging library. Logback
is used here, but log4j would also be fine. -->

View File

@ -23,7 +23,7 @@ import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
@Configuration
@EnableTransactionManagement()
public class AppCtxConfig extends BaseJavaConfigDstu2 {
public class FhirServerConfig extends BaseJavaConfigDstu2 {
/**
* Configure FHIR properties around the the JPA server via this bean

View File

@ -0,0 +1,56 @@
package ca.uhn.fhir.jpa.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.to.FhirTesterMvcConfig;
import ca.uhn.fhir.to.TesterConfig;
//@formatter:off
/**
* This spring config file configures the web testing module. It serves two
* purposes:
* 1. It imports FhirTesterMvcConfig, which is the spring config for the
* tester itself
* 2. It tells the tester which server(s) to talk to, via the testerConfig()
* method below
*/
@Configuration
@Import(FhirTesterMvcConfig.class)
public class FhirTesterConfig {
/**
* This bean tells the testing webpage which servers it should configure itself
* to communicate with. In this example we configure it to talk to the local
* server, as well as one public server. If you are creating a project to
* deploy somewhere else, you might choose to only put your own server's
* address here.
*
* Note the use of the ${serverBase} variable below. This will be replaced with
* the base URL as reported by the server itself. Often for a simple Tomcat
* (or other container) installation, this will end up being something
* like "http://localhost:8080/hapi-fhir-jpaserver-example". If you are
* deploying your server to a place with a fully qualified domain name,
* you might want to use that instead of using the variable.
*/
@Bean
public TesterConfig testerConfig() {
TesterConfig retVal = new TesterConfig();
retVal
.addServer()
.withId("home")
.withFhirVersion(FhirVersionEnum.DSTU2)
.withBaseUrl("${serverBase}/baseDstu2")
.withName("Local Tester")
.addServer()
.withId("hapi")
.withFhirVersion(FhirVersionEnum.DSTU2)
.withBaseUrl("http://fhirtest.uhn.ca/baseDstu2")
.withName("Public HAPI Test Server");
return retVal;
}
}
//@formatter:on

View File

@ -124,7 +124,7 @@ public class JpaServerDemo extends RestfulServer {
setPagingProvider(new FifoMemoryPagingProvider(10));
/*
* Load interceptors for the server from Spring (these are defined in AppCtxConfig.java)
* Load interceptors for the server from Spring (these are defined in FhirServerConfig.java)
*/
Collection<IServerInterceptor> interceptorBeans = myAppCtx.getBeansOfType(IServerInterceptor.class).values();
for (IServerInterceptor interceptor : interceptorBeans) {

View File

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="FHIR_UT" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>ca.uhn.fhir.jpa.entity.ForcedId</class>
<class>ca.uhn.fhir.jpa.entity.ResourceHistoryTable</class>
<class>ca.uhn.fhir.jpa.entity.ResourceHistoryTag</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri</class>
<class>ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords</class>
<class>ca.uhn.fhir.jpa.entity.ResourceLink</class>
<class>ca.uhn.fhir.jpa.entity.ResourceTable</class>
<class>ca.uhn.fhir.jpa.entity.ResourceTag</class>
<class>ca.uhn.fhir.jpa.entity.SubscriptionTable</class>
<class>ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource</class>
<class>ca.uhn.fhir.jpa.entity.Search</class>
<class>ca.uhn.fhir.jpa.entity.SearchResult</class>
<class>ca.uhn.fhir.jpa.entity.TagDefinition</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.jdbc.batch_size" value="0" />
<property name="hibernate.cache.use_minimal_puts" value="false" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
<property name="hibernate.cache.use_structured_entries" value="false" />
</properties>
</persistence-unit>
</persistence>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
"
default-autowire="no" default-lazy-init="false">
<context:annotation-config />
<context:mbean-server />
<bean id="myDaoConfig" class="ca.uhn.fhir.jpa.dao.DaoConfig">
</bean>
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="myTxManager" />
<util:list id="myServerInterceptors">
<ref bean="myLoggingInterceptor"/>
</util:list>
<!--
Do some fancy logging to create a nice access log that has details
about each incoming request.
-->
<bean id="myLoggingInterceptor" class="ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor">
<property name="loggerName" value="fhirtest.access"/>
<property name="messageFormat"
value="Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}]"/>
</bean>
</beans>

View File

@ -1,48 +0,0 @@
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--
This file configures the database connection for the HAPI JPA Server.
-->
<!--
The following bean configures the database connection. The 'url' property value
of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the
server should save resources in a directory called "jpaserver_derby_files".
A URL to a remote database could also be placed here, along with login credentials
and other properties supported by BasicDataSource.
-->
<bean id="myPersistenceDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="url" value="jdbc:derby:directory:target/jpaserver_derby_files;create=true" />
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"></property>
<property name="username" value=""/>
<property name="password" value=""/>
</bean>
<!--
Hibernate can be configured with other dialects if you wish to connect to another
database (e.g. Postgres). Consult the Hibernate documentation to see a list of
available dialects.
-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myPersistenceDataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
<property name="persistenceUnitName" value="FHIR_UT" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="ca.uhn.fhir.jpa.util.HapiDerbyTenSevenDialect" />
</bean>
</property>
</bean>
</beans>

View File

@ -1,23 +0,0 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean class="ca.uhn.fhir.to.TesterConfig">
<property name="servers">
<list>
<value>home , DSTU2 , Local Server , ${serverBase}/baseDstu2</value>
</list>
</property>
</bean>
<bean id="fhirContext" class="ca.uhn.fhir.context.FhirContext" factory-method="forDstu2">
</bean>
</beans>

View File

@ -1,6 +1,5 @@
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ./xsd/web-app_3_0.xsd">
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ./xsd/web-app_3_0.xsd">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
@ -14,7 +13,7 @@
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
ca.uhn.fhir.jpa.demo.AppCtxConfig
ca.uhn.fhir.jpa.demo.FhirServerConfig
</param-value>
</context-param>
@ -23,12 +22,13 @@
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/hapi-fhir-tester-application-context.xml
/WEB-INF/hapi-fhir-tester-config.xml
</param-value>
<param-value>ca.uhn.fhir.jpa.demo.FhirTesterConfig</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.jpa.demo;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
@ -27,6 +27,7 @@ public class ExampleServerIT {
private static int ourPort;
private static Server ourServer;
private static String ourServerBase;
@Test
public void testCreateAndRead() throws IOException {
@ -50,7 +51,7 @@ public class ExampleServerIT {
/*
* This runs under maven, and I'm not sure how else to figure out the target directory from code..
*/
String path = ExampleServerIT.class.getClassLoader().getResource("whereami.txt").getPath();
String path = ExampleServerIT.class.getClassLoader().getResource(".keep_hapi-fhir-jpaserver-example").getPath();
path = new File(path).getParent();
path = new File(path).getParent();
path = new File(path).getParent();
@ -71,7 +72,8 @@ public class ExampleServerIT {
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
ourClient = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort + "/baseDstu2");
ourServerBase = "http://localhost:" + ourPort + "/baseDstu2";
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true));
}

View File

@ -1 +0,0 @@
ust used for path resolution

File diff suppressed because it is too large Load Diff

View File

@ -129,7 +129,7 @@
<!-- This filters provide support for Cross Origin Resource Sharing (CORS) -->
<filter>
<filter-name>CORS Filter</filter-name>
<filter-class>org.ebaysf.web.cors.CORSFilter</filter-class>
<filter-class>ca.uhn.fhirtest.CORSFilter_</filter-class>
<init-param>
<description>A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.</description>
<param-name>cors.allowed.origins</param-name>

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
@ -10,6 +11,7 @@ import javax.servlet.DispatcherType;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPost;
@ -32,48 +34,33 @@ import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.rest.server.RestfulServerSelfReferenceTest.DummyPatientResourceProvider;
import ca.uhn.fhir.util.PortUtil;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class CorsTest {
private static CloseableHttpClient ourClient;
private static Server ourServer;
private static String ourBaseUri;
private static final FhirContext ourCtx = FhirContext.forDstu1();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CorsTest.class);
@Test
public void testContextWithSpace() throws Exception {
int port = PortUtil.findFreePort();
Server server = new Server(port);
RestfulServer restServer = new RestfulServer(ourCtx);
restServer.setResourceProviders(new DummyPatientResourceProvider());
// ServletHandler proxyHandler = new ServletHandler();
ServletHolder servletHolder = new ServletHolder(restServer);
FilterHolder fh = new FilterHolder();
fh.setHeldClass(CORSFilter.class);
fh.setInitParameter("cors.logging.enabled", "true");
fh.setInitParameter("cors.allowed.origins", "*");
fh.setInitParameter("cors.allowed.headers", "x-fhir-starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers");
fh.setInitParameter("cors.exposed.headers", "Location,Content-Location");
fh.setInitParameter("cors.allowed.methods", "GET,POST,PUT,DELETE,OPTIONS");
ServletContextHandler ch = new ServletContextHandler();
ch.setContextPath("/rootctx/rcp2");
ch.addServlet(servletHolder, "/fhirctx/fcp2/*");
ch.addFilter(fh, "/*", EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
server.setHandler(ch);
server.start();
try {
String baseUri = "http://localhost:" + port + "/rootctx/rcp2/fhirctx/fcp2";
public void testRequestWithNullOrigin() throws ClientProtocolException, IOException {
{
HttpOptions httpOpt = new HttpOptions(baseUri + "/Organization/b27ed191-f62d-4128-d99d-40b5e84f2bf2");
HttpOptions httpOpt = new HttpOptions(ourBaseUri + "/Organization/b27ed191-f62d-4128-d99d-40b5e84f2bf2");
httpOpt.addHeader("Access-Control-Request-Method", "GET");
httpOpt.addHeader("Origin", "null");
httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type");
HttpResponse status = ourClient.execute(httpOpt);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals("GET", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_METHODS).getValue());
assertEquals("null", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN).getValue());
}
}
@Test
public void testContextWithSpace() throws Exception {
{
HttpOptions httpOpt = new HttpOptions(ourBaseUri + "/Organization/b27ed191-f62d-4128-d99d-40b5e84f2bf2");
httpOpt.addHeader("Access-Control-Request-Method", "POST");
httpOpt.addHeader("Origin", "http://www.fhir-starter.com");
httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type");
@ -85,7 +72,7 @@ public class CorsTest {
assertEquals("http://www.fhir-starter.com", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN).getValue());
}
{
String uri = baseUri + "/Patient?identifier=urn:hapitest:mrns%7C00001";
String uri = ourBaseUri + "/Patient?identifier=urn:hapitest:mrns%7C00001";
HttpGet httpGet = new HttpGet(uri);
httpGet.addHeader("X-FHIR-Starter", "urn:fhir.starter");
httpGet.addHeader("Origin", "http://www.fhir-starter.com");
@ -104,7 +91,7 @@ public class CorsTest {
assertEquals(1, bundle.getEntries().size());
}
{
HttpPost httpOpt = new HttpPost(baseUri + "/Patient");
HttpPost httpOpt = new HttpPost(ourBaseUri + "/Patient");
httpOpt.addHeader("Access-Control-Request-Method", "POST");
httpOpt.addHeader("Origin", "http://www.fhir-starter.com");
httpOpt.addHeader("Access-Control-Request-Headers", "accept, x-fhir-starter, content-type");
@ -116,10 +103,11 @@ public class CorsTest {
ourLog.info("Response was:\n{}", responseContent);
assertEquals("http://www.fhir-starter.com", status.getFirstHeader(Constants.HEADER_CORS_ALLOW_ORIGIN).getValue());
}
} finally {
server.stop();
}
public static void afterClass() throws Exception {
ourServer.stop();
ourClient.close();
}
@BeforeClass
@ -129,6 +117,35 @@ public class CorsTest {
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
int port = PortUtil.findFreePort();
ourServer = new Server(port);
RestfulServer restServer = new RestfulServer(ourCtx);
restServer.setResourceProviders(new DummyPatientResourceProvider());
// ServletHandler proxyHandler = new ServletHandler();
ServletHolder servletHolder = new ServletHolder(restServer);
FilterHolder fh = new FilterHolder();
fh.setHeldClass(CORSFilter_.class);
fh.setInitParameter("cors.logging.enabled", "true");
fh.setInitParameter("cors.allowed.origins", "*");
fh.setInitParameter("cors.allowed.headers", "x-fhir-starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers");
fh.setInitParameter("cors.exposed.headers", "Location,Content-Location");
fh.setInitParameter("cors.allowed.methods", "GET,POST,PUT,DELETE,OPTIONS");
ServletContextHandler ch = new ServletContextHandler();
ch.setContextPath("/rootctx/rcp2");
ch.addServlet(servletHolder, "/fhirctx/fcp2/*");
ch.addFilter(fh, "/*", EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
ContextHandlerCollection contexts = new ContextHandlerCollection();
ourServer.setHandler(contexts);
ourServer.setHandler(ch);
ourServer.start();
ourBaseUri = "http://localhost:" + port + "/rootctx/rcp2/fhirctx/fcp2";
}
}

View File

@ -80,7 +80,7 @@ public abstract class PrimitiveType<T> extends Type implements IPrimitiveType<T>
}
public boolean hasValue() {
return !isEmpty();
return !StringUtils.isBlank(getValueAsString());
}
public String getValueAsString() {

View File

@ -0,0 +1,22 @@
package ca.uhn.fhir.model;
import static org.junit.Assert.*;
import org.hl7.fhir.instance.model.DecimalType;
import org.hl7.fhir.instance.model.StringType;
import org.junit.Test;
import org.thymeleaf.standard.expression.NumberTokenExpression;
public class PrimititeTest {
@Test
public void testHasValue() {
StringType type = new StringType();
assertFalse(type.hasValue());
type.addExtension().setUrl("http://foo").setValue(new DecimalType(123));
assertFalse(type.hasValue());
type.setValue("Hello");
assertTrue(type.hasValue());
}
}

View File

@ -48,14 +48,11 @@
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
@ -203,6 +200,7 @@
<artifactId>maven-war-plugin</artifactId>
<configuration>
<attachClasses>true</attachClasses>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>

View File

@ -0,0 +1,60 @@
package ca.uhn.fhir.to;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import ca.uhn.fhir.to.mvc.AnnotationMethodHandlerAdapterConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "ca.uhn.fhir.to")
public class FhirTesterMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry theRegistry) {
theRegistry.addResourceHandler("/css/**").addResourceLocations("/css/");
theRegistry.addResourceHandler("/fa/**").addResourceLocations("/fa/");
theRegistry.addResourceHandler("/fonts/**").addResourceLocations("/fonts/");
theRegistry.addResourceHandler("/img/**").addResourceLocations("/img/");
theRegistry.addResourceHandler("/js/**").addResourceLocations("/js/");
}
@Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}
@Bean
public AnnotationMethodHandlerAdapterConfigurer annotationMethodHandlerAdapterConfigurer() {
return new AnnotationMethodHandlerAdapterConfigurer();
}
@Bean
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
}

View File

@ -1,9 +1,12 @@
package ca.uhn.fhir.to;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Required;
@ -20,6 +23,26 @@ public class TesterConfig {
private LinkedHashMap<String, FhirVersionEnum> myIdToFhirVersion = new LinkedHashMap<String, FhirVersionEnum>();
private LinkedHashMap<String, String> myIdToServerBase = new LinkedHashMap<String, String>();
private LinkedHashMap<String, String> myIdToServerName = new LinkedHashMap<String, String>();
private List<ServerBuilder> myServerBuilders = new ArrayList<TesterConfig.ServerBuilder>();
public IServerBuilderStep1 addServer() {
ServerBuilder retVal = new ServerBuilder();
return retVal;
}
@PostConstruct
public void build() {
for (ServerBuilder next : myServerBuilders) {
Validate.notBlank(next.myId, "Found invalid server configuration - No ID supplied");
Validate.notNull(next.myVersion, "Found invalid server configuration - No FHIR version supplied");
Validate.notBlank(next.myBaseUrl, "Found invalid server configuration - No base URL supplied");
Validate.notBlank(next.myName, "Found invalid server configuration - No name supplied");
myIdToFhirVersion.put(next.myId, next.myVersion);
myIdToServerBase.put(next.myId, next.myBaseUrl);
myIdToServerName.put(next.myId, next.myName);
}
myServerBuilders.clear();
}
public ITestingUiClientFactory getClientFactory() {
return myClientFactory;
@ -80,4 +103,78 @@ public class TesterConfig {
}
}
public interface IServerBuilderStep1 {
IServerBuilderStep2 withId(String theId);
}
public interface IServerBuilderStep2 {
IServerBuilderStep3 withFhirVersion(FhirVersionEnum theVersion);
}
public interface IServerBuilderStep3 {
IServerBuilderStep4 withBaseUrl(String theBaseUrl);
}
public interface IServerBuilderStep4 {
IServerBuilderStep5 withName(String theName);
}
public interface IServerBuilderStep5 {
IServerBuilderStep1 addServer();
}
public class ServerBuilder implements IServerBuilderStep1, IServerBuilderStep2, IServerBuilderStep3, IServerBuilderStep4, IServerBuilderStep5 {
private String myBaseUrl;
private String myId;
private String myName;
private FhirVersionEnum myVersion;
@Override
public IServerBuilderStep1 addServer() {
ServerBuilder retVal = new ServerBuilder();
myServerBuilders.add(retVal);
return retVal;
}
@Override
public IServerBuilderStep4 withBaseUrl(String theBaseUrl) {
Validate.notBlank(theBaseUrl, "theBaseUrl can not be blank");
myBaseUrl = theBaseUrl;
return this;
}
@Override
public IServerBuilderStep3 withFhirVersion(FhirVersionEnum theVersion) {
Validate.notNull(theVersion);
myVersion = theVersion;
return this;
}
@Override
public IServerBuilderStep2 withId(String theId) {
Validate.notBlank(theId, "theId can not be blank");
myId = theId;
return this;
}
@Override
public IServerBuilderStep5 withName(String theName) {
Validate.notBlank(theName, "theName can not be blank");
myName = theName;
return this;
}
}
}

View File

@ -1,12 +1,18 @@
package ca.uhn.fhir.to.mvc;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
public class AnnotationMethodHandlerAdapterConfigurer {
@Autowired
@Qualifier("requestMappingHandlerAdapter")
private RequestMappingHandlerAdapter adapter;
@PostConstruct
public void init() {
adapter.setWebBindingInitializer(new ToBindingInitializer());
}

View File

@ -1,27 +0,0 @@
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean class="ca.uhn.fhir.to.TesterConfig">
<property name="servers">
<list>
<value>home , DSTU1 , Localhost Server DSTU1 , http://localhost:8887/fhir/contextDstu1</value>
<value>home_d2 , DSTU2 , Localhost Server DSTU2 , http://localhost:8887/fhir/contextDstu2</value>
<value>hi , DSTU1 , Health Intersections , http://fhir.healthintersections.com.au/open</value>
<value>furore , DSTU1 , Spark - Furore Reference Server , http://spark.furore.com/fhir</value>
<value>blaze , DSTU1 , Blaze (Orion Health) , https://fhir.orionhealth.com/blaze/fhir</value>
<value>oridashi , DSTU1 , Oridashi , http://demo.oridashi.com.au:8190</value>
<value>fhirbase , DSTU1 , FHIRPlace (Health Samurai) , http://try-fhirplace.hospital-systems.com/ </value>
</list>
</property>
</bean>
<bean id="fhirContext" class="ca.uhn.fhir.context.FhirContext">
</bean>
</beans>

View File

@ -1,44 +0,0 @@
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/hapi-fhir-tester-application-context.xml
/WEB-INF/hapi-fhir-tester-config.xml
</param-value>
</context-param>
<!-- Processes application requests -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/hapi-fhir-tester-application-context.xml
/WEB-INF/hapi-fhir-tester-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<trim-directive-whitespaces>true</trim-directive-whitespaces>
</jsp-property-group>
</jsp-config>
</web-app>

19
pom.xml
View File

@ -233,7 +233,7 @@
<mitreid-connect-version>1.1.8</mitreid-connect-version>
<phloc_schematron_version>2.7.1</phloc_schematron_version>
<phloc_commons_version>4.3.6</phloc_commons_version>
<spring_version>4.2.1.RELEASE</spring_version>
<spring_version>4.2.2.RELEASE</spring_version>
<thymeleaf-version>2.1.4.RELEASE</thymeleaf-version>
<ebay_cors_filter_version>1.0.1</ebay_cors_filter_version>
<xmlunit_version>1.6</xmlunit_version>
@ -258,7 +258,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@ -333,7 +333,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
@ -575,6 +575,11 @@
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
@ -626,7 +631,7 @@
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-javac-errorprone</artifactId>
<version>2.5</version>
<version>2.6</version>
</dependency>
</dependencies>
</plugin>
@ -648,7 +653,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.1</version>
<version>2.10.3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -861,7 +866,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>6.7</version>
<version>6.11.2</version>
</dependency>
</dependencies>
<configuration>
@ -1312,7 +1317,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.0</version>
<version>3.0.2</version>
<configuration>
<classFilesDirectory>./hapi-fhir-base/target/classes</classFilesDirectory>
</configuration>

View File

@ -52,6 +52,13 @@
<type>war</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>1.3-SNAPSHOT</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
<!--
HAPI-FHIR uses Logback for logging support. The logback library is included
@ -129,7 +136,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<version>3.3</version>
<configuration>
<source>1.6</source>
<target>1.6</target>

View File

@ -0,0 +1,63 @@
package ca.uhn.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.to.FhirTesterMvcConfig;
import ca.uhn.fhir.to.TesterConfig;
//@formatter:off
/**
* This spring config file configures the web testing module. It serves two
* purposes:
* 1. It imports FhirTesterMvcConfig, which is the spring config for the
* tester itself
* 2. It tells the tester which server(s) to talk to, via the testerConfig()
* method below
*/
@Configuration
@Import(FhirTesterMvcConfig.class)
public class FhirTesterConfig {
/**
* This bean tells the testing webpage which servers it should configure itself
* to communicate with. In this example we configure it to talk to the local
* server, as well as one public server. If you are creating a project to
* deploy somewhere else, you might choose to only put your own server's
* address here.
*
* Note the use of the ${serverBase} variable below. This will be replaced with
* the base URL as reported by the server itself. Often for a simple Tomcat
* (or other container) installation, this will end up being something
* like "http://localhost:8080/hapi-fhir-jpaserver-example". If you are
* deploying your server to a place with a fully qualified domain name,
* you might want to use that instead of using the variable.
*/
@Bean
public TesterConfig testerConfig() {
TesterConfig retVal = new TesterConfig();
retVal
.addServer()
.withId("home")
.withFhirVersion(FhirVersionEnum.DSTU2)
.withBaseUrl("${serverBase}/fhir")
.withName("Local Tester")
.addServer()
.withId("hapi")
.withFhirVersion(FhirVersionEnum.DSTU2)
.withBaseUrl("http://fhirtest.uhn.ca/baseDstu2")
.withName("Public HAPI Test Server");
/*
* Use the method below to supply a client "factory" which can be used
* if your server requires authentication
*/
// retVal.setClientFactory(clientFactory);
return retVal;
}
}
//@formatter:on

View File

@ -1,35 +0,0 @@
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--
The following bean supplies any configuration to the
FHIR Tester application.
-->
<bean class="ca.uhn.fhir.to.TesterConfig">
<property name="servers">
<list>
<!-- Each value is a reference to one FHIR server -->
<!-- Format is: [id],[FHIR version: DSTU1|DSTU2],[name],[base URL] -->
<!-- The URL should be customized to match the base URL for the FHIR endpoint -->
<value>example , DSTU1 , Restful Server Example , http://localhost:8080/fhir</value>
</list>
</property>
<!--
Add a property for the client factory if one is needed
<property name="clientFactory"><bean class="com.example.AuthorizingTesterUiClientFactory"/></property>
-->
</bean>
<!-- A FhirContext bean is also required -->
<bean id="fhirContext" class="ca.uhn.fhir.context.FhirContext">
</bean>
</beans>

View File

@ -1,26 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5">
<!-- The following entries are all here to enable the tester web application, and are not actually a part of the underlying FHIR server. -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/hapi-fhir-tester-application-context.xml
/WEB-INF/hapi-fhir-tester-config.xml
</param-value>
</context-param>
<!--
This servlet is for the testing webpage, which is imported via
the hapi-fhir-testpage-overlay Maven WAR overlay
-->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/hapi-fhir-tester-application-context.xml
/WEB-INF/hapi-fhir-tester-config.xml
</param-value>
<param-value>ca.uhn.example.config.FhirTesterConfig</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
@ -29,7 +23,23 @@
<url-pattern>/tester/*</url-pattern>
</servlet-mapping>
<!-- This filters provide support for Cross Origin Resource Sharing (CORS) -->
<!--
This is the actual FHIR server
-->
<servlet>
<servlet-name>fhirServlet</servlet-name>
<servlet-class>ca.uhn.example.servlet.ExampleRestfulServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>fhirServlet</servlet-name>
<url-pattern>/fhir/*</url-pattern>
</servlet-mapping>
<!--
This filters provide support for Cross Origin Resource Sharing (CORS). You
do not need this if you do not wish to support CORS in your own server.
-->
<filter>
<filter-name>CORS Filter</filter-name>
<filter-class>org.ebaysf.web.cors.CORSFilter</filter-class>
@ -74,16 +84,4 @@
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- The following entries are for the actual underlying FHIR server. -->
<servlet>
<servlet-name>fhir</servlet-name>
<servlet-class>ca.uhn.example.servlet.ExampleRestfulServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>fhir</servlet-name>
<url-pattern>/fhir/*</url-pattern>
</servlet-mapping>
</web-app>

View File

@ -12,13 +12,19 @@
latest versions (dependent HAPI modules listed in brackets):
<![CDATA[
<ul>
<li>Springframework (JPA, Web Tester): 4.1.5 -&gt; 4.2.1</li>
<li>Commons-lang3 (Core): 3.3.2 -&gt; 3.4</li>
<li>Logback (Core): 1.1.2 -&gt; 1.1.3</li>
<li>Springframework (JPA, Web Tester): 4.1.5 -&gt; 4.2.2</li>
<li>Hibernate (JPA, Web Tester): 4.2.17 -&gt; 5.0.2</li>
<li>Hibernate Validator (JPA, Web Tester): 5.2.1 -&gt; 5.2.2</li>
<li>Derby (JPA, CLI, Public Server): 10.11.1.1 -&gt; 10.12.1.1 </li>
<li>Jetty (JPA, CLI, Public Server): 9.2.6.v20141205 -&gt; 9.3.4.v20151007 </li>
</ul>
]]>
</action>
<action type="add">
JPA and Tester Overlay now use Spring Java config files instead
of the older XML config files. All example projects have been updated.
</action>
<action type="add">
JPA server removes duplicate resource index entries before storing them

View File

@ -48,6 +48,13 @@
<type>war</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
</dependencies>]]></source>
</p>
@ -75,18 +82,12 @@
</p>
<p>
Next, create the following directory in your project
if it doesn't already exist:<br/>
<code>src/main/webapp/WEB-INF</code>
</p>
<p>
Then, create a file in that directory
called <code>hapi-fhir-tester-config.xml</code>
Then, create a Java source file
called <code>FhirTesterConfig.java</code>
and copy in the following contents:
</p>
<macro name="snippet">
<param name="file" value="restful-server-example/src/main/webapp/WEB-INF/hapi-fhir-tester-config.xml" />
<param name="file" value="restful-server-example/src/main/java/ca/uhn/example/config/FhirTesterConfig.java" />
</macro>
<p>
@ -98,37 +99,39 @@
</p>
<p>
Finally, in the same directory you should open you web.xml file. This file is
required in order to deploy to a servlet container and you should create it if
it does not already exist. Place the following contents in that file.
Next, create the following directory in your project
if it doesn't already exist:<br/>
<code>src/main/webapp/WEB-INF</code>
</p>
<source><![CDATA[<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/hapi-fhir-tester-application-context.xml
/WEB-INF/hapi-fhir-tester-config.xml
</param-value>
</context-param>
<servlet>
<p>
In this directory you should open your <code>web.xml</code> file, or create
it if it doesn't exist.
This file is
required in order to deploy to a servlet container and you should create it if
it does not already exist. Place the following contents in that file, adjusting
the package on the <code>FhirTesterConfig</code> to match the
actual package in which you placed this file.
</p>
<source><![CDATA[<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/hapi-fhir-tester-application-context.xml
/WEB-INF/hapi-fhir-tester-config.xml
</param-value>
<param-value>ca.uhn.example.config.FhirTesterConfig</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/tester/*</url-pattern>
</servlet-mapping>]]></source>
</servlet-mapping>
]]></source>
</subsection>
@ -193,19 +196,6 @@
a client.
</p>
<p>
The following example shows an implementation of the client factory which registers
an authorization interceptor with hardcoded credentials.
</p>
<macro name="snippet">
<param name="file" value="restful-server-example/src/main/webapp/WEB-INF/hapi-fhir-tester-config.xml" />
</macro>
<p>
This client factory is then registered with the TesterConfig in the <code>hapi-fhir-tester-config.xml</code>
file, as shown above.
</p>
</section>
</body>