You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2018/07/09 06:46:12 UTC

[camel] branch master updated (3a7f436 -> 191f1cc)

This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from 3a7f436  CAMEL-12610 Fixed the issue of camel bean always invokes cached instance
     new 4130380  Lets make the camel-api-component-maven-plugin handle generic methods with single bounded type parameters
     new 35a99d1  [CAMEL-12625] Create Camel FHIR component
     new 191f1cc  [CAMEL-12625] Create Camel FHIR example

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../camel/util/component/ApiMethodParser.java      |  36 +-
 .../component/ArgumentSubstitutionParserTest.java  |  16 +-
 .../org/apache/camel/util/component/TestProxy.java |   8 +
 components/camel-fhir/camel-fhir-api/pom.xml       |  98 +++++
 .../camel/component/fhir/api/ExtraParameters.java  | 157 ++++++++
 .../camel/component/fhir/api/FhirCapabilities.java |  48 +++
 .../camel/component/fhir/api/FhirCreate.java       |  83 +++++
 .../camel/component/fhir/api/FhirDelete.java       |  90 +++++
 .../camel/component/fhir/api/FhirHistory.java      | 114 ++++++
 .../camel/component/fhir/api/FhirLoadPage.java     |  78 ++++
 .../apache/camel/component/fhir/api/FhirMeta.java  | 108 ++++++
 .../apache/camel/component/fhir/api/FhirPatch.java | 103 ++++++
 .../apache/camel/component/fhir/api/FhirRead.java  | 142 +++++++
 .../camel/component/fhir/api/FhirSearch.java       |  54 +++
 .../camel/component/fhir/api/FhirTransaction.java  |  72 ++++
 .../camel/component/fhir/api/FhirUpdate.java       |  80 ++++
 .../camel/component/fhir/api/FhirValidate.java     |  47 +++
 components/camel-fhir/camel-fhir-component/pom.xml | 353 ++++++++++++++++++
 .../signatures/capabilities-sig-api.txt            |  11 +-
 .../signatures/history-sig-api.txt                 |  19 +
 .../signatures/load-page-sig-api.txt}              |  21 +-
 .../signatures/meta-sig-api.txt                    |  21 ++
 .../src/main/docs/fhir-component.adoc              | 121 ++++++
 .../src/main/docs/fhirJson-dataformat.adoc         |   0
 .../src/main/docs/fhirXml-dataformat.adoc          |   0
 .../apache/camel/component/fhir/FhirComponent.java |  86 +++++
 .../camel/component/fhir/FhirConfiguration.java    | 378 +++++++++++++++++++
 .../apache/camel/component/fhir/FhirConsumer.java  |  32 ++
 .../apache/camel/component/fhir/FhirEndpoint.java  | 166 +++++++++
 .../camel/component/fhir/FhirJsonDataFormat.java   |   0
 .../apache/camel/component/fhir/FhirProducer.java  |  31 ++
 .../camel/component/fhir/FhirXmlDataFormat.java    |   0
 .../component/fhir/internal/FhirConstants.java     |  29 ++
 .../camel/component/fhir/internal/FhirHelper.java  | 150 ++++++++
 .../fhir/internal/FhirPropertiesHelper.java        |  39 ++
 .../services/org/apache/camel/component/fhir       |   1 +
 .../services/org/apache/camel/dataformat/fhirJson  |   0
 .../services/org/apache/camel/dataformat/fhirXml   |   0
 .../component/fhir/AbstractFhirTestSupport.java    | 133 +++++++
 .../camel/component/fhir/FhirCapabilitiesIT.java   |  72 ++++
 .../camel/component/fhir/FhirConfigurationIT.java  |  94 +++++
 .../apache/camel/component/fhir/FhirCreateIT.java  |  92 +++++
 .../fhir/FhirCustomClientConfigurationIT.java      | 409 +++++++++++++++++++++
 .../apache/camel/component/fhir/FhirDeleteIT.java  | 127 +++++++
 .../component/fhir/FhirExtraParametersIT.java      |  67 ++++
 .../apache/camel/component/fhir/FhirHistoryIT.java | 123 +++++++
 .../fhir/FhirJsonDataFormatSpringTest.java         |   0
 .../component/fhir/FhirJsonDataFormatTest.java     |   0
 .../camel/component/fhir/FhirLoadPageIT.java       | 164 +++++++++
 .../apache/camel/component/fhir/FhirMetaIT.java    | 169 +++++++++
 .../apache/camel/component/fhir/FhirPatchIT.java   | 139 +++++++
 .../apache/camel/component/fhir/FhirReadIT.java    | 275 ++++++++++++++
 .../apache/camel/component/fhir/FhirSearchIT.java  |  60 +++
 .../camel/component/fhir/FhirTransactionIT.java    | 132 +++++++
 .../apache/camel/component/fhir/FhirUpdateIT.java  | 196 ++++++++++
 .../camel/component/fhir/FhirValidateIT.java       |  78 ++++
 .../fhir/FhirXmlDataFormatSpringTest.java          |   0
 .../component/fhir/FhirXmlDataFormatTest.java      |   0
 .../Hl7v2PatientToFhirPatientIntegrationTest.java} |  27 +-
 .../camel/component/fhir/PatientProcessor.java     |  27 +-
 .../camel/component/fhir/UrlFetcherTest.java       |  39 ++
 .../src/test/resources/log4j2.properties           |   0
 .../fhir/json/FhirJsonDataFormatSpringTest.xml     |   0
 .../fhir/xml/FhirXmlDataFormatSpringTest.xml       |   0
 .../src/test/resources/test-options.properties     |   7 +-
 components/camel-fhir/pom.xml                      | 131 +------
 docs/user-manual/en/SUMMARY.md                     |   1 +
 examples/camel-example-fhir/README.md              |  53 +++
 examples/camel-example-fhir/pom.xml                | 112 ++++++
 .../camel-example-fhir/src/main/data/hl7v2.patient |   1 +
 .../org/apache/camel/example/fhir/Application.java |  80 ++++
 .../src/main/resources/META-INF/LICENSE.txt        |   0
 .../src/main/resources/META-INF/NOTICE.txt         |   0
 .../src/main/resources/META-INF/beans.xml          |   0
 .../src/main/resources/application.properties      |   8 +-
 .../src/main/resources/log4j2.properties           |   0
 examples/pom.xml                                   |   1 +
 parent/pom.xml                                     |   5 +
 .../springboot/FhirComponentAutoConfiguration.java | 128 +++++++
 .../springboot/FhirComponentConfiguration.java     | 267 ++++++++++++++
 .../src/main/resources/META-INF/spring.factories   |   5 +-
 81 files changed, 5802 insertions(+), 212 deletions(-)
 create mode 100644 components/camel-fhir/camel-fhir-api/pom.xml
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/ExtraParameters.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCapabilities.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCreate.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirDelete.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirLoadPage.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirMeta.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirPatch.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirRead.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirSearch.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirTransaction.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirUpdate.java
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirValidate.java
 create mode 100644 components/camel-fhir/camel-fhir-component/pom.xml
 copy platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories => components/camel-fhir/camel-fhir-component/signatures/capabilities-sig-api.txt (74%)
 create mode 100644 components/camel-fhir/camel-fhir-component/signatures/history-sig-api.txt
 copy components/camel-fhir/{src/test/resources/log4j2.properties => camel-fhir-component/signatures/load-page-sig-api.txt} (58%)
 create mode 100644 components/camel-fhir/camel-fhir-component/signatures/meta-sig-api.txt
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc
 rename components/camel-fhir/{ => camel-fhir-component}/src/main/docs/fhirJson-dataformat.adoc (100%)
 rename components/camel-fhir/{ => camel-fhir-component}/src/main/docs/fhirXml-dataformat.adoc (100%)
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirComponent.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConfiguration.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConsumer.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java
 rename components/camel-fhir/{ => camel-fhir-component}/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java (100%)
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirProducer.java
 rename components/camel-fhir/{ => camel-fhir-component}/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java (100%)
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirConstants.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirHelper.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirPropertiesHelper.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/component/fhir
 rename components/camel-fhir/{ => camel-fhir-component}/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirJson (100%)
 rename components/camel-fhir/{ => camel-fhir-component}/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirXml (100%)
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/AbstractFhirTestSupport.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCapabilitiesIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirConfigurationIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCreateIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCustomClientConfigurationIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirDeleteIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirExtraParametersIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirHistoryIT.java
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatSpringTest.java (100%)
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatTest.java (100%)
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirLoadPageIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirMetaIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirReadIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirSearchIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirTransactionIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirUpdateIT.java
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirValidateIT.java
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatSpringTest.java (100%)
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatTest.java (100%)
 rename components/camel-fhir/{src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIT.java => camel-fhir-component/src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIntegrationTest.java} (78%)
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/java/org/apache/camel/component/fhir/PatientProcessor.java (60%)
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/UrlFetcherTest.java
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/resources/log4j2.properties (100%)
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/resources/org/apache/camel/dataformat/fhir/json/FhirJsonDataFormatSpringTest.xml (100%)
 rename components/camel-fhir/{ => camel-fhir-component}/src/test/resources/org/apache/camel/dataformat/fhir/xml/FhirXmlDataFormatSpringTest.xml (100%)
 copy platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories => components/camel-fhir/camel-fhir-component/src/test/resources/test-options.properties (80%)
 create mode 100644 examples/camel-example-fhir/README.md
 create mode 100644 examples/camel-example-fhir/pom.xml
 create mode 100644 examples/camel-example-fhir/src/main/data/hl7v2.patient
 create mode 100644 examples/camel-example-fhir/src/main/java/org/apache/camel/example/fhir/Application.java
 copy {tooling/maven/guice-maven-plugin => examples/camel-example-fhir}/src/main/resources/META-INF/LICENSE.txt (100%)
 copy {tooling/maven/guice-maven-plugin => examples/camel-example-fhir}/src/main/resources/META-INF/NOTICE.txt (100%)
 copy {tests/camel-itest-cdi => examples/camel-example-fhir}/src/main/resources/META-INF/beans.xml (100%)
 copy platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories => examples/camel-example-fhir/src/main/resources/application.properties (80%)
 copy examples/{camel-example-widget-gadget-xml => camel-example-fhir}/src/main/resources/log4j2.properties (100%)
 create mode 100644 platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentAutoConfiguration.java
 create mode 100644 platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentConfiguration.java


[camel] 01/03: Lets make the camel-api-component-maven-plugin handle generic methods with single bounded type parameters

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 41303806213d03c504b31c6ded476758b9d61ab7
Author: jpoth <po...@gmail.com>
AuthorDate: Thu May 3 18:28:29 2018 +0200

    Lets make the camel-api-component-maven-plugin handle generic methods with single bounded type parameters
---
 .../camel/util/component/ApiMethodParser.java      | 36 +++++++++++++++-------
 .../component/ArgumentSubstitutionParserTest.java  | 16 +++++++++-
 .../org/apache/camel/util/component/TestProxy.java |  8 +++++
 3 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
