Skip to content

Commit 4f1e7a8

Browse files
committed
Use of serialization feature of Quakus (includes Sql and Nitrite)
1 parent 6489700 commit 4f1e7a8

File tree

17 files changed

+320
-122
lines changed

17 files changed

+320
-122
lines changed

docs/modules/ROOT/pages/reference/extensions/core.adoc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,27 @@ camel.beans.customBeanWithSetterInjection.counter = 123
104104

105105
As such, the class `PropertiesCustomBeanWithSetterInjection` needs to be link:https://quarkus.io/guides/writing-native-applications-tips#registering-for-reflection[registered for reflection], note that field access could be omitted in this case.
106106

107+
==== Serialization in native mode
108+
109+
If serialization support is requested via `quarkus.camel.native.reflection.serialization-enabled`, following classes are registered for serialization:
110+
111+
* `java.lang.Boolean`
112+
* `java.lang.Byte`
113+
* `java.lang.Character`
114+
* `java.lang.Float`
115+
* `java.lang.Double`
116+
* `java.lang.Integer`
117+
* `java.lang.Long`
118+
* `java.lang.Number`
119+
* `java.lang.String`
120+
* `java.math.BigInteger`
121+
* `java.util.Date`
122+
* `java.util.HashMap`
123+
* `java.util.LinkedHashMap`
124+
* `org.apache.camel.support.DefaultExchangeHolder`
125+
126+
Developers can register other classes for serialization via the `ReflectiveClassBuildItem`.
127+
107128

108129
[width="100%",cols="80,5,15",options="header"]
109130
|===
@@ -224,6 +245,13 @@ A comma separated list of Ant-path style patterns to match class names that shou
224245
| `string`
225246
|
226247

248+
|icon:lock[title=Fixed at build time] [[quarkus.camel.native.reflection.serialization-enabled]]`link:#quarkus.camel.native.reflection.serialization-enabled[quarkus.camel.native.reflection.serialization-enabled]`
249+
250+
If `true`, basic classes are registered for serialization; otherwise Java serialization will not work in native mode.
251+
Setting this to `false` helps to reduce the size of the native image. In JVM mode, there is no real benefit of setting this flag to `true` except for making the behavior consistent with native mode.
252+
| `boolean`
253+
| `false`
254+
227255
|icon:lock[title=Fixed at build time] [[quarkus.camel.csimple.on-build-time-analysis-failure]]`link:#quarkus.camel.csimple.on-build-time-analysis-failure[quarkus.camel.csimple.on-build-time-analysis-failure]`
228256

229257
What to do if it is not possible to extract CSimple expressions from a route definition at build time.

docs/modules/ROOT/pages/reference/extensions/nitrite.adoc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,10 @@ Check the xref:user-guide/index.adoc[User guide] for more information about writ
4141

4242
== Usage
4343

44-
If your persistence objects implement `java.io.Serializable`, you have to add configuration of all serializable classes.
45-
There is a new serialization support in GraalVM 21.0. Developers can configure classes
46-
for serialization via the serialization configuration file
47-
`-H:SerializationConfigurationResources=/path/to-serialization-config.json` option. For more
48-
information see https://github.com/oracle/graal/pull/2730[PR with feature].
44+
If your persistence objects in native mode implement `java.io.Serializable` and are not automatically registered for serialization,
45+
you have to register them for serialization. Look into xref:extensions/core.adoc#serialization_in_native_mode[documentation]
46+
to see which classes are registered and how to register other ones.
47+
4948

5049
If your persistence objects implement `org.dizitart.no2.mapper.Mappable`. All classes have to
5150
implement also `java.io.Serializable` and have to be registered for serialization (see previous option),

docs/modules/ROOT/pages/reference/extensions/sql.adoc

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,41 +40,6 @@ Or add the coordinates to your existing project:
4040

4141
Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
4242

43-
== Usage
44-
45-
If you are using SQL Aggregator in native mode, you have to register several classes for serialization using GraalVM
46-
feature. Serialization support since GraalVM 21.0 allows developers to configure classes for serialization via
47-
the serialization configuration file `-H:SerializationConfigurationResources=/path-to/serialization-config.json` option.
48-
For more information see https://github.com/oracle/graal/pull/2730[pull request with feature].
49-
50-
Several classes has to be registered for serialization every time to make SQL Aggregator work in native.
51-
Here is a template of `serialization-config.json` with all mandatory classes:
52-
53-
```
54-
[
55-
{
56-
"name" : "java.lang.Integer"
57-
},
58-
{
59-
"name" : "java.lang.Number"
60-
},
61-
{
62-
"name" : "java.lang.String"
63-
},
64-
{
65-
"name" : "java.util.HashMap"
66-
},
67-
{
68-
"name" : "java.util.LinkedHashMap"
69-
},
70-
{
71-
"name" : "org.apache.camel.support.DefaultExchangeHolder"
72-
}
73-
]
74-
```
75-
76-
77-
7843
== Additional Camel Quarkus configuration
7944

