Skip to content

Commit 488c5d2

Browse files
authored
Add AOT support for Pulsar binder. (#379)
- Adds native hints to allow the binder to run in a GraalVM native image.
1 parent 8300f1a commit 488c5d2

File tree

1 file changed

+168
-33
lines changed

1 file changed

+168
-33
lines changed

spring-pulsar/src/main/java/org/springframework/pulsar/aot/PulsarRuntimeHints.java

Lines changed: 168 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.TreeMap;
2121
import java.util.stream.Stream;
2222

23+
import org.apache.pulsar.client.admin.ListTopicsOptions;
2324
import org.apache.pulsar.client.admin.internal.OffloadProcessStatusImpl;
2425
import org.apache.pulsar.client.admin.internal.PulsarAdminBuilderImpl;
2526
import org.apache.pulsar.client.api.Authentication;
@@ -29,10 +30,6 @@
2930
import org.apache.pulsar.client.impl.conf.ProducerConfigurationData;
3031
import org.apache.pulsar.client.util.SecretsSerializer;
3132
import org.apache.pulsar.common.protocol.Commands;
32-
import org.apache.pulsar.shade.io.netty.buffer.AbstractByteBufAllocator;
33-
import org.apache.pulsar.shade.io.netty.channel.socket.nio.NioDatagramChannel;
34-
import org.apache.pulsar.shade.io.netty.channel.socket.nio.NioSocketChannel;
35-
import org.apache.pulsar.shade.io.netty.util.ReferenceCountUtil;
3633

3734
import org.springframework.aot.hint.MemberCategory;
3835
import org.springframework.aot.hint.ReflectionHints;
@@ -45,6 +42,7 @@
4542
* {@link RuntimeHintsRegistrar} for Spring for Apache Pulsar.
4643
*
4744
* @author Soby Chacko
45+
* @author Chris Bono
4846
*/
4947
public class PulsarRuntimeHints implements RuntimeHintsRegistrar {
5048

@@ -57,54 +55,191 @@ public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader)
5755
// core Pulsar classes,
5856
// some other shaded components available through Pulsar client.
5957
Stream.of(HashSet.class, TreeMap.class, Authentication.class, AuthenticationDataProvider.class,
60-
SecretsSerializer.class, NioSocketChannel.class, AbstractByteBufAllocator.class,
61-
NioDatagramChannel.class, PulsarAdminBuilderImpl.class, OffloadProcessStatusImpl.class, Commands.class,
62-
ReferenceCountUtil.class).forEach(
63-
type -> reflectionHints.registerType(type,
64-
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
65-
MemberCategory.INVOKE_DECLARED_METHODS,
66-
MemberCategory.INTROSPECT_PUBLIC_METHODS)));
58+
SecretsSerializer.class, PulsarAdminBuilderImpl.class, OffloadProcessStatusImpl.class, Commands.class)
59+
.forEach(type -> reflectionHints.registerType(type,
60+
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
61+
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS)));
6762

6863
// In addition to the above member category levels, these components need field
6964
// and declared class level access.
70-
Stream.of(ClientConfigurationData.class, ConsumerConfigurationData.class, ProducerConfigurationData.class)
65+
Stream.of(ClientConfigurationData.class, ConsumerConfigurationData.class, ProducerConfigurationData.class,
66+
ListTopicsOptions.class)
7167
.forEach(type -> reflectionHints.registerType(type,
7268
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
7369
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS,
7470
MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS)));
7571

