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 e8d45f1aaa9e49e71bf49368714b55d0362e94aa
Author: JiriOndrusek <jondr...@redhat.com>
AuthorDate: Wed Jan 15 16:45:36 2020 +0100

    CAMEL-13699 Add Json to Json transformation using JSLT
---
 apache-camel/pom.xml                               |   5 +
 apache-camel/src/main/descriptors/common-bin.xml   |   1 +
 bom/camel-bom/pom.xml                              |   5 +
 components/camel-jslt/pom.xml                      |  75 +++++++
 .../camel-jslt/src/main/docs/jslt-component.adoc   | 169 ++++++++++++++
 .../apache/camel/component/jslt/JsltComponent.java |  64 ++++++
 .../apache/camel/component/jslt/JsltConstants.java |  26 +++
 .../apache/camel/component/jslt/JsltEndpoint.java  | 147 ++++++++++++
 .../apache/camel/component/jslt/JsltBasicTest.java | 111 ++++++++++
 .../camel/component/jslt/JsltFunctionsTest.java    |  73 ++++++
 .../apache/camel/component/jslt/JsltQueryTest.java |  61 +++++
 .../src/test/resources/log4j2.properties           |  28 +++
 .../camel/component/jslt/demoPlayground/input.json |   8 +
 .../component/jslt/demoPlayground/output.json      |   1 +
 .../jslt/demoPlayground/outputPrettyPrint.json     |   8 +
 .../jslt/demoPlayground/transformation.json        |   8 +
 components/pom.xml                                 |   1 +
 .../endpoint/dsl/JsltEndpointBuilderFactory.java   | 246 +++++++++++++++++++++
 docs/components/modules/ROOT/nav.adoc              |   1 +
 docs/components/modules/ROOT/pages/index.adoc      |   5 +-
 .../modules/ROOT/pages/jslt-component.adoc         | 170 ++++++++++++++
 parent/pom.xml                                     |   6 +
 .../karaf/features/src/main/resources/features.xml |   8 +
 23 files changed, 1226 insertions(+), 1 deletion(-)

diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml
index 8789a03..3d48ab8 100644
--- a/apache-camel/pom.xml
+++ b/apache-camel/pom.xml
@@ -928,6 +928,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.camel</groupId>
+      <artifactId>camel-jslt</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
       <artifactId>camel-json-validator</artifactId>
       <version>${project.version}</version>
     </dependency>
diff --git a/apache-camel/src/main/descriptors/common-bin.xml 
b/apache-camel/src/main/descriptors/common-bin.xml
index 34b676be..d91b01b 100644
--- a/apache-camel/src/main/descriptors/common-bin.xml
+++ b/apache-camel/src/main/descriptors/common-bin.xml
@@ -206,6 +206,7 @@
         <include>org.apache.camel:camel-jooq</include>
         <include>org.apache.camel:camel-jpa</include>
         <include>org.apache.camel:camel-jsch</include>
+        <include>org.apache.camel:camel-jslt</include>
         <include>org.apache.camel:camel-json-validator</include>
         <include>org.apache.camel:camel-jsonapi</include>
         <include>org.apache.camel:camel-jsonpath</include>
diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index bd58384..a8a5525 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -964,6 +964,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
+        <artifactId>camel-jslt</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
         <artifactId>camel-json-validator</artifactId>
         <version>${project.version}</version>
       </dependency>