8045
=== Configuring a DataSource
@@ -102,3 +67,12 @@ Note that URI schemes such as `file` or `http` do not need to be listed.
10267
quarkus.native.resources.includes = queries.sql, sql/*.sql
10368
----
10469

70+
=== SQL Aggregator ===
71+
72+
If your exchanges in native mode contain objects, which are not automatically registered for serialization (see xref:extensions/core.adoc#serialization_in_native_mode[documentation]),
73+
you have to register them manually (see xref:extensions/core.adoc#serialization_in_native_mode[documentation])
74+
75+
76+
77+
78+
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.quarkus.core.deployment;
18+
19+
import java.math.BigInteger;
20+
import java.util.AbstractMap;
21+
import java.util.Date;
22+
import java.util.HashMap;
23+
import java.util.LinkedHashMap;
24+
import java.util.List;
25+
import java.util.stream.Stream;
26+
27+
import io.quarkus.deployment.annotations.BuildProducer;
28+
import io.quarkus.deployment.annotations.BuildStep;
29+
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
30+
import org.apache.camel.quarkus.core.CamelConfig;
31+
import org.apache.camel.quarkus.core.deployment.spi.CamelSerializationBuildItem;
32+
import org.apache.camel.support.DefaultExchangeHolder;
33+
import org.slf4j.Logger;
34+
import org.slf4j.LoggerFactory;
35+
36+
public class CamelSerializationProcessor {
37+
private static final Logger LOGGER = LoggerFactory.getLogger(CamelSerializationProcessor.class);
38+
39+
@BuildStep
40+
void produceSerializationBuildItem(CamelConfig config, BuildProducer<CamelSerializationBuildItem> serializationBuildItems) {
41+
final CamelConfig.ReflectionConfig reflectionConfig = config.native_.reflection;
42+
if (reflectionConfig.serializationEnabled) {
43+
LOGGER.debug(
44+
"Registration of basic types for serialization is enabled via quarkus.camel.native.reflection.serialization-enabled");
45+
serializationBuildItems.produce(new CamelSerializationBuildItem());
46+
}
47+
}
48+
49+
@BuildStep
50+
void baseSerializationClasses(List<CamelSerializationBuildItem> serializationRequests,
51+
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
52+
53+
if (!serializationRequests.isEmpty()) {
54+
String[] classes = Stream.of(Boolean.class,
55+
Byte.class,
56+
Character.class,
57+
Double.class,
58+
Float.class,
59+
Integer.class,
60+
Long.class,
61+
Number.class,
62+
Date.class,
63+
String.class,
64+
AbstractMap.class,
65+
HashMap.class,
66+
LinkedHashMap.class,
67+
BigInteger.class,
68+
DefaultExchangeHolder.class)
69+
.map(c -> c.getName()).toArray(String[]::new);
70+
71+
//required for serialization of BigInteger
72+
reflectiveClasses.produce(new ReflectiveClassBuildItem(false, false, byte[].class));
73+
74+
reflectiveClasses.produce(ReflectiveClassBuildItem.serializationClass(classes));
75+
}
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.quarkus.core.deployment.spi;
18+
19+
import io.quarkus.builder.item.MultiBuildItem;
20+
21+
/**
22+
* A build item that does not carry any data but it is used to signal that registration for serialization is requested.
23+
*/
24+
public final class CamelSerializationBuildItem extends MultiBuildItem {
25+
}

extensions-core/core/runtime/src/main/doc/configuration.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,24 @@ camel.beans.customBeanWithSetterInjection.counter = 123
5454
---
5555

5656
As such, the class `PropertiesCustomBeanWithSetterInjection` needs to be link:https://quarkus.io/guides/writing-native-applications-tips#registering-for-reflection[registered for reflection], note that field access could be omitted in this case.
57+
58+
==== Serialization in native mode
59+
60+
If serialization support is requested via `quarkus.camel.native.reflection.serialization-enabled`, following classes are registered for serialization:
61+
62+
* `java.lang.Boolean`
63+
* `java.lang.Byte`
64+
* `java.lang.Character`
65+
* `java.lang.Float`
66+
* `java.lang.Double`
67+
* `java.lang.Integer`
68+
* `java.lang.Long`
69+
* `java.lang.Number`
70+
* `java.lang.String`
71+
* `java.math.BigInteger`
72+
* `java.util.Date`
73+
* `java.util.HashMap`
74+
* `java.util.LinkedHashMap`
75+
* `org.apache.camel.support.DefaultExchangeHolder`
76+
77+
Developers can register other classes for serialization via the `ReflectiveClassBuildItem`.

extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ public static class ReflectionConfig {
281281
@ConfigItem
282282
public Optional<List<String>> includePatterns;
283283

284+
/**
285+
* If {@code true}, basic classes are registered for serialization; otherwise Java serialization will not work in
286+
* native mode.
287+
* <p>
288+
* Setting this to {@code false} helps to reduce the size of the native image. In JVM mode, there is no real
289+
* benefit of setting this flag to {@code true} except for making the behavior consistent with native mode.
290+
*/
291+
@ConfigItem(defaultValue = "false")
292+
public boolean serializationEnabled;
284293
}
285294

286295
@ConfigGroup

extensions/nitrite/deployment/src/main/java/org/apache/camel/quarkus/component/nitrite/deployment/NitriteProcessor.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@
1616
*/
1717
package org.apache.camel.quarkus.component.nitrite.deployment;
1818

19-
import java.util.Arrays;
20-
import java.util.List;
19+
import java.util.concurrent.atomic.AtomicBoolean;
2120

21+
import io.quarkus.deployment.annotations.BuildProducer;
2222
import io.quarkus.deployment.annotations.BuildStep;
2323
import io.quarkus.deployment.builditem.FeatureBuildItem;
2424
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
2525
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
26+
import org.apache.camel.quarkus.core.deployment.spi.CamelSerializationBuildItem;
27+
import org.dizitart.no2.Document;
28+
import org.dizitart.no2.Index;
29+
import org.dizitart.no2.NitriteId;
30+
import org.dizitart.no2.meta.Attributes;
2631

2732
class NitriteProcessor {
2833

@@ -33,15 +38,30 @@ FeatureBuildItem feature() {
3338
return new FeatureBuildItem(FEATURE);
3439
}
3540

41+
@BuildStep
42+
CamelSerializationBuildItem serialization() {
43+
return new CamelSerializationBuildItem();
44+
}
45+
3646
@BuildStep
3747
RuntimeInitializedClassBuildItem runtimeInitializedClass() {
3848
// this class uses a SecureRandom which needs to be initialised at run time
3949
return new RuntimeInitializedClassBuildItem("org.dizitart.no2.Security");
4050
}
4151

4252
@BuildStep
43-
List<ReflectiveClassBuildItem> reflectiveClasses() {
44-
return Arrays.asList(new ReflectiveClassBuildItem(false, false, org.h2.store.fs.FilePathNio.class),
45-
new ReflectiveClassBuildItem(true, false, "sun.reflect.ReflectionFactory"));
53+
void reflectiveClasses(BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
54+
reflectiveClasses.produce(new ReflectiveClassBuildItem(false, false, org.h2.store.fs.FilePathNio.class));
55+
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, false, "sun.reflect.ReflectionFactory"));
56+
57+
String[] dtos = new String[] { NitriteId.class.getName(),
58+
Document.class.getName(),
59+
Attributes.class.getName(),
60+
"org.dizitart.no2.internals.IndexMetaService$IndexMeta",
61+
AtomicBoolean.class.getName(),
62+
Index.class.getName() };
63+
64+
reflectiveClasses.produce(ReflectiveClassBuildItem.serializationClass(dtos));
65+
4666
}
4767
}

extensions/nitrite/runtime/src/main/doc/usage.adoc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
If your persistence objects implement `java.io.Serializable`, you have to add configuration of all serializable classes.
2-
There is a new serialization support in GraalVM 21.0. Developers can configure classes
3-
for serialization via the serialization configuration file
4-
`-H:SerializationConfigurationResources=/path/to-serialization-config.json` option. For more
5-
information see https://github.com/oracle/graal/pull/2730[PR with feature].
1+
If your persistence objects in native mode implement `java.io.Serializable` and are not automatically registered for serialization,
2+
you have to register them for serialization. Look into xref:extensions/core.adoc#serialization_in_native_mode[documentation]
3+
to see which classes are registered and how to register other ones.
4+
65

76
If your persistence objects implement `org.dizitart.no2.mapper.Mappable`. All classes have to
87
implement also `java.io.Serializable` and have to be registered for serialization (see previous option),

extensions/nitrite/runtime/src/main/resources/META-INF/native-image/serialization-config.json

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)