You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/08/17 07:30:17 UTC

[camel] 10/15: Polish and cleanup documentation

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

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

commit 0138f26aa66bbffaff07ad3c46c2b9c833ed9f0f
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 16 21:48:33 2021 +0200

    Polish and cleanup documentation
---
 .../modules/ROOT/pages/type-converter.adoc         | 269 +++++++--------------
 1 file changed, 84 insertions(+), 185 deletions(-)

diff --git a/docs/user-manual/modules/ROOT/pages/type-converter.adoc b/docs/user-manual/modules/ROOT/pages/type-converter.adoc
index a9c8feb..f40bff6 100644
--- a/docs/user-manual/modules/ROOT/pages/type-converter.adoc
+++ b/docs/user-manual/modules/ROOT/pages/type-converter.adoc
@@ -9,56 +9,75 @@ Conversions regularly occur between the following types:
 * `byte[]` and `ByteBuffer`
 * `InputStream` and `OutputStream`
 * `Reader` and `Writer`
-* `Document` and `Source`
+* XML payloads such as `Document` and `Source`
 
-To convert the body of a message to another type:
+For example to convert the message body to XML `Document` type
+then this can be done as follows in Java:
 
 [source,java]
 ----
-Message message = exchange.getIn();
-Document document = message.getBody(Document.class); // <1>
+Message message = exchange.getMessage();
+Document document = message.getBody(Document.class);
 ----
-<1> where https://www.javadoc.io/doc/org.apache.camel/camel-api/current/org/apache/camel/Message.html#getBody-java.lang.Class-[`Message#getBody(Class)`] performs the conversion.
 
-[[TypeConverter-HowTypeConversionworks]]
+Notice that the code only tells Camel what you *want* as the result type (`Document`)
+and not what the input type is, or how Camel should do this.
+
 == How Type Conversion works
 
 The type conversion strategy is defined by the
 https://www.javadoc.io/doc/org.apache.camel/camel-api/current/org/apache/camel/TypeConverter.html[TypeConverter]
-interface that can be customized on a
-https://www.javadoc.io/doc/org.apache.camel/camel-api/current/org/apache/camel/CamelContext.html[CamelContext].
+interface. The interface has several methods, however the most important and common API is:
+
+[source,java]
+----
+<T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException;
+----
+
+This API is used by Camel when it converts an object from one type to another. However if
+you pay attention then this API only has the result type in the contract. The input type
+is inferred from the _value_ parameter.
 
-Camel provides a default type converter registry.
-From Camel 3 onwards, the type converter registry implementation generates source code using the Camel Maven
-Package Plugin, allowing Camel, at runtime, to load and invoke these type converters via
-quick Java method invocations. In Camel 2, type converters are registered using annotation based discovery, invoking the type converters via the https://docs.oracle.com/javase/tutorial/reflect/[Java Reflection API].
+There are many type converters in Camel, some comes out of the box from camel-core, and others
+are additional converters that are shipped in various Camel components.
 
+=== Type converter registry
 
-[[TypeConverter-TypeConverterRegistry]]
-== TypeConverterRegistry
+To keep track of all those converters, then Camel has a registry for type converters
+(`org.apache.camel.spi.TypeConverterRegistry`).
 
-Add a `TypeConverter` to the
-https://www.javadoc.io/doc/org.apache.camel/camel-api/current/org/apache/camel/spi/TypeConverterRegistry.html[`TypeConverterRegistry`]
-at runtime using the xref:camelcontext.adoc[CamelContext]:
+This registry keeps track of all possible type converter combinations, such as which converters
+that can convert to an `InputStream` and so forth.
+
+So the example from before, what Camel would do is to lookup in the `TypeConverterRegistry`
+to find a suitable converter that can convert the given input value to the `Document` type.
+
+The `TypeConverterRegistry` can be accessed via Java:
 
 [source,java]
 ----
-CamelContext context = ...;
-context.getTypeConverterRegistry();
+TypeConverterRegistry tcr = camelContext.getTypeConverterRegistry();
+TypeConverter tc = tcr.lookup(Document.class, InputStream.class);
 ----
 
-NOTE: This is useful on platforms where the automatic type converters discovery fails due to classloading issues.
+However often you would not work directly with the `TypeConverterRegistry` or `TypeConverter` APIs in Camel;
+as type conversion are often implicit in use where you would just declare the result type; and Camel takes care of this.
 
-[[TypeConverter-TypeConverterRegistryutilizationstatistics]]
-=== TypeConverterRegistry utilization statistics
+[NOTE]
+====
+In Camel, all the official Camel components, comes with source code generated `TypeConverter`
+(via `camel-component-maven-plugin`) that allows Camel to load these converters very quickly,
+and invoke these type converters at runtime via quick Java method invocations (no reflection overhead).
+====
+
+=== Type converter registry utilization statistics
 
 Camel can gather utilization statistics of the runtime usage of type