diff --git a/components/camel-jslt/pom.xml b/components/camel-jslt/pom.xml
new file mode 100644
index 0000000..dd6c871
--- /dev/null
+++ b/components/camel-jslt/pom.xml
@@ -0,0 +1,75 @@
+<?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>
+        <artifactId>components</artifactId>
+        <groupId>org.apache.camel</groupId>
+        <version>3.1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-jslt</artifactId>
+    <packaging>jar</packaging>
+    <name>Camel :: Jslt</name>
+    <description>Camel Jslt Support</description>
+
+    <properties>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.schibsted.spt.data</groupId>
+            <artifactId>jslt</artifactId>
+            <version>${jslt-version}</version>
+        </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>
+
+        <!-- testing -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/components/camel-jslt/src/main/docs/jslt-component.adoc 
b/components/camel-jslt/src/main/docs/jslt-component.adoc
new file mode 100644
index 0000000..827ce2a
--- /dev/null
+++ b/components/camel-jslt/src/main/docs/jslt-component.adoc
@@ -0,0 +1,169 @@
+[[jslt-component]]
+= JSLT Component
+
+*Since Camel 3.1*
+
+// HEADER START
+*Only producer is supported*
+// HEADER END
+
+The Jslt component allows you to process a JSON messages using an
+https://github.com/schibsted/jslt[JSLT] expression. This can be
+ideal when doing JSON to JSON transformation or querying data.
+
+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-jslt</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+------------------------------------------------------------
+
+ 
+
+== URI format
+
+[source,java]
+-----------------------
+jslt:specName[?options]
+-----------------------
+
+Where *specName* is the classpath-local URI of the specification to
+invoke; or the complete URL of the remote specification
+(eg: \file://folder/myfile.vm).
+
+You can append query options to the URI in the following
+format, `?option=value&option=value&...`
+
+== Options
+
+
+
+
+// component options: START
+The JSLT component supports 3 options, which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *functions* (advanced) | JSLT can be extended by plugging in functions 
written in Java. |  | Collection
+| *basicPropertyBinding* (advanced) | Whether the component should use basic 
property binding (Camel 2.x) or the newer property binding with additional 
capabilities | false | boolean
+| *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
+|===
+// component options: END
+
+
+
+
+
+
+// endpoint options: START
+The JSLT endpoint is configured using URI syntax:
+
+----
+jslt:resourceUri
+----
+
+with the following path and query parameters:
+
+=== Path Parameters (1 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *resourceUri* | *Required* Path to the resource. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath is default). ref will lookup the 
resource in the registry. bean will call a method on a bean to be used as the 
resource. For bean you can specify the method name after dot, eg 
bean:myBean.myMethod. |  | String
+|===
+
+
+=== Query Parameters (5 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *prettyPrint* (common) | If true, JSON in output message is pretty printed. 
| false | boolean
+| *contentCache* (producer) | Sets whether to use resource content cache or 
not | false | boolean
+| *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
+| *basicPropertyBinding* (advanced) | Whether the endpoint should use basic 
property binding (Camel 2.x) or the newer property binding with additional 
capabilities | false | boolean
+| *synchronous* (advanced) | Sets whether synchronous processing should be 
strictly used, or Camel is allowed to use asynchronous processing (if 
supported). | false | boolean
+|===
+// endpoint options: END
+// spring-boot-auto-configure options: START
+== Spring Boot Auto-Configuration
+
+When using Spring Boot make sure to use the following Maven dependency to have 
support for auto configuration:
+
+[source,xml]
+----
+<dependency>
+  <groupId>org.apache.camel.springboot</groupId>
+  <artifactId>camel-jslt-starter</artifactId>
+  <version>x.x.x</version>
+  <!-- use the same version as your Camel core version -->
+</dependency>
+----
+
+
+The component supports 5 options, which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *camel.component.jslt.basic-property-binding* | Whether the component should 
use basic property binding (Camel 2.x) or the newer property binding with 
additional capabilities | false | Boolean
+| *camel.component.jslt.bridge-error-handler* | 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
+| *camel.component.jslt.enabled* | Whether to enable auto configuration of the 
jolt component. This is enabled by default. |  | Boolean
+| *camel.component.jslt.lazy-start-producer* | Whether the producer should be 
started lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a producer may otherwise 
fail during starting and cause the route to fail being started. By deferring 
this startup to be lazy then the startup failure can be handled during routing 
messages via Camel's routing error handlers. Beware that when the first message 
is processed then  [...]
+| *camel.component.jslt.transform* | Explicitly sets the Transform to use. If 
not set a Transform specified by the transformDsl will be created. The option 
is a com.bazaarvoice.jolt.Transform type. |  | String
+|===
+// spring-boot-auto-configure options: END
+
+
+
+
+== Samples
+
+For example you could use something like
+
+[source,java]
+--------------------------------------
+from("activemq:My.Queue").
+  to("jslt:com/acme/MyResponse.json");
+--------------------------------------
+
+And a file based resource:
+
+[source,java]
+---------------------------------------------------------------
+from("activemq:My.Queue").
+  to("jslt:file://myfolder/MyResponse.json?contentCache=true").
+  to("activemq:Another.Queue");
+---------------------------------------------------------------
+
+You can also specify which JSLT expression the component should use
+dynamically via a header, so for example:
+
+[source,java]
+---------------------------------------------------------------------
+from("direct:in").
+  setHeader("CamelJsltResourceUri").constant("path/to/my/spec.json").
+  to("jslt:dummy");
+---------------------------------------------------------------------
+
+Or send whole jslt expression via header: (suitable for querying)
+ 
+[source,java]
+---------------------------------------------------------------------
+from("direct:in").
+  setHeader("CamelJsltResourceUri").constant(".published").
+  to("jslt:dummy");
+---------------------------------------------------------------------
diff --git 
a/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltComponent.java
 
b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltComponent.java
new file mode 100644
index 0000000..a890301
--- /dev/null
+++ 
b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltComponent.java
@@ -0,0 +1,64 @@
+/*
+ * 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.jslt;
+
+import java.util.Collection;
+import java.util.Map;
+
+import com.schibsted.spt.data.jslt.Function;
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+import org.apache.camel.support.ResourceHelper;
+
+@Component("jslt")
+public class JsltComponent extends DefaultComponent {
+
+    @Metadata(label = "advanced")
+    private Collection<Function> functions;
+
+    public JsltComponent() {
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
+        boolean cache = getAndRemoveParameter(parameters, "contentCache", 
Boolean.class, Boolean.TRUE);
+
+        JsltEndpoint answer = new JsltEndpoint(uri, this, remaining);
+        answer.setContentCache(cache);
+
+        // if its a http resource then append any remaining parameters and 
update the resource uri
+        if (ResourceHelper.isHttpUri(remaining)) {
+            remaining = ResourceHelper.appendParameters(remaining, parameters);
+            answer.setResourceUri(remaining);
+        }
+
+        return answer;
+    }
+
+    /**
+     * JSLT can be extended by plugging in functions written in Java.
+     */
+    public Collection<Function> getFunctions() {
+        return functions;
+    }
+
+    public void setFunctions(Collection<Function> functions) {
+        this.functions = functions;
+    }
+}
diff --git 
a/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltConstants.java
 
b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltConstants.java
new file mode 100644
index 0000000..2cb1c78
--- /dev/null
+++ 
b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltConstants.java
@@ -0,0 +1,26 @@
+/*
+ * 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.jslt;
+
+public final class JsltConstants {
+
+    public static final String HEADER_JSLT_STRING = "CamelJsltString";
+    public static final String HEADER_JSLT_RESOURCE_URI = 
"CamelJsltResourceUri";
+
+    private JsltConstants() {
+    }
+}
diff --git 
a/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java
 
b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java
new file mode 100644
index 0000000..9143f8e
--- /dev/null
+++ 
b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java
@@ -0,0 +1,147 @@
+/*
+ * 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.jslt;
+
+import java.io.InputStream;
+import java.util.Collection;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.schibsted.spt.data.jslt.Expression;
+import com.schibsted.spt.data.jslt.Function;
+import com.schibsted.spt.data.jslt.Parser;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Message;
+import org.apache.camel.ValidationException;
+import org.apache.camel.component.ResourceEndpoint;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * The jslt component allows you to process a JSON messages using an JSLT 
transformations.
+ *
+ *  @author JiriOndrusek
+ */
+@UriEndpoint(firstVersion = "3.1.0", scheme = "jslt", title = "JSLT", syntax = 
"jslt:resourceUri", producerOnly = true, label = "transformation")
+public class JsltEndpoint extends ResourceEndpoint {
+
+    private Expression transform;
+
+    @UriParam(defaultValue = "false", label = "common")
+    private boolean prettyPrint;
+
+
+    public JsltEndpoint() {
+    }
+
+    public JsltEndpoint(String uri, JsltComponent component, String 
resourceUri) {
+        super(uri, component, resourceUri);
+    }
+
+    @Override
+    public ExchangePattern getExchangePattern() {
+        return ExchangePattern.InOut;
+    }
+
+    @Override
+    protected String createEndpointUri() {
+        return "jslt:" + getResourceUri();
+    }
+
+    private synchronized Expression getTransform(Message msg) throws Exception 
{
+        if (transform == null) {
+            if (log.isDebugEnabled()) {
+                String path = getResourceUri();
+                log.debug("Jslt content read from resource {} with 
resourceUri: {} for endpoint {}", getResourceUri(), path, getEndpointUri());
+            }
+
+            String jsltStringFromHeader = 
msg.getHeader(JsltConstants.HEADER_JSLT_STRING, String.class);
+            Collection<Function> functions = 
((JsltComponent)getComponent()).getFunctions();
+
+            if (jsltStringFromHeader != null) {
+                if (functions == null) {
+                    this.transform = 
Parser.compileString(jsltStringFromHeader);
+                } else {
+                    this.transform = 
Parser.compileString(jsltStringFromHeader, functions);
+                }
+            } else {
+                if (functions == null) {
+                    this.transform = Parser.compileResource(getResourceUri());
+                } else {
+                    this.transform = Parser.compileResource(getResourceUri(), 
functions);
+                }
+            }
+        }
+        return transform;
+    }
+
+
+    public JsltEndpoint findOrCreateEndpoint(String uri, String 
newResourceUri) {
+        String newUri = uri.replace(getResourceUri(), newResourceUri);
+        log.debug("Getting endpoint with URI: {}", newUri);
+        return getCamelContext().getEndpoint(newUri, JsltEndpoint.class);
+    }
+
+    @Override
+    protected void onExchange(Exchange exchange) throws Exception {
+        String path = getResourceUri();
+        ObjectHelper.notNull(path, "resourceUri");
+
+        String newResourceUri = 
exchange.getIn().getHeader(JsltConstants.HEADER_JSLT_RESOURCE_URI, 
String.class);
+        if (newResourceUri != null) {
+            
exchange.getIn().removeHeader(JsltConstants.HEADER_JSLT_RESOURCE_URI);
+
+            log.debug("{} set to {} creating new endpoint to handle exchange", 
JsltConstants.HEADER_JSLT_RESOURCE_URI, newResourceUri);
+            JsltEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), 
newResourceUri);
+            newEndpoint.onExchange(exchange);
+            return;
+        }
+
+        JsonNode input;
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        if (exchange.getIn().getBody() instanceof String) {
+            input = 
objectMapper.readTree(exchange.getIn().getBody(String.class));
+        } else if (exchange.getIn().getBody() instanceof InputStream) {
+            input = 
objectMapper.readTree(exchange.getIn().getBody(InputStream.class));
+        } else {
+            log.debug("Body content is not String neither InputStream.");
+            throw new ValidationException(exchange, "Allowed body types are 
String or InputStream.");
+        }
+
+        JsonNode output = getTransform(exchange.getMessage()).apply(input);
+
+        Message out = exchange.getMessage();
+
+        out.setBody(isPrettyPrint() ? output.toPrettyString() : 
output.toString());
+
+        out.setHeaders(exchange.getIn().getHeaders());
+    }
+
+    /**
+     * If true, JSON in output message is pretty printed.
+     */
+    public boolean isPrettyPrint() {
+        return prettyPrint;
+    }
+
+    public void setPrettyPrint(boolean prettyPrint) {
+        this.prettyPrint = prettyPrint;
+    }
+}
diff --git 
a/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltBasicTest.java
 
b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltBasicTest.java
new file mode 100644
index 0000000..45c2fb7
--- /dev/null
+++ 
b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltBasicTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.jslt;
+
+import java.util.Collections;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.junit.Test;
+
+/**
+ * Unit test based on the JSLT demo playground default values.
+ */
+public class JsltBasicTest extends CamelTestSupport {
+
+    @Test
+    public void testJsltAsInputStream() throws Exception {
+        getMockEndpoint("mock:result").expectedMinimumMessageCount(1);
+        getMockEndpoint("mock:result").expectedBodiesReceived(
+            IOHelper.loadText(
+                ResourceHelper.resolveMandatoryResourceAsInputStream(
+                    context, 
"org/apache/camel/component/jslt/demoPlayground/output.json")
+            ).trim() // Remove the last newline added by IOHelper.loadText()
+        );
+
+        sendBody("direct://start",
+                ResourceHelper.resolveMandatoryResourceAsInputStream(
+                        context, 
"org/apache/camel/component/jslt/demoPlayground/input.json"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testInvalidBody() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+
+        //type integer is not allowed
+        sendBody("direct://start", 4);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testJsltAsText() throws Exception {
+        getMockEndpoint("mock:result").expectedMinimumMessageCount(1);
+        getMockEndpoint("mock:result").expectedBodiesReceived(
+            IOHelper.loadText(
+                ResourceHelper.resolveMandatoryResourceAsInputStream(
+                    context, 
"org/apache/camel/component/jslt/demoPlayground/output.json")
+            ).trim() // Remove the last newline added by IOHelper.loadText()
+        );
+
+        sendBody("direct://start",
+                
IOHelper.loadText(ResourceHelper.resolveMandatoryResourceAsInputStream(
+                        context, 
"org/apache/camel/component/jslt/demoPlayground/input.json")));
+
+        assertMockEndpointsSatisfied();
+    }
+
+
+    @Test
+    public void testJsltAsInputStreamPrettyPrint() throws Exception {
+        getMockEndpoint("mock:result").expectedMinimumMessageCount(1);
+        getMockEndpoint("mock:result").expectedBodiesReceived(
+                IOHelper.loadText(
+                        ResourceHelper.resolveMandatoryResourceAsInputStream(
+                                context, 
"org/apache/camel/component/jslt/demoPlayground/outputPrettyPrint.json")
+                ).trim() // Remove the last newline added by 
IOHelper.loadText()
+        );
+
+        sendBody("direct://startPrettyPrint",
+                ResourceHelper.resolveMandatoryResourceAsInputStream(
+                        context, 
"org/apache/camel/component/jslt/demoPlayground/input.json"),
+                
Collections.singletonMap(JsltConstants.HEADER_JSLT_RESOURCE_URI, 
"org/apache/camel/component/jslt/demoPlayground/transformation.json"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct://start")
+                    
.to("jslt:org/apache/camel/component/jslt/demoPlayground/transformation.json")
+                    .to("mock:result");
+
+                from("direct://startPrettyPrint")
+                    .to("jslt:dummy?prettyPrint=true")
+                    .to("mock:result");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltFunctionsTest.java
 
b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltFunctionsTest.java
new file mode 100644
index 0000000..b8ee54e
--- /dev/null
+++ 
b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltFunctionsTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.jslt;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import com.schibsted.spt.data.jslt.Function;
+import com.schibsted.spt.data.jslt.FunctionUtils;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+/**
+ * Unit test using user defined functions
+ */
+public class JsltFunctionsTest extends CamelTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+
+        context.getPropertiesComponent().setLocation("ref:prop");
+
+        context.getComponent("jslt", 
JsltComponent.class).setFunctions(createFunctions());
+
+        return context;
+    }
+
+    private Collection<Function> createFunctions() throws 
ClassNotFoundException {
+        return Collections.singleton(
+                FunctionUtils.wrapStaticMethod("power", "java.lang.Math", 
"pow"));
+    }
+
+    @Test
+    public void testSimpleFunction() throws Exception {
+        getMockEndpoint("mock:result").expectedMinimumMessageCount(1);
+        getMockEndpoint("mock:result").expectedBodiesReceived("1024.0");
+
+        sendBody("direct://start", "{}", 
Collections.singletonMap(JsltConstants.HEADER_JSLT_STRING, "power(2, 10)"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct://start")
+                    .to("jslt:dummy")
+                    .to("mock:result");
+            }
+        };
+    }
+
+
+}
diff --git 
a/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltQueryTest.java
 
b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltQueryTest.java
new file mode 100644
index 0000000..4f16d35
--- /dev/null
+++ 
b/components/camel-jslt/src/test/java/org/apache/camel/component/jslt/JsltQueryTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.jslt;
+
+import java.util.Collections;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.junit.Test;
+
+
+
+/**
+ * Test using query expressions
+ */
+public class JsltQueryTest extends CamelTestSupport {
+
+
+    @Test
+    public void testSimpleQuery() throws Exception {
+        getMockEndpoint("mock:result").expectedMinimumMessageCount(1);
+        
getMockEndpoint("mock:result").expectedBodiesReceived("\"2017-05-04T09:13:29+02:00\"");
+
+        sendBody("direct://start",
+                
IOHelper.loadText(ResourceHelper.resolveMandatoryResourceAsInputStream(
+                        context, 
"org/apache/camel/component/jslt/demoPlayground/input.json")),
+                Collections.singletonMap(JsltConstants.HEADER_JSLT_STRING, 
".published"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct://start")
+                    .to("jslt:dummy")
+                    .to("mock:result");
+            }
+        };
+    }
+
+
+}
diff --git a/components/camel-jslt/src/test/resources/log4j2.properties 
b/components/camel-jslt/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..8503203
--- /dev/null
+++ b/components/camel-jslt/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-jslt-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.stdout.type = Console
+appender.stdout.name = stdout
+appender.stdout.layout.type = PatternLayout
+appender.stdout.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git 
a/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/input.json
 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/input.json
new file mode 100644
index 0000000..361d47a
--- /dev/null
+++ 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/input.json
@@ -0,0 +1,8 @@
+{
+  "schema" : "http://schemas.schibsted.io/thing/pulse-simple.json#1.json";,
+  "id" : "w23q7ca1-8729-24923-922b-1c0517ddffjf1",
+  "published" : "2017-05-04T09:13:29+02:00",
+  "type" : "View",
+  "environmentId" : "urn:schibsted.com:environment:uuid",
+  "url" : "http://www.aftenposten.no/";
+}
diff --git 
a/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/output.json
 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/output.json
new file mode 100644
index 0000000..3a4e267
--- /dev/null
+++ 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/output.json
@@ -0,0 +1 @@
+{"id":"xxxxxxxx-xxxx-xxxxx-xxxx-xxxxxxxxxxxxx","type":"Anonymized-View","schema":"http://schemas.schibsted.io/thing/pulse-simple.json#1.json","published":"2017-05-04T09:13:29+02:00","environmentId":"urn:schibsted.com:environment:uuid","url":"http://www.aftenposten.no/"}
\ No newline at end of file
diff --git 
a/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/outputPrettyPrint.json
 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/outputPrettyPrint.json
new file mode 100644
index 0000000..6d6bfd1
--- /dev/null
+++ 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/outputPrettyPrint.json
@@ -0,0 +1,8 @@
+{
+  "id" : "xxxxxxxx-xxxx-xxxxx-xxxx-xxxxxxxxxxxxx",
+  "type" : "Anonymized-View",
+  "schema" : "http://schemas.schibsted.io/thing/pulse-simple.json#1.json";,
+  "published" : "2017-05-04T09:13:29+02:00",
+  "environmentId" : "urn:schibsted.com:environment:uuid",
+  "url" : "http://www.aftenposten.no/";
+}
\ No newline at end of file
diff --git 
a/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/transformation.json
 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/transformation.json
new file mode 100644
index 0000000..6f23215
--- /dev/null
+++ 
b/components/camel-jslt/src/test/resources/org/apache/camel/component/jslt/demoPlayground/transformation.json
@@ -0,0 +1,8 @@
+let idparts = split(.id, "-")
+let xxx = [for ($idparts) "x" * size(.)]
+
+{
+"id" : join($xxx, "-"),
+"type" : "Anonymized-View",
+* : .
+}
diff --git a/components/pom.xml b/components/pom.xml
index 2652d37..f22066d 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -229,6 +229,7 @@
         <module>camel-jooq</module>
         <module>camel-jpa</module>
         <module>camel-jsch</module>
+        <module>camel-jslt</module>
         <module>camel-json-validator</module>
         <module>camel-jsonapi</module>
         <module>camel-jsonpath</module>
diff --git 
a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JsltEndpointBuilderFactory.java
 
b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JsltEndpointBuilderFactory.java
new file mode 100644
index 0000000..c61d523
--- /dev/null
+++ 
b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JsltEndpointBuilderFactory.java
@@ -0,0 +1,246 @@
+/*
+ * 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.builder.endpoint.dsl;
+
+import javax.annotation.Generated;
+import org.apache.camel.builder.EndpointConsumerBuilder;
+import org.apache.camel.builder.EndpointProducerBuilder;
+import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
+
+/**
+ * The jslt component allows you to process a JSON messages using an JSLT
+ * transformations.
+ * 
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
+public interface JsltEndpointBuilderFactory {
+
+
+    /**
+     * Builder for endpoint for the JSLT component.
+     */
+    public interface JsltEndpointBuilder extends EndpointProducerBuilder {
+        default AdvancedJsltEndpointBuilder advanced() {
+            return (AdvancedJsltEndpointBuilder) this;
+        }
+        /**
+         * If true, JSON in output message is pretty printed.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: common
+         */
+        default JsltEndpointBuilder prettyPrint(boolean prettyPrint) {
+            doSetProperty("prettyPrint", prettyPrint);
+            return this;
+        }
+        /**
+         * If true, JSON in output message is pretty printed.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: common
+         */
+        default JsltEndpointBuilder prettyPrint(String prettyPrint) {
+            doSetProperty("prettyPrint", prettyPrint);
+            return this;
+        }
+        /**
+         * Sets whether to use resource content cache or not.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: producer
+         */
+        default JsltEndpointBuilder contentCache(boolean contentCache) {
+            doSetProperty("contentCache", contentCache);
+            return this;
+        }
+        /**
+         * Sets whether to use resource content cache or not.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: producer
+         */
+        default JsltEndpointBuilder contentCache(String contentCache) {
+            doSetProperty("contentCache", contentCache);
+            return this;
+        }
+        /**
+         * Whether the producer should be started lazy (on the first message).
+         * By starting lazy you can use this to allow CamelContext and routes 
to
+         * startup in situations where a producer may otherwise fail during
+         * starting and cause the route to fail being started. By deferring 
this
+         * startup to be lazy then the startup failure can be handled during
+         * routing messages via Camel's routing error handlers. Beware that 
when
+         * the first message is processed then creating and starting the
+         * producer may take a little time and prolong the total processing 
time
+         * of the processing.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: producer
+         */
+        default JsltEndpointBuilder lazyStartProducer(boolean 
lazyStartProducer) {
+            doSetProperty("lazyStartProducer", lazyStartProducer);
+            return this;
+        }
+        /**
+         * Whether the producer should be started lazy (on the first message).
+         * By starting lazy you can use this to allow CamelContext and routes 
to
+         * startup in situations where a producer may otherwise fail during
+         * starting and cause the route to fail being started. By deferring 
this
+         * startup to be lazy then the startup failure can be handled during
+         * routing messages via Camel's routing error handlers. Beware that 
when
+         * the first message is processed then creating and starting the
+         * producer may take a little time and prolong the total processing 
time
+         * of the processing.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: producer
+         */
+        default JsltEndpointBuilder lazyStartProducer(String 
lazyStartProducer) {
+            doSetProperty("lazyStartProducer", lazyStartProducer);
+            return this;
+        }
+    }
+
+    /**
+     * Advanced builder for endpoint for the JSLT component.
+     */
+    public interface AdvancedJsltEndpointBuilder
+            extends
+                EndpointProducerBuilder {
+        default JsltEndpointBuilder basic() {
+            return (JsltEndpointBuilder) this;
+        }
+        /**
+         * Whether the endpoint should use basic property binding (Camel 2.x) 
or
+         * the newer property binding with additional capabilities.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedJsltEndpointBuilder basicPropertyBinding(
+                boolean basicPropertyBinding) {
+            doSetProperty("basicPropertyBinding", basicPropertyBinding);
+            return this;
+        }
+        /**
+         * Whether the endpoint should use basic property binding (Camel 2.x) 
or
+         * the newer property binding with additional capabilities.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedJsltEndpointBuilder basicPropertyBinding(
+                String basicPropertyBinding) {
+            doSetProperty("basicPropertyBinding", basicPropertyBinding);
+            return this;
+        }
+        /**
+         * Sets whether synchronous processing should be strictly used, or 
Camel
+         * is allowed to use asynchronous processing (if supported).
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedJsltEndpointBuilder synchronous(boolean synchronous) {
+            doSetProperty("synchronous", synchronous);
+            return this;
+        }
+        /**
+         * Sets whether synchronous processing should be strictly used, or 
Camel
+         * is allowed to use asynchronous processing (if supported).
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default AdvancedJsltEndpointBuilder synchronous(String synchronous) {
+            doSetProperty("synchronous", synchronous);
+            return this;
+        }
+    }
+
+    public interface JsltBuilders {
+        /**
+         * JSLT (camel-jslt)
+         * The jslt component allows you to process a JSON messages using an
+         * JSLT transformations.
+         * 
+         * Category: transformation
+         * Since: 3.1
+         * Maven coordinates: org.apache.camel:camel-jslt
+         * 
+         * Syntax: <code>jslt:resourceUri</code>
+         * 
+         * Path parameter: resourceUri (required)
+         * Path to the resource. You can prefix with: classpath, file, http,
+         * ref, or bean. classpath, file and http loads the resource using 
these
+         * protocols (classpath is default). ref will lookup the resource in 
the
+         * registry. bean will call a method on a bean to be used as the
+         * resource. For bean you can specify the method name after dot, eg
+         * bean:myBean.myMethod.
+         */
+        default JsltEndpointBuilder jslt(String path) {
+            return JsltEndpointBuilderFactory.jslt(path);
+        }
+    }
+    /**
+     * JSLT (camel-jslt)
+     * The jslt component allows you to process a JSON messages using an JSLT
+     * transformations.
+     * 
+     * Category: transformation
+     * Since: 3.1
+     * Maven coordinates: org.apache.camel:camel-jslt
+     * 
+     * Syntax: <code>jslt:resourceUri</code>
+     * 
+     * Path parameter: resourceUri (required)
+     * Path to the resource. You can prefix with: classpath, file, http, ref, 
or
+     * bean. classpath, file and http loads the resource using these protocols
+     * (classpath is default). ref will lookup the resource in the registry.
+     * bean will call a method on a bean to be used as the resource. For bean
+     * you can specify the method name after dot, eg bean:myBean.myMethod.
+     */
+    static JsltEndpointBuilder jslt(String path) {
+        class JsltEndpointBuilderImpl extends AbstractEndpointBuilder 
implements JsltEndpointBuilder, AdvancedJsltEndpointBuilder {
+            public JsltEndpointBuilderImpl(String path) {
+                super("jslt", path);
+            }
+        }
+        return new JsltEndpointBuilderImpl(path);
+    }
+}
\ No newline at end of file
diff --git a/docs/components/modules/ROOT/nav.adoc 
b/docs/components/modules/ROOT/nav.adoc
index 7f7cb4b..a470e6f 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -203,6 +203,7 @@
 * xref:jooq-component.adoc[JOOQ Component]
 * xref:jpa-component.adoc[JPA Component]
 * xref:scp-component.adoc[SCP Component]
+* xref:jslt-component.adoc[JSLT Component]
 * xref:json-validator-component.adoc[JSON Schema Validator Component]
 * xref:jsonApi-dataformat.adoc[JSonApi DataFormat]
 * xref:jsonpath-language.adoc[JsonPath Language]
diff --git a/docs/components/modules/ROOT/pages/index.adoc 
b/docs/components/modules/ROOT/pages/index.adoc
index ff486df..f038038 100644
--- a/docs/components/modules/ROOT/pages/index.adoc
+++ b/docs/components/modules/ROOT/pages/index.adoc
@@ -6,7 +6,8 @@ The following Apache Camel artifacts are provided:
 == Components
 
 // components: START
-Number of Components: 309 in 247 JAR artifacts (1 deprecated)
+=======
+Number of Components: 310 in 248 JAR artifacts (1 deprecated)
 
 [width="100%",cols="4,1,5",options="header"]
 |===
@@ -342,6 +343,8 @@ Number of Components: 309 in 247 JAR artifacts (1 
deprecated)
 
 | xref:jpa-component.adoc[JPA] (camel-jpa) | 1.0 | The jpa component enables 
you to store and retrieve Java objects from databases using JPA.
 
+| xref:jslt-component.adoc[JSLT] (camel-jslt) | 3.1 | The jslt component 
allows you to process a JSON messages using an JSLT transformations.
+
 | xref:json-validator-component.adoc[JSON Schema Validator] 
(camel-json-validator) | 2.20 | Validates the payload of a message using 
NetworkNT JSON Schema library.
 
 | xref:jt400-component.adoc[JT400] (camel-jt400) | 1.5 | The jt400 component 
allows you to exchanges messages with an AS/400 system using data queues or 
program call.
diff --git a/docs/components/modules/ROOT/pages/jslt-component.adoc 
b/docs/components/modules/ROOT/pages/jslt-component.adoc
new file mode 100644
index 0000000..85607f9
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/jslt-component.adoc
@@ -0,0 +1,170 @@
+[[jslt-component]]
+= JSLT Component
+:page-source: components/camel-jslt/src/main/docs/jslt-component.adoc
+
+*Since Camel 3.1*
+
+// HEADER START
+*Only producer is supported*
+// HEADER END
+
+The Jslt component allows you to process a JSON messages using an
+https://github.com/schibsted/jslt[JSLT] expression. This can be
+ideal when doing JSON to JSON transformation or querying data.
+
+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-jslt</artifactId>
+    <version>x.x.x</version>
+    <!-- use the same version as your Camel core version -->
+</dependency>
+------------------------------------------------------------
+
+ 
+
+== URI format
+
+[source,java]
+-----------------------
+jslt:specName[?options]
+-----------------------
+
+Where *specName* is the classpath-local URI of the specification to
+invoke; or the complete URL of the remote specification
+(eg: \file://folder/myfile.vm).
+
+You can append query options to the URI in the following
+format, `?option=value&option=value&...`
+
+== Options
+
+
+
+
+// component options: START
+The JSLT component supports 3 options, which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *functions* (advanced) | JSLT can be extended by plugging in functions 
written in Java. |  | Collection
+| *basicPropertyBinding* (advanced) | Whether the component should use basic 
property binding (Camel 2.x) or the newer property binding with additional 
capabilities | false | boolean
+| *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
+|===
+// component options: END
+
+
+
+
+
+
+// endpoint options: START
+The JSLT endpoint is configured using URI syntax:
+
+----
+jslt:resourceUri
+----
+
+with the following path and query parameters:
+
+=== Path Parameters (1 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *resourceUri* | *Required* Path to the resource. You can prefix with: 
classpath, file, http, ref, or bean. classpath, file and http loads the 
resource using these protocols (classpath is default). ref will lookup the 
resource in the registry. bean will call a method on a bean to be used as the 
resource. For bean you can specify the method name after dot, eg 
bean:myBean.myMethod. |  | String
+|===
+
+
+=== Query Parameters (5 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *prettyPrint* (common) | If true, JSON in output message is pretty printed. 
| false | boolean
+| *contentCache* (producer) | Sets whether to use resource content cache or 
not | false | boolean
+| *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
+| *basicPropertyBinding* (advanced) | Whether the endpoint should use basic 
property binding (Camel 2.x) or the newer property binding with additional 
capabilities | false | boolean
+| *synchronous* (advanced) | Sets whether synchronous processing should be 
strictly used, or Camel is allowed to use asynchronous processing (if 
supported). | false | boolean
+|===
+// endpoint options: END
+// spring-boot-auto-configure options: START
+== Spring Boot Auto-Configuration
+
+When using Spring Boot make sure to use the following Maven dependency to have 
support for auto configuration:
+
+[source,xml]
+----
+<dependency>
+  <groupId>org.apache.camel.springboot</groupId>
+  <artifactId>camel-jslt-starter</artifactId>
+  <version>x.x.x</version>
+  <!-- use the same version as your Camel core version -->
+</dependency>
+----
+
+
+The component supports 5 options, which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *camel.component.jslt.basic-property-binding* | Whether the component should 
use basic property binding (Camel 2.x) or the newer property binding with 
additional capabilities | false | Boolean
+| *camel.component.jslt.bridge-error-handler* | 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
+| *camel.component.jslt.enabled* | Whether to enable auto configuration of the 
jolt component. This is enabled by default. |  | Boolean
+| *camel.component.jslt.lazy-start-producer* | Whether the producer should be 
started lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a producer may otherwise 
fail during starting and cause the route to fail being started. By deferring 
this startup to be lazy then the startup failure can be handled during routing 
messages via Camel's routing error handlers. Beware that when the first message 
is processed then  [...]
+| *camel.component.jslt.transform* | Explicitly sets the Transform to use. If 
not set a Transform specified by the transformDsl will be created. The option 
is a com.bazaarvoice.jolt.Transform type. |  | String
+|===
+// spring-boot-auto-configure options: END
+
+
+
+
+== Samples
+
+For example you could use something like
+
+[source,java]
+--------------------------------------
+from("activemq:My.Queue").
+  to("jslt:com/acme/MyResponse.json");
+--------------------------------------
+
+And a file based resource:
+
+[source,java]
+---------------------------------------------------------------
+from("activemq:My.Queue").
+  to("jslt:file://myfolder/MyResponse.json?contentCache=true").
+  to("activemq:Another.Queue");
+---------------------------------------------------------------
+
+You can also specify which JSLT expression the component should use
+dynamically via a header, so for example:
+
+[source,java]
+---------------------------------------------------------------------
+from("direct:in").
+  setHeader("CamelJsltResourceUri").constant("path/to/my/spec.json").
+  to("jslt:dummy");
+---------------------------------------------------------------------
+
+Or send whole jslt expression via header: (suitable for querying)
+ 
+[source,java]
+---------------------------------------------------------------------
+from("direct:in").
+  setHeader("CamelJsltResourceUri").constant(".published").
+  to("jslt:dummy");
+---------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index f093d08..4a75caf 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -376,6 +376,7 @@
         <jose4j-version>0.6.4</jose4j-version>
         <josql-bundle-version>1.5_5</josql-bundle-version>
         <jsendnsca-version>2.1.1</jsendnsca-version>
+        <jslt-version>0.1.8</jslt-version>
         <jsmpp-version>2.3.7</jsmpp-version>
         <jsch-version>0.1.55</jsch-version>
         <jsch-bundle-version>0.1.55_1</jsch-bundle-version>
@@ -1660,6 +1661,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
+        <artifactId>camel-jslt</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
         <artifactId>camel-json-validator</artifactId>
         <version>${project.version}</version>
       </dependency>
diff --git a/platforms/karaf/features/src/main/resources/features.xml 
b/platforms/karaf/features/src/main/resources/features.xml
index 7134c2a..e9420ce 100644
--- a/platforms/karaf/features/src/main/resources/features.xml
+++ b/platforms/karaf/features/src/main/resources/features.xml
@@ -1561,6 +1561,14 @@
     <feature version='${project.version}'>camel-ftp</feature>
     <bundle>mvn:org.apache.camel/camel-jsch/${project.version}</bundle>
   </feature>
+  <feature name='camel-jslt' version='${project.version}' start-level='50'>
+    <feature version='${project.version}'>camel-core</feature>
+    <bundle 
dependency='true'>mvn:com.fasterxml.jackson.core/jackson-core/${jackson2-version}</bundle>
+    <bundle 
dependency='true'>mvn:com.fasterxml.jackson.core/jackson-databind/${jackson2-version}</bundle>
+    <bundle 
dependency='true'>mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson2-version}</bundle>
+    <bundle 
dependency='true'>wrap:mvn:com.schibsted.spt.data/jslt/${jslt-version}</bundle>
+    <bundle>mvn:org.apache.camel/camel-jslt/${project.version}</bundle>
+  </feature>
   <feature name='camel-json-validator' version='${project.version}' 
start-level='50'>
     <feature version='${project.version}'>camel-core</feature>
     <bundle 
dependency='true'>mvn:com.networknt/json-schema-validator/${networknt-json-schema-validator-version}</bundle>

Reply via email to