You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2019/02/26 08:16:53 UTC
[karaf-decanter] branch master updated: [KARAF-6118] Add SOAP
collector
This is an automated email from the ASF dual-hosted git repository.
jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf-decanter.git
The following commit(s) were added to refs/heads/master by this push:
new ff11e9b [KARAF-6118] Add SOAP collector
new f0146f0 Merge pull request #72 from jbonofre/KARAF-6118
ff11e9b is described below
commit ff11e9b04b0a61cbf49fc39b8a7f965d878efdd4
Author: Jean-Baptiste Onofré <jb...@nanthrax.net>
AuthorDate: Sun Feb 17 22:05:47 2019 +0100
[KARAF-6118] Add SOAP collector
---
assembly/src/main/feature/feature.xml | 11 ++
collector/pom.xml | 1 +
collector/soap/pom.xml | 114 +++++++++++++++++
.../org.apache.karaf.decanter.collector.soap.cfg | 27 ++++
.../decanter/collector/soap/SoapCollector.java | 141 +++++++++++++++++++++
.../decanter/collector/soap/EventAdminMock.java | 40 ++++++
.../decanter/collector/soap/SoapCollectorTest.java | 130 +++++++++++++++++++
.../karaf/decanter/collector/soap/TestService.java | 26 ++++
.../decanter/collector/soap/TestServiceImpl.java | 29 +++++
.../src/main/asciidoc/user-guide/collectors.adoc | 27 ++++
10 files changed, 546 insertions(+)
diff --git a/assembly/src/main/feature/feature.xml b/assembly/src/main/feature/feature.xml
index af953e6..fd4969d 100644
--- a/assembly/src/main/feature/feature.xml
+++ b/assembly/src/main/feature/feature.xml
@@ -107,6 +107,17 @@
<configfile finalname="/etc/org.apache.karaf.decanter.collector.rest-1.cfg">mvn:org.apache.karaf.decanter.collector/org.apache.karaf.decanter.collector.rest/${project.version}/cfg</configfile>
</feature>
+ <feature name="decanter-collector-soap-core" version="${project.version}" description="Karaf Decanter SOAP Collector Core">
+ <feature>decanter-common</feature>
+ <feature>scheduler</feature>
+ <bundle>mvn:org.apache.karaf.decanter.collector/org.apache.karaf.decanter.collector.soap/${project.version}</bundle>
+ </feature>
+
+ <feature name="decanter-collector-soap" version="${project.version}" description="Karaf Decanter SOAP Collector">
+ <feature>decanter-collector-soap-core</feature>
+ <configfile finalname="/etc/org.apache.karaf.decanter.collector.soap-1.cfg">mvn:org.apache.karaf.decanter.collector/org.apache.karaf.decanter.collector.soap/${project.version}/cfg</configfile>
+ </feature>
+
<feature name="decanter-collector-system" version="${project.version}" description="Karaf Decanter OS Collector">
<feature>decanter-common</feature>
<feature>scheduler</feature>
diff --git a/collector/pom.xml b/collector/pom.xml
index 9841651..fe92393 100644
--- a/collector/pom.xml
+++ b/collector/pom.xml
@@ -48,6 +48,7 @@
<module>process</module>
<module>rest</module>
<module>rest-servlet</module>
+ <module>soap</module>
<module>system</module>
<module>socket</module>
<module>jdbc</module>
diff --git a/collector/soap/pom.xml b/collector/soap/pom.xml
new file mode 100644
index 0000000..a02f369
--- /dev/null
+++ b/collector/soap/pom.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf.decanter</groupId>
+ <artifactId>collector</artifactId>
+ <version>2.2.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.karaf.decanter.collector</groupId>
+ <artifactId>org.apache.karaf.decanter.collector.soap</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: Decanter :: Collector :: SOAP</name>
+
+ <properties>
+ <cxf.version>3.2.6</cxf.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.karaf.decanter</groupId>
+ <artifactId>org.apache.karaf.decanter.api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.decanter.collector</groupId>
+ <artifactId>org.apache.karaf.decanter.collector.utils</artifactId>
+ </dependency>
+
+ <!-- test -->
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxws</artifactId>
+ <version>${cxf.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-http-jetty</artifactId>
+ <version>${cxf.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <inherited>true</inherited>
+ <extensions>true</extensions>
+ <configuration>
+ <obrRepository>NONE</obrRepository>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Export-Package>!*</Export-Package>
+ <Import-Package>*</Import-Package>
+ <Private-Package>
+ org.apache.karaf.decanter.collector.soap,
+ org.apache.karaf.decanter.collector.utils
+ </Private-Package>
+ <_dsannotations>*</_dsannotations>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>src/main/cfg/org.apache.karaf.decanter.collector.soap.cfg</file>
+ <type>cfg</type>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/collector/soap/src/main/cfg/org.apache.karaf.decanter.collector.soap.cfg b/collector/soap/src/main/cfg/org.apache.karaf.decanter.collector.soap.cfg
new file mode 100644
index 0000000..81d226d
--- /dev/null
+++ b/collector/soap/src/main/cfg/org.apache.karaf.decanter.collector.soap.cfg
@@ -0,0 +1,27 @@
+################################################################################
+#
+# 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.
+#
+################################################################################
+
+#
+# Decanter SOAP collector
+#
+
+url=http://localhost:8080/cxf/service
+soap.request=
+#topic=decanter/collect/soap
+
diff --git a/collector/soap/src/main/java/org/apache/karaf/decanter/collector/soap/SoapCollector.java b/collector/soap/src/main/java/org/apache/karaf/decanter/collector/soap/SoapCollector.java
new file mode 100644
index 0000000..738b978
--- /dev/null
+++ b/collector/soap/src/main/java/org/apache/karaf/decanter/collector/soap/SoapCollector.java
@@ -0,0 +1,141 @@
+/*
+ * 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.karaf.decanter.collector.soap;
+
+import org.apache.karaf.decanter.collector.utils.PropertiesPreparator;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component(
+ service = Runnable.class,
+ name = "org.apache.karaf.decanter.collector.soap",
+ immediate = true,
+ property = {
+ "decanter.collector.name=soap",
+ "scheduler.period:Long=60",
+ "scheduler.concurrent:Boolean=false",
+ "scheduler.name=decanter-collector-soap"
+ }
+)
+public class SoapCollector implements Runnable {
+
+ @Reference
+ public EventAdmin dispatcher;
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(SoapCollector.class);
+
+ private URL url;
+ private String soapRequest;
+ private String topic;
+ private Dictionary<String, Object> config;
+
+ @Activate
+ public void activate(ComponentContext componentContext) throws Exception {
+ activate(componentContext.getProperties());
+ }
+
+ public void activate(Dictionary<String, Object> config) throws MalformedURLException {
+ this.config = config;
+ if (config.get("url") == null) {
+ throw new IllegalArgumentException("url property is mandatory");
+ }
+ this.topic = "decanter/collect/soap";
+ if (config.get("topic") != null) {
+ this.topic = (String) config.get("topic");
+ }
+ url = new URL((String) config.get("url"));
+ if (config.get("soap.request") == null) {
+ throw new IllegalStateException("soap.request property is mandatory");
+ }
+ soapRequest = (String) config.get("soap.request");
+ }
+
+ @Override
+ public void run() {
+ Map<String, Object> data = new HashMap<>();
+ data.put("soap.request", soapRequest);
+ data.put("url", url);
+ data.put("type", "soap");
+
+ // custom fields
+ Enumeration<String> keys = config.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ data.put(key, config.get(key));
+ }
+
+ try {
+ PropertiesPreparator.prepare(data, config);
+ } catch (Exception e) {
+ LOGGER.warn("Can't prepare properties", e);
+ }
+
+ HttpURLConnection connection = null;
+ try {
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("POST");
+ connection.setDoOutput(true);
+ connection.setDoInput(true);
+ connection.setRequestProperty("Content-Type", "text/xml");
+ connection.setRequestProperty("Accept", "text/xml");
+ try (OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream())) {
+ writer.write(soapRequest);
+ writer.flush();
+ data.put("http.response.code", connection.getResponseCode());
+ data.put("http.response.message", connection.getResponseMessage());
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
+ StringBuffer buffer = new StringBuffer();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ buffer.append(line).append("\n");
+ }
+ data.put("soap.response", buffer.toString());
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.warn("Can't request SOAP service", e);
+ data.put("error", e.getClass().getName() + ": " + e.getMessage());
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+
+ dispatcher.postEvent(new Event(topic, data));
+ }
+
+}
diff --git a/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/EventAdminMock.java b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/EventAdminMock.java
new file mode 100644
index 0000000..8b9476d
--- /dev/null
+++ b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/EventAdminMock.java
@@ -0,0 +1,40 @@
+/*
+ * 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.karaf.decanter.collector.soap;
+
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EventAdminMock implements EventAdmin {
+
+ public List<Event> postedEvents = new ArrayList<>();
+ public List<Event> sentEvents = new ArrayList<>();
+
+ @Override
+ public void postEvent(Event event) {
+ postedEvents.add(event);
+ }
+
+ @Override
+ public void sendEvent(Event event) {
+ sentEvents.add(event);
+ }
+
+}
diff --git a/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/SoapCollectorTest.java b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/SoapCollectorTest.java
new file mode 100644
index 0000000..b4267f0
--- /dev/null
+++ b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/SoapCollectorTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.karaf.decanter.collector.soap;
+
+import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.feature.LoggingFeature;
+import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.service.event.Event;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+public class SoapCollectorTest {
+
+ private Server cxfServer;
+
+ @Before
+ public void setup() throws Exception {
+ JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
+
+ LoggingFeature loggingFeature = new LoggingFeature();
+ loggingFeature.setPrettyLogging(true);
+ factory.getFeatures().add(loggingFeature);
+
+ TestServiceImpl testService = new TestServiceImpl();
+ factory.setServiceBean(testService);
+ factory.setAddress("http://localhost:9090/test");
+ cxfServer = factory.create();
+ cxfServer.start();
+ }
+
+ @After
+ public void teardown() throws Exception {
+ cxfServer.stop();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBadConfiguration() throws Exception {
+ SoapCollector collector = new SoapCollector();
+ Dictionary<String, Object> config = new Hashtable<>();
+ collector.activate(config);
+ }
+
+ @Test
+ public void testWithInvalidRequest() throws Exception {
+ EventAdminMock eventAdminMock = new EventAdminMock();
+
+ SoapCollector collector = new SoapCollector();
+ Dictionary<String, Object> config = new Hashtable<>();
+ config.put("soap.request", "test");
+ config.put("url", "http://localhost:9090/test");
+ collector.dispatcher = eventAdminMock;
+ collector.activate(config);
+ collector.run();
+
+ Assert.assertEquals(1, eventAdminMock.postedEvents.size());
+
+ Event event = eventAdminMock.postedEvents.get(0);
+
+ Assert.assertEquals(500, event.getProperty("http.response.code"));
+ Assert.assertTrue(((String) event.getProperty("error")).contains("java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:9090/test"));
+ }
+
+ @Test
+ public void testWithBadUrl() throws Exception {
+ EventAdminMock eventAdminMock = new EventAdminMock();
+
+ SoapCollector collector = new SoapCollector();
+ Dictionary<String, Object> config = new Hashtable<>();
+ config.put("soap.request", "test");
+ config.put("url", "http://foo.bar/foo");
+ collector.dispatcher = eventAdminMock;
+ collector.activate(config);
+ collector.run();
+
+ Assert.assertEquals(1, eventAdminMock.postedEvents.size());
+
+ Event event = eventAdminMock.postedEvents.get(0);
+ Assert.assertEquals("java.net.UnknownHostException: foo.bar", event.getProperty("error"));
+ }
+
+ @Test
+ public void testWithValidRequest() throws Exception {
+ EventAdminMock eventAdminMock = new EventAdminMock();
+
+ SoapCollector collector = new SoapCollector();
+ Dictionary<String, Object> config = new Hashtable<>();
+ config.put("url", "http://localhost:9090/test");
+ config.put("soap.request", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:soap=\"http://soap.collector.decanter.karaf.apache.org/\">\n" +
+ " <soapenv:Header/>\n" +
+ " <soapenv:Body>\n" +
+ " <soap:echo>\n" +
+ " <!--Optional:-->\n" +
+ " <arg0>This is a test</arg0>\n" +
+ " </soap:echo>\n" +
+ " </soapenv:Body>\n" +
+ "</soapenv:Envelope>");
+ collector.dispatcher = eventAdminMock;
+ collector.activate(config);
+ collector.run();
+
+ Assert.assertEquals(1, eventAdminMock.postedEvents.size());
+
+ Event event = eventAdminMock.postedEvents.get(0);
+ Assert.assertNull(event.getProperty("error"));
+ Assert.assertEquals(200, event.getProperty("http.response.code"));
+ Assert.assertEquals("OK", event.getProperty("http.response.message"));
+ Assert.assertTrue(((String) event.getProperty("soap.response")).contains("hello This is a test"));
+ }
+
+}
diff --git a/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/TestService.java b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/TestService.java
new file mode 100644
index 0000000..94b880a
--- /dev/null
+++ b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/TestService.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.karaf.decanter.collector.soap;
+
+import javax.jws.WebService;
+
+@WebService
+public interface TestService {
+
+ String echo(String message);
+
+}
diff --git a/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/TestServiceImpl.java b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/TestServiceImpl.java
new file mode 100644
index 0000000..5f14b5b
--- /dev/null
+++ b/collector/soap/src/test/java/org/apache/karaf/decanter/collector/soap/TestServiceImpl.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.karaf.decanter.collector.soap;
+
+import javax.jws.WebService;
+
+@WebService(endpointInterface = "org.apache.karaf.decanter.collector.soap.TestService", serviceName = "TestService")
+public class TestServiceImpl implements TestService {
+
+ @Override
+ public String echo(String message) {
+ return "hello " + message;
+ }
+
+}
diff --git a/manual/src/main/asciidoc/user-guide/collectors.adoc b/manual/src/main/asciidoc/user-guide/collectors.adoc
index f1bbbe7..f10b6a9 100644
--- a/manual/src/main/asciidoc/user-guide/collectors.adoc
+++ b/manual/src/main/asciidoc/user-guide/collectors.adoc
@@ -779,6 +779,33 @@ The `decanter-collector-rest-servlet` feature installs the collector:
karaf@root()> feature:install decanter-collector-rest-servlet
----
+==== SOAP
+
+The Decanter SOAP collector periodically requests a SOAP service and returns the result (the SOAP Response, or error details if it failed).
+
+The `decanter-collector-soap` feature installs the collector:
+
+----
+karaf@root()> feature:install decanter-collector-soap
+----
+
+This feature also installs `etc/org.apache.karaf.decanter.collector.soap.cfg` configuration file where you can setup the URL of the service and the SOAP request to use:
+
+----
+#
+# Decanter SOAP collector
+#
+
+url=http://localhost:8080/cxf/service
+soap.request=
+----
+
+The collector send several collected properties to the dispatcher, especially:
+
+* `soap.response` property contains the actual SOAP response
+* `error` is only populated when the service request failed, containing the error detail
+* `http.response.code` contains the HTTP status code of the service request
+
==== Dropwizard Metrics
The Decanter Dropwizard Metrics collector get a `MetricSet` OSGi service and periodically get the metrics in the set.