index c3ff108..70013c8 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
@@ -39,7 +39,8 @@ public abstract class ApiMethodParser<T> {
     public static final Pattern ARGS_PATTERN = Pattern.compile("\\s*([^<\\s]+)\\s*(<[^>]+>)?\\s+([^\\s,]+)\\s*,?");
 
     private static final String METHOD_PREFIX = "^(\\s*(public|final|synchronized|native)\\s+)*(\\s*<[^>]>)?\\s*(\\S+)\\s+([^\\(]+\\s*)\\(";
-    private static final Pattern METHOD_PATTERN = Pattern.compile("\\s*([^<\\s]+)\\s*(<[^>]+>)?\\s+(\\S+)\\s*\\(\\s*([\\S\\s,]*)\\)\\s*;?\\s*");
+    private static final Pattern METHOD_PATTERN = Pattern.compile("\\s*([^<\\s]+)?\\s*(<[^>]+>)?(<(?<genericTypeParameterName>\\S+)\\s+extends\\s+"
+            + "(?<genericTypeParameterUpperBound>\\S+)>\\s+\\k<genericTypeParameterName>)?\\s+(\\S+)\\s*\\(\\s*(?<signature>[\\S\\s,]*)\\)\\s*;?\\s*");
 
     private static final String JAVA_LANG = "java.lang.";
     private static final Map<String, Class<?>> PRIMITIVE_TYPES;
@@ -116,24 +117,37 @@ public abstract class ApiMethodParser<T> {
             if (!methodMatcher.matches()) {
                 throw new IllegalArgumentException("Invalid method signature " + signature);
             }
+            // handle generic methods with single bounded type parameters
+            String genericTypeParameterName = null;
+            String genericTypeParameterUpperBound = null;
+            try {
+                genericTypeParameterName = methodMatcher.group("genericTypeParameterName");
+                genericTypeParameterUpperBound = methodMatcher.group("genericTypeParameterUpperBound");
+            } catch (IllegalArgumentException e) {
+                // ignore
+            }
 
-            // ignore generic type parameters in result, if any
-            final Class<?> resultType = forName(methodMatcher.group(1));
-            final String name = methodMatcher.group(3);
-            final String argSignature = methodMatcher.group(4);
+            final Class<?> resultType = genericTypeParameterName != null ? forName(genericTypeParameterUpperBound) : forName(methodMatcher.group(1));
+            final String name = methodMatcher.group(6);
+            final String argSignature = methodMatcher.group(7);
 
             final List<ApiMethodArg> arguments = new ArrayList<>();
             final List<Class<?>> argTypes = new ArrayList<>();
 
             final Matcher argsMatcher = ARGS_PATTERN.matcher(argSignature);
             while (argsMatcher.find()) {
-
-                final Class<?> type = forName(argsMatcher.group(1));
+                String genericParameterName = argsMatcher.group(1);
+                if (genericTypeParameterName != null && genericTypeParameterName.equals(genericParameterName)) {
+                    genericParameterName = genericTypeParameterUpperBound;
+                }
+                final Class<?> type = forName(genericParameterName);
                 argTypes.add(type);
-
-                final String typeArgsGroup = argsMatcher.group(2);
-                final String typeArgs = typeArgsGroup != null
-                    ? typeArgsGroup.substring(1, typeArgsGroup.length() - 1).replaceAll(" ", "") : null;
+                String genericParameterUpperbound = argsMatcher.group(2);
+                String typeArgs = genericParameterUpperbound != null
+                    ? genericParameterUpperbound.substring(1, genericParameterUpperbound.length() - 1).replaceAll(" ", "") : null;
+                if (typeArgs != null && typeArgs.equals(genericTypeParameterName)) {
+                    typeArgs = genericTypeParameterUpperBound;
+                }
                 arguments.add(new ApiMethodArg(argsMatcher.group(3), type, typeArgs));
             }
 
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java b/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
index 9ce7d40..55c3f4d 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.util.component;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.camel.util.component.ArgumentSubstitutionParser.Substitution;
 import org.junit.Test;
@@ -49,15 +50,28 @@ public class ArgumentSubstitutionParserTest {
         signatures.add("public final java.util.Map<String, String> greetAll(java.util.Map<String> nameMap);");
         signatures.add("public final String[] greetTimes(String name, int times);");
         signatures.add("public final String greetInnerChild(org.apache.camel.util.component.TestProxy.InnerChild child);");
+        signatures.add("public final <T extends java.util.Date> T sayHiResource(java.util.Set<T> resourceType, String resourceId);");
+        signatures.add("public final <T extends java.util.Date> T with(T theDate);");
         parser.setSignatures(signatures);
 
         final List<ApiMethodParser.ApiMethodModel> methodModels = parser.parse();
-        assertEquals(9, methodModels.size());
+        assertEquals(11, methodModels.size());
 
         final ApiMethodParser.ApiMethodModel sayHi1 = methodModels.get(8);
         assertEquals(PERSON, sayHi1.getArguments().get(0).getName());
         assertEquals("SAYHI_1", sayHi1.getUniqueName());
 
+        ApiMethodParser.ApiMethodModel sayHiResource = methodModels.get(9);
+        assertEquals(java.util.Date.class, sayHiResource.getResultType());
+        assertEquals(java.util.Set.class, sayHiResource.getArguments().get(0).getType());
+        assertEquals("resourceType", sayHiResource.getArguments().get(0).getName());
+        assertEquals("resourceId", sayHiResource.getArguments().get(1).getName());
+        assertEquals(String.class, sayHiResource.getArguments().get(1).getType());
+
+        ApiMethodParser.ApiMethodModel with = methodModels.get(10);
+        assertEquals(java.util.Date.class, with.getResultType());
+        assertEquals(java.util.Date.class, with.getArguments().get(0).getType());
+
         final ApiMethodParser.ApiMethodModel greetMe = methodModels.get(4);
         assertEquals(PERSON, greetMe.getArguments().get(0).getName());
 
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java b/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
index 41f9eae..00bf1c2 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
@@ -74,6 +74,14 @@ class TestProxy {
         return result;
     }
 
+    public final <T extends java.util.Date> T sayHiResource(java.util.Set<T> resourceType, String resourceId) {
+        return null;
+    }
+
+    public final <T extends java.util.Date> T with(T theDate) {
+        return null;
+    }
+
     public final String greetInnerChild(InnerChild child) {
         return sayHi(child.getName());
     }


[camel] 03/03: [CAMEL-12625] Create Camel FHIR example

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 191f1ccb32751b95d9ef119b94fe31049dd7198d
Author: jpoth <po...@gmail.com>
AuthorDate: Thu Jul 5 16:13:59 2018 +0200

    [CAMEL-12625] Create Camel FHIR example
---
 examples/camel-example-fhir/README.md              |  53 ++++++
 examples/camel-example-fhir/pom.xml                | 112 ++++++++++++
 .../camel-example-fhir/src/main/data/hl7v2.patient |   1 +
 .../org/apache/camel/example/fhir/Application.java |  80 ++++++++
 .../src/main/resources/META-INF/LICENSE.txt        | 203 +++++++++++++++++++++
 .../src/main/resources/META-INF/NOTICE.txt         |  11 ++
 .../src/main/resources/META-INF/beans.xml          |  20 ++
 .../src/main/resources/application.properties      |  19 ++
 .../src/main/resources/log4j2.properties           |  23 +++
 9 files changed, 522 insertions(+)

diff --git a/examples/camel-example-fhir/README.md b/examples/camel-example-fhir/README.md
new file mode 100644
index 0000000..bb08030
--- /dev/null
+++ b/examples/camel-example-fhir/README.md
@@ -0,0 +1,53 @@
+# FHIR Example - CDI
+
+### Introduction
+
+This is an example application of the `camel-fhir` component. We'll be using `camel-cdi` as well for an easy setup.
+
+This example will read HL7V2 patients from a directory and convert them to FHIR dtsu3 patients and upload them to a configured FHIR server. 
+
+The example assumes you have a running FHIR server at your disposal.
+You may use [hapi-fhir-jpa-server-example](https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-jpaserver-example)
+
+By default, the example uses `http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu3` as the FHIR server URL, DSTU3 as the FHIR version and `target/work/fhir/input`
+as the directory to look for HL7V2 patients.
+However, you can edit the `application.properties` file to override the defaults and provide your own configuration.
+
+### Build
+
+You can build this example using:
+
+```sh
+$ mvn package
+```
+
+### Run
+
+You can run this example using:
+
+```sh
+$ mvn camel:run
+```
+
+When the Camel application runs, you should see a folder created under `target/work/fhir/input`. Copy the file `hl7v2.patient`
+located in the `data` folder into it. You should see the following output:
+```
+2018-07-04 16:22:52,189 [cdi.Main.main()] INFO  DefaultCamelContext            - Route: fhir-example started and consuming from: file://target/work/fhir/input
+2018-07-04 16:22:52,189 [cdi.Main.main()] INFO  DefaultCamelContext            - Total 1 routes, of which 1 are started
+2018-07-04 16:22:52,190 [cdi.Main.main()] INFO  DefaultCamelContext            - Apache Camel 2.22.0-SNAPSHOT (CamelContext: camel-example-fhir-cdi) started in 0.636 seconds
+2018-07-04 16:22:52,203 [cdi.Main.main()] INFO  Bootstrap                      - WELD-ENV-002003: Weld SE container 357a3776-d8cd-40be-abb4-ad91a43c9755 initialized
+2018-07-04 16:22:57,705 [work/fhir/input] INFO  fhir-example                   - Converting hl7v2.patient
+2018-07-04 16:22:58,176 [work/fhir/input] INFO  fhir-example                   - Inserting Patient: {"resourceType":"Patient","id":"100005056","name":[{"family":"Freeman","given":["Vincent"]}]}
+2018-07-04 16:22:58,669 [ #3 - CamelFhir] INFO  fhir-example                   - Patient creating successfully: true
+```
+
+The Camel application can be stopped pressing <kbd>ctrl</kbd>+<kbd>c</kbd> in the shell.
+
+### Forum, Help, etc
+
+If you hit an problems please let us know on the Camel Forums
+<http://camel.apache.org/discussion-forums.html>
+
+Please help us make Apache Camel better - we appreciate any feedback you may have. Enjoy!
+
+The Camel riders!
\ No newline at end of file
diff --git a/examples/camel-example-fhir/pom.xml b/examples/camel-example-fhir/pom.xml
new file mode 100644
index 0000000..791507c
--- /dev/null
+++ b/examples/camel-example-fhir/pom.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.camel.example</groupId>
+    <artifactId>examples</artifactId>
+    <version>2.23.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>camel-example-fhir</artifactId>
+  <name>Camel :: Example :: FHIR</name>
+  <description>An example running Camel FHIR using Camel CDI </description>
+  <packaging>jar</packaging>
+
+  <properties>
+    <title>FHIR</title>
+  </properties>
+
+  <dependencies>
+
+    <!-- CDI API -->
+    <dependency>
+      <groupId>javax.enterprise</groupId>
+      <artifactId>cdi-api</artifactId>
+      <version>${cdi-api-1.2-version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <!-- Camel -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-cdi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-fhir</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-hl7</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>ca.uhn.hapi</groupId>
+      <artifactId>hapi-structures-v24</artifactId>
+      <version>${hapi-version}</version>
+    </dependency>
+
+    <!-- logging -->
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-maven-plugin</artifactId>
+        <version>${project.version}</version>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.deltaspike.cdictrl</groupId>
+            <artifactId>deltaspike-cdictrl-weld</artifactId>
+            <version>${deltaspike-version}</version>
+          </dependency>
+          <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se</artifactId>
+            <version>${weld2-version}</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+
+    </plugins>
+  </build>
+
+</project>
diff --git a/examples/camel-example-fhir/src/main/data/hl7v2.patient b/examples/camel-example-fhir/src/main/data/hl7v2.patient
new file mode 100644
index 0000000..b5ecbe7
--- /dev/null
+++ b/examples/camel-example-fhir/src/main/data/hl7v2.patient
@@ -0,0 +1 @@
+MSH|^~\&|Amalga HIS|BUM|New Tester|MS|20111121103141||ORU^R01|2847970-201111211031|P|2.4|||AL|NE|764|ASCII|||
PID||100005056|100005056||Freeman^Vincent^""^^""|""|19810813000000|F||CA|Street 1^""^""^""^34000^SGP^^""~""^""^""^""^Danling Street 5th^THA^^""||326-2275^PRN^PH^^66^675~476-5059^ORN^CP^^66^359~(123)456-7890^ORN^FX^^66^222~^NET^X.400^a@a.a~^NET^X.400^dummy@hotmail.com|(123)456-7890^WPN^PH^^66|UNK|S|BUD||BP000111899|D99999^""||CA|Bangkok|||THA||THA|""|N
PV1||OPD   ||||""^""^""||||CNSLT|||||C|VIP|||6262618|PB1||||||||||||||||||||||||20101208134638
PV2|||^Unknown|""^""||||""|""|0||""|||||||||||||||||||||||||||||HP1
ORC|NW|""|BMC1102771601|""|CM||^^^^^""|||||||||""^""^^^""
OBR|1|""|BMC1102771601|""^Brain (CT)||20111028124215||||||||||||||||||CTSCAN|F||^^^^^ROUTINE|||""||||||""|||||||||||^""
OBX|1|FT|""^Brain (CT)||++++ text of report goes here +++|||REQAT|||FINAL|||20111121103040||75929^Gosselin^Angelina
\ No newline at end of file
diff --git a/examples/camel-example-fhir/src/main/java/org/apache/camel/example/fhir/Application.java b/examples/camel-example-fhir/src/main/java/org/apache/camel/example/fhir/Application.java
new file mode 100644
index 0000000..400b3cc
--- /dev/null
+++ b/examples/camel-example-fhir/src/main/java/org/apache/camel/example/fhir/Application.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.fhir;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Named;
+import ca.uhn.hl7v2.HL7Exception;
+import ca.uhn.hl7v2.model.v24.message.ORU_R01;
+import ca.uhn.hl7v2.model.v24.segment.PID;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.cdi.ContextName;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.http.ProtocolException;
+import org.hl7.fhir.dstu3.model.Patient;
+
+public class Application {
+
+    @ContextName("camel-example-fhir-cdi")
+    static class FhirRoute extends RouteBuilder {
+
+        @Override
+        public void configure() {
+            from("file:{{input}}").routeId("fhir-example")
+                .onException(ProtocolException.class)
+                    .handled(true)
+                    .log(LoggingLevel.ERROR, "Error connecting to FHIR server with URL:{{serverUrl}}, please check the application.properties file ${exception.message}")
+                    .end()
+                .onException(HL7Exception.class)
+                    .handled(true)
+                    .log(LoggingLevel.ERROR, "Error unmarshalling ${file:name} ${exception.message}")
+                    .end()
+                .log("Converting ${file:name}")
+                // unmarshall file to hl7 message
+                .unmarshal().hl7()
+                // very simple mapping from a HLV2 patient to dstu3 patient
+                .process(exchange -> {
+                    ORU_R01 msg = exchange.getIn().getBody(ORU_R01.class);
+                    final PID pid = msg.getPATIENT_RESULT().getPATIENT().getPID();
+                    String surname = pid.getPatientName()[0].getFamilyName().getFn1_Surname().getValue();
+                    String name = pid.getPatientName()[0].getGivenName().getValue();
+                    String patientId = msg.getPATIENT_RESULT().getPATIENT().getPID().getPatientID().getCx1_ID().getValue();
+                    Patient patient = new Patient();
+                    patient.addName().addGiven(name);
+                    patient.getNameFirstRep().setFamily(surname);
+                    patient.setId(patientId);
+                    exchange.getIn().setBody(patient);
+                })
+                // marshall to JSON for logging
+                .marshal().fhirJson("{{fhirVersion}}")
+                .log("Inserting Patient: ${body}")
+                // create Patient in our FHIR server
+                .to("fhir://create/resource?inBody=resourceAsString&serverUrl={{serverUrl}}&fhirVersion={{fhirVersion}}")
+                // log the outcome
+                .log("Patient created successfully: ${body.getCreated}");
+        }
+    }
+
+    @Produces
+    @ApplicationScoped
+    @Named("properties")
+    PropertiesComponent properties() {
+        return new PropertiesComponent("classpath:application.properties");
+    }
+}
diff --git a/examples/camel-example-fhir/src/main/resources/META-INF/LICENSE.txt b/examples/camel-example-fhir/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/examples/camel-example-fhir/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
diff --git a/examples/camel-example-fhir/src/main/resources/META-INF/NOTICE.txt b/examples/camel-example-fhir/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/examples/camel-example-fhir/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.
diff --git a/examples/camel-example-fhir/src/main/resources/META-INF/beans.xml b/examples/camel-example-fhir/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..4d1f3eb
--- /dev/null
+++ b/examples/camel-example-fhir/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beans/>
\ No newline at end of file
diff --git a/examples/camel-example-fhir/src/main/resources/application.properties b/examples/camel-example-fhir/src/main/resources/application.properties
new file mode 100644
index 0000000..4699910
--- /dev/null
+++ b/examples/camel-example-fhir/src/main/resources/application.properties
@@ -0,0 +1,19 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+serverUrl=http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu3
+fhirVersion=DSTU3
+input=target/work/fhir/input
\ No newline at end of file
diff --git a/examples/camel-example-fhir/src/main/resources/log4j2.properties b/examples/camel-example-fhir/src/main/resources/log4j2.properties
new file mode 100644
index 0000000..9deb51c
--- /dev/null
+++ b/examples/camel-example-fhir/src/main/resources/log4j2.properties
@@ -0,0 +1,23 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.console.type = Console
+appender.console.name = console
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.console.ref = console


[camel] 02/03: [CAMEL-12625] Create Camel FHIR component

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 35a99d14d8fe85a2cd23fa16f36e38d9ebd6fbdc
Author: jpoth <po...@gmail.com>
AuthorDate: Thu Jul 5 16:15:23 2018 +0200

    [CAMEL-12625] Create Camel FHIR component
---
 components/camel-fhir/camel-fhir-api/pom.xml       |  98 +++++
 .../camel/component/fhir/api/ExtraParameters.java  | 157 ++++++++
 .../camel/component/fhir/api/FhirCapabilities.java |  48 +++
 .../camel/component/fhir/api/FhirCreate.java       |  83 +++++
 .../camel/component/fhir/api/FhirDelete.java       |  90 +++++
 .../camel/component/fhir/api/FhirHistory.java      | 114 ++++++
 .../camel/component/fhir/api/FhirLoadPage.java     |  78 ++++
 .../apache/camel/component/fhir/api/FhirMeta.java  | 108 ++++++
 .../apache/camel/component/fhir/api/FhirPatch.java | 103 ++++++
 .../apache/camel/component/fhir/api/FhirRead.java  | 142 +++++++
 .../camel/component/fhir/api/FhirSearch.java       |  54 +++
 .../camel/component/fhir/api/FhirTransaction.java  |  72 ++++
 .../camel/component/fhir/api/FhirUpdate.java       |  80 ++++
 .../camel/component/fhir/api/FhirValidate.java     |  47 +++
 components/camel-fhir/camel-fhir-component/pom.xml | 353 ++++++++++++++++++
 .../signatures/capabilities-sig-api.txt            |  11 +-
 .../signatures/history-sig-api.txt                 |  19 +
 .../signatures/load-page-sig-api.txt}              |  21 +-
 .../signatures/meta-sig-api.txt                    |  21 ++
 .../src/main/docs/fhir-component.adoc              | 121 ++++++
 .../src/main/docs/fhirJson-dataformat.adoc         |   0
 .../src/main/docs/fhirXml-dataformat.adoc          |   0
 .../apache/camel/component/fhir/FhirComponent.java |  86 +++++
 .../camel/component/fhir/FhirConfiguration.java    | 378 +++++++++++++++++++
 .../apache/camel/component/fhir/FhirConsumer.java  |  32 ++
 .../apache/camel/component/fhir/FhirEndpoint.java  | 166 +++++++++
 .../camel/component/fhir/FhirJsonDataFormat.java   |   0
 .../apache/camel/component/fhir/FhirProducer.java  |  31 ++
 .../camel/component/fhir/FhirXmlDataFormat.java    |   0
 .../component/fhir/internal/FhirConstants.java     |  29 ++
 .../camel/component/fhir/internal/FhirHelper.java  | 150 ++++++++
 .../fhir/internal/FhirPropertiesHelper.java        |  39 ++
 .../services/org/apache/camel/component/fhir       |   1 +
 .../services/org/apache/camel/dataformat/fhirJson  |   0
 .../services/org/apache/camel/dataformat/fhirXml   |   0
 .../component/fhir/AbstractFhirTestSupport.java    | 133 +++++++
 .../camel/component/fhir/FhirCapabilitiesIT.java   |  72 ++++
 .../camel/component/fhir/FhirConfigurationIT.java  |  94 +++++
 .../apache/camel/component/fhir/FhirCreateIT.java  |  92 +++++
 .../fhir/FhirCustomClientConfigurationIT.java      | 409 +++++++++++++++++++++
 .../apache/camel/component/fhir/FhirDeleteIT.java  | 127 +++++++
 .../component/fhir/FhirExtraParametersIT.java      |  67 ++++
 .../apache/camel/component/fhir/FhirHistoryIT.java | 123 +++++++
 .../fhir/FhirJsonDataFormatSpringTest.java         |   0
 .../component/fhir/FhirJsonDataFormatTest.java     |   0
 .../camel/component/fhir/FhirLoadPageIT.java       | 164 +++++++++
 .../apache/camel/component/fhir/FhirMetaIT.java    | 169 +++++++++
 .../apache/camel/component/fhir/FhirPatchIT.java   | 139 +++++++
 .../apache/camel/component/fhir/FhirReadIT.java    | 275 ++++++++++++++
 .../apache/camel/component/fhir/FhirSearchIT.java  |  60 +++
 .../camel/component/fhir/FhirTransactionIT.java    | 132 +++++++
 .../apache/camel/component/fhir/FhirUpdateIT.java  | 196 ++++++++++
 .../camel/component/fhir/FhirValidateIT.java       |  78 ++++
 .../fhir/FhirXmlDataFormatSpringTest.java          |   0
 .../component/fhir/FhirXmlDataFormatTest.java      |   0
 .../Hl7v2PatientToFhirPatientIntegrationTest.java} |  27 +-
 .../camel/component/fhir/PatientProcessor.java     |  27 +-
 .../camel/component/fhir/UrlFetcherTest.java       |  39 ++
 .../src/test/resources/log4j2.properties           |   0
 .../fhir/json/FhirJsonDataFormatSpringTest.xml     |   0
 .../fhir/xml/FhirXmlDataFormatSpringTest.xml       |   0
 .../src/test/resources/test-options.properties     |   7 +-
 components/camel-fhir/pom.xml                      | 131 +------
 docs/user-manual/en/SUMMARY.md                     |   1 +
 examples/pom.xml                                   |   1 +
 parent/pom.xml                                     |   5 +
 .../springboot/FhirComponentAutoConfiguration.java | 128 +++++++
 .../springboot/FhirComponentConfiguration.java     | 267 ++++++++++++++
 .../src/main/resources/META-INF/spring.factories   |   5 +-
 69 files changed, 5505 insertions(+), 195 deletions(-)

diff --git a/components/camel-fhir/camel-fhir-api/pom.xml b/components/camel-fhir/camel-fhir-api/pom.xml
new file mode 100644
index 0000000..9a097bf
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-fhir-parent</artifactId>
+    <version>2.23.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>camel-fhir-api</artifactId>
+  <name>Camel :: FHIR :: API</name>
+  <description>Camel FHIR API</description>
+  <packaging>jar</packaging>
+
+  <properties>
+    <camel.osgi.export.pkg>org.apache.camel.component.fhir.api*</camel.osgi.export.pkg>
+
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>ca.uhn.hapi.fhir</groupId>
+      <artifactId>hapi-fhir-base</artifactId>
+      <version>${hapi-fhir-version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <defaultGoal>install</defaultGoal>
+
+    <plugins>
+      
+      <!-- to generate API Javadoc -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-javadoc</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+            <configuration>
+              <attach>true</attach>
+              <source>${jdk.version}</source>
+              <quiet>true</quiet>
+              <detectOfflineLinks>false</detectOfflineLinks>
+              <javadocVersion>${jdk.version}</javadocVersion>
+              <encoding>UTF-8</encoding>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+    </plugins>
+  </build>
+
+  <!-- Disable Java 8 doclint checks to avoid Javadoc plugin failures -->
+  <profiles>
+    <profile>
+      <id>doclint-java8-disable</id>
+      <activation>
+        <jdk>[1.8,</jdk>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <additionalparam>-Xdoclint:none</additionalparam>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/ExtraParameters.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/ExtraParameters.java
new file mode 100644
index 0000000..4783c58
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/ExtraParameters.java
@@ -0,0 +1,157 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.List;
+import java.util.Map;
+import ca.uhn.fhir.rest.api.CacheControlDirective;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import ca.uhn.fhir.rest.api.SummaryEnum;
+import ca.uhn.fhir.rest.gclient.IClientExecutable;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+/**
+ * Encapsulates a list of extra parameters that are valid for *ALL* Camel FHIR APIs.
+ */
+public enum ExtraParameters {
+
+    /**
+     * Will encode the request to JSON
+     */
+    ENCODE_JSON("encodeJson"),
+
+    /**
+     * Will encode the request to XML
+     */
+    ENCODE_XML("encodeXml"),
+
+    /**
+     * Sets the <code>Cache-Control</code> header value, which advises the server (or any cache in front of it)
+     * how to behave in terms of cached requests"
+     */
+    CACHE_CONTROL_DIRECTIVE("cacheControlDirective"),
+
+    /**
+     * Request that the server return subsetted resources, containing only the elements specified in the given parameters.
+     * For example: <code>subsetElements("name", "identifier")</code> requests that the server only return
+     * the "name" and "identifier" fields in the returned resource, and omit any others.
+     */
+    SUBSET_ELEMENTS("subsetElements"),
+
+
+    ENCODING_ENUM("encodingEnum"),
+
+    /**
+     * Explicitly specify a custom structure type to attempt to use when parsing the response. This
+     * is useful for invocations where the response is a Bundle/Parameters containing nested resources,
+     * and you want to use specific custom structures for those nested resources.
+     * <p>
+     * See <a href="https://jamesagnew.github.io/hapi-fhir/doc_extensions.html">Profiles and Extensions</a> for more information on using custom structures
+     * </p>
+     */
+    PREFER_RESPONSE_TYPE("preferredResponseType"),
+
+    /**
+     * Explicitly specify a custom structure type to attempt to use when parsing the response. This
+     * is useful for invocations where the response is a Bundle/Parameters containing nested resources,
+     * and you want to use specific custom structures for those nested resources.
+     * <p>
+     * See <a href="https://jamesagnew.github.io/hapi-fhir/doc_extensions.html">Profiles and Extensions</a> for more information on using custom structures
+     * </p>
+     */
+    PREFER_RESPONSE_TYPES("preferredResponseTypes"),
+
+    /**
+     * Pretty print the request
+     */
+    PRETTY_PRINT("prettyPrint"),
+
+    /**
+     * Request that the server modify the response using the <code>_summary</code> param
+     */
+    SUMMARY_ENUM("summaryEnum");
+
+    private final String param;
+    private final String headerName;
+
+    ExtraParameters(String param) {
+        this.param = param;
+        this.headerName = "CamelFhir." + param;
+    }
+
+    public String getParam() {
+        return param;
+    }
+
+    public String getHeaderName() {
+        return headerName;
+    }
+
+    static <T extends IClientExecutable<?, ?>> void process(Map<ExtraParameters, Object> extraParameters, T clientExecutable) {
+        if (extraParameters == null) {
+            return;
+        }
+        for (Map.Entry<ExtraParameters, Object> entry : extraParameters.entrySet()) {
+            switch (entry.getKey()) {
+            case ENCODE_JSON:
+                Boolean encode = (Boolean) extraParameters.get(ENCODE_JSON);
+                if (encode) {
+                    clientExecutable.encodedJson();
+                }
+                break;
+            case ENCODE_XML:
+                Boolean encodeXml = (Boolean) extraParameters.get(ENCODE_XML);
+                if (encodeXml) {
+                    clientExecutable.encodedXml();
+                }
+                break;
+            case CACHE_CONTROL_DIRECTIVE:
+                CacheControlDirective cacheControlDirective = (CacheControlDirective) extraParameters.get(CACHE_CONTROL_DIRECTIVE);
+                clientExecutable.cacheControl(cacheControlDirective);
+                break;
+            case SUBSET_ELEMENTS:
+                String[] subsetElements = (String[]) extraParameters.get(SUBSET_ELEMENTS);
+                clientExecutable.elementsSubset(subsetElements);
+                break;
+            case ENCODING_ENUM:
+                EncodingEnum encodingEnum = (EncodingEnum) extraParameters.get(ENCODING_ENUM);
+                clientExecutable.encoded(encodingEnum);
+                break;
+            case PREFER_RESPONSE_TYPE:
+                Class<? extends IBaseResource> type = (Class<? extends IBaseResource>) extraParameters.get(PREFER_RESPONSE_TYPE);
+                clientExecutable.preferResponseType(type);
+                break;
+            case PREFER_RESPONSE_TYPES:
+                List<Class<? extends IBaseResource>> types = (List<Class<? extends IBaseResource>>) extraParameters.get(PREFER_RESPONSE_TYPES);
+                clientExecutable.preferResponseTypes(types);
+                break;
+            case PRETTY_PRINT:
+                Boolean prettyPrint = (Boolean) extraParameters.get(PRETTY_PRINT);
+                if (prettyPrint) {
+                    clientExecutable.prettyPrint();
+                }
+                break;
+            case SUMMARY_ENUM:
+                SummaryEnum summary = (SummaryEnum) extraParameters.get(SUMMARY_ENUM);
+                clientExecutable.summaryMode(summary);
+                break;
+            default:
+                throw new IllegalArgumentException("Unsupported FHIR extra parameter parameter: " + entry.getKey());
+            }
+        }
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCapabilities.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCapabilities.java
new file mode 100644
index 0000000..ba269a2
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCapabilities.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IFetchConformanceTyped;
+import org.hl7.fhir.instance.model.api.IBaseConformance;
+
+/**
+ * API to Fetch the capability statement for the server
+ */
+public class FhirCapabilities {
+
+    private final IGenericClient client;
+
+    public FhirCapabilities(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Retrieve the conformance statement using the given model type
+     * @param type the model type
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param <T> extends {@link IBaseConformance}
+     * @return the conformance statement
+     */
+    public <T extends IBaseConformance> T ofType(Class<T> type, Map<ExtraParameters, Object> extraParameters) {
+        IFetchConformanceTyped<T> fetchConformanceTyped = client.capabilities().ofType(type);
+        ExtraParameters.process(extraParameters, fetchConformanceTyped);
+        return fetchConformanceTyped.execute();
+    }
+
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCreate.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCreate.java
new file mode 100644
index 0000000..91ad4bd
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirCreate.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.PreferReturnEnum;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.ICreateTyped;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+/**
+ * API for the "create" operation, which creates a new resource instance on the server
+ */
+public class FhirCreate {
+
+    private final IGenericClient client;
+
+    public FhirCreate(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Creates a {@link IBaseResource} on the server
+     *
+     * @param resource The resource to create
+     * @param url The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
+     *                     for example: <code>Patient?name=Smith&amp;identifier=13.2.4.11.4%7C847366</code>, may be null
+     * @param preferReturn Add a <code>Prefer</code> header to the request, which requests that the server include
+     *                  or suppress the resource body as a part of the result. If a resource is returned by the server
+     *                  it will be parsed an accessible to the client via {@link MethodOutcome#getResource()}, may be null
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return The {@link MethodOutcome}
+     */
+    public MethodOutcome resource(IBaseResource resource, String url, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        ICreateTyped createTyped = client.create().resource(resource);
+        processOptionalParams(url, preferReturn, createTyped);
+        ExtraParameters.process(extraParameters, createTyped);
+        return createTyped.execute();
+    }
+
+    /**
+     * Creates a {@link IBaseResource} on the server
+     *
+     * @param resourceAsString The resource to create
+     * @param url The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
+     *                     for example: <code>Patient?name=Smith&amp;identifier=13.2.4.11.4%7C847366</code>, may be null
+     * @param preferReturn Add a <code>Prefer</code> header to the request, which requests that the server include
+     *                  or suppress the resource body as a part of the result. If a resource is returned by the server
+     *                  it will be parsed an accessible to the client via {@link MethodOutcome#getResource()}, may be null
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return The {@link MethodOutcome}
+     */
+    public MethodOutcome resource(String resourceAsString, String url, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        ICreateTyped createTyped = client.create().resource(resourceAsString);
+        processOptionalParams(url, preferReturn, createTyped);
+        ExtraParameters.process(extraParameters, createTyped);
+        return createTyped.execute();
+    }
+
+    private void processOptionalParams(String theSearchUrl, PreferReturnEnum theReturn, ICreateTyped createTyped) {
+        if (theSearchUrl != null) {
+            createTyped.conditionalByUrl(theSearchUrl);
+        }
+        if (theReturn != null) {
+            createTyped.prefer(theReturn);
+        }
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirDelete.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirDelete.java
new file mode 100644
index 0000000..d559da6
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirDelete.java
@@ -0,0 +1,90 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IDeleteTyped;
+import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+
+/**
+ * API for the "delete" operation, which performs a logical delete on a server resource.
+ */
+public class FhirDelete {
+
+    private final IGenericClient client;
+
+    public FhirDelete(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Deletes the given resource
+     *
+     * @param resource the {@link IBaseResource} to delete
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseOperationOutcome}
+     */
+    public IBaseOperationOutcome resource(IBaseResource resource, Map<ExtraParameters, Object> extraParameters) {
+        IDeleteTyped deleteTyped = client.delete().resource(resource);
+        ExtraParameters.process(extraParameters, deleteTyped);
+        return deleteTyped.execute();
+    }
+
+    /**
+     * * Deletes the given resource by {@link IIdType}
+     *
+     * @param id the {@link IIdType} referencing the resource
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseOperationOutcome}
+     */
+    public IBaseOperationOutcome resourceById(IIdType id, Map<ExtraParameters, Object> extraParameters) {
+        IDeleteTyped deleteTyped = client.delete().resourceById(id);
+        ExtraParameters.process(extraParameters, deleteTyped);
+        return deleteTyped.execute();
+    }
+
+    /**
+     * Deletes the resource by resource type e.g "Patient" and it's id
+     * @param type the resource type e.g "Patient"
+     * @param stringId it's id
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseOperationOutcome}
+     */
+    public IBaseOperationOutcome resourceById(String type, String stringId, Map<ExtraParameters, Object> extraParameters) {
+        IDeleteTyped deleteTyped = client.delete().resourceById(type, stringId);
+        ExtraParameters.process(extraParameters, deleteTyped);
+        return deleteTyped.execute();
+    }
+
+    /**
+     * Specifies that the delete should be performed as a conditional delete against a given search URL.
+     * @param url The search URL to use. The format of this URL should be of the form
+     *            <code>[ResourceType]?[Parameters]</code>,
+     *            for example: <code>Patient?name=Smith&amp;identifier=13.2.4.11.4%7C847366</code>
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseOperationOutcome}
+     */
+    public IBaseOperationOutcome resourceConditionalByUrl(String url, Map<ExtraParameters, Object> extraParameters) {
+        IDeleteTyped deleteTyped = client.delete().resourceConditionalByUrl(url);
+        ExtraParameters.process(extraParameters, deleteTyped);
+        return deleteTyped.execute();
+    }
+
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java
new file mode 100644
index 0000000..e477c53
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Date;
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IHistoryTyped;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.hl7.fhir.instance.model.api.IBaseConformance;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.hl7.fhir.instance.model.api.IPrimitiveType;
+
+/**
+ * API for the "history" method
+ */
+public class FhirHistory {
+
+    private final IGenericClient client;
+
+    public FhirHistory(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Perform the operation across all versions of all resources of all types on the server
+     *
+     * @param returnType Request that the method return a Bundle resource (such as <code>ca.uhn.fhir.model.dstu2.resource.Bundle</code>).
+     *                Use this method if you are accessing a DSTU2+ server.
+     * @param count Request that the server return only up to <code>theCount</code> number of resources, may be NULL
+     * @param cutoff Request that the server return only resource versions that were created at or after the given time (inclusive), may be NULL
+     * @param iCutoff Request that the server return only resource versions that were created at or after the given time (inclusive), may be NULL
+     * @param <T> extends {@link IBaseBundle}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseBundle}
+     */
+    public <T extends IBaseBundle> T onServer(Class<T> returnType, Integer count, Date cutoff, IPrimitiveType<Date> iCutoff, Map<ExtraParameters, Object> extraParameters) {
+        IHistoryTyped<T> tiHistoryTyped = client.history().onServer().andReturnBundle(returnType);
+        processOptionalParams(count, cutoff, iCutoff, tiHistoryTyped);
+        ExtraParameters.process(extraParameters, tiHistoryTyped);
+        return tiHistoryTyped.execute();
+    }
+
+    /**
+     * Perform the operation across all versions of all resources of the given type on the server
+     *
+     * @param resourceType The resource type to search for
+     * @param returnType Request that the method return a Bundle resource (such as <code>ca.uhn.fhir.model.dstu2.resource.Bundle</code>).
+     *                Use this method if you are accessing a DSTU2+ server.
+     * @param count Request that the server return only up to <code>theCount</code> number of resources, may be NULL
+     * @param cutoff Request that the server return only resource versions that were created at or after the given time (inclusive), may be NULL
+     * @param iCutoff Request that the server return only resource versions that were created at or after the given time (inclusive), may be NULL
+     * @param <T> extends {@link IBaseBundle}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseBundle}
+     */
+    public <T extends IBaseBundle> T onType(Class<IBaseResource> resourceType, Class<T> returnType, Integer count, Date cutoff,
+                                            IPrimitiveType<Date> iCutoff, Map<ExtraParameters, Object> extraParameters) {
+        IHistoryTyped<T> tiHistoryTyped = client.history().onType(resourceType).andReturnBundle(returnType);
+        processOptionalParams(count, cutoff, iCutoff, tiHistoryTyped);
+        ExtraParameters.process(extraParameters, tiHistoryTyped);
+        return tiHistoryTyped.execute();
+    }
+
+    /**
+     * Perform the operation across all versions of a specific resource (by ID and type) on the server.
+     * Note that <code>theId</code> must be populated with both a resource type and a resource ID at
+     * a minimum.
+     * @param id the {@link IIdType} which must be populated with both a resource type and a resource ID at
+     * @param returnType Request that the method return a Bundle resource (such as <code>ca.uhn.fhir.model.dstu2.resource.Bundle</code>).
+     *                Use this method if you are accessing a DSTU2+ server.
+     * @param count Request that the server return only up to <code>theCount</code> number of resources, may be NULL
+     * @param cutoff Request that the server return only resource versions that were created at or after the given time (inclusive), may be NULL
+     * @param iCutoff Request that the server return only resource versions that were created at or after the given time (inclusive), may be NULL
+     * @param <T> extends {@link IBaseBundle}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @throws IllegalArgumentException If <code>theId</code> does not contain at least a resource type and ID
+     * @return the {@link IBaseBundle}
+     */
+    public <T extends IBaseBundle> T onInstance(IIdType id, Class<T> returnType, Integer count, Date cutoff, IPrimitiveType<Date> iCutoff, Map<ExtraParameters, Object> extraParameters) {
+        IHistoryTyped<T> tiHistoryTyped = client.history().onInstance(id).andReturnBundle(returnType);
+        processOptionalParams(count, cutoff, iCutoff, tiHistoryTyped);
+        ExtraParameters.process(extraParameters, tiHistoryTyped);
+        return tiHistoryTyped.execute();
+    }
+
+    private <T extends IBaseBundle> void processOptionalParams(Integer count, Date theCutoff, IPrimitiveType<Date> cutoff, IHistoryTyped<T> tiHistoryTyped) {
+        if (count != null) {
+            tiHistoryTyped.count(count);
+        }
+        if (theCutoff != null) {
+            tiHistoryTyped.since(theCutoff);
+        }
+        if (cutoff != null) {
+            tiHistoryTyped.since(cutoff);
+        }
+    }
+
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirLoadPage.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirLoadPage.java
new file mode 100644
index 0000000..4ff42a4
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirLoadPage.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IGetPageTyped;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+
+/**
+ * API that Loads the previous/next bundle of resources from a paged set, using the link specified in the "link type=next" tag within the atom bundle.
+ */
+public class FhirLoadPage {
+
+    private final IGenericClient client;
+
+    public FhirLoadPage(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Load the next page of results using the link with relation "next" in the bundle. This
+     * method accepts a DSTU2 Bundle resource
+     * @param <T> extends {@link IBaseBundle}
+     * @param bundle the {@link IBaseBundle}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the next {@link IBaseBundle}
+     */
+    public <T extends IBaseBundle> T next(T bundle, Map<ExtraParameters, Object> extraParameters) {
+        IGetPageTyped<T> getPageTyped = client.loadPage().next(bundle);
+        ExtraParameters.process(extraParameters, getPageTyped);
+        return getPageTyped.execute();
+    }
+
+    /**
+     * Load the previous page of results using the link with relation "prev" in the bundle. This
+     * method accepts a DSTU2+ Bundle resource
+     * @param <T> extends {@link IBaseBundle}
+     * @param bundle the {@link IBaseBundle}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the previous {@link IBaseBundle}
+     */
+    public <T extends IBaseBundle> T previous(T bundle, Map<ExtraParameters, Object> extraParameters) {
+        IGetPageTyped<T> getPageTyped = client.loadPage().previous(bundle);
+        ExtraParameters.process(extraParameters, getPageTyped);
+        return getPageTyped.execute();
+    }
+
+    /**
+     * Load a page of results using the given URL and bundle type and return a DSTU1 Atom bundle
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param <T> extends {@link IBaseBundle}
+     * @param url the search url
+     * @param returnType the return type
+     * @return the {@link IBaseBundle} page
+     */
+    public <T extends IBaseBundle> T byUrl(String url, Class<T> returnType, Map<ExtraParameters, Object> extraParameters) {
+        IGetPageTyped<T> getPageTyped = client.loadPage().byUrl(url).andReturnBundle(returnType);
+        ExtraParameters.process(extraParameters, getPageTyped);
+        return getPageTyped.execute();
+    }
+
+
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirMeta.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirMeta.java
new file mode 100644
index 0000000..5bd6e99
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirMeta.java
@@ -0,0 +1,108 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IClientExecutable;
+import ca.uhn.fhir.rest.gclient.IMeta;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.hl7.fhir.instance.model.api.IBaseMetaType;
+import org.hl7.fhir.instance.model.api.IIdType;
+
+/**
+ * API for the "meta" operations, which can be used to get, add and remove tags and other
+ * Meta elements from a resource or across the server.
+ */
+public class FhirMeta {
+
+    private final IGenericClient client;
+
+    public FhirMeta(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Fetch the current metadata from the whole Server
+     *
+     * @param metaType The type of the meta datatype for the given FHIR model version (should be <code>MetaDt.class</code> or <code>MetaType.class</code>)
+     * @param <T> extends {@link IBaseMetaType}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseMetaType}
+     */
+    public <T extends IBaseMetaType> T getFromServer(Class<T> metaType, Map<ExtraParameters, Object> extraParameters) {
+        IClientExecutable<IClientExecutable<?, T>, T> clientExecutable = client.meta().get(metaType).fromServer();
+        ExtraParameters.process(extraParameters, clientExecutable);
+        return clientExecutable.execute();
+    }
+
+    /**
+     * Fetch the current metadata from a specific resource
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param metaType the {@link IBaseMetaType} class
+     * @param id the id
+     * @param <T> extends {@link IBaseMetaType}
+     * @return the {@link IBaseMetaType}
+     */
+    public <T extends IBaseMetaType> T getFromResource(Class<T> metaType, IIdType id, Map<ExtraParameters, Object> extraParameters) {
+        IClientExecutable<IClientExecutable<?, T>, T> clientExecutable = client.meta().get(metaType).fromResource(id);
+        ExtraParameters.process(extraParameters, clientExecutable);
+        return clientExecutable.execute();
+    }
+
+    /**
+     * Fetch the current metadata from a specific type
+     * @param <T> extends {@link IBaseMetaType}
+     * @param metaType the {@link IBaseMetaType} class
+     * @param resourceType the resource type e.g "Patient"
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseMetaType}
+     */
+    public <T extends IBaseMetaType> T getFromType(Class<T> metaType, String resourceType, Map<ExtraParameters, Object> extraParameters) {
+        IClientExecutable<IClientExecutable<?, T>, T> clientExecutable = client.meta().get(metaType).fromType(resourceType);
+        ExtraParameters.process(extraParameters, clientExecutable);
+        return clientExecutable.execute();
+    }
+
+    /**
+     * Add the elements in the given metadata to the already existing set (do not remove any)
+     * @param <T> extends {@link IBaseMetaType}
+     * @param id the id
+     * @param meta the {@link IBaseMetaType} class
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseMetaType}
+     */
+    public <T extends IBaseMetaType> T add(T meta, IIdType id, Map<ExtraParameters, Object> extraParameters) {
+        IClientExecutable<IClientExecutable<?, T>, T> clientExecutable = client.meta().add().onResource(id).meta(meta);
+        ExtraParameters.process(extraParameters, clientExecutable);
+        return clientExecutable.execute();
+    }
+
+    /**
+     * Delete the elements in the given metadata from the given id
+     * @param <T> extends {@link IBaseMetaType}
+     * @param id the id
+     * @param meta the {@link IBaseMetaType} class
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseMetaType}
+     */
+    public <T extends IBaseMetaType> T delete(T meta, IIdType id, Map<ExtraParameters, Object> extraParameters) {
+        IClientExecutable<IClientExecutable<?, T>, T> clientExecutable = client.meta().delete().onResource(id).meta(meta);
+        ExtraParameters.process(extraParameters, clientExecutable);
+        return clientExecutable.execute();
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirPatch.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirPatch.java
new file mode 100644
index 0000000..ecdd70d
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirPatch.java
@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.PreferReturnEnum;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IPatchExecutable;
+import org.hl7.fhir.instance.model.api.IBaseMetaType;
+import org.hl7.fhir.instance.model.api.IIdType;
+
+/**
+ * API for the "patch" operation, which performs a logical patch on a server resource
+ */
+public class FhirPatch {
+
+    private final IGenericClient client;
+
+    public FhirPatch(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Specifies that the update should be performed as a conditional create
+     * against a given search URL.
+     *
+     * @param url The search URL to use. The format of this URL should be of the form <code>[ResourceType]?[Parameters]</code>,
+     *            for example: <code>Patient?name=Smith&amp;identifier=13.2.4.11.4%7C847366</code>
+     * @param patchBody The body of the patch document serialized in either XML or JSON which conforms to
+     *                  http://jsonpatch.com/ or http://tools.ietf.org/html/rfc5261
+     * @param preferReturn Add a <code>Prefer</code> header to the request, which requests that the server include
+     *                     or suppress the resource body as a part of the result. If a resource is returned by the server
+     *                     it will be parsed an accessible to the client via {@link MethodOutcome#getResource()}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link MethodOutcome}
+     */
+    public MethodOutcome patchByUrl(String patchBody, String url, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IPatchExecutable patchExecutable = client.patch().withBody(patchBody).conditionalByUrl(url);
+        if (preferReturn != null) {
+            patchExecutable.prefer(preferReturn);
+        }
+        ExtraParameters.process(extraParameters, patchExecutable);
+        return patchExecutable.execute();
+    }
+
+    /**
+     * Applies the patch to the given resource ID
+     *
+     * @param patchBody The body of the patch document serialized in either XML or JSON which conforms to
+     *                  http://jsonpatch.com/ or http://tools.ietf.org/html/rfc5261
+     * @param id The resource ID to patch
+     * @param preferReturn Add a <code>Prefer</code> header to the request, which requests that the server include
+     *                     or suppress the resource body as a part of the result. If a resource is returned by the server
+     *                     it will be parsed an accessible to the client via {@link MethodOutcome#getResource()}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link MethodOutcome}
+     */
+    public MethodOutcome patchById(String patchBody, IIdType id, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IPatchExecutable patchExecutable = client.patch().withBody(patchBody).withId(id);
+        if (preferReturn != null) {
+            patchExecutable.prefer(preferReturn);
+        }
+        ExtraParameters.process(extraParameters, patchExecutable);
+        return patchExecutable.execute();
+    }
+
+    /**
+     * Applies the patch to the given resource ID
+     *
+     * @param patchBody The body of the patch document serialized in either XML or JSON which conforms to
+     *                  http://jsonpatch.com/ or http://tools.ietf.org/html/rfc5261
+     * @param stringId The resource ID to patch
+     * @param preferReturn Add a <code>Prefer</code> header to the request, which requests that the server include
+     *                     or suppress the resource body as a part of the result. If a resource is returned by the server
+     *                     it will be parsed an accessible to the client via {@link MethodOutcome#getResource()}
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link MethodOutcome}
+     */
+    public MethodOutcome patchById(String patchBody, String stringId, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IPatchExecutable patchExecutable = client.patch().withBody(patchBody).withId(stringId);
+        if (preferReturn != null) {
+            patchExecutable.prefer(preferReturn);
+        }
+        ExtraParameters.process(extraParameters, patchExecutable);
+        return patchExecutable.execute();
+    }
+
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirRead.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirRead.java
new file mode 100644
index 0000000..f01292b
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirRead.java
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IReadExecutable;
+import ca.uhn.fhir.rest.gclient.IReadIfNoneMatch;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * API method for "read" operations
+ */
+public class FhirRead {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirRead.class);
+    private final IGenericClient client;
+
+
+    public FhirRead(IGenericClient client) {
+        this.client = client;
+    }
+
+
+    public IBaseResource resourceById(Class<IBaseResource> resource, IIdType id, String ifVersionMatches,
+                                      Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resource).withId(id);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceById(String resourceClass, IIdType id, String ifVersionMatches, Boolean returnNull,
+                                      IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resourceClass).withId(id);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceByUrl(Class<IBaseResource> resource, IIdType iUrl, String ifVersionMatches,
+                                       Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resource).withUrl(iUrl);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceByUrl(String resourceClass, IIdType iUrl, String ifVersionMatches, Boolean returnNull,
+                                       IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resourceClass).withUrl(iUrl);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource  resourceById(Class<IBaseResource> resource, String stringId, String ifVersionMatches,
+                                       Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resource).withId(stringId);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceByUrl(Class<IBaseResource> resource, String url, String ifVersionMatches,
+                                       Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resource).withUrl(url);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceById(String resourceClass, String stringId, String ifVersionMatches,
+                                      Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resourceClass).withId(stringId);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceByIdAndVersion(String resourceClass, String stringId, String version,
+                                                String ifVersionMatches, Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resourceClass).withIdAndVersion(stringId, version);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceByIdAndVersion(Class<IBaseResource> resource, String stringId, String version,
+                                                String ifVersionMatches, Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resource).withIdAndVersion(stringId, version);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceByUrl(String resourceClass, String url, String ifVersionMatches, Boolean returnNull,
+                                       IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resourceClass).withUrl(url);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceById(Class<IBaseResource> resource, Long longId, String ifVersionMatches,
+                                      Boolean returnNull, IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resource).withId(longId);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+    public IBaseResource resourceById(String resourceClass, Long longId, String ifVersionMatches, Boolean returnNull,
+                                      IBaseResource returnResource, Boolean throwError, Map<ExtraParameters, Object> extraParameters) {
+        IReadExecutable<IBaseResource> readExecutable = client.read().resource(resourceClass).withId(longId);
+        ExtraParameters.process(extraParameters, readExecutable);
+        return processOptionalParams(ifVersionMatches, returnNull, returnResource, throwError, readExecutable);
+    }
+
+
+    private IBaseResource processOptionalParams(String ifVersionMatches, Boolean returnNull, IBaseResource returnResource,
+                                                Boolean throwError, IReadExecutable<IBaseResource> readExecutable) {
+        if (ifVersionMatches != null) {
+            IReadIfNoneMatch<IBaseResource> tiReadIfNoneMatch = readExecutable.ifVersionMatches(ifVersionMatches);
+            if (returnNull != null  && returnNull) {
+                return tiReadIfNoneMatch.returnNull().execute();
+            } else if (returnResource != null) {
+                return tiReadIfNoneMatch.returnResource(returnResource).execute();
+            } else if (throwError != null) {
+                return tiReadIfNoneMatch.throwNotModifiedException().execute();
+            }
+            LOG.warn("No operation was specified with the If-None-Match header, ignoring");
+        }
+        return readExecutable.execute();
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirSearch.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirSearch.java
new file mode 100644
index 0000000..ed74aec
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirSearch.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IQuery;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+
+/**
+ * API to search for resources matching a given set of criteria. Searching is a very powerful
+ * feature in FHIR with many features for specifying exactly what should be searched for
+ * and how it should be returned. See the <a href="http://www.hl7.org/fhir/search.html">specification on search</a>
+ * for more information.
+ */
+public class FhirSearch {
+
+    private final IGenericClient client;
+
+    public FhirSearch(IGenericClient client) {
+        this.client = client;
+    }
+
+
+    /**
+     * Perform a search directly by URL.
+     *
+     * @param url The URL to search for. Note that this URL may be complete (e.g. "http://example.com/base/Patient?name=foo") in which case the client's base URL will be ignored. Or it can be relative
+     *            (e.g. "Patient?name=foo") in which case the client's base URL will be used.
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseBundle}
+     */
+    public IBaseBundle searchByUrl(String url, Map<ExtraParameters, Object> extraParameters) {
+        IQuery<IBaseBundle> query = client.search().byUrl(url);
+        ExtraParameters.process(extraParameters, query);
+        return query.execute();
+    }
+
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirTransaction.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirTransaction.java
new file mode 100644
index 0000000..c0f6ba2
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirTransaction.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.List;
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.ITransactionTyped;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+/**
+ * API for sending a transaction (collection of resources) to the server to be executed as a single unit.
+ */
+public class FhirTransaction {
+
+    private final IGenericClient client;
+
+    public FhirTransaction(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Use a list of resources as the transaction input
+     * @param resources resources to use in the transaction
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseResource}s
+     */
+    public List<IBaseResource> withResources(List<IBaseResource> resources, Map<ExtraParameters, Object> extraParameters) {
+        ITransactionTyped<List<IBaseResource>> transactionTyped = client.transaction().withResources(resources);
+        ExtraParameters.process(extraParameters, transactionTyped);
+        return transactionTyped.execute();
+    }
+
+    /**
+     * Use the given Bundle resource as the transaction input
+     * @param bundle bundle to use in the transaction
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseBundle}
+     */
+    public IBaseBundle withBundle(IBaseBundle bundle, Map<ExtraParameters, Object> extraParameters) {
+        ITransactionTyped<IBaseBundle> transactionTyped = client.transaction().withBundle(bundle);
+        ExtraParameters.process(extraParameters, transactionTyped);
+        return transactionTyped.execute();
+    }
+
+    /**
+     * Use the given raw text (should be a Bundle resource) as the transaction input
+     * @param stringBundle bundle to use in the transaction
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @return the {@link IBaseBundle} as string
+     */
+    public String withBundle(String stringBundle, Map<ExtraParameters, Object> extraParameters) {
+        ITransactionTyped<String> transactionTyped = client.transaction().withBundle(stringBundle);
+        ExtraParameters.process(extraParameters, transactionTyped);
+        return transactionTyped.execute();
+    }
+}
\ No newline at end of file
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirUpdate.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirUpdate.java
new file mode 100644
index 0000000..28e2a85
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirUpdate.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.PreferReturnEnum;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IUpdateExecutable;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+
+/**
+ * API for the "update" operation, which performs a logical delete on a server resource
+ */
+public class FhirUpdate {
+
+    private final IGenericClient client;
+
+    public FhirUpdate(IGenericClient client) {
+        this.client = client;
+    }
+
+    public MethodOutcome resource(IBaseResource resource, IIdType id, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IUpdateExecutable updateExecutable = client.update().resource(resource).withId(id);
+        ExtraParameters.process(extraParameters, updateExecutable);
+        return processOptionalParam(preferReturn, updateExecutable);
+    }
+
+    public MethodOutcome resource(String resourceAsString, IIdType id, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IUpdateExecutable updateExecutable = client.update().resource(resourceAsString).withId(id);
+        ExtraParameters.process(extraParameters, updateExecutable);
+        return processOptionalParam(preferReturn, updateExecutable);
+    }
+
+    public MethodOutcome resource(IBaseResource resource, String stringId, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IUpdateExecutable updateExecutable = client.update().resource(resource).withId(stringId);
+        ExtraParameters.process(extraParameters, updateExecutable);
+        return processOptionalParam(preferReturn, updateExecutable);
+    }
+
+    public MethodOutcome resource(String resourceAsString, String stringId, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IUpdateExecutable updateExecutable = client.update().resource(resourceAsString).withId(stringId);
+        ExtraParameters.process(extraParameters, updateExecutable);
+        return processOptionalParam(preferReturn, updateExecutable);
+    }
+
+    public MethodOutcome resourceBySearchUrl(IBaseResource resource, String url, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IUpdateExecutable updateExecutable = client.update().resource(resource).conditionalByUrl(url);
+        ExtraParameters.process(extraParameters, updateExecutable);
+        return processOptionalParam(preferReturn, updateExecutable);
+    }
+
+    public MethodOutcome resourceBySearchUrl(String resourceAsString, String url, PreferReturnEnum preferReturn, Map<ExtraParameters, Object> extraParameters) {
+        IUpdateExecutable updateExecutable = client.update().resource(resourceAsString).conditionalByUrl(url);
+        ExtraParameters.process(extraParameters, updateExecutable);
+        return processOptionalParam(preferReturn, updateExecutable);
+    }
+
+    private MethodOutcome processOptionalParam(PreferReturnEnum preferReturn, IUpdateExecutable updateExecutable) {
+        if (preferReturn != null) {
+            return updateExecutable.prefer(preferReturn).execute();
+        }
+        return updateExecutable.execute();
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirValidate.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirValidate.java
new file mode 100644
index 0000000..80d5cd6
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirValidate.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IValidateUntyped;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+/**
+ * API for validating resources
+ */
+public class FhirValidate {
+
+    private final IGenericClient client;
+
+    public FhirValidate(IGenericClient client) {
+        this.client = client;
+    }
+
+    public MethodOutcome resource(IBaseResource resource, Map<ExtraParameters, Object> extraParameters) {
+        IValidateUntyped validateUntyped = client.validate().resource(resource);
+        ExtraParameters.process(extraParameters, validateUntyped);
+        return validateUntyped.execute();
+    }
+
+    public MethodOutcome resource(String resourceAsString, Map<ExtraParameters, Object> extraParameters) {
+        IValidateUntyped validateUntyped = client.validate().resource(resourceAsString);
+        ExtraParameters.process(extraParameters, validateUntyped);
+        return validateUntyped.execute();
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/pom.xml b/components/camel-fhir/camel-fhir-component/pom.xml
new file mode 100644
index 0000000..eff51ad
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/pom.xml
@@ -0,0 +1,353 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-fhir-parent</artifactId>
+    <version>2.23.0-SNAPSHOT</version>
+  </parent>
+  
+  <artifactId>camel-fhir</artifactId>
+  <packaging>jar</packaging>
+  <name>Camel :: Fhir</name>
+  <description>Camel FHIR HL7 support</description>
+
+  <properties>
+    <componentName>Fhir</componentName>
+    <schemeName>fhir</schemeName>
+    <componentPackage>org.apache.camel.component.fhir</componentPackage>
+    <outPackage>org.apache.camel.component.fhir.internal</outPackage>
+    <camel.osgi.export.pkg>
+      org.apache.camel.component.fhir.*
+    </camel.osgi.export.pkg>
+    <camel.osgi.dynamic>
+      org.hl7.fhir.*
+    </camel.osgi.dynamic>
+    <camel.osgi.export.service>
+      org.apache.camel.spi.DataFormatResolver;dataformat=fhirJson,
+      org.apache.camel.spi.DataFormatResolver;dataformat=fhirXml,
+      org.apache.camel.spi.ComponentResolver;component=${schemeName}
+    </camel.osgi.export.service>
+    <camel.osgi.private.pkg>${outPackage}</camel.osgi.private.pkg>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>ca.uhn.hapi.fhir</groupId>
+      <artifactId>hapi-fhir-base</artifactId>
+      <version>${hapi-fhir-version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>ca.uhn.hapi.fhir</groupId>
+      <artifactId>hapi-fhir-client</artifactId>
+      <version>${hapi-fhir-version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-fhir-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <!-- Component API javadoc in provided scope to read API signatures -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-fhir-api</artifactId>
+      <version>${project.version}</version>
+      <classifier>javadoc</classifier>
+      <scope>provided</scope>
+    </dependency>
+
+    <!-- These aren't needed for compilation but makes camel-fhir easier to use for third party projects/users e.g wildfly-camel -->
+    <dependency>
+      <groupId>ca.uhn.hapi.fhir</groupId>
+      <artifactId>hapi-fhir-structures-dstu3</artifactId>
+      <version>${hapi-fhir-version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>ca.uhn.hapi.fhir</groupId>
+      <artifactId>hapi-fhir-structures-dstu2</artifactId>
+      <version>${hapi-fhir-version}</version>
+    </dependency>
+
+    <!-- testing -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-hl7</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>ca.uhn.hapi</groupId>
+      <artifactId>hapi-structures-v24</artifactId>
+      <version>${hapi-version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- logging -->
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <defaultGoal>install</defaultGoal>
+    <plugins>
+      <!-- generate Component source and test source -->
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-api-component-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>generate-test-component-classes</id>
+            <goals>
+              <goal>fromApis</goal>
+            </goals>
+            <configuration>
+              <apis>
+                <api>
+                  <apiName>capabilities</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirCapabilities</proxyClass>
+                  <fromSignatureFile>signatures/capabilities-sig-api.txt</fromSignatureFile>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>create</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirCreate</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>url</nullableOption>
+                    <nullableOption>preferReturn</nullableOption>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>delete</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirDelete</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>history</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirHistory</proxyClass>
+                  <fromSignatureFile>signatures/history-sig-api.txt</fromSignatureFile>
+                  <nullableOptions>
+                    <nullableOption>count</nullableOption>
+                    <nullableOption>cutoff</nullableOption>
+                    <nullableOption>iCutoff</nullableOption>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>load-page</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirLoadPage</proxyClass>
+                  <fromSignatureFile>signatures/load-page-sig-api.txt</fromSignatureFile>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>meta</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirMeta</proxyClass>
+                  <fromSignatureFile>signatures/meta-sig-api.txt</fromSignatureFile>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>patch</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirPatch</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>preferReturn</nullableOption>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>read</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirRead</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>ifVersionMatches</nullableOption>
+                    <nullableOption>returnNull</nullableOption>
+                    <nullableOption>returnResource</nullableOption>
+                    <nullableOption>throwError</nullableOption>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>search</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirSearch</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>transaction</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirTransaction</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>update</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirUpdate</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>preferReturn</nullableOption>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
+                  <apiName>validate</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirValidate</proxyClass>
+                  <fromJavadoc/>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                  </nullableOptions>
+                </api>
+              </apis>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <!-- add generated source and test source to build -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.10</version>
+        <executions>
+          <execution>
+            <id>add-generated-sources</id>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${project.build.directory}/generated-sources/camel-component</source>
+              </sources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>add-generated-test-sources</id>
+            <goals>
+              <goal>add-test-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${project.build.directory}/generated-test-sources/camel-component</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.camel</groupId>
+          <artifactId>camel-api-component-maven-plugin</artifactId>
+          <version>${project.version}</version>
+          <configuration>
+            <scheme>${schemeName}</scheme>
+            <componentName>${componentName}</componentName>
+            <componentPackage>${componentPackage}</componentPackage>
+            <outPackage>${outPackage}</outPackage>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-api-component-maven-plugin</artifactId>
+        <configuration>
+          <scheme>${schemeName}</scheme>
+          <componentName>${componentName}</componentName>
+          <componentPackage>${componentPackage}</componentPackage>
+          <outPackage>${outPackage}</outPackage>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+  <profiles>
+    <profile>
+      <id>it-fhir</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories b/components/camel-fhir/camel-fhir-component/signatures/capabilities-sig-api.txt
similarity index 74%
copy from platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories
copy to components/camel-fhir/camel-fhir-component/signatures/capabilities-sig-api.txt
index 3df2200..a1bfe8e 100644
--- a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories
+++ b/components/camel-fhir/camel-fhir-component/signatures/capabilities-sig-api.txt
@@ -1,4 +1,4 @@
-## ---------------------------------------------------------------------------
+## ------------------------------------------------------------------------
 ## Licensed to the Apache Software Foundation (ASF) under one or more
 ## contributor license agreements.  See the NOTICE file distributed with
 ## this work for additional information regarding copyright ownership.
@@ -6,16 +6,13 @@
 ## (the "License"); you may not use this file except in compliance with
 ## the License.  You may obtain a copy of the License at
 ##
-##      http://www.apache.org/licenses/LICENSE-2.0
+## http://www.apache.org/licenses/LICENSE-2.0
 ##
 ## Unless required by applicable law or agreed to in writing, software
 ## distributed under the License is distributed on an "AS IS" BASIS,
 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
-## ---------------------------------------------------------------------------
-
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.apache.camel.component.fhir.springboot.FhirJsonDataFormatAutoConfiguration,\
-org.apache.camel.component.fhir.springboot.FhirXmlDataFormatAutoConfiguration
+## ------------------------------------------------------------------------
 
+<T extends org.hl7.fhir.instance.model.api.IBaseConformance> T ofType(Class<T> type, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
\ No newline at end of file
diff --git a/components/camel-fhir/camel-fhir-component/signatures/history-sig-api.txt b/components/camel-fhir/camel-fhir-component/signatures/history-sig-api.txt
new file mode 100644
index 0000000..d50a5f3
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/signatures/history-sig-api.txt
@@ -0,0 +1,19 @@
+## ------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ------------------------------------------------------------------------
+<T extends org.hl7.fhir.instance.model.api.IBaseBundle> T onServer(Class<T> returnType, Integer count, java.util.Date cutoff, org.hl7.fhir.instance.model.api.IPrimitiveType<java.util.Date> iCutoff, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseBundle> T onType(Class<org.hl7.fhir.instance.model.api.IBaseResource> resourceType, Class<T> returnType, Integer count, java.util.Date cutoff, org.hl7.fhir.instance.model.api.IPrimitiveType<java.util.Date> iCutoff, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseBundle> T onInstance(org.hl7.fhir.instance.model.api.IIdType id, Class<T> returnType, Integer count, java.util.Date cutoff, org.hl7.fhir.instance.model.api.IPrimitiveType<java.util.Date> iCutoff, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
\ No newline at end of file
diff --git a/components/camel-fhir/src/test/resources/log4j2.properties b/components/camel-fhir/camel-fhir-component/signatures/load-page-sig-api.txt
similarity index 58%
copy from components/camel-fhir/src/test/resources/log4j2.properties
copy to components/camel-fhir/camel-fhir-component/signatures/load-page-sig-api.txt
index 3c6189a..505e088 100644
--- a/components/camel-fhir/src/test/resources/log4j2.properties
+++ b/components/camel-fhir/camel-fhir-component/signatures/load-page-sig-api.txt
@@ -1,4 +1,4 @@
-## ---------------------------------------------------------------------------
+## ------------------------------------------------------------------------
 ## Licensed to the Apache Software Foundation (ASF) under one or more
 ## contributor license agreements.  See the NOTICE file distributed with
 ## this work for additional information regarding copyright ownership.
@@ -6,23 +6,14 @@
 ## (the "License"); you may not use this file except in compliance with
 ## the License.  You may obtain a copy of the License at
 ##
-##      http://www.apache.org/licenses/LICENSE-2.0
+## http://www.apache.org/licenses/LICENSE-2.0
 ##
 ## Unless required by applicable law or agreed to in writing, software
 ## distributed under the License is distributed on an "AS IS" BASIS,
 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
-## ---------------------------------------------------------------------------
-
-appender.file.type = File
-appender.file.name = file
-appender.file.fileName = target/camel-fhir-test.log
-appender.file.layout.type = PatternLayout
-appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
-appender.out.type = Console
-appender.out.name = out
-appender.out.layout.type = PatternLayout
-appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
-rootLogger.level = DEBUG
-rootLogger.appenderRef.file.ref = file
+## ------------------------------------------------------------------------
+<T extends org.hl7.fhir.instance.model.api.IBaseBundle> T next(T bundle, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseBundle> T previous(T bundle, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseBundle> T byUrl(String url, Class<T> returnType, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
diff --git a/components/camel-fhir/camel-fhir-component/signatures/meta-sig-api.txt b/components/camel-fhir/camel-fhir-component/signatures/meta-sig-api.txt
new file mode 100644
index 0000000..ac901bd
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/signatures/meta-sig-api.txt
@@ -0,0 +1,21 @@
+## ------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ------------------------------------------------------------------------
+<T extends org.hl7.fhir.instance.model.api.IBaseMetaType> T getFromServer(Class<T> metaType, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseMetaType> T getFromResource(Class<T> metaType, org.hl7.fhir.instance.model.api.IIdType id, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseMetaType> T getFromType(Class<T> metaType, String theResourceName, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseMetaType> T add(T meta, org.hl7.fhir.instance.model.api.IIdType id, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+<T extends org.hl7.fhir.instance.model.api.IBaseMetaType> T delete(T meta, org.hl7.fhir.instance.model.api.IIdType id, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
diff --git a/components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc b/components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc
new file mode 100644
index 0000000..ea755c5
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc
@@ -0,0 +1,121 @@
+[[fhir-component]]
+== FHIR Component
+
+*Available as of Camel version 2.23*
+
+The FHIR component integrates with the
+http://hapifhir.io/[HAPI-FHIR] library which is an open-source implementation of the
+http://hl7.org/implement/standards/fhir/[FHIR] (Fast Healthcare Interoperability Resources) specification in Java.
+
+
+Maven users will need to add the following dependency to their pom.xml
+for this component:
+
+
+[source,xml]
+--------------------------------------------
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-fhir</artifactId>
+    <version>${camel-version}</version>
+</dependency>
+--------------------------------------------
+
+### URI Format
+
+'''''
+
+The FHIR Component uses the following URI format:
+
+---------------------------------------------------------
+        fhir://endpoint-prefix/endpoint?[options]
+
+---------------------------------------------------------
+
+Endpoint prefix can be one of:
+
+* capabilities
+* create
+* delete
+* history
+* load-page
+* meta
+* patch
+* read
+* search
+* transaction
+* update
+* validate
+
+### FhirComponent
+
+*Available as of Camel version 2.23*
+
+// component options: START
+The FHIR component supports 2 options, which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *configuration* (common) | To use the shared configuration |  | FhirConfiguration
+| *resolveProperty Placeholders* (advanced) | Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders. | true | boolean
+|===
+// component options: END
+
+
+// endpoint options: START
+The FHIR endpoint is configured using URI syntax:
+
+----
+fhir:apiName/methodName
+----
+
+with the following path and query parameters:
+
+==== Path Parameters (2 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *apiName* | *Required* What kind of operation to perform |  | FhirApiName
+| *methodName* | *Required* What sub operation to use for the selected operation |  | String
+|===
+
+
+==== Query Parameters (26 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *encoding* (common) | Encoding to use for all request |  | String
+| *fhirVersion* (common) | The FHIR Version to use | DSTU3 | String
+| *inBody* (common) | Sets the name of a parameter to be passed in the exchange In Body |  | String
+| *log* (common) | Will log every requests and responses | false | boolean
+| *prettyPrint* (common) | Pretty print all request | false | boolean
+| *serverUrl* (common) | The FHIR server base URL |  | String
+| *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
+| *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this options is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
+| *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. |  | ExchangePattern
+| *compress* (advanced) | Compresses outgoing (POST/PUT) contents to the GZIP format | false | boolean
+| *connectionTimeout* (advanced) | How long to try and establish the initial TCP connection (in ms) | 10000 | Integer
+| *deferModelScanning* (advanced) | When this option is set, model classes will not be scanned for children until the child list for the given type is actually accessed. | false | boolean
+| *fhirContext* (advanced) | FhirContext is an expensive object to create. To avoid creating multiple instances, it can be set directly. |  | FhirContext
+| *forceConformanceCheck* (advanced) | Force conformance check | false | boolean
+| *sessionCookie* (advanced) | HTTP session cookie to add to every request |  | String
+| *socketTimeout* (advanced) | How long to block for individual read/write operations (in ms) | 10000 | Integer
+| *summary* (advanced) | Request that the server modify the response using the _summary param |  | String
+| *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+| *validationMode* (advanced) | When should Camel validate the FHIR Server's conformance statement | ONCE | String
+| *proxyHost* (proxy) | The proxy host |  | String
+| *proxyPassword* (proxy) | The proxy password |  | String
+| *proxyPort* (proxy) | The proxy port |  | Integer
+| *proxyUser* (proxy) | The proxy username |  | String
+| *accessToken* (security) | OAuth access token |  | String
+| *password* (security) | Username to use for basic authentication |  | String
+| *username* (security) | Username to use for basic authentication |  | String
+|===
+// endpoint options: END
\ No newline at end of file
diff --git a/components/camel-fhir/src/main/docs/fhirJson-dataformat.adoc b/components/camel-fhir/camel-fhir-component/src/main/docs/fhirJson-dataformat.adoc
similarity index 100%
rename from components/camel-fhir/src/main/docs/fhirJson-dataformat.adoc
rename to components/camel-fhir/camel-fhir-component/src/main/docs/fhirJson-dataformat.adoc
diff --git a/components/camel-fhir/src/main/docs/fhirXml-dataformat.adoc b/components/camel-fhir/camel-fhir-component/src/main/docs/fhirXml-dataformat.adoc
similarity index 100%
rename from components/camel-fhir/src/main/docs/fhirXml-dataformat.adoc
rename to components/camel-fhir/camel-fhir-component/src/main/docs/fhirXml-dataformat.adoc
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirComponent.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirComponent.java
new file mode 100644
index 0000000..b8cb9f4
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirComponent.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirApiName;
+import org.apache.camel.component.fhir.internal.FhirHelper;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.util.component.AbstractApiComponent;
+
+/**
+ * Represents the component that manages {@link FhirEndpoint}.
+ */
+public class FhirComponent extends AbstractApiComponent<FhirApiName, FhirConfiguration, FhirApiCollection> {
+
+    @Metadata(label = "advanced")
+    private IGenericClient client;
+
+    public FhirComponent() {
+        super(FhirEndpoint.class, FhirApiName.class, FhirApiCollection.getCollection());
+    }
+
+    public FhirComponent(CamelContext context) {
+        super(context, FhirEndpoint.class, FhirApiName.class, FhirApiCollection.getCollection());
+    }
+
+    @Override
+    protected FhirApiName getApiName(String apiNameStr) throws IllegalArgumentException {
+        return FhirApiName.fromValue(apiNameStr);
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String methodName, FhirApiName apiName,
+                                      FhirConfiguration endpointConfiguration) {
+        endpointConfiguration.setApiName(apiName);
+        endpointConfiguration.setMethodName(methodName);
+        return new FhirEndpoint(uri, this, apiName, methodName, endpointConfiguration);
+    }
+
+    public IGenericClient getClient(FhirConfiguration endpointConfiguration) {
+        final IGenericClient result;
+        if (endpointConfiguration.equals(this.configuration)) {
+            synchronized (this) {
+                if (client == null) {
+                    client = FhirHelper.createClient(this.configuration, getCamelContext());
+                }
+            }
+            result = client;
+        } else {
+            result = FhirHelper.createClient(endpointConfiguration, getCamelContext());
+        }
+        return result;
+    }
+
+    /**
+     * To use the shared configuration
+     */
+    @Override
+    public void setConfiguration(FhirConfiguration configuration) {
+        super.setConfiguration(configuration);
+    }
+
+    @Override
+    public FhirConfiguration getConfiguration() {
+        return super.getConfiguration();
+    }
+
+}
+
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConfiguration.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConfiguration.java
new file mode 100644
index 0000000..604d084
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConfiguration.java
@@ -0,0 +1,378 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.FhirVersionEnum;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import ca.uhn.fhir.rest.api.SummaryEnum;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
+import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
+import org.apache.camel.component.fhir.internal.FhirApiName;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Component configuration for FHIR component.
+ */
+@UriParams
+public class FhirConfiguration {
+
+    @UriPath
+    @Metadata(enums = "capabilities, create, delete, history, load-page, meta, patch, read, search, transaction, update, validate", required = "true")
+    private FhirApiName apiName;
+    @UriPath
+    @Metadata(required = "true")
+    private String methodName;
+
+    @UriParam(description = "The FHIR server base URL")
+    private String serverUrl;
+
+    @UriParam(description = "The FHIR Version to use", enums = "DSTU2, DSTU2_HL7ORG, DSTU2_1, DSTU3, R4", defaultValue = "DSTU3", javaType = "java.lang.String")
+    private FhirVersionEnum fhirVersion = FhirVersionEnum.DSTU3;
+
+    @UriParam(description = "Pretty print all request")
+    private boolean prettyPrint;
+
+    @UriParam(description = "Encoding to use for all request", enums = "JSON, XML", javaType = "java.lang.String")
+    private EncodingEnum encoding;
+
+    @UriParam(description = "Username to use for basic authentication", label = "security", secret = true)
+    private String username;
+
+    @UriParam(description = "Username to use for basic authentication", label = "security", secret = true)
+    private String password;
+
+    @UriParam(description = "OAuth access token", label = "security", secret = true)
+    private String accessToken;
+
+    @UriParam(description = "Will log every requests and responses")
+    private boolean log;
+
+    @UriParam(description = "Compresses outgoing (POST/PUT) contents to the GZIP format", label = "advanced")
+    private boolean compress;
+
+    @UriParam(description = "Request that the server modify the response using the <code>_summary</code> param", enums = "TRUE, FALSE, TEXT, DATA, COUNT",
+            label = "advanced", javaType = "java.lang.String")
+    private SummaryEnum summary;
+
+    @UriParam(description = "HTTP session cookie to add to every request", label = "advanced")
+    private String sessionCookie;
+
+    @UriParam(description = "FhirContext is an expensive object to create. To avoid creating multiple instances,"
+            + " it can be set directly.", label = "advanced")
+    private FhirContext fhirContext;
+
+    @UriParam(description = "Force conformance check", label = "advanced")
+    private boolean forceConformanceCheck;
+
+    @UriParam(description = "When should Camel validate the FHIR Server's conformance statement", enums = "NEVER, ONCE",
+            defaultValue = "ONCE", label = "advanced", javaType = "java.lang.String")
+    private ServerValidationModeEnum validationMode;
+
+    @UriParam(description = "When this option is set, model classes will not be scanned for children until the"
+            + " child list for the given type is actually accessed.", defaultValue = "false", label = "advanced")
+    private boolean deferModelScanning;
+
+    @UriParam(description = "How long to try and establish the initial TCP connection (in ms)", label = "advanced", defaultValue = "10000")
+    private Integer connectionTimeout;
+
+    @UriParam(description = "How long to block for individual read/write operations (in ms)", label = "advanced", defaultValue = "10000")
+    private Integer socketTimeout;
+
+    @UriParam(label = "proxy", description = "The proxy host")
+    private String proxyHost;
+
+    @UriParam(label = "proxy", description = "The proxy port")
+    private Integer proxyPort;
+
+    @UriParam(label = "proxy", description = "The proxy username")
+    private String proxyUser;
+
+    @UriParam(label = "proxy", description = "The proxy password")
+    private String proxyPassword;
+
+    @Metadata(label = "advanced", description = "To use the custom client")
+    private IGenericClient client;
+
+    @Metadata(label = "advanced", description = "To use the custom client factory")
+    private IRestfulClientFactory clientFactory;
+
+    public String getServerUrl() {
+        return serverUrl;
+    }
+
+    public void setServerUrl(String serverUrl) {
+        this.serverUrl = serverUrl;
+    }
+
+    public FhirVersionEnum getFhirVersion() {
+        return fhirVersion;
+    }
+
+    public void setFhirVersion(String fhirVersion) {
+        this.fhirVersion = FhirVersionEnum.valueOf(fhirVersion);
+    }
+
+    public EncodingEnum getEncoding() {
+        return encoding;
+    }
+
+    public void setEncoding(String encoding) {
+        this.encoding = EncodingEnum.valueOf(encoding);
+    }
+
+
+    public boolean isPrettyPrint() {
+        return prettyPrint;
+    }
+
+    public void setPrettyPrint(boolean prettyPrint) {
+        this.prettyPrint = prettyPrint;
+    }
+
+    public SummaryEnum getSummary() {
+        return summary;
+    }
+
+    public void setSummary(String summary) {
+        this.summary = SummaryEnum.valueOf(summary);
+    }
+
+    public FhirApiName getApiName() {
+        return apiName;
+    }
+
+    /**
+     * What kind of operation to perform
+     */
+    public void setApiName(FhirApiName apiName) {
+        this.apiName = apiName;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    /**
+     * What sub operation to use for the selected operation
+     */
+    public void setMethodName(String methodName) {
+        this.methodName = methodName;
+    }
+
+    public FhirContext getFhirContext() {
+        return fhirContext;
+    }
+
+    public void setFhirContext(FhirContext fhirContext) {
+        this.fhirContext = fhirContext;
+    }
+
+    public boolean isForceConformanceCheck() {
+        return forceConformanceCheck;
+    }
+
+    public void setForceConformanceCheck(boolean forceConformanceCheck) {
+        this.forceConformanceCheck = forceConformanceCheck;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    public void setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    public boolean isLog() {
+        return log;
+    }
+
+    public void setLog(boolean log) {
+        this.log = log;
+    }
+
+    public boolean isCompress() {
+        return compress;
+    }
+
+    public void setCompress(boolean compress) {
+        this.compress = compress;
+    }
+
+    public String getSessionCookie() {
+        return sessionCookie;
+    }
+
+    public void setSessionCookie(String sessionCookie) {
+        this.sessionCookie = sessionCookie;
+    }
+
+    public ServerValidationModeEnum getValidationMode() {
+        return validationMode;
+    }
+
+    public void setValidationMode(String validationMode) {
+        this.validationMode = ServerValidationModeEnum.valueOf(validationMode);
+    }
+
+    public boolean isDeferModelScanning() {
+        return deferModelScanning;
+    }
+
+    public void setDeferModelScanning(boolean deferModelScanning) {
+        this.deferModelScanning = deferModelScanning;
+    }
+
+    public Integer getConnectionTimeout() {
+        return connectionTimeout;
+    }
+
+    public void setConnectionTimeout(Integer connectionTimeout) {
+        this.connectionTimeout = connectionTimeout;
+    }
+
+    public Integer getSocketTimeout() {
+        return socketTimeout;
+    }
+
+    public void setSocketTimeout(Integer socketTimeout) {
+        this.socketTimeout = socketTimeout;
+    }
+
+    public String getProxyHost() {
+        return proxyHost;
+    }
+
+    public void setProxyHost(String proxyHost) {
+        this.proxyHost = proxyHost;
+    }
+
+    public String getProxyPassword() {
+        return proxyPassword;
+    }
+
+    public void setProxyPassword(String proxyPassword) {
+        this.proxyPassword = proxyPassword;
+    }
+
+    public Integer getProxyPort() {
+        return proxyPort;
+    }
+
+    public void setProxyPort(Integer proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+
+    public String getProxyUser() {
+        return proxyUser;
+    }
+
+    public void setProxyUser(String proxyUser) {
+        this.proxyUser = proxyUser;
+    }
+
+    public IGenericClient getClient() {
+        return client;
+    }
+
+    public void setClient(IGenericClient client) {
+        this.client = client;
+    }
+
+    public IRestfulClientFactory getClientFactory() {
+        return clientFactory;
+    }
+
+    public void setClientFactory(IRestfulClientFactory clientFactory) {
+        this.clientFactory = clientFactory;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof FhirConfiguration) {
+            FhirConfiguration otherFhirConfiguration = (FhirConfiguration) other;
+            return ObjectHelper.equal(prettyPrint, otherFhirConfiguration.isPrettyPrint())
+                    && ObjectHelper.equal(log, otherFhirConfiguration.isLog())
+                    && ObjectHelper.equal(compress, otherFhirConfiguration.isCompress())
+                    && ObjectHelper.equal(forceConformanceCheck, otherFhirConfiguration.isForceConformanceCheck())
+                    && ObjectHelper.equal(fhirVersion, otherFhirConfiguration.getFhirVersion())
+                    && ObjectHelper.equal(deferModelScanning, otherFhirConfiguration.isDeferModelScanning())
+                    && ObjectHelper.equal(encoding, otherFhirConfiguration.getEncoding())
+                    && ObjectHelper.equal(username, otherFhirConfiguration.getUsername())
+                    && ObjectHelper.equal(password, otherFhirConfiguration.getPassword())
+                    && ObjectHelper.equal(accessToken, otherFhirConfiguration.getAccessToken())
+                    && ObjectHelper.equal(summary, otherFhirConfiguration.getSummary())
+                    && ObjectHelper.equal(sessionCookie, otherFhirConfiguration.getSessionCookie())
+                    && ObjectHelper.equal(validationMode, otherFhirConfiguration.getValidationMode())
+                    && ObjectHelper.equal(connectionTimeout, otherFhirConfiguration.getConnectionTimeout())
+                    && ObjectHelper.equal(socketTimeout, otherFhirConfiguration.getSocketTimeout())
+                    && ObjectHelper.equal(proxyHost, otherFhirConfiguration.getProxyHost())
+                    && ObjectHelper.equal(proxyPort, otherFhirConfiguration.getProxyPort())
+                    && ObjectHelper.equal(proxyUser, otherFhirConfiguration.getProxyUser())
+                    && ObjectHelper.equal(proxyPassword, otherFhirConfiguration.getProxyPassword())
+                    && ObjectHelper.equal(serverUrl, otherFhirConfiguration.getServerUrl());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = serverUrl != null ? serverUrl.hashCode() : 0;
+        result = 31 * result + (fhirVersion != null ? fhirVersion.hashCode() : 0);
+        result = 31 * result + (prettyPrint ? 1 : 0);
+        result = 31 * result + (encoding != null ? encoding.hashCode() : 0);
+        result = 31 * result + (username != null ? username.hashCode() : 0);
+        result = 31 * result + (password != null ? password.hashCode() : 0);
+        result = 31 * result + (accessToken != null ? accessToken.hashCode() : 0);
+        result = 31 * result + (log ? 1 : 0);
+        result = 31 * result + (compress ? 1 : 0);
+        result = 31 * result + (summary != null ? summary.hashCode() : 0);
+        result = 31 * result + (sessionCookie != null ? sessionCookie.hashCode() : 0);
+        result = 31 * result + (forceConformanceCheck ? 1 : 0);
+        result = 31 * result + (validationMode != null ? validationMode.hashCode() : 0);
+        result = 31 * result + (deferModelScanning ? 1 : 0);
+        result = 31 * result + (connectionTimeout != null ? connectionTimeout.hashCode() : 0);
+        result = 31 * result + (socketTimeout != null ? socketTimeout.hashCode() : 0);
+        result = 31 * result + (proxyHost != null ? proxyHost.hashCode() : 0);
+        result = 31 * result + (proxyPort != null ? proxyPort.hashCode() : 0);
+        result = 31 * result + (proxyUser != null ? proxyUser.hashCode() : 0);
+        result = 31 * result + (proxyPassword != null ? proxyPassword.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConsumer.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConsumer.java
new file mode 100644
index 0000000..f4a80f9
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirConsumer.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import org.apache.camel.Processor;
+import org.apache.camel.component.fhir.internal.FhirApiName;
+import org.apache.camel.util.component.AbstractApiConsumer;
+
+/**
+ * The FHIR consumer.
+ */
+public class FhirConsumer extends AbstractApiConsumer<FhirApiName, FhirConfiguration> {
+
+    public FhirConsumer(FhirEndpoint endpoint, Processor processor) {
+        super(endpoint, processor);
+    }
+
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java
new file mode 100644
index 0000000..7093185
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java
@@ -0,0 +1,166 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.api.FhirCapabilities;
+import org.apache.camel.component.fhir.api.FhirCreate;
+import org.apache.camel.component.fhir.api.FhirDelete;
+import org.apache.camel.component.fhir.api.FhirHistory;
+import org.apache.camel.component.fhir.api.FhirLoadPage;
+import org.apache.camel.component.fhir.api.FhirMeta;
+import org.apache.camel.component.fhir.api.FhirPatch;
+import org.apache.camel.component.fhir.api.FhirRead;
+import org.apache.camel.component.fhir.api.FhirSearch;
+import org.apache.camel.component.fhir.api.FhirTransaction;
+import org.apache.camel.component.fhir.api.FhirUpdate;
+import org.apache.camel.component.fhir.api.FhirValidate;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirApiName;
+import org.apache.camel.component.fhir.internal.FhirConstants;
+import org.apache.camel.component.fhir.internal.FhirPropertiesHelper;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.util.component.AbstractApiEndpoint;
+import org.apache.camel.util.component.ApiMethod;
+import org.apache.camel.util.component.ApiMethodPropertiesHelper;
+
+/**
+ * Represents a FHIR endpoint.
+ */
+@UriEndpoint(firstVersion = "2.23.0", scheme = "fhir", title = "FHIR", syntax = "fhir:apiName/methodName",
+        consumerClass = FhirConsumer.class, label = "api")
+public class FhirEndpoint extends AbstractApiEndpoint<FhirApiName, FhirConfiguration> {
+
+    private static final String EXTRA_PARAMETERS_PROPERTY = "extraParameters";
+
+    private Object apiProxy;
+
+    @UriParam
+    private FhirConfiguration configuration;
+
+    public FhirEndpoint(String uri, FhirComponent component,
+                        FhirApiName apiName, String methodName, FhirConfiguration endpointConfiguration) {
+        super(uri, component, apiName, methodName, FhirApiCollection.getCollection().getHelper(apiName), endpointConfiguration);
+        this.configuration = endpointConfiguration;
+    }
+
+    public Producer createProducer() throws Exception {
+        return new FhirProducer(this);
+    }
+
+    public Consumer createConsumer(Processor processor) throws Exception {
+        // make sure inBody is not set for consumers
+        if (inBody != null) {
+            throw new IllegalArgumentException("Option inBody is not supported for consumer endpoint");
+        }
+        final FhirConsumer consumer = new FhirConsumer(this, processor);
+        // also set consumer.* properties
+        configureConsumer(consumer);
+        return consumer;
+    }
+
+    @Override
+    protected ApiMethodPropertiesHelper<FhirConfiguration> getPropertiesHelper() {
+        return FhirPropertiesHelper.getHelper();
+    }
+
+    protected String getThreadProfileName() {
+        return FhirConstants.THREAD_PROFILE_NAME;
+    }
+
+    @Override
+    protected void afterConfigureProperties() {
+        IGenericClient client = getClient();
+        switch (apiName) {
+        case CAPABILITIES:
+            apiProxy = new FhirCapabilities(client);
+            break;
+        case CREATE:
+            apiProxy = new FhirCreate(client);
+            break;
+        case DELETE:
+            apiProxy = new FhirDelete(client);
+            break;
+        case HISTORY:
+            apiProxy = new FhirHistory(client);
+            break;
+        case LOAD_PAGE:
+            apiProxy = new FhirLoadPage(client);
+            break;
+        case META:
+            apiProxy = new FhirMeta(client);
+            break;
+        case PATCH:
+            apiProxy = new FhirPatch(client);
+            break;
+        case READ:
+            apiProxy = new FhirRead(client);
+            break;
+        case SEARCH:
+            apiProxy = new FhirSearch(client);
+            break;
+        case TRANSACTION:
+            apiProxy = new FhirTransaction(client);
+            break;
+        case UPDATE:
+            apiProxy = new FhirUpdate(client);
+            break;
+        case VALIDATE:
+            apiProxy = new FhirValidate(client);
+            break;
+        default:
+            throw new IllegalArgumentException("Invalid API name " + apiName);
+        }
+    }
+
+    @Override
+    public void interceptProperties(Map<String, Object> properties) {
+        Map<ExtraParameters, Object> extraProperties = getExtraParameters(properties);
+        for (ExtraParameters extraParameter : ExtraParameters.values()) {
+            Object value = properties.get(extraParameter.getParam());
+            if (value != null) {
+                extraProperties.put(extraParameter, value);
+            }
+        }
+        properties.put(EXTRA_PARAMETERS_PROPERTY, extraProperties);
+
+    }
+
+    IGenericClient getClient() {
+        return ((FhirComponent) getComponent()).getClient(configuration);
+    }
+
+    private Map<ExtraParameters, Object> getExtraParameters(Map<String, Object> properties) {
+        Object extraParameters = properties.get(EXTRA_PARAMETERS_PROPERTY);
+        if (extraParameters == null) {
+            return new HashMap<>();
+        }
+        return (Map<ExtraParameters, Object>) extraParameters;
+    }
+
+    @Override
+    public Object getApiProxy(ApiMethod method, Map<String, Object> args) {
+        return apiProxy;
+    }
+}
diff --git a/components/camel-fhir/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java
similarity index 100%
rename from components/camel-fhir/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java
rename to components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirProducer.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirProducer.java
new file mode 100644
index 0000000..0c856ae
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirProducer.java
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import org.apache.camel.component.fhir.internal.FhirApiName;
+import org.apache.camel.component.fhir.internal.FhirPropertiesHelper;
+import org.apache.camel.util.component.AbstractApiProducer;
+
+/**
+ * The FHIR producer.
+ */
+public class FhirProducer extends AbstractApiProducer<FhirApiName, FhirConfiguration> {
+
+    public FhirProducer(FhirEndpoint endpoint) {
+        super(endpoint, FhirPropertiesHelper.getHelper());
+    }
+}
diff --git a/components/camel-fhir/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java
similarity index 100%
rename from components/camel-fhir/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java
rename to components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirConstants.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirConstants.java
new file mode 100644
index 0000000..c584042
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirConstants.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.internal;
+
+/**
+ * Constants for FHIR component.
+ */
+public interface FhirConstants {
+
+    // suffix for parameters when passed as exchange header properties
+    String PROPERTY_PREFIX = "CamelFhir.";
+
+    // thread profile name for this component
+    String THREAD_PROFILE_NAME = "CamelFhir";
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirHelper.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirHelper.java
new file mode 100644
index 0000000..01b65fb
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirHelper.java
@@ -0,0 +1,150 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.internal;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.FhirVersionEnum;
+import ca.uhn.fhir.context.PerformanceOptionsEnum;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import ca.uhn.fhir.rest.api.SummaryEnum;
+import ca.uhn.fhir.rest.client.apache.GZipContentInterceptor;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
+import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
+import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
+import ca.uhn.fhir.rest.client.interceptor.BearerTokenAuthInterceptor;
+import ca.uhn.fhir.rest.client.interceptor.CookieInterceptor;
+import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
+import org.apache.camel.CamelContext;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.fhir.FhirConfiguration;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Utility class for creating FHIR {@link ca.uhn.fhir.rest.client.api.IGenericClient}
+ */
+public final class FhirHelper {
+
+    private FhirHelper() {
+        // hide utility class constructor
+    }
+
+    public static IGenericClient createClient(FhirConfiguration endpointConfiguration, CamelContext camelContext) {
+        if (endpointConfiguration.getClient() != null) {
+            return endpointConfiguration.getClient();
+        }
+        FhirContext fhirContext = getFhirContext(endpointConfiguration);
+        if (endpointConfiguration.isDeferModelScanning()) {
+            fhirContext.setPerformanceOptions(PerformanceOptionsEnum.DEFERRED_MODEL_SCANNING);
+        }
+        if (endpointConfiguration.getClientFactory() != null) {
+            fhirContext.setRestfulClientFactory(endpointConfiguration.getClientFactory());
+        }
+
+        IRestfulClientFactory restfulClientFactory = fhirContext.getRestfulClientFactory();
+        configureClientFactory(endpointConfiguration, restfulClientFactory, camelContext);
+        IGenericClient genericClient = fhirContext.newRestfulGenericClient(endpointConfiguration.getServerUrl());
+        genericClient.setPrettyPrint(endpointConfiguration.isPrettyPrint());
+        EncodingEnum encoding = endpointConfiguration.getEncoding();
+        SummaryEnum summary = endpointConfiguration.getSummary();
+
+        if (encoding != null) {
+            genericClient.setEncoding(encoding);
+        }
+        if (summary != null) {
+            genericClient.setSummary(summary);
+        }
+        if (endpointConfiguration.isForceConformanceCheck()) {
+            genericClient.forceConformanceCheck();
+        }
+
+        registerClientInterceptors(genericClient, endpointConfiguration);
+        return genericClient;
+    }
+
+    private static void configureClientFactory(FhirConfiguration endpointConfiguration, IRestfulClientFactory restfulClientFactory, CamelContext camelContext) {
+        Integer connectionTimeout = endpointConfiguration.getConnectionTimeout();
+        Integer socketTimeout = endpointConfiguration.getSocketTimeout();
+
+        if (ObjectHelper.isNotEmpty(connectionTimeout)) {
+            restfulClientFactory.setConnectTimeout(connectionTimeout);
+        }
+        if (ObjectHelper.isNotEmpty(socketTimeout)) {
+            restfulClientFactory.setSocketTimeout(socketTimeout);
+        }
+
+        configureProxy(endpointConfiguration, restfulClientFactory, camelContext);
+    }
+
+    private static void configureProxy(FhirConfiguration endpointConfiguration, IRestfulClientFactory restfulClientFactory, CamelContext camelContext) {
+        ServerValidationModeEnum validationMode = endpointConfiguration.getValidationMode();
+        String proxyHost = endpointConfiguration.getProxyHost();
+        Integer proxyPort = endpointConfiguration.getProxyPort();
+        String proxyUser = endpointConfiguration.getProxyUser();
+        String proxyPassword = endpointConfiguration.getProxyPassword();
+
+        String camelProxyHost = camelContext.getGlobalOption("http.proxyHost");
+        String camelProxyPort = camelContext.getGlobalOption("http.proxyPort");
+
+        if (ObjectHelper.isNotEmpty(camelProxyHost) && ObjectHelper.isNotEmpty(camelProxyPort)) {
+            restfulClientFactory.setProxy(camelProxyHost, Integer.parseInt(camelProxyPort));
+        }
+        if (ObjectHelper.isNotEmpty(proxyHost) && ObjectHelper.isNotEmpty(proxyPort)) {
+            restfulClientFactory.setProxy(proxyHost, proxyPort);
+        }
+        if (ObjectHelper.isNotEmpty(proxyUser)) {
+            restfulClientFactory.setProxyCredentials(proxyUser, proxyPassword);
+        }
+        if (ObjectHelper.isNotEmpty(validationMode)) {
+            restfulClientFactory.setServerValidationMode(validationMode);
+        }
+    }
+
+    private static void registerClientInterceptors(IGenericClient genericClient, FhirConfiguration endpointConfiguration) {
+        String username = endpointConfiguration.getUsername();
+        String password = endpointConfiguration.getPassword();
+        String accessToken = endpointConfiguration.getAccessToken();
+        String sessionCookie = endpointConfiguration.getSessionCookie();
+        if (ObjectHelper.isNotEmpty(username)) {
+            genericClient.registerInterceptor(new BasicAuthInterceptor(username, password));
+        }
+        if (ObjectHelper.isNotEmpty(accessToken)) {
+            genericClient.registerInterceptor(new BearerTokenAuthInterceptor(accessToken));
+        }
+        if (endpointConfiguration.isLog()) {
+            genericClient.registerInterceptor(new LoggingInterceptor(true));
+        }
+        if (endpointConfiguration.isCompress()) {
+            genericClient.registerInterceptor(new GZipContentInterceptor());
+        }
+        if (ObjectHelper.isNotEmpty(sessionCookie)) {
+            genericClient.registerInterceptor(new CookieInterceptor(sessionCookie));
+        }
+    }
+
+    private static FhirContext getFhirContext(FhirConfiguration endpointConfiguration) {
+        FhirContext context = endpointConfiguration.getFhirContext();
+        if (context != null) {
+            return context;
+        }
+        if (ObjectHelper.isEmpty(endpointConfiguration.getServerUrl())) {
+            throw new RuntimeCamelException("The FHIR URL must be set!");
+        }
+        FhirVersionEnum fhirVersion = endpointConfiguration.getFhirVersion();
+        return new FhirContext(fhirVersion);
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirPropertiesHelper.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirPropertiesHelper.java
new file mode 100644
index 0000000..3149e1b
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/internal/FhirPropertiesHelper.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.internal;
+
+import org.apache.camel.component.fhir.FhirConfiguration;
+import org.apache.camel.util.component.ApiMethodPropertiesHelper;
+
+/**
+ * Singleton {@link ApiMethodPropertiesHelper} for FHIR component.
+ */
+public final class FhirPropertiesHelper extends ApiMethodPropertiesHelper<FhirConfiguration> {
+
+    private static FhirPropertiesHelper helper;
+
+    private FhirPropertiesHelper() {
+        super(FhirConfiguration.class, FhirConstants.PROPERTY_PREFIX);
+    }
+
+    public static synchronized FhirPropertiesHelper getHelper() {
+        if (helper == null) {
+            helper = new FhirPropertiesHelper();
+        }
+        return helper;
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/component/fhir b/components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/component/fhir
new file mode 100644
index 0000000..ae8e6e0
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/component/fhir
@@ -0,0 +1 @@
+class=org.apache.camel.component.fhir.FhirComponent
diff --git a/components/camel-fhir/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirJson b/components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirJson
similarity index 100%
rename from components/camel-fhir/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirJson
rename to components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirJson
diff --git a/components/camel-fhir/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirXml b/components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirXml
similarity index 100%
rename from components/camel-fhir/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirXml
rename to components/camel-fhir/camel-fhir-component/src/main/resources/META-INF/services/org/apache/camel/dataformat/fhirXml
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/AbstractFhirTestSupport.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/AbstractFhirTestSupport.java
new file mode 100644
index 0000000..48e91bf
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/AbstractFhirTestSupport.java
@@ -0,0 +1,133 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.FhirVersionEnum;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.IntrospectionSupport;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.HumanName;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Before;
+
+/**
+ * Abstract base class for Fhir Integration tests generated by Camel API component maven plugin.
+ */
+public abstract class AbstractFhirTestSupport extends CamelTestSupport {
+
+    private static final String TEST_OPTIONS_PROPERTIES = "/test-options.properties";
+    private static final ThreadLocal<FhirContext> FHIR_CONTEXT_THREAD_LOCAL =  new ThreadLocal<>();
+    private static final ThreadLocal<IGenericClient> GENERIC_CLIENT_THREAD_LOCAL = new ThreadLocal<>();
+    protected Patient patient;
+    FhirContext fhirContext;
+    IGenericClient fhirClient;
+
+    @Before
+    public void cleanFhirServerState() {
+        if (patientExists()) {
+            deletePatient();
+        }
+        createPatient();
+    }
+
+    boolean patientExists() {
+        try {
+            Bundle bundle = fhirClient.search().byUrl("Patient?given=Vincent&family=Freeman").returnBundle(Bundle.class).execute();
+            return !bundle.getEntry().isEmpty();
+        } catch (ResourceGoneException e) {
+            return false;
+        }
+    }
+
+    private void deletePatient() {
+        fhirClient.delete().resourceConditionalByUrl("Patient?given=Vincent&family=Freeman").execute();
+    }
+
+    private void createPatient() {
+        this.patient = new Patient().addName(new HumanName().addGiven("Vincent").setFamily("Freeman")).setActive(false);
+        this.patient.setId(fhirClient.create().resource(patient).execute().getId());
+    }
+
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+
+        final CamelContext context = super.createCamelContext();
+
+        // read Fhir component configuration from TEST_OPTIONS_PROPERTIES
+        final Properties properties = new Properties();
+        try {
+            properties.load(getClass().getResourceAsStream(TEST_OPTIONS_PROPERTIES));
+        } catch (Exception e) {
+            throw new IOException(String.format("%s could not be loaded: %s", TEST_OPTIONS_PROPERTIES, e.getMessage()),
+                e);
+        }
+
+        Map<String, Object> options = new HashMap<>();
+        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+            options.put(entry.getKey().toString(), entry.getValue());
+        }
+
+        FhirVersionEnum version = FhirVersionEnum.valueOf((String) options.get("fhirVersion"));
+        this.fhirContext = new FhirContext(version);
+        FHIR_CONTEXT_THREAD_LOCAL.set(this.fhirContext);
+        this.fhirClient = this.fhirContext.newRestfulGenericClient((String) options.get("serverUrl"));
+        GENERIC_CLIENT_THREAD_LOCAL.set(this.fhirClient);
+        final FhirConfiguration configuration = new FhirConfiguration();
+        IntrospectionSupport.setProperties(configuration, options);
+        configuration.setFhirContext(this.fhirContext);
+
+        // add FhirComponent to Camel context
+        final FhirComponent component = new FhirComponent(context);
+        component.setConfiguration(configuration);
+        context.addComponent("fhir", component);
+        return context;
+    }
+
+    @Override
+    protected void postProcessTest() throws Exception {
+        super.postProcessTest();
+        this.fhirContext = FHIR_CONTEXT_THREAD_LOCAL.get();
+        this.fhirClient = GENERIC_CLIENT_THREAD_LOCAL.get();
+    }
+
+    @Override
+    public boolean isCreateCamelContextPerClass() {
+        // only create the context once for this class
+        return true;
+    }
+
+    @SuppressWarnings("unchecked")
+    <T> T requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers)
+        throws CamelExecutionException {
+        return (T) template().requestBodyAndHeaders(endpointUri, body, headers);
+    }
+
+    @SuppressWarnings("unchecked")
+    <T> T requestBody(String endpoint, Object body) throws CamelExecutionException {
+        return (T) template().requestBody(endpoint, body);
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCapabilitiesIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCapabilitiesIT.java
new file mode 100644
index 0000000..8e5c6ff
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCapabilitiesIT.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirCapabilitiesApiMethod;
+import org.hl7.fhir.dstu3.model.CapabilityStatement;
+import org.hl7.fhir.dstu3.model.Enumerations;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirCapabilities} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirCapabilitiesIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirCapabilitiesIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirCapabilitiesApiMethod.class).getName();
+
+    @Test
+    public void testOfType() throws Exception {
+        org.hl7.fhir.instance.model.api.IBaseConformance result = requestBody("direct://OF_TYPE", CapabilityStatement.class);
+
+        LOG.debug("ofType: " + result);
+        assertNotNull("ofType result", result);
+        assertEquals(Enumerations.PublicationStatus.ACTIVE, ((CapabilityStatement)result).getStatus());
+    }
+
+    @Test
+    public void testEncodeJSON() throws Exception {
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ExtraParameters.ENCODE_JSON.getHeaderName(), Boolean.TRUE);
+
+        org.hl7.fhir.instance.model.api.IBaseConformance result = requestBodyAndHeaders("direct://OF_TYPE", CapabilityStatement.class, headers);
+
+        LOG.debug("ofType: " + result);
+        assertNotNull("ofType result", result);
+        assertEquals(Enumerations.PublicationStatus.ACTIVE, ((CapabilityStatement)result).getStatus());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for ofType
+                from("direct://OF_TYPE")
+                    .to("fhir://" + PATH_PREFIX + "/ofType?inBody=type&log=true");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirConfigurationIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirConfigurationIT.java
new file mode 100644
index 0000000..060e2a8
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirConfigurationIT.java
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.List;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import ca.uhn.fhir.rest.api.SummaryEnum;
+import ca.uhn.fhir.rest.client.api.IClientInterceptor;
+import ca.uhn.fhir.rest.client.impl.GenericClient;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirCreateApiMethod;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.Test;
+
+/**
+ * Test class for {@link FhirConfiguration} APIs.
+ */
+public class FhirConfigurationIT extends AbstractFhirTestSupport {
+
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirCreateApiMethod.class).getName();
+
+    private static final String TEST_URI = "fhir://" + PATH_PREFIX + "/resource?inBody=resourceAsString&log=true&"
+            + "encoding=JSON&summary=TEXT&compress=true&username=art&password=tatum&sessionCookie=mycookie%3DChips%20Ahoy"
+            + "&accessToken=token&serverUrl=http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu3&fhirVersion=DSTU3";
+    private FhirConfiguration componentConfiguration;
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        final CamelContext context = new DefaultCamelContext(createRegistry());
+
+        // add FhirComponent to Camel context but don't set up componentConfiguration
+        final FhirComponent component = new FhirComponent(context);
+        FhirConfiguration fhirConfiguration = new FhirConfiguration();
+        fhirConfiguration.setLog(true);
+        fhirConfiguration.setEncoding("JSON");
+        fhirConfiguration.setSummary("TEXT");
+        fhirConfiguration.setCompress(true);
+        fhirConfiguration.setUsername("art");
+        fhirConfiguration.setPassword("tatum");
+        fhirConfiguration.setSessionCookie("mycookie=Chips Ahoy");
+        fhirConfiguration.setAccessToken("token");
+        fhirConfiguration.setServerUrl("http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu3");
+        fhirConfiguration.setFhirVersion("DSTU3");
+        component.setConfiguration(fhirConfiguration);
+        this.componentConfiguration = fhirConfiguration;
+        context.addComponent("fhir", component);
+
+        return context;
+    }
+
+    @Test
+    public void testConfiguration() throws Exception {
+        FhirEndpoint endpoint = getMandatoryEndpoint(TEST_URI, FhirEndpoint.class);
+        GenericClient client = (GenericClient) endpoint.getClient();
+        FhirConfiguration configuration = endpoint.getConfiguration();
+        assertEquals(this.componentConfiguration, configuration);
+        assertEquals("http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu3", client.getUrlBase());
+        assertEquals(EncodingEnum.JSON, client.getEncoding());
+        assertEquals(SummaryEnum.TEXT, client.getSummary());
+        List<IClientInterceptor> interceptors = client.getInterceptors();
+        assertEquals(5, interceptors.size());
+    }
+
+    @Override
+    public void cleanFhirServerState() {
+        // do nothing
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct://CONFIGURATION").to(TEST_URI);
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCreateIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCreateIT.java
new file mode 100644
index 0000000..456771b
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCreateIT.java
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirCreateApiMethod;
+import org.hl7.fhir.dstu3.model.HumanName;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirCreate} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirCreateIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirCreateIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirCreateApiMethod.class).getName();
+
+    @Test
+    public void testCreateResource() throws Exception {
+        Patient patient = new Patient().addName(new HumanName().addGiven("Vincent").setFamily("Freeman"));
+
+        MethodOutcome result = requestBody("direct://RESOURCE", patient);
+
+        LOG.debug("resource: " + result);
+        assertNotNull("resource result", result);
+        assertTrue(result.getCreated());
+    }
+
+    @Test
+    public void testCreateStringResource() throws Exception {
+        Patient patient = new Patient().addName(new HumanName().addGiven("Vincent").setFamily("Freeman"));
+        String patientString = this.fhirContext.newXmlParser().encodeResourceToString(patient);
+
+        MethodOutcome result = requestBody("direct://RESOURCE_STRING", patientString);
+
+        LOG.debug("resource: " + result);
+        assertNotNull("resource result", result);
+        assertTrue(result.getCreated());
+    }
+
+    @Test
+    public void testCreateStringResourceEncodeXml() throws Exception {
+        Patient patient = new Patient().addName(new HumanName().addGiven("Vincent").setFamily("Freeman"));
+        String patientString = this.fhirContext.newXmlParser().encodeResourceToString(patient);
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ExtraParameters.ENCODE_XML.getHeaderName(), Boolean.TRUE);
+        MethodOutcome result = requestBodyAndHeaders("direct://RESOURCE_STRING", patientString, headers);
+
+        LOG.debug("resource: " + result);
+        assertNotNull("resource result", result);
+        assertTrue(result.getCreated());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for resource
+                from("direct://RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resource?inBody=resource");
+
+                // test route for resource
+                from("direct://RESOURCE_STRING")
+                    .to("fhir://" + PATH_PREFIX + "/resource?inBody=resourceAsString&log=true");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCustomClientConfigurationIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCustomClientConfigurationIT.java
new file mode 100644
index 0000000..a856cb1
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirCustomClientConfigurationIT.java
@@ -0,0 +1,409 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.List;
+import java.util.Map;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.model.primitive.UriDt;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.RequestTypeEnum;
+import ca.uhn.fhir.rest.api.SummaryEnum;
+import ca.uhn.fhir.rest.client.api.Header;
+import ca.uhn.fhir.rest.client.api.IClientInterceptor;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.client.api.IHttpClient;
+import ca.uhn.fhir.rest.client.api.IRestfulClient;
+import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
+import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
+import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
+import ca.uhn.fhir.rest.gclient.ICreate;
+import ca.uhn.fhir.rest.gclient.IDelete;
+import ca.uhn.fhir.rest.gclient.IFetchConformanceUntyped;
+import ca.uhn.fhir.rest.gclient.IGetPage;
+import ca.uhn.fhir.rest.gclient.IHistory;
+import ca.uhn.fhir.rest.gclient.IMeta;
+import ca.uhn.fhir.rest.gclient.IOperation;
+import ca.uhn.fhir.rest.gclient.IPatch;
+import ca.uhn.fhir.rest.gclient.IRead;
+import ca.uhn.fhir.rest.gclient.ITransaction;
+import ca.uhn.fhir.rest.gclient.IUntypedQuery;
+import ca.uhn.fhir.rest.gclient.IUpdate;
+import ca.uhn.fhir.rest.gclient.IValidate;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirCreateApiMethod;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.JndiRegistry;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.junit.Test;
+
+/**
+ * Test class for {@link FhirConfiguration} APIs.
+ */
+public class FhirCustomClientConfigurationIT extends AbstractFhirTestSupport {
+
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirCreateApiMethod.class).getName();
+
+    private static final String TEST_URI_CUSTOM_CLIENT = "fhir://" + PATH_PREFIX + "/resource?inBody=resourceAsString&client=#customClient";
+
+    private static final String TEST_URI_CUSTOM_CLIENT_FACTORY = "fhir://" + PATH_PREFIX + "/resource?inBody=resourceAsString&clientFactory=#customClientFactory&serverUrl=foobar";
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        final CamelContext context = new DefaultCamelContext(createRegistry());
+
+        // add FhirComponent to Camel context but don't set up componentConfiguration
+        final FhirComponent component = new FhirComponent(context);
+        context.addComponent("fhir", component);
+
+        return context;
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry registry = super.createRegistry();
+        registry.bind("customClient", new CustomClient());
+        registry.bind("customClientFactory", new CustomClientFactory());
+        return registry;
+    }
+
+    @Test
+    public void testConfigurationWithCustomClient() throws Exception {
+        FhirEndpoint endpoint = getMandatoryEndpoint(TEST_URI_CUSTOM_CLIENT, FhirEndpoint.class);
+        IGenericClient client = endpoint.getClient();
+        assertTrue(client instanceof CustomClient);
+    }
+
+    @Test
+    public void testConfigurationWithCustomFactory() throws Exception {
+        FhirEndpoint endpoint = getMandatoryEndpoint(TEST_URI_CUSTOM_CLIENT_FACTORY, FhirEndpoint.class);
+        IGenericClient client = endpoint.getClient();
+        assertTrue(client instanceof CustomClient);
+    }
+
+    @Override
+    public void cleanFhirServerState() {
+        // do nothing
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct://CONFIGURATION_CUSTOM_CLIENT").to(TEST_URI_CUSTOM_CLIENT);
+                from("direct://CONFIGURATION_CUSTOM_CLIENT_FACTORY").to(TEST_URI_CUSTOM_CLIENT_FACTORY);
+            }
+        };
+    }
+
+    private class CustomClientFactory implements IRestfulClientFactory {
+
+        @Override
+        public int getConnectionRequestTimeout() {
+            return 0;
+        }
+
+        @Override
+        public int getConnectTimeout() {
+            return 0;
+        }
+
+        @Override
+        public IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
+            return null;
+        }
+
+        @Override
+        public ServerValidationModeEnum getServerValidationModeEnum() {
+            return null;
+        }
+
+        @Override
+        public ServerValidationModeEnum getServerValidationMode() {
+            return null;
+        }
+
+        @Override
+        public int getSocketTimeout() {
+            return 0;
+        }
+
+        @Override
+        public int getPoolMaxTotal() {
+            return 0;
+        }
+
+        @Override
+        public int getPoolMaxPerRoute() {
+            return 0;
+        }
+
+        @Override
+        public <T extends IRestfulClient> T newClient(Class<T> theClientType, String theServerBase) {
+            return null;
+        }
+
+        @Override
+        public IGenericClient newGenericClient(String theServerBase) {
+            return new CustomClient();
+        }
+
+        @Override
+        public void setConnectionRequestTimeout(int theConnectionRequestTimeout) {
+
+        }
+
+        @Override
+        public void setConnectTimeout(int theConnectTimeout) {
+
+        }
+
+        @Override
+        public <T> void setHttpClient(T theHttpClient) {
+
+        }
+
+        @Override
+        public void setProxy(String theHost, Integer thePort) {
+
+        }
+
+        @Override
+        public void setProxyCredentials(String theUsername, String thePassword) {
+
+        }
+
+        @Override
+        public void setServerValidationModeEnum(ServerValidationModeEnum theServerValidationMode) {
+
+        }
+
+        @Override
+        public void setServerValidationMode(ServerValidationModeEnum theServerValidationMode) {
+
+        }
+
+        @Override
+        public void setSocketTimeout(int theSocketTimeout) {
+
+        }
+
+        @Override
+        public void setPoolMaxTotal(int thePoolMaxTotal) {
+
+        }
+
+        @Override
+        public void setPoolMaxPerRoute(int thePoolMaxPerRoute) {
+
+        }
+
+        @Override
+        public void validateServerBase(String theServerBase, IHttpClient theHttpClient, IRestfulClient theClient) {
+
+        }
+
+        @Override
+        public void validateServerBaseIfConfiguredToDoSo(String theServerBase, IHttpClient theHttpClient, IRestfulClient theClient) {
+
+        }
+    }
+
+    private class CustomClient implements IGenericClient {
+
+        @Override
+        public IFetchConformanceUntyped capabilities() {
+            return null;
+        }
+
+        @Override
+        public ICreate create() {
+            return null;
+        }
+
+        @Override
+        public IDelete delete() {
+            return null;
+        }
+
+        @Override
+        public IFetchConformanceUntyped fetchConformance() {
+            return null;
+        }
+
+        @Override
+        public void forceConformanceCheck() throws FhirClientConnectionException {
+
+        }
+
+        @Override
+        public IHistory history() {
+            return null;
+        }
+
+        @Override
+        public IGetPage loadPage() {
+            return null;
+        }
+
+        @Override
+        public IMeta meta() {
+            return null;
+        }
+
+        @Override
+        public IOperation operation() {
+            return null;
+        }
+
+        @Override
+        public IPatch patch() {
+            return null;
+        }
+
+        @Override
+        public IRead read() {
+            return null;
+        }
+
+        @Override
+        public <T extends IBaseResource> T read(Class<T> theType, String theId) {
+            return null;
+        }
+
+        @Override
+        public <T extends IBaseResource> T read(Class<T> theType, UriDt theUrl) {
+            return null;
+        }
+
+        @Override
+        public IBaseResource read(UriDt theUrl) {
+            return null;
+        }
+
+        @Override
+        public <T extends IBaseResource> T fetchResourceFromUrl(Class<T> theResourceType, String theUrl) {
+            return null;
+        }
+
+        @Override
+        public EncodingEnum getEncoding() {
+            return null;
+        }
+
+        @Override
+        public FhirContext getFhirContext() {
+            return null;
+        }
+
+        @Override
+        public IHttpClient getHttpClient() {
+            return null;
+        }
+
+        @Override
+        public List<IClientInterceptor> getInterceptors() {
+            return null;
+        }
+
+        @Override
+        public String getServerBase() {
+            return null;
+        }
+
+        @Override
+        public void registerInterceptor(IClientInterceptor theInterceptor) {
+
+        }
+
+        @Override
+        public void setEncoding(EncodingEnum theEncoding) {
+
+        }
+
+        @Override
+        public void setPrettyPrint(Boolean thePrettyPrint) {
+
+        }
+
+        @Override
+        public void setSummary(SummaryEnum theSummary) {
+
+        }
+
+        @Override
+        public <T extends IBaseBundle> IUntypedQuery<T> search() {
+            return null;
+        }
+
+        @Override
+        public void setLogRequestAndResponse(boolean theLogRequestAndResponse) {
+
+        }
+
+        @Override
+        public ITransaction transaction() {
+            return null;
+        }
+
+        @Override
+        public void unregisterInterceptor(IClientInterceptor theInterceptor) {
+
+        }
+
+        @Override
+        public IUpdate update() {
+            return null;
+        }
+
+        @Override
+        public MethodOutcome update(IdDt theId, IBaseResource theResource) {
+            return null;
+        }
+
+        @Override
+        public MethodOutcome update(String theId, IBaseResource theResource) {
+            return null;
+        }
+
+        @Override
+        public IValidate validate() {
+            return null;
+        }
+
+        @Override
+        public MethodOutcome validate(IBaseResource theResource) {
+            return null;
+        }
+
+        @Override
+        public <T extends IBaseResource> T vread(Class<T> theType, IdDt theId) {
+            return null;
+        }
+
+        @Override
+        public <T extends IBaseResource> T vread(Class<T> theType, String theId, String theVersionId) {
+            return null;
+        }
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirDeleteIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirDeleteIT.java
new file mode 100644
index 0000000..b9ba5c6
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirDeleteIT.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import ca.uhn.fhir.rest.api.CacheControlDirective;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirDeleteApiMethod;
+import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirDelete} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirDeleteIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirDeleteIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirDeleteApiMethod.class).getName();
+
+    @Test
+    public void testDeleteResource() throws Exception {
+        assertTrue(patientExists());
+        // using org.hl7.fhir.instance.model.api.IBaseResource message body for single parameter "resource"
+        IBaseOperationOutcome result = requestBody("direct://RESOURCE", this.patient);
+
+        LOG.debug("resource: " + result);
+        assertNotNull("resource result", result);
+        assertFalse(patientExists());
+    }
+
+    @Test
+    public void testDeleteResourceById() throws Exception {
+        assertTrue(patientExists());
+
+        // using org.hl7.fhir.instance.model.api.IIdType message body for single parameter "id"
+        IBaseOperationOutcome result = requestBody("direct://RESOURCE_BY_ID", this.patient.getIdElement());
+
+        LOG.debug("resourceById: " + result);
+        assertNotNull("resourceById result", result);
+        assertFalse(patientExists());
+    }
+
+    @Test
+    public void testDeleteResourceByStringId() throws Exception {
+        assertTrue(patientExists());
+
+        Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.type", "Patient");
+        // parameter type is String
+        headers.put("CamelFhir.stringId", this.patient.getIdElement().getIdPart());
+
+        IBaseOperationOutcome result = requestBodyAndHeaders("direct://RESOURCE_BY_STRING_ID", null, headers);
+
+        LOG.debug("resourceById: " + result);
+        assertNotNull("resourceById result", result);
+        assertFalse(patientExists());
+    }
+
+    @Test
+    public void testDeleteResourceConditionalByUrl() throws Exception {
+        assertTrue(patientExists());
+
+        IBaseOperationOutcome result = requestBody("direct://RESOURCE_CONDITIONAL_BY_URL", "Patient?given=Vincent&family=Freeman");
+
+        LOG.debug("resourceConditionalByUrl: " + result);
+        assertNotNull("resourceConditionalByUrl result", result);
+        assertFalse(patientExists());
+    }
+
+    @Test
+    public void testDeleteResourceConditionalByUrlCacheControlDirective() throws Exception {
+        assertTrue(patientExists());
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ExtraParameters.CACHE_CONTROL_DIRECTIVE.getHeaderName(), new CacheControlDirective().setNoCache(true));
+
+        IBaseOperationOutcome result = requestBodyAndHeaders("direct://RESOURCE_CONDITIONAL_BY_URL", "Patient?given=Vincent&family=Freeman", headers);
+
+        LOG.debug("resourceConditionalByUrl: " + result);
+        assertNotNull("resourceConditionalByUrl result", result);
+        assertFalse(patientExists());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for resource
+                from("direct://RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resource?inBody=resource");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_ID")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById?inBody=id");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_STRING_ID")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById");
+
+                // test route for resourceConditionalByUrl
+                from("direct://RESOURCE_CONDITIONAL_BY_URL")
+                    .to("fhir://" + PATH_PREFIX + "/resourceConditionalByUrl?inBody=url");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirExtraParametersIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirExtraParametersIT.java
new file mode 100644
index 0000000..26fcb19
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirExtraParametersIT.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirSearchApiMethod;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirSearch} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirExtraParametersIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirExtraParametersIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirSearchApiMethod.class).getName();
+
+    @Test
+    public void testEncodeRequestToXml() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // encode request to XML
+        headers.put(ExtraParameters.ENCODE_XML.getHeaderName(), Boolean.TRUE);
+        String url = "Patient?given=Vincent&family=Freeman&_format=json";
+
+        Bundle result = requestBodyAndHeaders("direct://SEARCH_BY_URL", url, headers);
+
+        LOG.debug("searchByUrl: " + result);
+        assertNotNull("searchByUrl result", result);
+        Patient patient = (Patient) result.getEntry().get(0).getResource();
+        assertNotNull(patient);
+        assertEquals("Freeman", patient.getName().get(0).getFamily());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for searchByUrl
+                from("direct://SEARCH_BY_URL")
+                    .to("fhir://" + PATH_PREFIX + "/searchByUrl?inBody=url");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirHistoryIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirHistoryIT.java
new file mode 100644
index 0000000..b42251f
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirHistoryIT.java
@@ -0,0 +1,123 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirHistoryApiMethod;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirHistory} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirHistoryIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirHistoryIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirHistoryApiMethod.class).getName();
+
+    @Test
+    public void testOnInstance() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", Bundle.class);
+        // parameter type is Integer
+        headers.put("CamelFhir.count", 1);
+
+        Bundle result = requestBodyAndHeaders("direct://ON_INSTANCE", null, headers);
+
+        LOG.debug("onInstance: " + result);
+        assertNotNull("onInstance result", result);
+        assertEquals(1, result.getEntry().size());
+    }
+
+    @Test
+    public void testOnServer() throws Exception {
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("CamelFhir.returnType", Bundle.class);
+        headers.put("CamelFhir.count", 1);
+        Bundle result = requestBodyAndHeaders("direct://ON_SERVER", null, headers);
+
+        LOG.debug("onServer: " + result);
+        assertNotNull("onServer result", result);
+        assertEquals(1, result.getEntry().size());
+    }
+
+    @Test
+    public void testOnType() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resourceType", Patient.class);
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", Bundle.class);
+        // parameter type is Integer
+        headers.put("CamelFhir.count", 1);
+
+        Bundle result = requestBodyAndHeaders("direct://ON_TYPE", null, headers);
+
+        LOG.debug("onType: " + result);
+        assertNotNull("onType result", result);
+        assertEquals(1, result.getEntry().size());
+    }
+
+    @Test
+    public void testOnTypeWithSubsetElements() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resourceType", Patient.class);
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", Bundle.class);
+        // parameter type is Integer
+        headers.put("CamelFhir.count", 1);
+        // only include the identifier and name
+        headers.put(ExtraParameters.SUBSET_ELEMENTS.getHeaderName(), new String[]{"identifier", "name"});
+
+
+        Bundle result = requestBodyAndHeaders("direct://ON_TYPE", null, headers);
+
+        LOG.debug("onType: " + result);
+        assertNotNull("onType result", result);
+        assertEquals(1, result.getEntry().size());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for onInstance
+                from("direct://ON_INSTANCE")
+                    .to("fhir://" + PATH_PREFIX + "/onInstance");
+
+                // test route for onServer
+                from("direct://ON_SERVER")
+                    .to("fhir://" + PATH_PREFIX + "/onServer");
+
+                // test route for onType
+                from("direct://ON_TYPE")
+                    .to("fhir://" + PATH_PREFIX + "/onType");
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatSpringTest.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatSpringTest.java
similarity index 100%
rename from components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatSpringTest.java
rename to components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatSpringTest.java
diff --git a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatTest.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatTest.java
similarity index 100%
rename from components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatTest.java
rename to components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirJsonDataFormatTest.java
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirLoadPageIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirLoadPageIT.java
new file mode 100644
index 0000000..e673947
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirLoadPageIT.java
@@ -0,0 +1,164 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirLoadPageApiMethod;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.HumanName;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirLoadPage} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirLoadPageIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirLoadPageIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirLoadPageApiMethod.class).getName();
+
+    @Test
+    public void testByUrl() throws Exception {
+        String url = "Patient?_count=2";
+        Bundle bundle = this.fhirClient.search()
+                .byUrl(url)
+                .returnBundle(Bundle.class).execute();
+        assertNotNull(bundle.getLink(Bundle.LINK_NEXT));
+
+        String nextPageLink = bundle.getLink("next").getUrl();
+
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.url", nextPageLink);
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", Bundle.class);
+
+        IBaseBundle result = requestBodyAndHeaders("direct://BY_URL", null, headers);
+
+        LOG.debug("byUrl: " + result);
+        assertNotNull("byUrl result", result);
+    }
+
+    @Test
+    public void testNext() throws Exception {
+        String url = "Patient?_count=2";
+        Bundle bundle = this.fhirClient.search()
+                                       .byUrl(url)
+                                       .returnBundle(Bundle.class).execute();
+        assertNotNull(bundle.getLink(Bundle.LINK_NEXT));
+
+        // using org.hl7.fhir.instance.model.api.IBaseBundle message body for single parameter "bundle"
+        Bundle result = requestBody("direct://NEXT", bundle);
+
+        assertNotNull("next result", result);
+        LOG.debug("next: " + result);
+    }
+
+    @Test
+    public void testPrevious() throws Exception {
+        String url = "Patient?_count=2";
+        Bundle bundle = this.fhirClient.search()
+                .byUrl(url)
+                .returnBundle(Bundle.class).execute();
+        assertNotNull(bundle.getLink(Bundle.LINK_NEXT));
+
+        String nextPageLink = bundle.getLink("next").getUrl();
+        bundle = this.fhirClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
+        assertNotNull(bundle.getLink(Bundle.LINK_PREV));
+
+        // using org.hl7.fhir.instance.model.api.IBaseBundle message body for single parameter "bundle"
+        Bundle result = requestBody("direct://PREVIOUS", bundle);
+
+        LOG.debug("previous: " + result);
+        assertNotNull("previous result", result);
+    }
+
+    @Test
+    public void testPreviousWithEncodingEnum() throws Exception {
+        String url = "Patient?_count=2";
+        Bundle bundle = this.fhirClient.search()
+                .byUrl(url)
+                .returnBundle(Bundle.class).execute();
+        assertNotNull(bundle.getLink(Bundle.LINK_NEXT));
+
+        String nextPageLink = bundle.getLink("next").getUrl();
+        bundle = this.fhirClient.loadPage().byUrl(nextPageLink).andReturnBundle(Bundle.class).execute();
+        assertNotNull(bundle.getLink(Bundle.LINK_PREV));
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ExtraParameters.ENCODING_ENUM.getHeaderName(), EncodingEnum.XML);
+
+        // using org.hl7.fhir.instance.model.api.IBaseBundle message body for single parameter "bundle"
+        Bundle result = requestBodyAndHeaders("direct://PREVIOUS", bundle, headers);
+
+        LOG.debug("previous: " + result);
+        assertNotNull("previous result", result);
+    }
+
+    @Before
+    public void populateServer() {
+        List<IBaseResource> input = new ArrayList<>();
+
+        Patient p1 = new Patient();
+        p1.addName().setFamily("PATIENT1");
+        input.add(p1);
+
+        Patient p2 = new Patient();
+        p2.addName().setFamily("PATIENT2");
+        input.add(p2);
+
+        input.add(new Patient().addName(new HumanName().setFamily("PATIENT3")));
+
+        List<IBaseResource> response = fhirClient.transaction()
+                .withResources(input)
+                .encodedJson()
+                .execute();
+        assertEquals(3, response.size());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for byUrl
+                from("direct://BY_URL")
+                    .to("fhir://" + PATH_PREFIX + "/byUrl");
+
+                // test route for next
+                from("direct://NEXT")
+                    .to("fhir://" + PATH_PREFIX + "/next?inBody=bundle");
+
+                // test route for previous
+                from("direct://PREVIOUS")
+                    .to("fhir://" + PATH_PREFIX + "/previous?inBody=bundle");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirMetaIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirMetaIT.java
new file mode 100644
index 0000000..aa6f915
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirMetaIT.java
@@ -0,0 +1,169 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirMetaApiMethod;
+import org.hl7.fhir.dstu3.model.Meta;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.instance.model.api.IBaseMetaType;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirMeta} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirMetaIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirMetaIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirMetaApiMethod.class).getName();
+
+    @Test
+    public void testAdd() throws Exception {
+        //assert no meta
+        Meta meta = fhirClient.meta().get(Meta.class).fromResource(this.patient.getIdElement()).execute();
+        assertEquals(0, meta.getTag().size());
+        Meta inMeta = new Meta();
+        inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseMetaType
+        headers.put("CamelFhir.meta", inMeta);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+
+        IBaseMetaType result = requestBodyAndHeaders("direct://ADD", null, headers);
+
+        LOG.debug("add: " + result);
+        assertNotNull("add result", result);
+        assertEquals(1, result.getTag().size());
+    }
+
+    @Test
+    public void testDelete() throws Exception {
+        //assert no meta
+        Meta meta = fhirClient.meta().get(Meta.class).fromResource(this.patient.getIdElement()).execute();
+        assertEquals(0, meta.getTag().size());
+        Meta inMeta = new Meta();
+        inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
+        // add meta
+        meta = fhirClient.meta().
+                                add().
+                                onResource(this.patient.getIdElement()).
+                                meta(inMeta).
+                                execute();
+        assertEquals(1, meta.getTag().size());
+
+        //delete meta
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseMetaType
+        headers.put("CamelFhir.meta", meta);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+
+        IBaseMetaType result = requestBodyAndHeaders("direct://DELETE", null, headers);
+
+        LOG.debug("delete: " + result);
+        assertNotNull("delete result", result);
+        assertEquals(0, result.getTag().size());
+    }
+
+    @Test
+    public void testGetFromResource() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.metaType", Meta.class);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+
+        IBaseMetaType result = requestBodyAndHeaders("direct://GET_FROM_RESOURCE", null, headers);
+
+        LOG.debug("getFromResource: " + result);
+        assertNotNull("getFromResource result", result);
+        assertEquals(0, result.getTag().size());
+    }
+
+    @Test
+    public void testGetFromServer() throws Exception {
+        // using Class message body for single parameter "metaType"
+        IBaseMetaType result = requestBody("direct://GET_FROM_SERVER", Meta.class);
+        assertNotNull("getFromServer result", result);
+        LOG.debug("getFromServer: " + result);
+    }
+
+    @Test
+    public void testGetFromType() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.metaType", Meta.class);
+        // parameter type is String
+        headers.put("CamelFhir.theResourceName", "Patient");
+
+        IBaseMetaType result = requestBodyAndHeaders("direct://GET_FROM_TYPE", null, headers);
+
+        LOG.debug("getFromType: " + result);
+        assertNotNull("getFromType result", result);
+    }
+
+    @Test
+    public void testGetFromTypePreferResponseType() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.metaType", Meta.class);
+        // parameter type is String
+        headers.put("CamelFhir.theResourceName", "Patient");
+        headers.put(ExtraParameters.PREFER_RESPONSE_TYPE.getHeaderName(), Patient.class);
+
+        Meta result = requestBodyAndHeaders("direct://GET_FROM_TYPE", null, headers);
+
+        LOG.debug("getFromType: " + result);
+        assertNotNull("getFromType result", result);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for add
+                from("direct://ADD")
+                    .to("fhir://" + PATH_PREFIX + "/add");
+
+                // test route for delete
+                from("direct://DELETE")
+                    .to("fhir://" + PATH_PREFIX + "/delete");
+
+                // test route for getFromResource
+                from("direct://GET_FROM_RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/getFromResource");
+
+                // test route for getFromServer
+                from("direct://GET_FROM_SERVER")
+                    .to("fhir://" + PATH_PREFIX + "/getFromServer?inBody=metaType");
+
+                // test route for getFromType
+                from("direct://GET_FROM_TYPE")
+                    .to("fhir://" + PATH_PREFIX + "/getFromType");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java
new file mode 100644
index 0000000..1a7116c
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java
@@ -0,0 +1,139 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirPatchApiMethod;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirPatch} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirPatchIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirPatchIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirPatchApiMethod.class).getName();
+    private static final String PATCH = "[ { \"op\":\"replace\", \"path\":\"/active\", \"value\":true } ]";
+
+    @Test
+    public void testPatchById() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.patchBody", PATCH);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", null);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://PATCH_BY_ID", null, headers);
+        assertNotNull("patchById result", result);
+        assertActive(result);
+    }
+
+    @Test
+    public void testPatchByStringId() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.patchBody", PATCH);
+        // parameter type is String
+        headers.put("CamelFhir.stringId", this.patient.getId());
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", null);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://PATCH_BY_SID", null, headers);
+        assertActive(result);
+    }
+
+    @Test
+    public void testPatchByStringIdPreferResponseTypes() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.patchBody", PATCH);
+        // parameter type is String
+        headers.put("CamelFhir.stringId", this.patient.getId());
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", null);
+
+        List<Class<? extends IBaseResource>> preferredResponseTypes = new ArrayList<>();
+        preferredResponseTypes.add(Patient.class);
+        headers.put(ExtraParameters.PREFER_RESPONSE_TYPES.getHeaderName(), preferredResponseTypes);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://PATCH_BY_SID", null, headers);
+        assertActive(result);
+    }
+
+    @Test
+    @Ignore(value = "https://github.com/jamesagnew/hapi-fhir/issues/955")
+    public void testPatchByUrl() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.patchBody", PATCH);
+        // parameter type is String
+        headers.put("CamelFhir.url", "Patient?given=Vincent&family=Freeman");
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", null);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://PATCH_BY_URL", null, headers);
+
+        assertNotNull("patchByUrl result", result);
+        LOG.debug("patchByUrl: " + result);
+        assertActive(result);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for patchById
+                from("direct://PATCH_BY_ID")
+                    .to("fhir://" + PATH_PREFIX + "/patchById");
+
+                // test route for patchBySId
+                from("direct://PATCH_BY_SID")
+                    .to("fhir://" + PATH_PREFIX + "/patchById");
+
+                // test route for patchByUrl
+                from("direct://PATCH_BY_URL")
+                    .to("fhir://" + PATH_PREFIX + "/patchByUrl");
+
+            }
+        };
+    }
+
+    private void assertActive(MethodOutcome result) {
+        LOG.debug("result: " + result);
+        IIdType id = result.getId();
+
+        Patient patient = fhirClient.read().resource(Patient.class).withId(id).preferResponseType(Patient.class).execute();
+        System.out.print(fhirContext.newJsonParser().encodeResourceToString(patient));
+        assertTrue(patient.getActive());
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirReadIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirReadIT.java
new file mode 100644
index 0000000..42fc00c
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirReadIT.java
@@ -0,0 +1,275 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirReadApiMethod;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirRead} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirReadIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirReadIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirReadApiMethod.class).getName();
+
+    @Test
+    public void testResourceById() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", patient.getIdElement());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_ID", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByLongId() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is Long
+        headers.put("CamelFhir.longId", Long.valueOf(patient.getIdElement().getIdPart()));
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_LONG_ID", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByStringId() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is Long
+        headers.put("CamelFhir.stringId", patient.getIdElement().getIdPart());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_STRING_ID", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByIdAndStringResource() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resourceClass", "Patient");
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", patient.getIdElement());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_ID_AND_STRING_RESOURCE", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByLongIdAndStringResource() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is Long
+        headers.put("CamelFhir.longId", Long.valueOf(patient.getIdElement().getIdPart()));
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_LONG_ID_AND_STRING_RESOURCE", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByStringIdAndStringResource() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is Long
+        headers.put("CamelFhir.stringId", patient.getIdElement().getIdPart());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_STRING_ID_AND_STRING_RESOURCE", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByStringIdAndVersion() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is Long
+        headers.put("CamelFhir.stringId", patient.getIdElement().getIdPart());
+        // parameter type is String
+        headers.put("CamelFhir.version", patient.getIdElement().getVersionIdPart());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_STRING_ID_AND_VERSION", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByStringIdAndVersionWithResourceClass() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resourceClass", "Patient");
+        // parameter type is Long
+        headers.put("CamelFhir.stringId", patient.getIdElement().getIdPart());
+        // parameter type is String
+        headers.put("CamelFhir.version", patient.getIdElement().getVersionIdPart());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_STRING_ID_AND_VERSION_AND_STRING_RESOURCE", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByiUrl() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.iUrl", new IdType(this.patient.getId()));
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_IURL", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByUrl() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is Class
+        headers.put("CamelFhir.resource", Patient.class);
+        // parameter type is String
+        headers.put("CamelFhir.url", this.patient.getId());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_URL", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByStringUrlAndStringResource() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.resourceClass", "Patient");
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.iUrl", new IdType(this.patient.getId()));
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_STRING_URL_AND_STRING_RESOURCE", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByUrlAndStringResource() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.resourceClass", "Patient");
+        // parameter type is String
+        headers.put("CamelFhir.url", this.patient.getId());
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_URL_AND_STRING_RESOURCE", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    @Test
+    public void testResourceByUrlAndStringResourcePrettyPrint() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.resourceClass", "Patient");
+        // parameter type is String
+        headers.put("CamelFhir.url", this.patient.getId());
+        headers.put(ExtraParameters.PRETTY_PRINT.getHeaderName(), Boolean.TRUE);
+
+        Patient result = requestBodyAndHeaders("direct://RESOURCE_BY_URL_AND_STRING_RESOURCE", null, headers);
+
+        assertValidResponse(result);
+    }
+
+    private void assertValidResponse(Patient result) {
+        LOG.debug("response: " + result);
+        assertNotNull("resourceByUrl result", result);
+        assertEquals("Freeman", result.getName().get(0).getFamily());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for resourceById
+                from("direct://RESOURCE_BY_ID")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_LONG_ID")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_STRING_ID")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_ID_AND_STRING_RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_LONG_ID_AND_STRING_RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_STRING_ID_AND_STRING_RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resourceById");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_STRING_ID_AND_VERSION")
+                    .to("fhir://" + PATH_PREFIX + "/resourceByIdAndVersion");
+
+                // test route for resourceById
+                from("direct://RESOURCE_BY_STRING_ID_AND_VERSION_AND_STRING_RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resourceByIdAndVersion");
+
+                // test route for resourceByUrl
+                from("direct://RESOURCE_BY_IURL")
+                    .to("fhir://" + PATH_PREFIX + "/resourceByUrl");
+
+                // test route for resourceByUrl
+                from("direct://RESOURCE_BY_URL")
+                    .to("fhir://" + PATH_PREFIX + "/resourceByUrl");
+
+                // test route for resourceByUrl
+                from("direct://RESOURCE_BY_STRING_URL_AND_STRING_RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resourceByUrl");
+
+                // test route for resourceByUrl
+                from("direct://RESOURCE_BY_URL_AND_STRING_RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resourceByUrl");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirSearchIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirSearchIT.java
new file mode 100644
index 0000000..be85ca0
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirSearchIT.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirSearchApiMethod;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirSearch} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirSearchIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirSearchIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirSearchApiMethod.class).getName();
+
+    @Test
+    public void testSearchByUrl() throws Exception {
+        String url = "Patient?given=Vincent&family=Freeman&_format=json";
+        Bundle result = requestBody("direct://SEARCH_BY_URL", url);
+
+        LOG.debug("searchByUrl: " + result);
+        assertNotNull("searchByUrl result", result);
+        Patient patient = (Patient) result.getEntry().get(0).getResource();
+        assertNotNull(patient);
+        assertEquals("Freeman", patient.getName().get(0).getFamily());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for searchByUrl
+                from("direct://SEARCH_BY_URL")
+                    .to("fhir://" + PATH_PREFIX + "/searchByUrl?inBody=url");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirTransactionIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirTransactionIT.java
new file mode 100644
index 0000000..a31193a
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirTransactionIT.java
@@ -0,0 +1,132 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import ca.uhn.fhir.rest.api.SummaryEnum;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.api.ExtraParameters;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirTransactionApiMethod;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.HumanName;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirTransaction} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirTransactionIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirTransactionIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirTransactionApiMethod.class).getName();
+
+    @Test
+    public void testWithBundle() throws Exception {
+        // using org.hl7.fhir.instance.model.api.IBaseBundle message body for single parameter "bundle"
+        Bundle result = requestBody("direct://WITH_BUNDLE", createTransactionBundle());
+
+        assertNotNull("withBundle result", result);
+        assertTrue(result.getEntry().get(0).getResponse().getStatus().contains("Created"));
+        LOG.debug("withBundle: " + result);
+    }
+
+    @Test
+    public void testWithStringBundle() throws Exception {
+        Bundle transactionBundle = createTransactionBundle();
+        String stringBundle = fhirContext.newJsonParser().encodeResourceToString(transactionBundle);
+
+        // using String message body for single parameter "sBundle"
+        final String result = requestBody("direct://WITH_STRING_BUNDLE", stringBundle);
+
+        assertNotNull("withBundle result", result);
+        assertTrue(result.contains("Bundle"));
+        LOG.debug("withBundle: " + result);
+    }
+
+    @Test
+    public void testWithResources() throws Exception {
+        Patient oscar = new Patient().addName(new HumanName().addGiven("Oscar").setFamily("Peterson"));
+        Patient bobbyHebb = new Patient().addName(new HumanName().addGiven("Bobby").setFamily("Hebb"));
+        List<IBaseResource> patients = new ArrayList<>(2);
+        patients.add(oscar);
+        patients.add(bobbyHebb);
+
+        // using java.util.List message body for single parameter "resources"
+        List<IBaseResource> result = requestBody("direct://WITH_RESOURCES", patients);
+
+        assertNotNull("withResources result", result);
+        LOG.debug("withResources: " + result);
+        assertTrue(result.size() == 2);
+    }
+
+    @Test
+    public void testWithResourcesSummaryEnum() throws Exception {
+        Patient oscar = new Patient().addName(new HumanName().addGiven("Oscar").setFamily("Peterson"));
+        Patient bobbyHebb = new Patient().addName(new HumanName().addGiven("Bobby").setFamily("Hebb"));
+        List<IBaseResource> patients = new ArrayList<>(2);
+        patients.add(oscar);
+        patients.add(bobbyHebb);
+        final Map<String, Object> headers = new HashMap<>();
+        headers.put(ExtraParameters.SUMMARY_ENUM.getHeaderName(), SummaryEnum.DATA);
+
+        // using java.util.List message body for single parameter "resources"
+        List<IBaseResource> result = requestBodyAndHeaders("direct://WITH_RESOURCES", patients, headers);
+
+        assertNotNull("withResources result", result);
+        LOG.debug("withResources: " + result);
+        assertTrue(result.size() == 2);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for withBundle
+                from("direct://WITH_BUNDLE")
+                    .to("fhir://" + PATH_PREFIX + "/withBundle?inBody=bundle");
+
+                // test route for withBundle
+                from("direct://WITH_STRING_BUNDLE")
+                    .to("fhir://" + PATH_PREFIX + "/withBundle?inBody=stringBundle");
+
+                // test route for withResources
+                from("direct://WITH_RESOURCES")
+                    .to("fhir://" + PATH_PREFIX + "/withResources?inBody=resources");
+
+            }
+        };
+    }
+
+    private Bundle createTransactionBundle() {
+        Bundle input = new Bundle();
+        input.setType(Bundle.BundleType.TRANSACTION);
+        input.addEntry()
+            .setResource(new Patient().addName(new HumanName().addGiven("Art").setFamily("Tatum")))
+            .getRequest()
+            .setMethod(Bundle.HTTPVerb.POST);
+        return input;
+    }
+
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirUpdateIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirUpdateIT.java
new file mode 100644
index 0000000..4e97050
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirUpdateIT.java
@@ -0,0 +1,196 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.rest.api.PreferReturnEnum;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirUpdateApiMethod;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirUpdate} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirUpdateIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirUpdateIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirUpdateApiMethod.class).getName();
+
+    @Test
+    public void testResource() throws Exception {
+        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("1998-04-29");
+        assertNotEquals(date, patient.getBirthDate());
+        this.patient.setBirthDate(date);
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseResource
+        headers.put("CamelFhir.resource", this.patient);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", PreferReturnEnum.REPRESENTATION);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://RESOURCE", null, headers);
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertEquals("Birth date not updated!", date, ((Patient)result.getResource()).getBirthDate());
+    }
+
+    @Test
+    public void testResourceStringId() throws Exception {
+        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("1998-04-29");
+        assertNotEquals(date, patient.getBirthDate());
+        this.patient.setBirthDate(date);
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseResource
+        headers.put("CamelFhir.resource", this.patient);
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.stringId", this.patient.getIdElement().getIdPart());
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", PreferReturnEnum.REPRESENTATION);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://RESOURCE_WITH_STRING_ID", null, headers);
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertEquals("Birth date not updated!", date, ((Patient)result.getResource()).getBirthDate());
+    }
+
+    @Test
+    public void testResourceAsString() throws Exception {
+        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("1998-04-29");
+        assertNotEquals(date, patient.getBirthDate());
+        this.patient.setBirthDate(date);
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseResource
+        headers.put("CamelFhir.resourceAsString", this.fhirContext.newJsonParser().encodeResourceToString(this.patient));
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", PreferReturnEnum.REPRESENTATION);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://RESOURCE_AS_STRING", null, headers);
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertEquals("Birth date not updated!", date, ((Patient)result.getResource()).getBirthDate());
+    }
+
+    @Test
+    public void testResourceAsStringWithStringId() throws Exception {
+        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("1998-04-29");
+        assertNotEquals(date, patient.getBirthDate());
+        this.patient.setBirthDate(date);
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseResource
+        headers.put("CamelFhir.resourceAsString", this.fhirContext.newJsonParser().encodeResourceToString(this.patient));
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.stringId", this.patient.getIdElement().getIdPart());
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", PreferReturnEnum.REPRESENTATION);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://RESOURCE_AS_STRING_WITH_STRING_ID", null, headers);
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertEquals("Birth date not updated!", date, ((Patient)result.getResource()).getBirthDate());
+    }
+
+    @Test
+    public void testResourceBySearchUrl() throws Exception {
+        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("1998-04-29");
+        assertNotEquals(date, patient.getBirthDate());
+        this.patient.setBirthDate(date);
+        String url = "Patient?" + Patient.SP_IDENTIFIER + '=' + URLEncoder.encode(this.patient.getId(), "UTF-8");
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseResource
+        headers.put("CamelFhir.resource", this.patient);
+        // parameter type is String
+        headers.put("CamelFhir.url", url);
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", PreferReturnEnum.REPRESENTATION);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://RESOURCE_BY_SEARCH_URL", null, headers);
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertEquals("Birth date not updated!", date, ((Patient)result.getResource()).getBirthDate());
+    }
+
+    @Test
+    public void testResourceBySearchUrlAndResourceAsString() throws Exception {
+        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("1998-04-29");
+        assertNotEquals(date, patient.getBirthDate());
+        this.patient.setBirthDate(date);
+        String url = "Patient?" + Patient.SP_IDENTIFIER + '=' + URLEncoder.encode(this.patient.getId(), "UTF-8");
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseResource
+        headers.put("CamelFhir.resourceAsString", this.fhirContext.newJsonParser().encodeResourceToString(this.patient));
+        // parameter type is String
+        headers.put("CamelFhir.url", url);
+        // parameter type is ca.uhn.fhir.rest.api.PreferReturnEnum
+        headers.put("CamelFhir.preferReturn", PreferReturnEnum.REPRESENTATION);
+
+        MethodOutcome result = requestBodyAndHeaders("direct://RESOURCE_BY_SEARCH_URL_AND_RESOURCE_AS_STRING", null, headers);
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertEquals("Birth date not updated!", date, ((Patient)result.getResource()).getBirthDate());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for resource
+                from("direct://RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resource");
+
+                // test route for resource
+                from("direct://RESOURCE_WITH_STRING_ID")
+                    .to("fhir://" + PATH_PREFIX + "/resource");
+
+                // test route for resource
+                from("direct://RESOURCE_AS_STRING")
+                    .to("fhir://" + PATH_PREFIX + "/resource");
+
+                // test route for resource
+                from("direct://RESOURCE_AS_STRING_WITH_STRING_ID")
+                    .to("fhir://" + PATH_PREFIX + "/resource");
+
+                // test route for resourceBySearchUrl
+                from("direct://RESOURCE_BY_SEARCH_URL")
+                    .to("fhir://" + PATH_PREFIX + "/resourceBySearchUrl");
+
+                // test route for resourceBySearchUrl
+                from("direct://RESOURCE_BY_SEARCH_URL_AND_RESOURCE_AS_STRING")
+                    .to("fhir://" + PATH_PREFIX + "/resourceBySearchUrl");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirValidateIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirValidateIT.java
new file mode 100644
index 0000000..df55c38
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirValidateIT.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirValidateApiMethod;
+import org.hl7.fhir.dstu3.model.HumanName;
+import org.hl7.fhir.dstu3.model.OperationOutcome;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirValidate} APIs.
+ * The class source won't be generated again if the generator MOJO finds it under src/test/java.
+ */
+public class FhirValidateIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirValidateIT.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirValidateApiMethod.class).getName();
+
+    @Test
+    public void testResource() throws Exception {
+        Patient bobbyHebb      = new Patient().addName(new HumanName().addGiven("Bobby").setFamily("Hebb"));
+        // using org.hl7.fhir.instance.model.api.IBaseResource message body for single parameter "resource"
+        MethodOutcome result = requestBody("direct://RESOURCE", bobbyHebb);
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertNotNull(result.getOperationOutcome());
+        assertTrue(((OperationOutcome) result.getOperationOutcome()).getText().getDivAsString().contains("No issues detected during validation"));
+    }
+
+    @Test
+    public void testResourceAsString() throws Exception {
+        Patient bobbyHebb      = new Patient().addName(new HumanName().addGiven("Bobby").setFamily("Hebb"));
+        // using org.hl7.fhir.instance.model.api.IBaseResource message body for single parameter "resource"
+        MethodOutcome result = requestBody("direct://RESOURCE_AS_STRING", this.fhirContext.newXmlParser().encodeResourceToString(bobbyHebb));
+
+        assertNotNull("resource result", result);
+        LOG.debug("resource: " + result);
+        assertNotNull(result.getOperationOutcome());
+        assertTrue(((OperationOutcome) result.getOperationOutcome()).getText().getDivAsString().contains("No issues detected during validation"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for resource
+                from("direct://RESOURCE")
+                    .to("fhir://" + PATH_PREFIX + "/resource?inBody=resource");
+
+                // test route for resource
+                from("direct://RESOURCE_AS_STRING")
+                    .to("fhir://" + PATH_PREFIX + "/resource?inBody=resourceAsString");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatSpringTest.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatSpringTest.java
similarity index 100%
rename from components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatSpringTest.java
rename to components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatSpringTest.java
diff --git a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatTest.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatTest.java
similarity index 100%
rename from components/camel-fhir/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatTest.java
rename to components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirXmlDataFormatTest.java
diff --git a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIntegrationTest.java
similarity index 78%
rename from components/camel-fhir/src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIT.java
rename to components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIntegrationTest.java
index 3641021..455394d 100644
--- a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIT.java
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/Hl7v2PatientToFhirPatientIntegrationTest.java
@@ -18,22 +18,17 @@ package org.apache.camel.component.fhir;
 
 import java.io.ByteArrayInputStream;
 import java.nio.charset.Charset;
-import ca.uhn.fhir.context.FhirContext;
 import ca.uhn.fhir.rest.api.MethodOutcome;
-import ca.uhn.fhir.rest.client.api.IGenericClient;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.hl7.HL7DataFormat;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.hl7.fhir.dstu3.model.Patient;
 import org.junit.Test;
 
 /**
- * This test demonstrates how to convert a HL7V2 patient to a FHIR dtsu3 Patient.
+ * This test demonstrates how to convert a HL7V2 patient to a FHIR dtsu3 Patient and then insert it into a FHIR server.
  */
-public class Hl7v2PatientToFhirPatientIT extends CamelTestSupport {
+public class Hl7v2PatientToFhirPatientIntegrationTest extends AbstractFhirTestSupport {
 
     /*
     Segment Purpose                 FHIR Resource
@@ -49,7 +44,7 @@ public class Hl7v2PatientToFhirPatientIT extends CamelTestSupport {
     */
     private static final String HL7_MESSAGE = "MSH|^~\\&|Amalga HIS|BUM|New Tester|MS|20111121103141||ORU^R01|2847970-2"
             + "01111211031|P|2.4|||AL|NE|764|ASCII|||\r"
-            + "PID||100005056|100005056||Dasher^Mary^\"\"^^\"\"|\"\"|19810813000000|F||CA|Street 1^\"\"^\"\"^\"\"^34000^SGP^^"
+            + "PID||100005056|100005056||Freeman^Vincent^\"\"^^\"\"|\"\"|19810813000000|F||CA|Street 1^\"\"^\"\"^\"\"^34000^SGP^^"
             + "\"\"~\"\"^\"\"^\"\"^\"\"^Danling Street 5th^THA^^\"\"||326-2275^PRN^PH^^66^675~476-5059^ORN^CP^^66^359~(123)"
             + "456-7890^ORN^FX^^66^222~^NET^X.400^a@a.a~^NET^X.400^dummy@hotmail.com|(123)456-7890^WPN^PH^^66|UNK|S|BUD||BP000111899|"
             + "D99999^\"\"||CA|Bangkok|||THA||THA|\"\"|N\r"
@@ -59,10 +54,6 @@ public class Hl7v2PatientToFhirPatientIT extends CamelTestSupport {
             + "OBR|1|\"\"|BMC1102771601|\"\"^Brain (CT)||20111028124215||||||||||||||||||CTSCAN|F||^^^^^ROUTINE|||\"\"||||||\"\"|||||||||||^\"\"\r"
             + "OBX|1|FT|\"\"^Brain (CT)||++++ text of report goes here +++|||REQAT|||FINAL|||20111121103040||75929^Gosselin^Angelina";
 
-    private FhirContext fhirContext = FhirContext.forDstu3();
-    private IGenericClient client   = fhirContext.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu3");
-    private HL7DataFormat hl7       = new HL7DataFormat();
-
     @Test
     public void testUnmarshalWithExplicitUTF16Charset() throws Exception {
         MockEndpoint mock = getMockEndpoint("mock:result");
@@ -75,19 +66,19 @@ public class Hl7v2PatientToFhirPatientIT extends CamelTestSupport {
 
         mock.assertIsSatisfied();
 
-        final MethodOutcome results = (MethodOutcome) mock.getExchanges().get(0).getIn().getBody();
-        Patient patient = (Patient) results.getResource();
-        assertNotNull(patient);
-        assertEquals("Dasher", patient.getNameFirstRep().getFamily());
+        MethodOutcome result = mock.getExchanges().get(0).getIn().getBody(MethodOutcome.class);
+        assertNotNull("resource result", result);
+        assertTrue(result.getCreated());
     }
 
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             public void configure() throws Exception {
-                Processor patientProcessor = new PatientProcessor(client, getContext());
+                Processor patientProcessor = new PatientProcessor();
                 from("direct:input")
-                    .unmarshal(hl7)
+                    .unmarshal().hl7()
                     .process(patientProcessor)
+                    .to("fhir://create/resource?inBody=resource")
                     .to("mock:result");
             }
         };
diff --git a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/PatientProcessor.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/PatientProcessor.java
similarity index 60%
rename from components/camel-fhir/src/test/java/org/apache/camel/component/fhir/PatientProcessor.java
rename to components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/PatientProcessor.java
index 1063ae9..ce2fbe2 100644
--- a/components/camel-fhir/src/test/java/org/apache/camel/component/fhir/PatientProcessor.java
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/PatientProcessor.java
@@ -16,48 +16,23 @@
  */
 package org.apache.camel.component.fhir;
 
-import java.util.List;
-import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
-import ca.uhn.fhir.rest.api.PreferReturnEnum;
-import ca.uhn.fhir.rest.client.api.IGenericClient;
-import ca.uhn.fhir.rest.gclient.IClientExecutable;
 import ca.uhn.hl7v2.model.v24.message.ORU_R01;
 import ca.uhn.hl7v2.model.v24.segment.PID;
-import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.hl7.fhir.dstu3.model.Patient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Simple Patient processor that converts the Patient segment of a {@link ORU_R01} message into a FHIR dtsu3 {@link Patient}.
  */
 public class PatientProcessor implements Processor {
-    private final Logger log = LoggerFactory.getLogger(PatientProcessor.class.getName());
-    private final IGenericClient client;
-    private final CamelContext camelContext;
-
-    public PatientProcessor(IGenericClient client, CamelContext camelContext) {
-        this.client = client;
-        this.camelContext = camelContext;
-    }
 
     @Override
     public void process(Exchange exchange) throws Exception {
         ORU_R01 msg = exchange.getIn().getBody(ORU_R01.class);
         //map to Patient
         Patient patient = getPatient(msg);
-        log.info("Mapped Dtsu3 patient {}", camelContext.getTypeConverter().convertTo(String.class, exchange, patient));
-        final IClientExecutable clientExecutable = client.create().resource(patient).prefer(PreferReturnEnum.REPRESENTATION);
-        Object result = clientExecutable.execute();
-        if (result instanceof BaseOperationOutcome) {
-            List<? extends BaseOperationOutcome.BaseIssue> issues = ((BaseOperationOutcome) result).getIssue();
-            if (!issues.isEmpty()) {
-                exchange.setException(new Exception("Error executing client operation: " + issues.get(0).getDetailsElement().getValue()));
-            }
-        }
-        exchange.getIn().setBody(result);
+        exchange.getIn().setBody(patient);
     }
 
     /**
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/UrlFetcherTest.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/UrlFetcherTest.java
new file mode 100644
index 0000000..9423f41
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/UrlFetcherTest.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Helper class to generate search URLs based on HAPI-FHIR's search API")
+public class UrlFetcherTest {
+
+    @Test
+    public void getUrlTest() {
+        // Create a client to talk to your favorite test server
+        FhirContext ctx = FhirContext.forDstu3();
+        IGenericClient client = ctx.newRestfulGenericClient("http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu3");
+        // URL will be logged in console, see log4j2.properties
+        client.registerInterceptor(new LoggingInterceptor(true));
+
+        client.search().forResource("Patient").where(Patient.IDENTIFIER.exactly().identifier("this/is/my/id")).execute();
+    }
+}
diff --git a/components/camel-fhir/src/test/resources/log4j2.properties b/components/camel-fhir/camel-fhir-component/src/test/resources/log4j2.properties
similarity index 100%
rename from components/camel-fhir/src/test/resources/log4j2.properties
rename to components/camel-fhir/camel-fhir-component/src/test/resources/log4j2.properties
diff --git a/components/camel-fhir/src/test/resources/org/apache/camel/dataformat/fhir/json/FhirJsonDataFormatSpringTest.xml b/components/camel-fhir/camel-fhir-component/src/test/resources/org/apache/camel/dataformat/fhir/json/FhirJsonDataFormatSpringTest.xml
similarity index 100%
rename from components/camel-fhir/src/test/resources/org/apache/camel/dataformat/fhir/json/FhirJsonDataFormatSpringTest.xml
rename to components/camel-fhir/camel-fhir-component/src/test/resources/org/apache/camel/dataformat/fhir/json/FhirJsonDataFormatSpringTest.xml
diff --git a/components/camel-fhir/src/test/resources/org/apache/camel/dataformat/fhir/xml/FhirXmlDataFormatSpringTest.xml b/components/camel-fhir/camel-fhir-component/src/test/resources/org/apache/camel/dataformat/fhir/xml/FhirXmlDataFormatSpringTest.xml
similarity index 100%
rename from components/camel-fhir/src/test/resources/org/apache/camel/dataformat/fhir/xml/FhirXmlDataFormatSpringTest.xml
rename to components/camel-fhir/camel-fhir-component/src/test/resources/org/apache/camel/dataformat/fhir/xml/FhirXmlDataFormatSpringTest.xml
diff --git a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories b/components/camel-fhir/camel-fhir-component/src/test/resources/test-options.properties
similarity index 80%
copy from platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories
copy to components/camel-fhir/camel-fhir-component/src/test/resources/test-options.properties
index 3df2200..db11449 100644
--- a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories
+++ b/components/camel-fhir/camel-fhir-component/src/test/resources/test-options.properties
@@ -15,7 +15,6 @@
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
 
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.apache.camel.component.fhir.springboot.FhirJsonDataFormatAutoConfiguration,\
-org.apache.camel.component.fhir.springboot.FhirXmlDataFormatAutoConfiguration
-
+#serverUrl=http://Fhirtest.uhn.ca/baseDstu3
+serverUrl=http://localhost:8080/hapi-fhir-jpaserver-example/baseDstu3
+fhirVersion=DSTU3
\ No newline at end of file
diff --git a/components/camel-fhir/pom.xml b/components/camel-fhir/pom.xml
index 5ebbb06..cfc4be4 100644
--- a/components/camel-fhir/pom.xml
+++ b/components/camel-fhir/pom.xml
@@ -18,7 +18,6 @@
 
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
@@ -26,130 +25,16 @@
     <artifactId>components</artifactId>
     <version>2.23.0-SNAPSHOT</version>
   </parent>
-  
-  <artifactId>camel-fhir</artifactId>
-  <packaging>jar</packaging>
-  <name>Camel :: Fhir</name>
-  <description>Camel FHIR HL7 support</description>
-
-  <properties>
-    <camel.osgi.export.pkg>
-      org.apache.camel.component.fhir.*
-    </camel.osgi.export.pkg>
-    <camel.osgi.dynamic>
-      org.hl7.fhir.*
-    </camel.osgi.dynamic>
-    <camel.osgi.export.service>
-      org.apache.camel.spi.DataFormatResolver;dataformat=fhirJson,
-      org.apache.camel.spi.DataFormatResolver;dataformat=fhirXml
-    </camel.osgi.export.service>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.camel</groupId>
-      <artifactId>camel-core</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>ca.uhn.hapi.fhir</groupId>
-      <artifactId>hapi-fhir-base</artifactId>
-      <version>${hapi-fhir-version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>ca.uhn.hapi.fhir</groupId>
-      <artifactId>hapi-fhir-client</artifactId>
-      <version>${hapi-fhir-version}</version>
-    </dependency>
-
-    <!-- These aren't needed for compilation but makes camel-fhir easier to use for third party projects/users e.g wildfly-camel -->
-    <dependency>
-      <groupId>ca.uhn.hapi.fhir</groupId>
-      <artifactId>hapi-fhir-structures-dstu3</artifactId>
-      <version>${hapi-fhir-version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>ca.uhn.hapi.fhir</groupId>
-      <artifactId>hapi-fhir-structures-dstu2</artifactId>
-      <version>${hapi-fhir-version}</version>
-    </dependency>
-
-    <!-- testing -->
-    <dependency>
-      <groupId>org.apache.camel</groupId>
-      <artifactId>camel-test</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.camel</groupId>
-      <artifactId>camel-test-spring</artifactId>
-      <scope>test</scope>
-    </dependency>
 
-    <dependency>
-      <groupId>org.apache.camel</groupId>
-      <artifactId>camel-hl7</artifactId>
-      <scope>test</scope>
-    </dependency>
+  <artifactId>camel-fhir-parent</artifactId>
+  <packaging>pom</packaging>
 
-    <dependency>
-      <groupId>ca.uhn.hapi</groupId>
-      <artifactId>hapi-structures-v24</artifactId>
-      <version>${hapi-version}</version>
-      <scope>test</scope>
-    </dependency>
+  <name>Camel :: FHIR :: Parent</name>
+  <description>Camel FHIR parent</description>
 
-    <!-- logging -->
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-api</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-core</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-slf4j-impl</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
+  <modules>
+    <module>camel-fhir-api</module>
+    <module>camel-fhir-component</module>
+  </modules>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <includes>
-            <!--Let's skip over IT tests as they rely on a public external test server being up and running-->
-            <include>**/*Test</include>
-          </includes>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <profiles>
-    <profile>
-      <id>it.fhir</id>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-surefire-plugin</artifactId>
-            <configuration>
-              <includes>
-                <include>**/*</include>
-              </includes>
-            </configuration>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
 </project>
diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md
index 59fb768..e3c4bbe 100644
--- a/docs/user-manual/en/SUMMARY.md
+++ b/docs/user-manual/en/SUMMARY.md
@@ -197,6 +197,7 @@
 	* [etcd](etcd-component.adoc)
 	* [Exec](exec-component.adoc)
 	* [Facebook](facebook-component.adoc)
+	* [FHIR](fhir-component.adoc)
 	* [Flatpack](flatpack-component.adoc)
 	* [FOP](fop-component.adoc)
 	* [Freemarker](freemarker-component.adoc)
diff --git a/examples/pom.xml b/examples/pom.xml
index afa7066..1ab7918 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -45,6 +45,7 @@
     <module>camel-example-cdi</module>
     <module>camel-example-cdi-aws-s3</module>
     <module>camel-example-cdi-cassandraql</module>
+    <module>camel-example-fhir</module>
     <module>camel-example-cdi-kubernetes</module>
     <module>camel-example-cdi-metrics</module>
     <module>camel-example-cdi-osgi</module>
diff --git a/parent/pom.xml b/parent/pom.xml
index 4b331e2..6e74a86 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1185,6 +1185,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
+        <artifactId>camel-fhir-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
         <artifactId>camel-flatpack</artifactId>
         <version>${project.version}</version>
       </dependency>
diff --git a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentAutoConfiguration.java b/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentAutoConfiguration.java
new file mode 100644
index 0000000..ea435e6
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentAutoConfiguration.java
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.springboot;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.fhir.FhirComponent;
+import org.apache.camel.spi.ComponentCustomizer;
+import org.apache.camel.spi.HasId;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.ComponentConfigurationProperties;
+import org.apache.camel.spring.boot.util.CamelPropertiesHelper;
+import org.apache.camel.spring.boot.util.ConditionalOnCamelContextAndAutoConfigurationBeans;
+import org.apache.camel.spring.boot.util.GroupCondition;
+import org.apache.camel.spring.boot.util.HierarchicalPropertiesEvaluator;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+
+/**
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.SpringBootAutoConfigurationMojo")
+@Configuration
+@Conditional({ConditionalOnCamelContextAndAutoConfigurationBeans.class,
+        FhirComponentAutoConfiguration.GroupConditions.class})
+@AutoConfigureAfter(CamelAutoConfiguration.class)
+@EnableConfigurationProperties({ComponentConfigurationProperties.class,
+        FhirComponentConfiguration.class})
+public class FhirComponentAutoConfiguration {
+
+    private static final Logger LOGGER = LoggerFactory
+            .getLogger(FhirComponentAutoConfiguration.class);
+    @Autowired
+    private ApplicationContext applicationContext;
+    @Autowired
+    private CamelContext camelContext;
+    @Autowired
+    private FhirComponentConfiguration configuration;
+    @Autowired(required = false)
+    private List<ComponentCustomizer<FhirComponent>> customizers;
+
+    static class GroupConditions extends GroupCondition {
+        public GroupConditions() {
+            super("camel.component", "camel.component.fhir");
+        }
+    }
+
+    @Lazy
+    @Bean(name = "fhir-component")
+    @ConditionalOnMissingBean(FhirComponent.class)
+    public FhirComponent configureFhirComponent() throws Exception {
+        FhirComponent component = new FhirComponent();
+        component.setCamelContext(camelContext);
+        Map<String, Object> parameters = new HashMap<>();
+        IntrospectionSupport.getProperties(configuration, parameters, null,
+                false);
+        for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+            Object value = entry.getValue();
+            Class<?> paramClass = value.getClass();
+            if (paramClass.getName().endsWith("NestedConfiguration")) {
+                Class nestedClass = null;
+                try {
+                    nestedClass = (Class) paramClass.getDeclaredField(
+                            "CAMEL_NESTED_CLASS").get(null);
+                    HashMap<String, Object> nestedParameters = new HashMap<>();
+                    IntrospectionSupport.getProperties(value, nestedParameters,
+                            null, false);
+                    Object nestedProperty = nestedClass.newInstance();
+                    CamelPropertiesHelper.setCamelProperties(camelContext,
+                            nestedProperty, nestedParameters, false);
+                    entry.setValue(nestedProperty);
+                } catch (NoSuchFieldException e) {
+                }
+            }
+        }
+        CamelPropertiesHelper.setCamelProperties(camelContext, component,
+                parameters, false);
+        if (ObjectHelper.isNotEmpty(customizers)) {
+            for (ComponentCustomizer<FhirComponent> customizer : customizers) {
+                boolean useCustomizer = (customizer instanceof HasId)
+                        ? HierarchicalPropertiesEvaluator.evaluate(
+                                applicationContext.getEnvironment(),
+                                "camel.component.customizer",
+                                "camel.component.fhir.customizer",
+                                ((HasId) customizer).getId())
+                        : HierarchicalPropertiesEvaluator.evaluate(
+                                applicationContext.getEnvironment(),
+                                "camel.component.customizer",
+                                "camel.component.fhir.customizer");
+                if (useCustomizer) {
+                    LOGGER.debug("Configure component {}, with customizer {}",
+                            component, customizer);
+                    customizer.customize(component);
+                }
+            }
+        }
+        return component;
+    }
+}
\ No newline at end of file
diff --git a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentConfiguration.java
new file mode 100644
index 0000000..f53079a
--- /dev/null
+++ b/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/java/org/apache/camel/component/fhir/springboot/FhirComponentConfiguration.java
@@ -0,0 +1,267 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fhir.springboot;
+
+import javax.annotation.Generated;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
+import org.apache.camel.component.fhir.internal.FhirApiName;
+import org.apache.camel.spring.boot.ComponentConfigurationPropertiesCommon;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+
+/**
+ * Represents a FHIR endpoint.
+ * 
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.SpringBootAutoConfigurationMojo")
+@ConfigurationProperties(prefix = "camel.component.fhir")
+public class FhirComponentConfiguration
+        extends
+            ComponentConfigurationPropertiesCommon {
+
+    /**
+     * To use the shared configuration
+     */
+    private FhirConfigurationNestedConfiguration configuration;
+    /**
+     * Whether the component should resolve property placeholders on itself when
+     * starting. Only properties which are of String type can use property
+     * placeholders.
+     */
+    private Boolean resolvePropertyPlaceholders = true;
+
+    public FhirConfigurationNestedConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(
+            FhirConfigurationNestedConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    public Boolean getResolvePropertyPlaceholders() {
+        return resolvePropertyPlaceholders;
+    }
+
+    public void setResolvePropertyPlaceholders(
+            Boolean resolvePropertyPlaceholders) {
+        this.resolvePropertyPlaceholders = resolvePropertyPlaceholders;
+    }
+
+    public static class FhirConfigurationNestedConfiguration {
+        public static final Class CAMEL_NESTED_CLASS = org.apache.camel.component.fhir.FhirConfiguration.class;
+        private String serverUrl;
+        private Boolean prettyPrint = false;
+        /**
+         * What kind of operation to perform
+         */
+        private FhirApiName apiName;
+        /**
+         * What sub operation to use for the selected operation
+         */
+        private String methodName;
+        @NestedConfigurationProperty
+        private FhirContext fhirContext;
+        private Boolean forceConformanceCheck = false;
+        private String username;
+        private String password;
+        private String accessToken;
+        private Boolean log = false;
+        private Boolean compress = false;
+        private String sessionCookie;
+        private Boolean deferModelScanning = false;
+        private Integer connectionTimeout = 10000;
+        private Integer socketTimeout = 10000;
+        private String proxyHost;
+        private String proxyPassword;
+        private Integer proxyPort;
+        private String proxyUser;
+        private IGenericClient client;
+        private IRestfulClientFactory clientFactory;
+
+        public String getServerUrl() {
+            return serverUrl;
+        }
+
+        public void setServerUrl(String serverUrl) {
+            this.serverUrl = serverUrl;
+        }
+
+        public Boolean getPrettyPrint() {
+            return prettyPrint;
+        }
+
+        public void setPrettyPrint(Boolean prettyPrint) {
+            this.prettyPrint = prettyPrint;
+        }
+
+        public FhirApiName getApiName() {
+            return apiName;
+        }
+
+        public void setApiName(FhirApiName apiName) {
+            this.apiName = apiName;
+        }
+
+        public String getMethodName() {
+            return methodName;
+        }
+
+        public void setMethodName(String methodName) {
+            this.methodName = methodName;
+        }
+
+        public FhirContext getFhirContext() {
+            return fhirContext;
+        }
+
+        public void setFhirContext(FhirContext fhirContext) {
+            this.fhirContext = fhirContext;
+        }
+
+        public Boolean getForceConformanceCheck() {
+            return forceConformanceCheck;
+        }
+
+        public void setForceConformanceCheck(Boolean forceConformanceCheck) {
+            this.forceConformanceCheck = forceConformanceCheck;
+        }
+
+        public String getUsername() {
+            return username;
+        }
+
+        public void setUsername(String username) {
+            this.username = username;
+        }
+
+        public String getPassword() {
+            return password;
+        }
+
+        public void setPassword(String password) {
+            this.password = password;
+        }
+
+        public String getAccessToken() {
+            return accessToken;
+        }
+
+        public void setAccessToken(String accessToken) {
+            this.accessToken = accessToken;
+        }
+
+        public Boolean getLog() {
+            return log;
+        }
+
+        public void setLog(Boolean log) {
+            this.log = log;
+        }
+
+        public Boolean getCompress() {
+            return compress;
+        }
+
+        public void setCompress(Boolean compress) {
+            this.compress = compress;
+        }
+
+        public String getSessionCookie() {
+            return sessionCookie;
+        }
+
+        public void setSessionCookie(String sessionCookie) {
+            this.sessionCookie = sessionCookie;
+        }
+
+        public Boolean getDeferModelScanning() {
+            return deferModelScanning;
+        }
+
+        public void setDeferModelScanning(Boolean deferModelScanning) {
+            this.deferModelScanning = deferModelScanning;
+        }
+
+        public Integer getConnectionTimeout() {
+            return connectionTimeout;
+        }
+
+        public void setConnectionTimeout(Integer connectionTimeout) {
+            this.connectionTimeout = connectionTimeout;
+        }
+
+        public Integer getSocketTimeout() {
+            return socketTimeout;
+        }
+
+        public void setSocketTimeout(Integer socketTimeout) {
+            this.socketTimeout = socketTimeout;
+        }
+
+        public String getProxyHost() {
+            return proxyHost;
+        }
+
+        public void setProxyHost(String proxyHost) {
+            this.proxyHost = proxyHost;
+        }
+
+        public String getProxyPassword() {
+            return proxyPassword;
+        }
+
+        public void setProxyPassword(String proxyPassword) {
+            this.proxyPassword = proxyPassword;
+        }
+
+        public Integer getProxyPort() {
+            return proxyPort;
+        }
+
+        public void setProxyPort(Integer proxyPort) {
+            this.proxyPort = proxyPort;
+        }
+
+        public String getProxyUser() {
+            return proxyUser;
+        }
+
+        public void setProxyUser(String proxyUser) {
+            this.proxyUser = proxyUser;
+        }
+
+        public IGenericClient getClient() {
+            return client;
+        }
+
+        public void setClient(IGenericClient client) {
+            this.client = client;
+        }
+
+        public IRestfulClientFactory getClientFactory() {
+            return clientFactory;
+        }
+
+        public void setClientFactory(IRestfulClientFactory clientFactory) {
+            this.clientFactory = clientFactory;
+        }
+    }
+}
\ No newline at end of file
diff --git a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories b/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories
index 3df2200..d8da287 100644
--- a/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories
+++ b/platforms/spring-boot/components-starter/camel-fhir-starter/src/main/resources/META-INF/spring.factories
@@ -17,5 +17,6 @@
 
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 org.apache.camel.component.fhir.springboot.FhirJsonDataFormatAutoConfiguration,\
-org.apache.camel.component.fhir.springboot.FhirXmlDataFormatAutoConfiguration
-
+org.apache.camel.component.fhir.springboot.FhirXmlDataFormatAutoConfiguration,\
+org.apache.camel.component.fhir.springboot.fhirComponentAutoConfiguration,\
+org.apache.camel.component.fhir.springboot.FhirComponentAutoConfiguration
\ No newline at end of file