diff --git a/hapi-fhir-base-example-embedded-ws/pom.xml b/hapi-fhir-base-example-embedded-ws/pom.xml new file mode 100644 index 00000000000..98dac37f470 --- /dev/null +++ b/hapi-fhir-base-example-embedded-ws/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + + ca.uhn.hapi.fhir + hapi-fhir + 1.2 + + + jar + + hapi-fhir-base-example-embedded-ws + + + org.eclipse.jetty + jetty-servlet + + + org.eclipse.jetty + jetty-webapp + + + com.google.guava + guava + + + com.google.inject + guice + 3.0 + + + com.google.inject.extensions + guice-servlet + 3.0 + + + com.sun.jersey.contribs + jersey-guice + 1.18.1 + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu2 + 1.2 + + + \ No newline at end of file diff --git a/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/ContextListener.java b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/ContextListener.java new file mode 100644 index 00000000000..02019b886cb --- /dev/null +++ b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/ContextListener.java @@ -0,0 +1,37 @@ +package embedded; +import java.util.Map; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.servlet.GuiceServletContextListener; +import com.sun.jersey.api.container.filter.GZIPContentEncodingFilter; +import com.sun.jersey.api.core.ResourceConfig; +import com.sun.jersey.guice.JerseyServletModule; + +import filters.CharsetResponseFilter; +import filters.CorsResponseFilter; + +public class ContextListener extends GuiceServletContextListener { + + @Override + protected Injector getInjector() { + + return Guice.createInjector(new JerseyServletModule() { + + @Override + protected void configureServlets() { + final Map params = ImmutableMap + . builder() + .put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, + Joiner.on(";").join( + CharsetResponseFilter.class.getName(), + CorsResponseFilter.class.getName(), + GZIPContentEncodingFilter.class + .getName())).build(); + serve("/model/*").with(FhirRestfulServlet.class, params); + } + }); + } +} diff --git a/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/FhirRestfulServlet.java b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/FhirRestfulServlet.java new file mode 100644 index 00000000000..a7e082015b9 --- /dev/null +++ b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/FhirRestfulServlet.java @@ -0,0 +1,59 @@ +package embedded; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Singleton; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; +import ca.uhn.fhir.narrative.INarrativeGenerator; +import ca.uhn.fhir.rest.server.IResourceProvider; +import ca.uhn.fhir.rest.server.RestfulServer; +import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; + +@Singleton +public class FhirRestfulServlet extends RestfulServer { + + /** + * + */ + private static final long serialVersionUID = -3931111342737918913L; + + public FhirRestfulServlet() { + super(FhirContext.forDstu2()); // Support DSTU2 + } + + /** + * This method is called automatically when the servlet is initializing. + */ + @Override + public void initialize() { + /* + * Two resource providers are defined. Each one handles a specific type + * of resource. + */ + final List providers = new ArrayList(); + providers.add(new SomeResourceProvider()); + setResourceProviders(providers); + + /* + * Use a narrative generator. This is a completely optional step, but + * can be useful as it causes HAPI to generate narratives for resources + * which don't otherwise have one. + */ + final INarrativeGenerator narrativeGen = new DefaultThymeleafNarrativeGenerator(); + getFhirContext().setNarrativeGenerator(narrativeGen); + + /* + * Tells HAPI to use content types which are not technically FHIR + * compliant when a browser is detected as the requesting client. This + * prevents browsers from trying to download resource responses instead + * of displaying them inline which can be handy for troubleshooting. + */ + setUseBrowserFriendlyContentTypes(true); + + registerInterceptor(new ResponseHighlighterInterceptor()); + + } +} diff --git a/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/ServerStartup.java b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/ServerStartup.java new file mode 100644 index 00000000000..fb8dde91365 --- /dev/null +++ b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/ServerStartup.java @@ -0,0 +1,25 @@ +package embedded; +import java.util.EnumSet; + +import javax.servlet.DispatcherType; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; + +import com.google.inject.servlet.GuiceFilter; + +public class ServerStartup { + + public static void main(final String[] args) throws Exception { + + final Server server = new Server(9090); + final ServletContextHandler sch = new ServletContextHandler(server, "/"); + sch.addEventListener(new ContextListener()); + sch.addFilter(GuiceFilter.class, "/*", + EnumSet.of(DispatcherType.REQUEST)); + sch.addServlet(DefaultServlet.class, "/"); + server.start(); + } + +} diff --git a/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/SomeResourceProvider.java b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/SomeResourceProvider.java new file mode 100644 index 00000000000..aac9da8adb9 --- /dev/null +++ b/hapi-fhir-base-example-embedded-ws/src/main/java/embedded/SomeResourceProvider.java @@ -0,0 +1,28 @@ +package embedded; + +import java.util.List; + +import org.hl7.fhir.instance.model.api.IBaseResource; + +import ca.uhn.fhir.model.dstu2.resource.Practitioner; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.rest.annotation.RequiredParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.server.IResourceProvider; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; + +public class SomeResourceProvider implements IResourceProvider { + + @Override + public Class getResourceType() { + return Practitioner.class; + } + + @Search() + public List findPractitionersByName( + @RequiredParam(name = Practitioner.SP_NAME) final StringDt theName) { + throw new UnprocessableEntityException( + "Please provide more than 4 characters for the name"); + } + +} diff --git a/hapi-fhir-base-example-embedded-ws/src/main/java/filters/CharsetResponseFilter.java b/hapi-fhir-base-example-embedded-ws/src/main/java/filters/CharsetResponseFilter.java new file mode 100644 index 00000000000..656f7535578 --- /dev/null +++ b/hapi-fhir-base-example-embedded-ws/src/main/java/filters/CharsetResponseFilter.java @@ -0,0 +1,24 @@ +package filters; + + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; + +import com.sun.jersey.spi.container.ContainerRequest; +import com.sun.jersey.spi.container.ContainerResponse; +import com.sun.jersey.spi.container.ContainerResponseFilter; + +public class CharsetResponseFilter implements ContainerResponseFilter { + + @Override + public ContainerResponse filter(final ContainerRequest request, + final ContainerResponse response) { + + final MediaType contentType = response.getMediaType(); + if (contentType != null) { + response.getHttpHeaders().putSingle(HttpHeaders.CONTENT_TYPE, + contentType.toString() + ";charset=UTF-8"); + } + return response; + } +} \ No newline at end of file diff --git a/hapi-fhir-base-example-embedded-ws/src/main/java/filters/CorsResponseFilter.java b/hapi-fhir-base-example-embedded-ws/src/main/java/filters/CorsResponseFilter.java new file mode 100644 index 00000000000..cab06c28419 --- /dev/null +++ b/hapi-fhir-base-example-embedded-ws/src/main/java/filters/CorsResponseFilter.java @@ -0,0 +1,33 @@ +package filters; + + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; + +import com.sun.jersey.spi.container.ContainerRequest; +import com.sun.jersey.spi.container.ContainerResponse; +import com.sun.jersey.spi.container.ContainerResponseFilter; + +public class CorsResponseFilter implements ContainerResponseFilter { + + @Override + public ContainerResponse filter(final ContainerRequest req, + final ContainerResponse contResp) { + + final ResponseBuilder resp = Response.fromResponse(contResp + .getResponse()); + resp.header("Access-Control-Allow-Origin", "*").header( + "Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + + final String reqHead = req + .getHeaderValue("Access-Control-Request-Headers"); + + if (null != reqHead && !reqHead.equals("")) { + resp.header("Access-Control-Allow-Headers", reqHead); + } + + contResp.setResponse(resp.build()); + return contResp; + } + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index ab805cbb44a..5bfdc74a027 100644 --- a/pom.xml +++ b/pom.xml @@ -1378,4 +1378,7 @@ + + hapi-fhir-base-example-embedded-ws +