Some refactoring - Currently does not compile,will fix this afternoon

This commit is contained in:
jamesagnew 2014-04-22 08:58:28 -04:00
parent e9a71d843a
commit 5da4698fab
21 changed files with 637 additions and 287 deletions

View File

@ -1,15 +1,3 @@
* Implement JSON parser and encoder- I'm thinking probably just using GSON
and writing the encode() part from scratch. For the parse() part, the
ParserState class from the XML parser should be able to be shared with
the Json parser, which will make it a lot easier to implement..?
* Implement strategy for narrative generation- I'm thinking maybe
an interface that turns a given resource into an HTML representation
and then a default implementation for our basic types (Patient, Observation)
and maybe a way to configure this in the FhirContext so that the parser
can take advantage?
* Add SimpleSetters for all primitive datatypes
* Implement and add Simple Getters in a similar way to simple setters

View File

@ -14,9 +14,11 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
@ -36,18 +38,25 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ReflectionUtil;
public abstract class BaseMethodBinding {
private Method myMethod;
private FhirContext myContext;
private Object myProvider;
public BaseMethodBinding(Method theMethod, FhirContext theConetxt) {
public BaseMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider) {
assert theMethod != null;
assert theConetxt != null;
myMethod = theMethod;
myContext = theConetxt;
myProvider = theProvider;
}
public Object getProvider() {
return myProvider;
}
public FhirContext getContext() {
@ -78,7 +87,7 @@ public abstract class BaseMethodBinding {
return parser;
}
public static BaseMethodBinding bindMethod(Class<? extends IResource> theReturnType, Method theMethod, FhirContext theContext, IResourceProvider theProvider) {
public static BaseMethodBinding bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
Read read = theMethod.getAnnotation(Read.class);
Search search = theMethod.getAnnotation(Search.class);
Metadata conformance = theMethod.getAnnotation(Metadata.class);
@ -87,34 +96,63 @@ public abstract class BaseMethodBinding {
Delete delete = theMethod.getAnnotation(Delete.class);
History history = theMethod.getAnnotation(History.class);
// ** if you add another annotation above, also add it to the next line:
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance,create,update,delete,history)) {
if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance, create, update, delete, history)) {
return null;
}
Class<? extends IResource> returnType = theReturnType;
if (returnType == null) {
Class<? extends IResource> returnTypeFromRp = null;
if (theProvider instanceof IResourceProvider) {
returnTypeFromRp = ((IResourceProvider) theProvider).getResourceType();
if (!verifyIsValidResourceReturnType(returnTypeFromRp)) {
throw new ConfigurationException("getResourceType() from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returned " + toLogString(returnTypeFromRp) + " - Must return a resource type");
}
}
Class<?> returnTypeFromMethod = theMethod.getReturnType();
if (Collection.class.isAssignableFrom(returnTypeFromMethod)) {
returnTypeFromMethod = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
}
if (Bundle.class.isAssignableFrom(returnTypeFromMethod)) {
returnTypeFromMethod = returnTypeFromRp;
}
if (!IResource.class.isAssignableFrom(returnTypeFromMethod)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type " + returnTypeFromMethod.getCanonicalName() + " - Must return a resource type");
}
if (returnTypeFromRp != null) {
if (returnTypeFromRp.equals(returnTypeFromMethod) == false) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type " + returnTypeFromMethod.getCanonicalName() + " but must return " + returnTypeFromRp.getCanonicalName());
}
}
if (returnTypeFromMethod == null) {
if (read != null) {
returnType = read.type();
returnTypeFromMethod = read.type();
} else if (search != null) {
returnType = search.type();
returnTypeFromMethod = search.type();
}
if (returnType == IResource.class) {
if (returnTypeFromMethod == IResource.class) {
throw new ConfigurationException("Could not determine return type for method '" + theMethod.getName() + "'. Try explicitly specifying one in the operation annotation.");
}
}
@SuppressWarnings("unchecked")
Class<? extends IResource> retType = (Class<? extends IResource>) returnTypeFromMethod;
if (read != null) {
return new ReadMethodBinding(returnType, theMethod, theContext);
return new ReadMethodBinding(retType, theMethod, theContext, theProvider);
} else if (search != null) {
String queryName = search.queryName();
return new SearchMethodBinding(returnType, theMethod, queryName, theContext);
return new SearchMethodBinding(retType, theMethod, queryName, theContext, theProvider);
} else if (conformance != null) {
return new ConformanceMethodBinding(theMethod, theContext);
return new ConformanceMethodBinding(theMethod, theContext, theProvider);
} else if (create != null) {
return new CreateMethodBinding(theMethod, theContext);
return new CreateMethodBinding(theMethod, theContext, theProvider);
} else if (update != null) {
return new UpdateMethodBinding(theMethod, theContext);
return new UpdateMethodBinding(theMethod, theContext, theProvider);
} else if (delete != null) {
return new DeleteMethodBinding(theMethod, theContext, theProvider);
} else if (history != null) {
@ -145,6 +183,22 @@ public abstract class BaseMethodBinding {
// return sm;
}
private static boolean verifyIsValidResourceReturnType(Class<?> theReturnType) {
if (theReturnType==null) {
return false;
}
if (!IResource.class.isAssignableFrom(theReturnType)) {
return false;
}
}
private static String toLogString(Class<? extends IResource> theType) {
if (theType==null) {
return null;
}
return theType.getCanonicalName();
}
public static boolean verifyMethodHasZeroOrOneOperationAnnotation(Method theNextMethod, Object... theAnnotations) {
Object obj1 = null;
for (Object object : theAnnotations) {
@ -152,8 +206,8 @@ public abstract class BaseMethodBinding {
if (obj1 == null) {
obj1 = object;
} else {
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @"
+ obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName() + ". Can not have both.");
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @" + obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName()
+ ". Can not have both.");
}
}
@ -215,4 +269,5 @@ public abstract class BaseMethodBinding {
return bindMethod(null, theMethod, theContext, null);
}
}

View File

@ -43,8 +43,8 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
private List<IParameter> myParameters;
private boolean myReturnVoid;
public BaseOutcomeReturningMethodBinding(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation) {
super(theMethod, theContext);
public BaseOutcomeReturningMethodBinding(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation, Object theProvider) {
super(theMethod, theContext, theProvider);
myParameters = Util.getResourceParameters(theMethod);
if (!theMethod.getReturnType().equals(MethodOutcome.class)) {
@ -132,7 +132,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
MethodOutcome response;
try {
response = (MethodOutcome) this.getMethod().invoke(theRequest.getResourceProvider(), params);
response = (MethodOutcome) this.getMethod().invoke(getProvider(), params);
} catch (IllegalAccessException e) {
throw new InternalErrorException(e);
} catch (IllegalArgumentException e) {

View File

@ -27,8 +27,8 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends
private int myResourceParameterIndex;
private String myResourceName;
public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation) {
super(theMethod, theContext, theMethodAnnotation);
public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext, Class<?> theMethodAnnotation, Object theProvider) {
super(theMethod, theContext, theMethodAnnotation, theProvider);
ResourceParameter resourceParameter = null;
@ -76,7 +76,7 @@ public abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends
MethodOutcome response;
try {
response = (MethodOutcome) this.getMethod().invoke(theRequest.getResourceProvider(), params);
response = (MethodOutcome) this.getMethod().invoke(getProvider(), params);
} catch (IllegalAccessException e) {
throw new InternalErrorException(e);
} catch (IllegalArgumentException e) {

View File

@ -56,8 +56,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
private String myResourceName;
public BaseResourceReturningMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theConetxt) {
super(theMethod, theConetxt);
public BaseResourceReturningMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theConetxt, Object theProvider) {
super(theMethod, theConetxt, theProvider);
Class<?> methodReturnType = theMethod.getReturnType();
if (Collection.class.isAssignableFrom(methodReturnType)) {
@ -165,7 +165,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
requestIsBrowser = true;
}
List<IResource> result = invokeServer(theRequest.getResourceProvider(), theRequest.getId(), theRequest.getVersion(), theRequest.getParameters());
List<IResource> result = invokeServer(getProvider(), theRequest.getId(), theRequest.getVersion(), theRequest.getParameters());
switch (getReturnType()) {
case BUNDLE:
streamResponseAsBundle(theServer, theResponse, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode);

View File

@ -19,8 +19,8 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding {
public ConformanceMethodBinding(Method theMethod, FhirContext theContext) {
super(Conformance.class, theMethod, theContext);
public ConformanceMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
super(Conformance.class, theMethod, theContext, theProvider);
if (getMethodReturnType() != MethodReturnTypeEnum.RESOURCE || theMethod.getReturnType() != Conformance.class) {
throw new ConfigurationException("Conformance resource provider method '" + theMethod.getName() + "' should return type " + Conformance.class);

View File

@ -17,8 +17,8 @@ public class CreateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
public CreateMethodBinding(Method theMethod, FhirContext theContext) {
super(theMethod, theContext, Create.class);
public CreateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
super(theMethod, theContext, Create.class, theProvider);
}
@Override

View File

@ -27,8 +27,9 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
private String myResourceName;
private Integer myIdParameterIndex;
public DeleteMethodBinding(Method theMethod, FhirContext theContext, IResourceProvider theProvider) {
super(theMethod, theContext, Delete.class);
public DeleteMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
super(theMethod, theContext, Delete.class,
theProvider);
Delete deleteAnnotation = theMethod.getAnnotation(Delete.class);
Class<? extends IResource> resourceType = deleteAnnotation.resourceType();
@ -36,8 +37,8 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
RuntimeResourceDefinition def = theContext.getResourceDefinition(resourceType);
myResourceName = def.getName();
} else {
if (theProvider != null) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(theProvider.getResourceType());
if (theProvider != null && theProvider instanceof IResourceProvider) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(((IResourceProvider) theProvider).getResourceType());
myResourceName = def.getName();
} else {
throw new ConfigurationException("Can not determine resource type for method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getCanonicalName() + " - Did you forget to include the resourceType() value on the @"

View File

@ -35,8 +35,8 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
private Integer mySinceParamIndex;
private Integer myCountParamIndex;
public HistoryMethodBinding(Method theMethod, FhirContext theConetxt, IResourceProvider theProvider) {
super(toReturnType(theMethod, theProvider), theMethod, theConetxt);
public HistoryMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider) {
super(toReturnType(theMethod, theProvider), theMethod, theConetxt, theProvider);
myIdParamIndex = Util.findIdParameterIndex(theMethod);
mySinceParamIndex = Util.findSinceParameterIndex(theMethod);
@ -45,8 +45,8 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
History historyAnnotation = theMethod.getAnnotation(History.class);
Class<? extends IResource> type = historyAnnotation.resourceType();
if (type == History.AllResources.class) {
if (theProvider != null) {
type = theProvider.getResourceType();
if (theProvider instanceof IResourceProvider) {
type = ((IResourceProvider) theProvider).getResourceType();
if (myIdParamIndex != null) {
myResourceOperationType = RestfulOperationTypeEnum.HISTORY_INSTANCE;
} else {
@ -74,9 +74,9 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
}
private static Class<? extends IResource> toReturnType(Method theMethod, IResourceProvider theProvider) {
if (theProvider != null) {
return theProvider.getResourceType();
private static Class<? extends IResource> toReturnType(Method theMethod, Object theProvider) {
if (theProvider instanceof IResourceProvider) {
return ((IResourceProvider) theProvider).getResourceType();
}
History historyAnnotation = theMethod.getAnnotation(History.class);
Class<? extends IResource> type = historyAnnotation.resourceType();

View File

@ -25,8 +25,8 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
private Integer myVersionIdIndex;
private int myParameterCount;
public ReadMethodBinding(Class<? extends IResource> theAnnotatedResourceType, Method theMethod, FhirContext theContext) {
super( theAnnotatedResourceType, theMethod, theContext);
public ReadMethodBinding(Class<? extends IResource> theAnnotatedResourceType, Method theMethod, FhirContext theContext, Object theProvider) {
super( theAnnotatedResourceType, theMethod, theContext, theProvider);
Validate.notNull(theMethod, "Method must not be null");

View File

@ -20,7 +20,6 @@ public class Request {
private Map<String, String[]> myParameters;
private RequestType myRequestType;
private String myResourceName;
private Object myResourceProvider;
private IdDt myVersion;
private HttpServletRequest myServletRequest;
@ -56,21 +55,16 @@ public class Request {
return myResourceName;
}
public Object getResourceProvider() {
return myResourceProvider;
}
public IdDt getVersion() {
return myVersion;
}
public void setCompleteUrl(String theCompleteUrl) {
myCompleteUrl=theCompleteUrl;
myCompleteUrl = theCompleteUrl;
}
public void setFhirServerBase(String theFhirServerBase) {
myFhirServerBase=theFhirServerBase;
myFhirServerBase = theFhirServerBase;
}
public void setId(IdDt theId) {
@ -78,7 +72,7 @@ public class Request {
}
public void setInputReader(Reader theReader) {
myInputReader=theReader;
myInputReader = theReader;
}
public void setOperation(String theOperation) {
@ -89,7 +83,6 @@ public class Request {
myParameters = theParams;
}
public void setRequestType(RequestType theRequestType) {
myRequestType = theRequestType;
}
@ -98,10 +91,6 @@ public class Request {
myResourceName = theResourceName;
}
public void setResourceProvider(Object theProvider) {
myResourceProvider=theProvider;
}
public void setVersion(IdDt theVersion) {
myVersion = theVersion;
}
@ -119,7 +108,7 @@ public class Request {
}
public void setServletRequest(HttpServletRequest theRequest) {
myServletRequest=theRequest;
myServletRequest = theRequest;
}
public HttpServletRequest getServletRequest() {

View File

@ -34,8 +34,8 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
private List<IParameter> myParameters;
private String myQueryName;
public SearchMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, String theQueryName, FhirContext theContext) {
super(theReturnResourceType, theMethod, theContext);
public SearchMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, String theQueryName, FhirContext theContext, Object theProvider) {
super(theReturnResourceType, theMethod, theContext, theProvider);
this.myParameters = Util.getResourceParameters(theMethod);
this.myQueryName = StringUtils.defaultIfBlank(theQueryName, null);
this.myDeclaredResourceType = theMethod.getReturnType();

View File

@ -21,6 +21,7 @@ import ca.uhn.fhir.rest.client.BaseClientInvocation;
import ca.uhn.fhir.rest.client.PutClientInvocation;
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceParam {
@ -29,8 +30,8 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
private Integer myVersionIdParameterIndex;
public UpdateMethodBinding(Method theMethod, FhirContext theContext) {
super(theMethod, theContext, Update.class);
public UpdateMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
super(theMethod, theContext, Update.class, theProvider);
myIdParameterIndex = Util.findIdParameterIndex(theMethod);
if (myIdParameterIndex == null) {

View File

@ -15,7 +15,6 @@ public class ResourceBinding {
private String resourceName;
private List<BaseMethodBinding> methods = new ArrayList<BaseMethodBinding>();
private IResourceProvider resourceProvider;
public ResourceBinding() {
}
@ -27,7 +26,7 @@ public class ResourceBinding {
public BaseMethodBinding getMethod(Request theRequest) throws Exception {
if (null == methods) {
ourLog.warn("No methods exist for resource provider: {}", resourceProvider.getClass());
ourLog.warn("No methods exist for resource: {}", resourceName);
return null;
}
@ -75,12 +74,4 @@ public class ResourceBinding {
return 0;
}
public void setResourceProvider(IResourceProvider theProvider) {
resourceProvider = theProvider;
}
public IResourceProvider getResourceProvider() {
return resourceProvider;
}
}

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.rest.server;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@ -14,98 +15,295 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.stax2.ri.evt.ProcInstrEventImpl;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
import ca.uhn.fhir.rest.method.Request;
import ca.uhn.fhir.rest.method.SearchMethodBinding;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.ConfigurationException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
import ca.uhn.fhir.rest.server.provider.ServerProfileProvider;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.VersionUtil;
public abstract class RestfulServer extends HttpServlet {
public class RestfulServer extends HttpServlet {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServer.class);
private static final long serialVersionUID = 1L;
private FhirContext myFhirContext;
private Collection<Object> myProviders;
private Map<String, ResourceBinding> myResourceNameToProvider = new HashMap<String, ResourceBinding>();
private Object myServerConformanceProvider;
private Map<Class<? extends IResource>, IResourceProvider> myTypeToProvider = new HashMap<Class<? extends IResource>, IResourceProvider>();
private boolean myUseBrowserFriendlyContentTypes;
private ISecurityManager securityManager;
private Collection<IResourceProvider> myResourceProviders;
private ISecurityManager mySecurityManager;
private BaseMethodBinding myServerConformanceMethod;
private Object myServerConformanceProvider;
private String myServerName = "HAPI FHIR Server";
private String myServerVersion = VersionUtil.getVersion();
private String myServerVersion = VersionUtil.getVersion(); // defaults to
// HAPI version
private boolean myUseBrowserFriendlyContentTypes;
public RestfulServer() {
myFhirContext = new FhirContext();
myServerConformanceProvider=new ServerConformanceProvider(this);
myServerConformanceProvider = new ServerConformanceProvider(this);
}
public void addHapiHeader(HttpServletResponse theHttpResponse) {
theHttpResponse.addHeader("X-CatchingFhir", "Powered by HAPI FHIR " + VersionUtil.getVersion());
}
@Override
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.DELETE, request, response);
public FhirContext getFhirContext() {
return myFhirContext;
}
/**
* Provides the non-resource specific providers which implement method calls
* on this server
*
* @see #getResourceProviders()
*/
public Collection<Object> getProviders() {
return myProviders;
}
public Collection<ResourceBinding> getResourceBindings() {
return myResourceNameToProvider.values();
}
/**
* Provides the resource providers for this server
*/
public Collection<IResourceProvider> getResourceProviders() {
return myResourceProviders;
}
/**
* Provides the security manager, or <code>null</code> if none
*/
public ISecurityManager getSecurityManager() {
return mySecurityManager;
}
/**
* Returns the server conformance provider, which is the provider that is
* used to generate the server's conformance (metadata) statement.
* <p>
* By default, the {@link ServerConformanceProvider} is used, but this can
* be changed, or set to <code>null</code> if you do not wish to export a
* conformance statement.
* </p>
*/
public Object getServerConformanceProvider() {
return myServerConformanceProvider;
}
/**
* Gets the server's name, as exported in conformance profiles exported by
* the server. This is informational only, but can be helpful to set with
* something appropriate.
*
* @see RestfulServer#setServerName(StringDt)
*/
public String getServerName() {
return myServerName;
}
public IResourceProvider getServerProfilesProvider() {
return new ServerProfileProvider(getFhirContext());
}
/**
* Gets the server's version, as exported in conformance profiles exported
* by the server. This is informational only, but can be helpful to set with
* something appropriate.
*/
public String getServerVersion() {
return myServerVersion;
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.GET, request, response);
public final void init() throws ServletException {
initialize();
try {
ourLog.info("Initializing HAPI FHIR restful server");
mySecurityManager = getSecurityManager();
if (null == mySecurityManager) {
ourLog.warn("No security manager has been provided, requests will not be authenticated!");
}
Collection<IResourceProvider> resourceProvider = getResourceProviders();
if (resourceProvider != null) {
Map<Class<? extends IResource>, IResourceProvider> typeToProvider = new HashMap<Class<? extends IResource>, IResourceProvider>();
for (IResourceProvider nextProvider : resourceProvider) {
Class<? extends IResource> resourceType = nextProvider.getResourceType();
if (resourceType == null) {
throw new NullPointerException("getResourceType() on class '" + nextProvider.getClass().getCanonicalName() + "' returned null");
}
if (typeToProvider.containsKey(resourceType)) {
throw new ServletException("Multiple providers for type: " + resourceType.getCanonicalName());
}
typeToProvider.put(resourceType, nextProvider);
}
ourLog.info("Got {} resource providers", typeToProvider.size());
for (IResourceProvider provider : typeToProvider.values()) {
findResourceMethods(provider);
}
}
Collection<Object> providers = getProviders();
if (providers != null) {
for (Object next : providers) {
findResourceMethods(next);
}
}
findResourceMethods(getServerProfilesProvider());
findSystemMethods(getServerConformanceProvider());
} catch (Exception ex) {
ourLog.error("An error occurred while loading request handlers!", ex);
throw new ServletException("Failed to initialize FHIR Restful server", ex);
}
ourLog.info("A FHIR has been lit on this server");
}
@Override
protected void doOptions(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.OPTIONS, theReq, theResp);
public boolean isUseBrowserFriendlyContentTypes() {
return myUseBrowserFriendlyContentTypes;
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.POST, request, response);
/**
* Sets the non-resource specific providers which implement method calls on
* this server
*
* @see #setResourceProviders(Collection)
*/
public void setProviders(Collection<Object> theProviders) {
myProviders = theProviders;
}
@Override
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.PUT, request, response);
/**
* Sets the non-resource specific providers which implement method calls on
* this server
*
* @see #setResourceProviders(Collection)
*/
public void setProviders(Object... theProviders) {
myProviders = Arrays.asList(theProviders);
}
private void findResourceMethods(IResourceProvider theProvider) throws Exception {
/**
* Sets the resource providers for this server
*/
public void setResourceProviders(Collection<IResourceProvider> theResourceProviders) {
myResourceProviders = theResourceProviders;
}
Class<? extends IResource> resourceType = theProvider.getResourceType();
RuntimeResourceDefinition definition = myFhirContext.getResourceDefinition(resourceType);
/**
* Sets the resource providers for this server
*/
public void setResourceProviders(IResourceProvider... theResourceProviders) {
myResourceProviders = Arrays.asList(theResourceProviders);
}
ResourceBinding r = new ResourceBinding();
r.setResourceProvider(theProvider);
r.setResourceName(definition.getName());
myResourceNameToProvider.put(definition.getName(), r);
/**
* Sets the security manager, or <code>null</code> if none
*/
public void setSecurityManager(ISecurityManager theSecurityManager) {
mySecurityManager = theSecurityManager;
}
/**
* Returns the server conformance provider, which is the provider that is
* used to generate the server's conformance (metadata) statement.
* <p>
* By default, the {@link ServerConformanceProvider} is used, but this can
* be changed, or set to <code>null</code> if you do not wish to export a
* conformance statement.
* </p>
* Note that this method can only be called before the server is
* initialized.
*
* @throws IllegalStateException
* Note that this method can only be called prior to
* {@link #init() initialization} and will throw an
* {@link IllegalStateException} if called after that.
*/
public void setServerConformanceProvider(Object theServerConformanceProvider) {
if (myFhirContext != null) {
throw new IllegalStateException("Server is already started");
}
myServerConformanceProvider = theServerConformanceProvider;
}
/**
* Gets the server's name, as exported in conformance profiles exported by
* the server. This is informational only, but can be helpful to set with
* something appropriate.
*
* @see RestfulServer#setServerName(StringDt)
*/
public void setServerName(String theServerName) {
myServerName = theServerName;
}
/**
* Gets the server's version, as exported in conformance profiles exported
* by the server. This is informational only, but can be helpful to set with
* something appropriate.
*/
public void setServerVersion(String theServerVersion) {
myServerVersion = theServerVersion;
}
/**
* If set to <code>true</code> (default is false), the server will use
* browser friendly content-types (instead of standard FHIR ones) when it
* detects that the request is coming from a browser instead of a FHIR
*/
public void setUseBrowserFriendlyContentTypes(boolean theUseBrowserFriendlyContentTypes) {
myUseBrowserFriendlyContentTypes = theUseBrowserFriendlyContentTypes;
}
private void findResourceMethods(Object theProvider) throws Exception {
ourLog.info("Scanning type for RESTful methods: {}", theProvider.getClass());
Class<?> clazz = theProvider.getClass();
for (Method m : clazz.getDeclaredMethods()) {
if (Modifier.isPublic(m.getModifiers())) {
if (Modifier.isPublic(m.getModifiers()) && !Modifier.isStatic(m.getModifiers())) {
ourLog.debug("Scanning public method: {}#{}", theProvider.getClass(), m.getName());
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(theProvider.getResourceType(), m, myFhirContext, theProvider);
BaseMethodBinding foundMethodBinding = BaseMethodBinding.bindMethod(m, myFhirContext, theProvider);
if (foundMethodBinding != null) {
r.addMethod(foundMethodBinding);
RuntimeResourceDefinition definition = myFhirContext.getResourceDefinition(retType);
ResourceBinding resourceBinding;
if (myResourceNameToProvider.containsKey(definition.getName())) {
resourceBinding = myResourceNameToProvider.get(definition.getName());
} else {
resourceBinding = new ResourceBinding();
String resourceName = definition.getName();
resourceBinding.setResourceName(resourceName);
myResourceNameToProvider.put(resourceName, resourceBinding);
}
resourceBinding.addMethod(foundMethodBinding);
ourLog.info(" * Method: {}#{} is a handler", theProvider.getClass(), m.getName());
} else {
ourLog.debug(" * Method: {}#{} is not a handler", theProvider.getClass(), m.getName());
@ -134,55 +332,59 @@ public abstract class RestfulServer extends HttpServlet {
}
public FhirContext getFhirContext() {
return myFhirContext;
@Override
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.DELETE, request, response);
}
// /**
// * Sets the {@link INarrativeGenerator Narrative Generator} to use when
// serializing responses from this server, or <code>null</code> (which is
// the default) to disable narrative generation.
// * Note that this method can only be called before the server is
// initialized.
// *
// * @throws IllegalStateException
// * Note that this method can only be called prior to {@link #init()
// initialization} and will throw an {@link IllegalStateException} if called
// after that.
// */
// public void setNarrativeGenerator(INarrativeGenerator
// theNarrativeGenerator) {
// myNarrativeGenerator = theNarrativeGenerator;
// }
public Collection<ResourceBinding> getResourceBindings() {
return myResourceNameToProvider.values();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.GET, request, response);
}
/**
* This method must be overridden to provide one or more resource providers
*/
public abstract Collection<IResourceProvider> getResourceProviders();
/**
* This method should be overridden to provide a security manager instance. By default, returns null.
*/
public ISecurityManager getSecurityManager() {
return null;
@Override
protected void doOptions(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.OPTIONS, theReq, theResp);
}
/**
* Returns the server conformance provider, which is the provider that
* is used to generate the server's conformance (metadata) statement.
* <p>
* By default, the {@link ServerConformanceProvider} is used, but
* this can be changed, or set to <code>null</code> if you do not wish
* to export a conformance statement.
* </p>
*/
public Object getServerConformanceProvider() {
return myServerConformanceProvider;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.POST, request, response);
}
public IResourceProvider getServerProfilesProvider() {
return new ServerProfileProvider(getFhirContext());
@Override
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
handleRequest(SearchMethodBinding.RequestType.PUT, request, response);
}
protected void handleRequest(SearchMethodBinding.RequestType requestType, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
if (null != securityManager) {
securityManager.authenticate(request);
if (null != mySecurityManager) {
mySecurityManager.authenticate(request);
}
String resourceName = null;
String requestFullPath = StringUtils.defaultString(request.getRequestURI());
// String contextPath = StringUtils.defaultString(request.getContextPath());
// String contextPath =
// StringUtils.defaultString(request.getContextPath());
String servletPath = StringUtils.defaultString(request.getServletPath());
StringBuffer requestUrl = request.getRequestURL();
String servletContextPath = "";
@ -230,24 +432,17 @@ public abstract class RestfulServer extends HttpServlet {
}
resourceName = tok.nextToken();
Object provider=null;
ResourceBinding resourceBinding=null;
BaseMethodBinding resourceMethod=null;
ResourceBinding resourceBinding = null;
BaseMethodBinding resourceMethod = null;
if ("metadata".equals(resourceName)) {
provider = myServerConformanceProvider;
if (provider==null) {
throw new ResourceNotFoundException("This server does not support 'metadata' query");
}
resourceMethod = myServerConformanceMethod;
} else {
resourceBinding = myResourceNameToProvider.get(resourceName);
if (resourceBinding == null) {
throw new MethodNotFoundException("Unknown resource type '" + resourceName+"' - Server knows how to handle: "+myResourceNameToProvider.keySet());
throw new MethodNotFoundException("Unknown resource type '" + resourceName + "' - Server knows how to handle: " + myResourceNameToProvider.keySet());
}
provider = resourceBinding.getResourceProvider();
}
if (tok.hasMoreTokens()) {
String nextString = tok.nextToken();
if (nextString.startsWith("_")) {
@ -260,7 +455,7 @@ public abstract class RestfulServer extends HttpServlet {
if (tok.hasMoreTokens()) {
String nextString = tok.nextToken();
if (nextString.startsWith("_")) {
if (operation !=null) {
if (operation != null) {
throw new InvalidRequestException("URL Path contains two operations (part beginning with _): " + requestPath);
}
operation = nextString;
@ -281,7 +476,6 @@ public abstract class RestfulServer extends HttpServlet {
r.setOperation(operation);
r.setParameters(params);
r.setRequestType(requestType);
r.setResourceProvider(provider);
r.setInputReader(request.getReader());
r.setFhirServerBase(fhirServerBase);
r.setCompleteUrl(completeUrl);
@ -325,140 +519,20 @@ public abstract class RestfulServer extends HttpServlet {
}
@Override
public final void init() throws ServletException {
initialize();
try {
ourLog.info("Initializing HAPI FHIR restful server");
securityManager = getSecurityManager();
if (null == securityManager) {
ourLog.warn("No security manager has been provided, requests will not be authenticated!");
}
Collection<IResourceProvider> resourceProvider = getResourceProviders();
for (IResourceProvider nextProvider : resourceProvider) {
Class<? extends IResource> resourceType = nextProvider.getResourceType();
if (resourceType==null) {
throw new NullPointerException("getResourceType() on class '" + nextProvider.getClass().getCanonicalName() + "' returned null");
}
if (myTypeToProvider.containsKey(resourceType)) {
throw new ServletException("Multiple providers for type: " + resourceType.getCanonicalName());
}
myTypeToProvider.put(resourceType, nextProvider);
}
ourLog.info("Got {} resource providers", myTypeToProvider.size());
for (IResourceProvider provider : myTypeToProvider.values()) {
findResourceMethods(provider);
}
findResourceMethods(getServerProfilesProvider());
findSystemMethods(getServerConformanceProvider());
} catch (Exception ex) {
ourLog.error("An error occurred while loading request handlers!", ex);
throw new ServletException("Failed to initialize FHIR Restful server", ex);
}
ourLog.info("A FHIR has been lit on this server");
}
/**
* This method may be overridden by subclasses to do perform initialization that needs to be performed prior to the server being used.
* This method may be overridden by subclasses to do perform initialization
* that needs to be performed prior to the server being used.
*/
protected void initialize() {
// nothing by default
}
public boolean isUseBrowserFriendlyContentTypes() {
return myUseBrowserFriendlyContentTypes;
}
// /**
// * Sets the {@link INarrativeGenerator Narrative Generator} to use when serializing responses from this server, or <code>null</code> (which is the default) to disable narrative generation.
// * Note that this method can only be called before the server is initialized.
// *
// * @throws IllegalStateException
// * Note that this method can only be called prior to {@link #init() initialization} and will throw an {@link IllegalStateException} if called after that.
// */
// public void setNarrativeGenerator(INarrativeGenerator theNarrativeGenerator) {
// myNarrativeGenerator = theNarrativeGenerator;
// }
/**
* Returns the server conformance provider, which is the provider that
* is used to generate the server's conformance (metadata) statement.
* <p>
* By default, the {@link ServerConformanceProvider} is used, but
* this can be changed, or set to <code>null</code> if you do not wish
* to export a conformance statement.
* </p>
* Note that this method can only be called before the server is initialized.
*
* @throws IllegalStateException
* Note that this method can only be called prior to {@link #init() initialization} and will throw an {@link IllegalStateException} if called after that.
*/
public void setServerConformanceProvider(Object theServerConformanceProvider) {
if (myFhirContext!=null) {
throw new IllegalStateException("Server is already started");
}
myServerConformanceProvider = theServerConformanceProvider;
}
/**
* If set to <code>true</code> (default is false), the server will use browser friendly content-types (instead of standard FHIR ones) when it detects that the request is coming from a browser
* instead of a FHIR
*/
public void setUseBrowserFriendlyContentTypes(boolean theUseBrowserFriendlyContentTypes) {
myUseBrowserFriendlyContentTypes = theUseBrowserFriendlyContentTypes;
}
public enum NarrativeModeEnum {
NORMAL,
ONLY,
SUPPRESS;
NORMAL, ONLY, SUPPRESS;
public static NarrativeModeEnum valueOfCaseInsensitive(String theCode) {
return valueOf(NarrativeModeEnum.class, theCode.toUpperCase());
}
}
/**
* Gets the server's name, as exported in conformance profiles exported by the server. This
* is informational only, but can be helpful to set with something appropriate.
*
* @see RestfulServer#setServerName(StringDt)
*/
public String getServerName() {
return myServerName;
}
/**
* Gets the server's name, as exported in conformance profiles exported by the server. This
* is informational only, but can be helpful to set with something appropriate.
*
* @see RestfulServer#setServerName(StringDt)
*/
public void setServerName(String theServerName) {
myServerName = theServerName;
}
/**
* Gets the server's version, as exported in conformance profiles exported by the server. This
* is informational only, but can be helpful to set with something appropriate.
*/
public void setServerVersion(String theServerVersion) {
myServerVersion = theServerVersion;
}
/**
* Gets the server's version, as exported in conformance profiles exported by the server. This
* is informational only, but can be helpful to set with something appropriate.
*/
public String getServerVersion() {
return myServerVersion;
}
}

View File

@ -4,6 +4,10 @@ import javax.servlet.ServletException;
public class ConfigurationException extends ServletException {
public ConfigurationException(String theString) {
super(theString);
}
private static final long serialVersionUID = 1L;
}

View File

@ -8,7 +8,6 @@ import java.util.Set;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
@ -57,8 +56,8 @@ public class ServerConformanceProvider {
Set<RestfulOperationTypeEnum> resourceOps = new HashSet<RestfulOperationTypeEnum>();
RestResource resource = rest.addResource();
Class<? extends IResource> resourceType = next.getResourceProvider().getResourceType();
RuntimeResourceDefinition def = myRestfulServer.getFhirContext().getResourceDefinition(resourceType);
String resourceName = next.getResourceName();
RuntimeResourceDefinition def = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
resource.getType().setValue(def.getName());
resource.getProfile().setId(new IdDt(def.getResourceProfile()));

View File

@ -0,0 +1,161 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.testutil.RandomServerPortProvider;
public class NonResourceProviderServerTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(NonResourceProviderServerTest.class);
private static int ourPort;
private static Server ourServer;
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx;
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = RandomServerPortProvider.findFreePort();
ourServer = new Server(ourPort);
ourCtx = new FhirContext(Patient.class);
ServletHandler proxyHandler = new ServletHandler();
ServletHolder servletHolder = new ServletHolder(new DummyRestfulServer());
proxyHandler.addServletWithMapping(servletHolder, "/fhir/context/*");
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
}
@Test
public void testSearchByParamIdentifier() throws Exception {
String baseUri = "http://localhost:" + ourPort + "/fhir/context";
String uri = baseUri + "/Patient?identifier=urn:hapitest:mrns%7C00001";
HttpGet httpGet = new HttpGet(uri);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.getEntries().size());
Patient patient = (Patient) bundle.getEntries().get(0).getResource();
assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue());
assertEquals(uri, bundle.getLinkSelf().getValue());
assertEquals(baseUri, bundle.getLinkBase().getValue());
}
public static class DummyRestfulServer extends RestfulServer {
private static final long serialVersionUID = 1L;
public DummyRestfulServer() {
setProviders(new DummyProvider());
}
}
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class DummyProvider {
public Map<String, Patient> getIdToPatient() {
Map<String, Patient> idToPatient = new HashMap<String, Patient>();
{
Patient patient = new Patient();
patient.addIdentifier();
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
patient.getIdentifier().get(0).setValue("00001");
patient.addName();
patient.getName().get(0).addFamily("Test");
patient.getName().get(0).addGiven("PatientOne");
patient.getGender().setText("M");
idToPatient.put("1", patient);
}
{
Patient patient = new Patient();
patient.getIdentifier().add(new IdentifierDt());
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
patient.getIdentifier().get(0).setValue("00002");
patient.getName().add(new HumanNameDt());
patient.getName().get(0).addFamily("Test");
patient.getName().get(0).addGiven("PatientTwo");
patient.getGender().setText("F");
idToPatient.put("2", patient);
}
return idToPatient;
}
@Search(type = Patient.class)
public Patient findPatient(@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
for (Patient next : getIdToPatient().values()) {
for (IdentifierDt nextId : next.getIdentifier()) {
if (nextId.matchesSystemAndValue(theIdentifier)) {
return next;
}
}
}
return null;
}
/**
* Retrieve the resource by its identifier
*
* @param theId
* The resource identity
* @return The resource
*/
@Read(type = Patient.class)
public Patient getPatientById(@IdParam IdDt theId) {
return getIdToPatient().get(theId.getValue());
}
}
}

View File

@ -29,7 +29,7 @@ public class ResourceMethodTest {
@Before
public void before() throws NoSuchMethodException, SecurityException {
rm = new SearchMethodBinding(Patient.class, ResourceMethodTest.class.getMethod("foo"), null, new FhirContext());
rm = new SearchMethodBinding(Patient.class, ResourceMethodTest.class.getMethod("foo"), null, new FhirContext(), null);
}
@Test

View File

@ -0,0 +1,67 @@
package ca.uhn.fhir.rest.server;
import javax.servlet.ServletException;
import org.junit.Test;
import ca.uhn.fhir.model.api.BaseResource;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.server.exceptions.ConfigurationException;
public class ServerInvalidDefinitionTest {
@Test(expected=ConfigurationException.class)
public void testNonInstantiableTypeForResourceProvider() throws ServletException {
RestfulServer srv = new RestfulServer();
srv.setResourceProviders(new NonInstantiableTypeForResourceProvider());
srv.init();
}
/**
* Normal, should initialize properly
*/
@Test()
public void testBaseline() throws ServletException {
RestfulServer srv = new RestfulServer();
srv.setResourceProviders(new InstantiableTypeForResourceProvider());
srv.init();
}
private static class NonInstantiableTypeForResourceProvider implements IResourceProvider
{
@Override
public Class<? extends IResource> getResourceType() {
return BaseResource.class;
}
@SuppressWarnings("unused")
@Read
public BaseResource read(@IdParam IdDt theId) {
return null;
}
}
private static class InstantiableTypeForResourceProvider implements IResourceProvider
{
@Override
public Class<Patient> getResourceType() {
return Patient.class;
}
@SuppressWarnings("unused")
@Read
public Patient read(@IdParam IdDt theId) {
return null;
}
}
}

22
pom.xml
View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>6</version>
<version>7</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -85,6 +85,26 @@
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>