-converters. These statistics are available in JMX as well as
+converters. These statistics are available in xref:jmx.adoc[JMX] as well as
 from https://www.javadoc.io/doc/org.apache.camel/camel-api/latest/org/apache/camel/spi/TypeConverterRegistry.html#getStatistics--[`TypeConverterRegistry#getStatistics()`].
 
 These statistics are turned off by
-default as there is some performance overhead under very high concurrent
-load.
+default as there is some performance overhead under very high concurrent load.
 
 Enabling statistics in Java:
 
@@ -72,113 +91,46 @@ Enabling statistics in XML DSL:
 
 [source,xml]
 ----
-<camelContext xmlns="http://camel.apache.org/schema/spring" typeConverterStatisticsEnabled="true">
+<camelContext typeConverterStatisticsEnabled="true">
     ...
 </camelContext>
 ----
 
-[[TypeConverter-Addtypeconverterclassesatruntime]]
-=== Add type converter classes at runtime
+== TypeConverter using @Converter annotation
+
+All the type converters that comes out of the box are coded as Java methods on _converter_ classes.
 
-Classes implementing https://www.javadoc.io/doc/org.apache.camel/camel-api/latest/org/apache/camel/TypeConverters.html[`TypeConverters`] are added to the type converter registry
-at runtime. Use https://javadoc.io/doc/org.apache.camel/camel-api/latest/org/apache/camel/Converter.html[`@Converter`] to mark each type converter.
+This means a class has been annotated with `@Converter` and the methods in the class
+becomes a type converter _pair_ when the methods is also annotated with `@Converter` such as:
 
 [source,java]
 ----