76-
// These are inaccessible interfaces/classes in a normal scenario, thus using the
77-
// String version,
78-
// and we need field level access in them.
79-
Stream.of(
80-
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
81-
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
72+
// These are shaded classes and other inaccessible interfaces/classes (thus using
73+
// string version of API).
74+
// @formatter:off
75+
Stream.of("com.github.benmanes.caffeine.cache.SSMSA",
76+
"com.github.benmanes.caffeine.cache.PSAMS",
77+
"org.apache.pulsar.client.admin.internal.JacksonConfigurator",
78+
"org.apache.pulsar.client.impl.conf.TopicConsumerConfigurationData",
79+
"org.apache.pulsar.client.impl.conf.TopicConsumerConfigurationData$TopicNameMatcher",
80+
"org.apache.pulsar.client.util.SecretsSerializer",
81+
"org.apache.pulsar.common.classification.InterfaceAudience$Public",
82+
"org.apache.pulsar.common.protocol.ByteBufPair$Encoder",
83+
"org.apache.pulsar.common.protocol.PulsarDecoder",
84+
"org.apache.pulsar.common.util.netty.DnsResolverUtil",
85+
"org.apache.pulsar.shade.com.fasterxml.jackson.databind.ext.Java7HandlersImpl",
86+
"org.apache.pulsar.shade.com.fasterxml.jackson.databind.ext.Java7SupportImpl",
87+
"org.apache.pulsar.shade.com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector",
88+
"org.apache.pulsar.shade.com.fasterxml.jackson.module.jaxb.deser.DataHandlerJsonDeserializer",
89+
"org.apache.pulsar.shade.com.fasterxml.jackson.module.jaxb.ser.DataHandlerJsonSerializer",
90+
"org.apache.pulsar.shade.com.google.common.util.concurrent.AbstractFuture",
91+
"org.apache.pulsar.shade.com.google.common.util.concurrent.AbstractFuture$Waiter",
92+
"org.apache.pulsar.shade.io.netty.buffer.AbstractByteBufAllocator",
93+
"org.apache.pulsar.shade.io.netty.buffer.AbstractReferenceCountedByteBuf",
94+
"org.apache.pulsar.shade.io.netty.channel.ChannelDuplexHandler",
95+
"org.apache.pulsar.shade.io.netty.channel.ChannelHandlerAdapter",
96+
"org.apache.pulsar.shade.io.netty.channel.ChannelInboundHandlerAdapter",
97+
"org.apache.pulsar.shade.io.netty.channel.ChannelInitializer",
98+
"org.apache.pulsar.shade.io.netty.channel.ChannelOutboundHandlerAdapter",
99+
"org.apache.pulsar.shade.io.netty.channel.CombinedChannelDuplexHandler",
100+
"org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$HeadContext",
101+
"org.apache.pulsar.shade.io.netty.channel.DefaultChannelPipeline$TailContext",
102+
"org.apache.pulsar.shade.io.netty.channel.DefaultFileRegion",
103+
"org.apache.pulsar.shade.io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket",
104+
"org.apache.pulsar.shade.io.netty.channel.socket.nio.NioDatagramChannel",
105+
"org.apache.pulsar.shade.io.netty.channel.socket.nio.NioSocketChannel",
106+
"org.apache.pulsar.shade.io.netty.channel.unix.PeerCredentials",
107+
"org.apache.pulsar.shade.io.netty.handler.codec.ByteToMessageDecoder",
108+
"org.apache.pulsar.shade.io.netty.handler.codec.LengthFieldBasedFrameDecoder",
109+
"org.apache.pulsar.shade.io.netty.handler.codec.MessageToMessageDecoder",
110+
"org.apache.pulsar.shade.io.netty.handler.codec.MessageToMessageEncoder",
111+
"org.apache.pulsar.shade.io.netty.handler.codec.dns.DatagramDnsQueryEncoder",
112+
"org.apache.pulsar.shade.io.netty.handler.codec.http.HttpClientCodec",
113+
"org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecoder",
114+
"org.apache.pulsar.shade.io.netty.handler.codec.http.HttpContentDecompressor",
115+
"org.apache.pulsar.shade.io.netty.handler.flush.FlushConsolidationHandler",
116+
"org.apache.pulsar.shade.io.netty.handler.stream.ChunkedWriteHandler",
117+
"org.apache.pulsar.shade.io.netty.resolver.dns.DnsNameResolver$1",
118+
"org.apache.pulsar.shade.io.netty.resolver.dns.DnsNameResolver$3",
119+
"org.apache.pulsar.shade.io.netty.resolver.dns.DnsNameResolver$DnsResponseHandler",
120+
"org.apache.pulsar.shade.io.netty.util.AbstractReferenceCounted",
121+
"org.apache.pulsar.shade.io.netty.util.ReferenceCountUtil",
82122
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields",
123+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields",
124+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
125+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
126+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
127+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
128+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField",
129+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField",
130+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField",
83131
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField",
84132
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField",
85-
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField")
86-
.forEach(typeName -> reflectionHints.registerTypeIfPresent(classLoader, typeName,
87-
MemberCategory.DECLARED_FIELDS));
88-
89-
Stream.of("com.github.benmanes.caffeine.cache.SSMSA", "com.github.benmanes.caffeine.cache.PSAMS")
90-
.forEach(typeName -> reflectionHints.registerTypeIfPresent(classLoader, typeName,
91-
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS,
92-
MemberCategory.INTROSPECT_PUBLIC_METHODS));
133+
"org.apache.pulsar.shade.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField",
134+
"org.apache.pulsar.shade.javax.inject.Named",
135+
"org.apache.pulsar.shade.javax.inject.Singleton",
136+
"org.apache.pulsar.shade.org.asynchttpclient.config.AsyncHttpClientConfigDefaults",
137+
"org.apache.pulsar.shade.org.asynchttpclient.config.AsyncHttpClientConfigHelper",
138+
"org.apache.pulsar.shade.org.asynchttpclient.netty.channel.ChannelManager$1",
139+
"org.apache.pulsar.shade.org.asynchttpclient.netty.handler.AsyncHttpClientHandler",
140+
"org.apache.pulsar.shade.org.asynchttpclient.netty.handler.HttpHandler",
141+
"org.apache.pulsar.shade.org.glassfish.hk2.api.DynamicConfigurationService",
142+
"org.apache.pulsar.shade.org.glassfish.hk2.internal.PerThreadContext",
143+
"org.apache.pulsar.shade.org.glassfish.hk2.internal.PerThreadContext",
144+
"org.apache.pulsar.shade.org.glassfish.hk2.utilities.ServiceLocatorUtilities",
145+
"org.apache.pulsar.shade.org.glassfish.jersey.client.ChunkedInputReader",
146+
"org.apache.pulsar.shade.org.glassfish.jersey.client.ClientAsyncExecutor",
147+
"org.apache.pulsar.shade.org.glassfish.jersey.client.ClientBackgroundScheduler",
148+
"org.apache.pulsar.shade.org.glassfish.jersey.client.DefaultClientAsyncExecutorProvider",
149+
"org.apache.pulsar.shade.org.glassfish.jersey.client.DefaultClientBackgroundSchedulerProvider",
150+
"org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyClientBuilder",
151+
"org.apache.pulsar.shade.org.glassfish.jersey.client.JerseyClientBuilder",
152+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.ContextInjectionResolverImpl",
153+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.ContextInjectionResolverImpl",
154+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory",
155+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory",
156+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.Hk2RequestScope",
157+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.Hk2RequestScope",
158+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.InstanceSupplierFactoryBridge",
159+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.JerseyErrorService",
160+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.JerseyErrorService",
161+
"org.apache.pulsar.shade.org.glassfish.jersey.inject.hk2.RequestContext",
162+
"org.apache.pulsar.shade.org.glassfish.jersey.internal.JaxrsProviders",
163+
"org.apache.pulsar.shade.org.glassfish.jersey.internal.RuntimeDelegateImpl",
164+
"org.apache.pulsar.shade.org.glassfish.jersey.internal.RuntimeDelegateImpl",
165+
"org.apache.pulsar.shade.org.glassfish.jersey.internal.config.ExternalPropertiesAutoDiscoverable",
166+
"org.apache.pulsar.shade.org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFeature",
167+
"org.apache.pulsar.shade.org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFeature",
168+
"org.apache.pulsar.shade.org.glassfish.jersey.internal.inject.Custom",
169+
"org.apache.pulsar.shade.org.glassfish.jersey.jackson.JacksonFeature",
170+
"org.apache.pulsar.shade.org.glassfish.jersey.jackson.JacksonFeature",
171+
"org.apache.pulsar.shade.org.glassfish.jersey.jackson.internal.DefaultJacksonJaxbJsonProvider",
172+
"org.apache.pulsar.shade.org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable",
173+
"org.apache.pulsar.shade.org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase",
174+
"org.apache.pulsar.shade.org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider",
175+
"org.apache.pulsar.shade.org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider",
176+
"org.apache.pulsar.shade.org.glassfish.jersey.logging.LoggingFeatureAutoDiscoverable",
177+
"org.apache.pulsar.shade.org.glassfish.jersey.media.multipart.MultiPartFeature",
178+
"org.apache.pulsar.shade.org.glassfish.jersey.media.multipart.MultiPartFeature",
179+
"org.apache.pulsar.shade.org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide",
180+
"org.apache.pulsar.shade.org.glassfish.jersey.media.multipart.internal.MultiPartWriter",
181+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.AbstractFormProvider",
182+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider",
183+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.BasicTypesMessageProvider",
184+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.BasicTypesMessageProvider",
185+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.ByteArrayProvider",
186+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.ByteArrayProvider",
187+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.DataSourceProvider",
188+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.EnumMessageProvider",
189+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.EnumMessageProvider",
190+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.FileProvider",
191+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.FileProvider",
192+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.FormMultivaluedMapProvider",
193+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.FormMultivaluedMapProvider",
194+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.FormProvider",
195+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.FormProvider",
196+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.InputStreamProvider",
197+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.InputStreamProvider",
198+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.ReaderProvider",
199+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.ReaderProvider",
200+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.RenderedImageProvider",
201+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.RenderedImageProvider",
202+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.SourceProvider",
203+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.SourceProvider$DomSourceReader",
204+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.SourceProvider$DomSourceReader",
205+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.SourceProvider$SaxSourceReader",
206+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.SourceProvider$SourceWriter",
207+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.SourceProvider$StreamSourceReader",
208+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.SourceProvider$StreamSourceReader",
209+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.StreamingOutputProvider",
210+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.StringMessageProvider",
211+
"org.apache.pulsar.shade.org.glassfish.jersey.message.internal.StringMessageProvider",
212+
"org.apache.pulsar.shade.org.glassfish.jersey.process.internal.RequestScope",
213+
"org.apache.pulsar.shade.org.glassfish.jersey.spi.AbstractThreadPoolProvider",
214+
"org.apache.pulsar.shade.org.glassfish.jersey.spi.ScheduledThreadPoolExecutorProvider",
215+
"org.apache.pulsar.shade.org.glassfish.jersey.spi.ThreadPoolExecutorProvider",
216+
"org.apache.pulsar.shade.org.jvnet.hk2.internal.DynamicConfigurationServiceImpl",
217+
"org.apache.pulsar.shade.org.jvnet.hk2.internal.DynamicConfigurationServiceImpl",
218+
"org.apache.pulsar.shade.org.jvnet.hk2.internal.ServiceLocatorRuntimeImpl",
219+
"org.apache.pulsar.shade.org.jvnet.hk2.internal.ServiceLocatorRuntimeImpl")
220+
.forEach(type -> reflectionHints.registerTypeIfPresent(classLoader, type,
221+
builder -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
222+
MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS,
223+
MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.DECLARED_CLASSES,
224+
MemberCategory.DECLARED_FIELDS)));
225+
// @formatter:on
93226

