This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch tc-loader in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/tc-loader by this push: new c2448ea CAMEL-13313: Add support for generating type converter loader source code to be able to load component type converters in a faster way c2448ea is described below commit c2448ead98923e03a4153180372724611d21f5a2 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Mar 18 11:17:22 2019 +0100 CAMEL-13313: Add support for generating type converter loader source code to be able to load component type converters in a faster way --- .../modules/ROOT/pages/type-converter.adoc | 210 +++++++-------------- 1 file changed, 63 insertions(+), 147 deletions(-) diff --git a/docs/user-manual/modules/ROOT/pages/type-converter.adoc b/docs/user-manual/modules/ROOT/pages/type-converter.adoc index 7ce937b..cbd6e33 100644 --- a/docs/user-manual/modules/ROOT/pages/type-converter.adoc +++ b/docs/user-manual/modules/ROOT/pages/type-converter.adoc @@ -36,32 +36,17 @@ http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/TypeCo interface that can be customized on a http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/CamelContext.html[CamelContext]. -The default implementation, -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/converter/DefaultTypeConverter.html[DefaultTypeConverter], -uses pluggable strategies to load type converters via -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/converter/TypeConverterLoader.html[TypeConverterLoader]. -The default strategy, -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.html[AnnotationTypeConverterLoader], -uses a discovery mechanism to find converters. - -*New in Camel 1.5* - -The default implementation, -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/converter/DefaultTypeConverter.html[DefaultTypeConverter], -now throws a -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/NoTypeConversionAvailableException.html[NoTypeConversionAvailableException] -if a suitable conversion cannot be found -(https://issues.apache.org/jira/browse/CAMEL-84[CAMEL-84]). -The semantical ambiguity of `null` (both valid result and indication -of no conversion found) is now resolved, but this may impact existing -code in that it should now catch the exception instead of checking -for `null`. +Camel provides two type converter registy implementations: + +- FastTypeConverterRegistry (new default) +- DefaultTypeConverterRegistry (old) + +From Camel 3 onwards there is a faster type converter registry implementation that is enabled by default. This implementation uses source code generation via the `camel-apt` compiler plugin to generate source code, that allows Camel at runtime to load and invoke these type converters via quick java method invocations. The older implementation in Camel 2 uses a annotation based discover to load and register type converters and invokes the type converters via Java method call reflections. + [[TypeConverter-TypeConverterRegistry]] ==== TypeConverterRegistry -*New in Camel 2.0* - Exposed the http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/spi/TypeConverterRegistry.html[TypeConverterRegistry] from link:camelcontext.adoc[CamelContext] so end users more easily will @@ -84,7 +69,7 @@ Camel can gather utilization statistics of the runtime usage of type converters. These stats are available in JMX, and as well as from the `getStatistics()` method from `TypeConverterRegistry`. -From *Camel 2.11.0/2.10.5* onwards these statistics are turned off by +These statistics are turned off by default as there is some performance overhead under very high concurrent load. To enable the statistics in Java, do the following: @@ -103,26 +88,10 @@ Or in the XML DSL with: </camelContext> ---- -[[TypeConverter-Addtypeconverteratruntime]] -===== Add type converter at runtime - -The following sample demonstrates how to add a type converter at -runtime: + -link:../../../camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryTest.java[/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryTest.java] - -And our type converter is implemented as: + -link:../../../camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryTest.java[/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryTest.java] - -And then we can convert from String to MyOrder as we are used to with the -type converter: + -link:../../../camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryTest.java[/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryTest.java] - [[TypeConverter-Addtypeconverterclassesatruntime]] ===== Add type converter classes at runtime -*Available as of Camel 2.16* - -From Camel 2.16 onwards you type converter classes can +You can add new type converters at runtime, by having your classes implement `org.apache.camel.TypeConverters` which is an marker interface. Then for each type converter you want use the `@Converter` annotation. @@ -158,30 +127,28 @@ then `CamelContext` will automatic discover and add the converters. </camelContext> ---- -You can declare multiple `<bean>`s if you have more clases. - -Using this technique do not require to scan the classpath and using the -file `META-INF/services/org/apache/camel/TypeConverter` as discussed in -the <<TypeConverter-DiscoveringTypeConverters,Discovering Type Converters>> -section. However the latter is highly -recommended when developing Camel components or data formats as then the -type converters is automatic included out of the box. The functionality -from this section requires the end users to explicit add the converters -to their Camel applications. +You can declare multiple `<bean>`s if you have more classes. [[TypeConverter-DiscoveringTypeConverters]] ==== Discovering Type Converters -The -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.html[AnnotationTypeConverterLoader] -will search the classpath for a file called -`META-INF/services/org/apache/camel/TypeConverter`. The contents are -expected to be comma separated package names. These packages are then -recursively searched for any objects with the -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Converter[@Converter] -annotation. Then any method marked with @Converter is assumed to be a -conversion method; where the parameter is the from value and the return -is the to value. +Camel will automatic discover and load type converters from all the JARs in the classpath on startup. + +Camel will search the classpath for a file called +`META-INF/services/org/apache/camel/TypeConverterLoader`, which lists +all type converter loader classes (they are automatic source code generated by the `camel-apt` compilter plugin). +These _loader_ classes will load the type converters into the Camel type converter registry +and invoking these type converters is done in a _fast way_ using standard java method calls. + +The discover will fallback and discover Camel 2.x compatible type converters by +search the classpath for a file called `META-INF/services/org/apache/camel/TypeConverter`, +which lists all the type converter classes. These classes will then automatic +be registered in the type converter registry. However invoking these type converters +does **not** happen in a _fast way_ but uses Java method call reflection. It is therefore +recommended to migrate your type converters to use the faster way. See further below. + +The converter classes must be annotated on the top class level with the `@Converter` annotation, +and each converter method as well. E.g. the following shows how to register a converter from `File` to `InputStream`: @@ -197,15 +164,33 @@ public class IOConverter { } ---- -Static methods are invoked; non-static methods require an instance of -the converter object to be created (which is then cached). If a -converter requires configuration you can plug in an Injector interface -to the `DefaultTypeConverter` which can construct and inject converter -objects via Spring or Guice. +===== Discovering Type Converters in the fast way + +To enable the fast type converter way, you should enable `loader = true` +on the class level annotation as shown: + +[source,java] +---- +@Converter(loader = true) +public class IOConverter { + @Converter + public static InputStream toInputStream(File file) throws FileNotFoundException { + return new BufferedInputStream(new FileInputStream(file)); + } +} +---- -We have most of the common converters for common Java types in the -http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/converter/package-summary.html[org.apache.camel.converter] -package and its children. +And then you should have the `camel-apt` JAR as dependency when compiling the project. +When using Maven you add: + +[source,xml] +---- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>apt</artifactId> + <scope>provided</scope> +</dependency> +---- [[TypeConverter-Returningnullvalues]] ===== Returning null values @@ -297,86 +282,19 @@ public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, Ty [[TypeConverter-WritingyourownTypeConverters]] ==== Writing your own Type Converters -[NOTE] -==== -*Use FQN* - -In Camel 2.8 the TypeConverter file now supports specifying the FQN -class name. This is recommended to be used. See below for more details. -Using FQN must be used. The older way with just package name is -deprecated and should not be used, and it may also not work in some -application servers due to classpath scanning issues. -==== - - You are welcome to write your own converters. Remember to use the -`@Converter` annotations on the classes and methods you wish to use. Then -add the packages to a file called -`META-INF/services/org/apache/camel/TypeConverter` in your jar. Remember -to make sure that : +`@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_ +of using type converters. * static methods are encouraged to reduce caching, but instance methods are fine, particularly if you want to allow optional dependency injection to customize the converter * converter methods should be thread safe and reentrant -[[TypeConverter-ExamplesofTypeConverterfile]] -===== Examples of TypeConverter file - -The file in the JAR: `META-INF/services/org/apache/camel/TypeConverter` -contains the following line(s): - ----- -com.foo com.bar ----- - -Each line in the file is a package name. This tells Camel to go scan -those packages for any classes that has been annotated with the -`@Converter`. - -[[TypeConverter-ImprovedTypeConverterbyusingFQNclassnames]] -===== Improved TypeConverter by using FQN class names - -*Available as of Camel 2.8* - -In Camel 2.8 we improved the type converter loader to support specifying -the FQN class name of the converter classes. This has the advantage of -avoiding having to scan packages for `@Converter` classes. Instead it -loads the `@Converter` class directly. This is a *highly* recommend -approach to use going forward. - -[[TypeConverter-ExamplesofTypeConverterfile.1]] -===== Examples of TypeConverter file - -The file in the JAR: `META-INF/services/org/apache/camel/TypeConverter` -contains the following line(s) for FQN class names: - ----- -com.foo.MyConverter -com.bar.MyOtherConverter -com.bar.YetOtherConverter ----- - -As you can see each line in the file now contains a FQN class name. This -is the recommended approach. - -[[TypeConverter-Encodingsupportforbyte[]andStringConversion]] -==== Encoding support for byte[] and String Conversion - -*Available in Camel 1.5* - -Since Java provides converting the `byte[]` to `String` and `String` to `byte[]` -with the -http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/Charset.html[charset -name] parameter. You can define the charset name by setting the exchange -property name `Exchange.CHARSET_NAME` with the charset name, such as -`"UTF-8"` or `"iso-8859-1"`. - [[TypeConverter-Exchangeparameter]] ==== Exchange parameter -*Available in Camel 1.5* - The type converter accepts the `Exchange` as an optional 2nd parameter. This is usable if the type converter for instance needs information from the current exchange. For instance combined with the encoding support @@ -388,16 +306,14 @@ converter: ---- @Converter public static String toString(byte[] data, Exchange exchange) { - if (exchange != null) { - String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class); - if (charsetName != null) { - try { - return new String(data, charsetName); - } catch (UnsupportedEncodingException e) { - LOG.warn("Can't convert the byte to String with the charset " + charsetName, e); - } + String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class); + if (charsetName != null) { + try { + return new String(data, charsetName); + } catch (UnsupportedEncodingException e) { + // ignore } + return new String(data); } - return new String(data); } ----