-private class MyOrderTypeConverters implements TypeConverters {
+@Converter(generateLoader = true)
+public class IOConverter {
     @Converter
-    public MyOrder toMyOrder(String orderId) {
-        MyOrder order = new MyOrder();
-        order.setId(Integer.parseInt(orderId));
-        return order;
+    public static InputStream toInputStream(File file) throws FileNotFoundException {
+        return new BufferedInputStream(new FileInputStream(file));
     }
 }
 ----
 
-Then, add these converters to the registry:
-
-[source,xml]
-----
-MyOrderTypeConverters myClass = ...;
-context.getTypeConverterRegistry().addTypeConverters(myClass);
-----
-
-If you are using Spring or Blueprint, then you can just declare a `<bean>`
-then `CamelContext` will automatic discover and add the converters.
-
-[source,xml]
-----
-<bean id="myOrderTypeConverters" class="..."/>
-    <camelContext ...>
-        ...
-    </camelContext>
-----
+This is from camel-core where the `IOConverter` class has a number of converters (only 1 shown).
+The method `toInputStream` is annotated with `@Converter` which then becomes a type converter
+that can convert from `File` to `InputStream`.
 
-You can declare multiple `<bean>`s if you have more classes.
+All these _converter_ classes are discovered and loaded by Camel.
 
-[[TypeConverter-DiscoveringTypeConverters]]
 == Discovering Type Converters
 
 Camel automatically discovers and loads the type converters from all JARs on the classpath at startup.
 
 Camel searches the classpath for a file called
 `META-INF/services/org/apache/camel/TypeConverterLoader` which lists
-all type converter loader classes. These are automatically generated by the Camel Maven Package Plugin.
+all type converter loader classes. These are automatically generated by the Camel Component Package Plugin.
 These _loader_ classes will load the type converters into the Camel type converter registry
 and invoke them in a _fast way_ using standard Java method calls.
 
-=== Discovering Camel 2.x based type converters (not loader)
-
-Camel will not perform additional package scanning for type converters which have no source code generated for loader classes.
-
-To enable additional package scanning in Java:
-
-[source,java]
-----
-camelContext.setLoadTypeConverters(true);
-----
-
-In XML DSL:
-
-[source,xml]
-----
-<camelContext loadTypeConverters="true">
-...
-</camelContext>
-----
-
-In Spring Boot `application.properties`:
-
-[source,properties]
-----
-camel.springboot.load-type-converters=true
-----
-
-Camel will discover Camel 2.x compatible type converters by
-searching the classpath for a file called `META-INF/services/org/apache/camel/TypeConverter`
-which lists all type converter classes. These classes are automatically registered in the type converter
-registry. However, invoking these type converters does **not** happen in a _fast way_ and uses the Java Reflection API.
-It is therefore recommended to upgrade any type converters to use the faster way. See below for more details.
-
-TIP: You can turn off the fallback of discovering Camel 2.x compatible type converters by
-setting `CamelContext.setLoadTypeConverters(false)`.
-
-`@Converter` must appear at the class and method level for each type converter.
-
-.Register a type converter from `File` to `InputStream`
-
-[source,java]
-----
-@Converter
-public class IOConverter {
-    @Converter
-    public static InputStream toInputStream(File file) throws FileNotFoundException {
-        return new BufferedInputStream(new FileInputStream(file));
-    }
-}
-----
-
-=== Discovering Type Converters in the fast way
+=== Discovering Type Converters (fast way)
 
 To enable the fast type converter way, you should enable `generateLoader = true`
 on the class level annotation as shown:
@@ -194,78 +146,10 @@ public class IOConverter {
 }
 ----
 
-And then you should have the Camel Maven Package Plugin in as build plugin when compiling the project.
-Also add the build helper plugin which ensures the generated source code in `src/generated` will be included in the source path.
-
-When using Maven you add:
-
-[source,xml]
-----
-      <plugin>
-        <groupId>org.apache.camel</groupId>
-        <artifactId>camel-package-maven-plugin</artifactId>
-        <version>${camel-version}</version>
-        <executions>
-          <execution>
-            <id>generate</id>
-            <goals>
-              <goal>generate-component</goal>
-            </goals>
-            <phase>process-classes</phase>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <phase>initialize</phase>
-            <goals>
-              <goal>add-source</goal>
-              <goal>add-resource</goal>
-            </goals>
-            <configuration>
-              <sources>
-                <source>src/generated/java</source>
-              </sources>
-              <resources>
-                <resource>
-                  <directory>src/generated/resources</directory>
-                </resource>
-              </resources>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-----
-
-[[TypeConverter-Returningnullvalues]]
-=== Returning null values
-
-By default when using a method in a POJO annotation with @Converter
-returning null is not a valid response. If null is returned, then Camel
-will regard that type converter as a _miss_, and prevent from using it
-in the future. If null should be allowed as a valid response, then from
-*Camel 2.11.2/2.12* onwards you can specify this in the annotation as
-shown:
-
-[source,java]
-----
-@Converter(allowNull = true)
-public static InputStream toInputStream(File file) throws IOException {
-    if (file.exist()) {
-        return new BufferedInputStream(new FileInputStream(file));
-    } else {
-        return null;
-    }
-}
-----
+And then you should have the xref:camel-component-maven-plugin.adoc[Camel Component Package Plugin] in as build plugin when compiling the project.
 
 === Discovering Type Converters in the fastest way
 
-*Available in Camel 3.7*
-
 In Camel 3.7 we optimized the type converter system for optimal performance when using the built-in converters.
 This was done by bulking together all the converters in the same Maven module into a single class. The class has a single
 `convert` method where all the supported converters are available and discovered in a fast way using Java primitives.
@@ -288,7 +172,7 @@ There is a few limitations:
 
 - fallback converters is not supported
 - the order of the `@Converter` methods matters. If you have multiple `@Converter` methods that accept as _from_ type
-  types which are from the same class hierachy then put the methods first that are the most concrete.
+types which are from the same class hierachy then put the methods first that are the most concrete.
 
 For example in `camel-xml-jaxp` we have in the `XmlConverter` multiple `@Converter` methods which can convert to `DomSource`.
 We had to put the method that takes `org.w3c.dom.Document` before the method that takes `org.w3c.dom.Node` as `Document` extends `Node`.
@@ -306,10 +190,27 @@ The following code shows snippet of the source code generated bulk class. As you
             }
 ----
 
-[[TypeConverter-DiscoveringFallbackTypeConverters]]
-== Discovering Fallback Type Converters
+=== Returning null values
+
+By default, when using a method in a POJO annotation with `@Converter`
+returning `null` is not a valid response. If null is returned, then Camel
+will regard that type converter as a _miss_, and prevent from using it
+in the future. If `null` should be allowed as a valid response, then
+you must specify this in the annotation (via `allowNull`) as shown:
+
+[source,java]
+----
+@Converter(allowNull = true)
+public static InputStream toInputStream(File file) throws IOException {
+    if (file.exist()) {
+        return new BufferedInputStream(new FileInputStream(file));
+    } else {
+        return null;
+    }
+}
+----
 
-*Available in Camel 2.0*
+== Fallback Type Converters
 
 The
 https://www.javadoc.io/doc/org.apache.camel/camel-base/current/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.html[AnnotationTypeConverterLoader]
@@ -371,12 +272,11 @@ public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, Ty
 }
 ----
 
-[[TypeConverter-WritingyourownTypeConverters]]
 == Writing your own Type Converters
 
 You are welcome to write your own converters. Remember to use the
 `@Converter` annotations on the classes and methods you wish to use.
-And on the top-level class add `Converter(loader = true)` to support the _fast way_
+And on the top-level class add `Converter(generateLoader = true)` to support the _fast way_
 of using type converters.
 
 * static methods are encouraged to reduce caching, but instance methods
@@ -384,8 +284,7 @@ are fine, particularly if you want to allow optional dependency
 injection to customize the converter
 * converter methods should be thread safe and reentrant
 
-[[TypeConverter-Exchangeparameter]]
-== Exchange parameter
+=== Exchange parameter
 
 The type converter accepts the `Exchange` as an optional 2nd parameter.
 This is usable if the type converter for instance needs information from