94227
// Registering JDK dynamic proxies for these interfaces. Since the Connection
95-
// interface is protected,
96-
// wee need to use the string version of proxy registration. Although the other
97-
// interfaces are public,
98-
// due to ConnectionHandler$Connection being protected forces all of them to be
99-
// registered using the
100-
// string version of the API because all of them need to be registered through a
101-
// single call.
228+
// interface is protected, we need to use the string version of proxy
229+
// registration.
230+
// Although the other interfaces are public, due to ConnectionHandler$Connection
231+
// being protected forces all of them to be registered using the string version
232+
// of the API because all of them need to be registered through a single call.
102233
hints.proxies().registerJdkProxy(TypeReference.of("org.apache.pulsar.shade.io.netty.util.TimerTask"),
103234
TypeReference.of("org.apache.pulsar.client.impl.ConnectionHandler$Connection"),
104235
TypeReference.of("org.apache.pulsar.client.api.Producer"),
105236
TypeReference.of("org.springframework.aop.SpringProxy"),
106237
TypeReference.of("org.springframework.aop.framework.Advised"),
107238
TypeReference.of("org.springframework.core.DecoratingProxy"));
239+
240+
// Register required properties files
241+
hints.resources().registerPatternIfPresent(classLoader, "org/apache/pulsar/shade/org/asynchttpclient/config/",
242+
builder -> builder.includes("*.properties"));
108243
}
109244

110245
}

0 commit comments

Comments
 (0)