diff --git a/benchmark/src/main/java/com/eatthepath/pushy/apns/ApnsClientBenchmark.java b/benchmark/src/main/java/com/eatthepath/pushy/apns/ApnsClientBenchmark.java index 438d864b1..6ba40b4f7 100644 --- a/benchmark/src/main/java/com/eatthepath/pushy/apns/ApnsClientBenchmark.java +++ b/benchmark/src/main/java/com/eatthepath/pushy/apns/ApnsClientBenchmark.java @@ -44,7 +44,7 @@ @State(Scope.Thread) public class ApnsClientBenchmark { - private NioEventLoopGroup clientEventLoopGroup; + private ApnsClientResources clientResources; private NioEventLoopGroup serverEventLoopGroup; private ApnsClient client; @@ -75,7 +75,7 @@ public class ApnsClientBenchmark { @Setup public void setUp() throws Exception { - this.clientEventLoopGroup = new NioEventLoopGroup(this.concurrentConnections); + this.clientResources = new ApnsClientResources(new NioEventLoopGroup(this.concurrentConnections)); this.serverEventLoopGroup = new NioEventLoopGroup(this.concurrentConnections); final ApnsSigningKey signingKey; @@ -91,7 +91,7 @@ public void setUp() throws Exception { .setConcurrentConnections(this.concurrentConnections) .setSigningKey(signingKey) .setTrustedServerCertificateChain(ApnsClientBenchmark.class.getResourceAsStream(CA_CERTIFICATE_FILENAME)) - .setEventLoopGroup(this.clientEventLoopGroup) + .setApnsClientResources(this.clientResources) .build(); this.server = new BenchmarkApnsServerBuilder() @@ -136,7 +136,7 @@ public void tearDown() throws Exception { this.client.close().get(); this.server.shutdown().get(); - final Future clientShutdownFuture = this.clientEventLoopGroup.shutdownGracefully(); + final Future clientShutdownFuture = this.clientResources.shutdownGracefully(); final Future serverShutdownFuture = this.serverEventLoopGroup.shutdownGracefully(); clientShutdownFuture.await(); diff --git a/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsChannelFactory.java b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsChannelFactory.java index c41b4575b..acd0fd4fc 100644 --- a/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsChannelFactory.java +++ b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsChannelFactory.java @@ -31,8 +31,6 @@ import io.netty.handler.timeout.IdleStateHandler; import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.NoopAddressResolverGroup; -import io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider; -import io.netty.resolver.dns.RoundRobinDnsAddressResolverGroup; import io.netty.util.AttributeKey; import io.netty.util.ReferenceCounted; import io.netty.util.concurrent.Future; @@ -69,7 +67,7 @@ class ApnsChannelFactory implements PooledObjectFactory, Closeable { AttributeKey.valueOf(ApnsChannelFactory.class, "channelReadyPromise"); ApnsChannelFactory(final ApnsClientConfiguration clientConfiguration, - final EventLoopGroup eventLoopGroup) { + final ApnsClientResources clientResources) { this.sslContext = clientConfiguration.getSslContext(); @@ -77,16 +75,12 @@ class ApnsChannelFactory implements PooledObjectFactory, Closeable { ((ReferenceCounted) this.sslContext).retain(); } - if (clientConfiguration.getProxyHandlerFactory().isPresent()) { - this.addressResolverGroup = NoopAddressResolverGroup.INSTANCE; - } else { - this.addressResolverGroup = new RoundRobinDnsAddressResolverGroup( - ClientChannelClassUtil.getDatagramChannelClass(eventLoopGroup), - DefaultDnsServerAddressStreamProvider.INSTANCE); - } + this.addressResolverGroup = clientConfiguration.getProxyHandlerFactory().isPresent() + ? NoopAddressResolverGroup.INSTANCE + : clientResources.getRoundRobinDnsAddressResolverGroup(); this.bootstrapTemplate = new Bootstrap(); - this.bootstrapTemplate.group(eventLoopGroup); + this.bootstrapTemplate.group(clientResources.getEventLoopGroup()); this.bootstrapTemplate.option(ChannelOption.TCP_NODELAY, true); this.bootstrapTemplate.remoteAddress(clientConfiguration.getApnsServerAddress()); this.bootstrapTemplate.resolver(this.addressResolverGroup); diff --git a/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClient.java b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClient.java index cba284ef9..2a0471b16 100644 --- a/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClient.java +++ b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClient.java @@ -25,7 +25,6 @@ import com.eatthepath.pushy.apns.util.concurrent.PushNotificationFuture; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; -import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; @@ -45,12 +44,12 @@ * UserNotifications Framework documentation * for a detailed discussion of the APNs protocol, topics, and certificate/key provisioning.

* - *

Clients are constructed using an {@link ApnsClientBuilder}. Callers may - * optionally specify an {@link EventLoopGroup} when constructing a new client. If no event loop group is specified, - * clients will create and manage their own single-thread event loop group. If many clients are operating in parallel, - * specifying a shared event loop group serves as a mechanism to keep the total number of threads in check. Callers may - * also want to provide a specific event loop group to take advantage of platform-specific features (i.e. - * {@code epoll} or {@code KQueue}).

+ *

Clients are constructed using an {@link ApnsClientBuilder}. Callers may optionally specify a set of + * {@link ApnsClientResources} when constructing a new client. If no client resources are specified, + * clients will create and manage their own resources with a single-thread event loop group. If many clients are + * operating in parallel, specifying a shared ser of resources serves as a mechanism to keep the total number of threads + * in check. Callers may also want to provide a specific event loop group to take advantage of platform-specific + * features (i.e. {@code epoll} or {@code KQueue}).

* *

Callers must either provide an SSL context with the client's certificate or a signing key at client construction * time. If a signing key is provided, the client will use token authentication when sending notifications; otherwise, @@ -67,17 +66,17 @@ * *

APNs clients are intended to be long-lived, persistent resources. They are also inherently thread-safe and can be * shared across many threads in a complex application. Callers must shut them down via the {@link ApnsClient#close()} - * method when they are no longer needed (i.e. when shutting down the entire application). If an event loop group was - * specified at construction time, callers should shut down that event loop group when all clients using that group have - * been disconnected.

+ * method when they are no longer needed (i.e. when shutting down the entire application). If a set of client resources + * was provided at construction time, callers should shut down that resource set when all clients using that group have + * been disconnected (see {@link ApnsClientResources#shutdownGracefully()}).

* * @author Jon Chambers * * @since 0.5 */ public class ApnsClient { - private final EventLoopGroup eventLoopGroup; - private final boolean shouldShutDownEventLoopGroup; + private final ApnsClientResources clientResources; + private final boolean shouldShutDownClientResources; private final ApnsChannelPool channelPool; @@ -122,21 +121,20 @@ public void handleConnectionCreationFailed(final ApnsClient apnsClient) { } } - protected ApnsClient(final ApnsClientConfiguration clientConfiguration, final EventLoopGroup eventLoopGroup) { + ApnsClient(final ApnsClientConfiguration clientConfiguration, final ApnsClientResources clientResources) { - if (eventLoopGroup != null) { - this.eventLoopGroup = eventLoopGroup; - this.shouldShutDownEventLoopGroup = false; + if (clientResources != null) { + this.clientResources = clientResources; + this.shouldShutDownClientResources = false; } else { - this.eventLoopGroup = new NioEventLoopGroup(1); - this.shouldShutDownEventLoopGroup = true; + this.clientResources = new ApnsClientResources(new NioEventLoopGroup(1)); + this.shouldShutDownClientResources = true; } this.metricsListener = clientConfiguration.getMetricsListener() .orElseGet(NoopApnsClientMetricsListener::new); - final ApnsChannelFactory channelFactory = - new ApnsChannelFactory(clientConfiguration, this.eventLoopGroup); + final ApnsChannelFactory channelFactory = new ApnsChannelFactory(clientConfiguration, this.clientResources); final ApnsChannelPoolMetricsListener channelPoolMetricsListener = new ApnsChannelPoolMetricsListener() { @@ -156,7 +154,10 @@ public void handleConnectionCreationFailed() { } }; - this.channelPool = new ApnsChannelPool(channelFactory, clientConfiguration.getConcurrentConnections(), this.eventLoopGroup.next(), channelPoolMetricsListener); + this.channelPool = new ApnsChannelPool(channelFactory, + clientConfiguration.getConcurrentConnections(), + this.clientResources.getEventLoopGroup().next(), + channelPoolMetricsListener); } /** @@ -230,7 +231,7 @@ public PushNotificationFuture * *

The returned {@code Future} will be marked as complete when all connections in this client's pool have closed - * completely and (if no {@code EventLoopGroup} was provided at construction time) the client's event loop group has + * completely and (if no {@code ApnsClientResources} were provided at construction time) the client's resources have * shut down. If the client has already shut down, the returned {@code Future} will be marked as complete * immediately.

* @@ -249,8 +250,8 @@ public CompletableFuture close() { closeFuture = new CompletableFuture<>(); this.channelPool.close().addListener((GenericFutureListener>) closePoolFuture -> { - if (ApnsClient.this.shouldShutDownEventLoopGroup) { - ApnsClient.this.eventLoopGroup.shutdownGracefully().addListener(future -> closeFuture.complete(null)); + if (ApnsClient.this.shouldShutDownClientResources) { + ApnsClient.this.clientResources.shutdownGracefully().addListener(future -> closeFuture.complete(null)); } else { closeFuture.complete(null); } diff --git a/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClientBuilder.java b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClientBuilder.java index 44971304e..58c79f858 100644 --- a/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClientBuilder.java +++ b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClientBuilder.java @@ -24,7 +24,6 @@ import com.eatthepath.pushy.apns.auth.ApnsSigningKey; import com.eatthepath.pushy.apns.proxy.ProxyHandlerFactory; -import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http2.Http2FrameLogger; import io.netty.handler.codec.http2.Http2SecurityUtil; import io.netty.handler.ssl.*; @@ -70,7 +69,7 @@ public class ApnsClientBuilder { private boolean enableHostnameVerification = true; - private EventLoopGroup eventLoopGroup; + private ApnsClientResources apnsClientResources; private int concurrentConnections = 1; @@ -390,24 +389,30 @@ public ApnsClientBuilder setHostnameVerificationEnabled(final boolean hostnameVe } /** - *

Sets the event loop group to be used by the client under construction. If not set (or if {@code null}), the - * client will create and manage its own event loop group.

+ *

Sets the client resources to be used by the client under construction. If not set (or if {@code null}), the + * client will manage its own resources.

* - *

Generally speaking, callers don't need to set event loop groups for clients, but it may be useful to specify - * an event loop group under certain circumstances. In particular, specifying an event loop group that is shared - * among multiple {@code ApnsClient} instances can keep thread counts manageable. Regardless of the number of - * concurrent {@code ApnsClient} instances, callers may also wish to specify an event loop group to take advantage - * of certain platform-specific optimizations (e.g. {@code epoll} or {@code KQueue} event loop groups).

+ *

Callers generally don't need to specify resources groups for clients if they only expect to have a single + * {@code ApnsClient} instance, but may benefit from specifying a shared set of {@code ApnsClientResources} if they + * expect to have multiple concurrent clients. Specifying an event loop group that is shared among multiple + * {@code ApnsClient} instances can keep thread counts in check because each client will not need to create its own + * thread pool. Regardless of the number of concurrent {@code ApnsClient} instances, callers may also wish to + * specify an event loop group to take advantage of certain platform-specific optimizations (e.g. {@code epoll} or + * {@code KQueue} event loop groups).

* - * @param eventLoopGroup the event loop group to use for this client, or {@code null} to let the client manage its - * own event loop group + *

Callers that expect to have multiple concurrent {@code ApnsClient} instances will also benefit from sharing an + * {@code ApnsClientResources} instance between clients because resource sets contain a shared DNS resolver, + * eliminating the need for each client to manage its own DNS connections.

+ * + * @param apnsClientResources the client resources to use for this client, or {@code null} to let the client manage + * its own resources * * @return a reference to this builder * - * @since 0.8 + * @since 0.16 */ - public ApnsClientBuilder setEventLoopGroup(final EventLoopGroup eventLoopGroup) { - this.eventLoopGroup = eventLoopGroup; + public ApnsClientBuilder setApnsClientResources(final ApnsClientResources apnsClientResources) { + this.apnsClientResources = apnsClientResources; return this; } @@ -634,7 +639,7 @@ public ApnsClient build() throws SSLException { this.metricsListener, this.frameLogger); - return new ApnsClient(clientConfiguration, this.eventLoopGroup); + return new ApnsClient(clientConfiguration, this.apnsClientResources); } finally { if (sslContext instanceof ReferenceCounted) { ((ReferenceCounted) sslContext).release(); diff --git a/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClientResources.java b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClientResources.java new file mode 100644 index 000000000..65792a552 --- /dev/null +++ b/pushy/src/main/java/com/eatthepath/pushy/apns/ApnsClientResources.java @@ -0,0 +1,70 @@ +package com.eatthepath.pushy.apns; + +import io.netty.channel.EventLoopGroup; +import io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider; +import io.netty.resolver.dns.RoundRobinDnsAddressResolverGroup; +import io.netty.util.concurrent.Future; + +import java.util.Objects; + +/** + * APNs client resources are bundles of relatively "expensive" objects (thread pools, DNS resolvers, etc.) that can be + * shared between {@link ApnsClient} instances. + * + * @see ApnsClientBuilder#setApnsClientResources(ApnsClientResources) + * + * @author Jon Chambers + * + * @since 0.16 + */ +public class ApnsClientResources { + + private final EventLoopGroup eventLoopGroup; + private final RoundRobinDnsAddressResolverGroup roundRobinDnsAddressResolverGroup; + + /** + * Constructs a new set of client resources that uses the given default event loop group. Clients that use this + * resource set will use the given event loop group for IO operations. + * + * @param eventLoopGroup the event loop group for this set of resources + */ + public ApnsClientResources(final EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = Objects.requireNonNull(eventLoopGroup); + + this.roundRobinDnsAddressResolverGroup = new RoundRobinDnsAddressResolverGroup( + ClientChannelClassUtil.getDatagramChannelClass(eventLoopGroup), + DefaultDnsServerAddressStreamProvider.INSTANCE); + } + + /** + * Returns the event loop group for this resource set. + * + * @return the event loop group for this resource set + */ + public EventLoopGroup getEventLoopGroup() { + return eventLoopGroup; + } + + /** + * Returns the DNS resolver for this resource set. + * + * @return the DNS resolver for this resource set + */ + public RoundRobinDnsAddressResolverGroup getRoundRobinDnsAddressResolverGroup() { + return roundRobinDnsAddressResolverGroup; + } + + /** + * Gracefully shuts down any long-lived resources in this resource group. If callers manage their own + * {@code ApnsClientResources} instances (as opposed to using default resources provided by {@link ApnsClientBuilder}, + * then they must call this method after all clients that use a given set of resources have been shut down. + * + * @return a future that completes once the long-lived resources in this set of resources has finished shutting down + * + * @see ApnsClientBuilder#setApnsClientResources(ApnsClientResources) + */ + public Future shutdownGracefully() { + roundRobinDnsAddressResolverGroup.close(); + return eventLoopGroup.shutdownGracefully(); + } +} diff --git a/pushy/src/test/java/com/eatthepath/pushy/apns/AbstractClientServerTest.java b/pushy/src/test/java/com/eatthepath/pushy/apns/AbstractClientServerTest.java index 8b73fc5f1..36d8aeae3 100644 --- a/pushy/src/test/java/com/eatthepath/pushy/apns/AbstractClientServerTest.java +++ b/pushy/src/test/java/com/eatthepath/pushy/apns/AbstractClientServerTest.java @@ -47,7 +47,7 @@ @Timeout(10) public class AbstractClientServerTest { - protected static NioEventLoopGroup CLIENT_EVENT_LOOP_GROUP; + protected static ApnsClientResources CLIENT_RESOURCES; protected static NioEventLoopGroup SERVER_EVENT_LOOP_GROUP; protected static final String CA_CERTIFICATE_FILENAME = "/ca.pem"; @@ -81,7 +81,7 @@ public class AbstractClientServerTest { @BeforeAll public static void setUpBeforeClass() { - CLIENT_EVENT_LOOP_GROUP = new NioEventLoopGroup(2); + CLIENT_RESOURCES = new ApnsClientResources(new NioEventLoopGroup(2)); SERVER_EVENT_LOOP_GROUP = new NioEventLoopGroup(2); } @@ -100,7 +100,7 @@ public void setUp() throws Exception { @AfterAll public static void tearDownAfterClass() throws Exception { final PromiseCombiner combiner = new PromiseCombiner(ImmediateEventExecutor.INSTANCE); - combiner.addAll(CLIENT_EVENT_LOOP_GROUP.shutdownGracefully(), SERVER_EVENT_LOOP_GROUP.shutdownGracefully()); + combiner.addAll(CLIENT_RESOURCES.shutdownGracefully(), SERVER_EVENT_LOOP_GROUP.shutdownGracefully()); final Promise shutdownPromise = new DefaultPromise<>(GlobalEventExecutor.INSTANCE); combiner.finish(shutdownPromise); @@ -117,7 +117,7 @@ protected ApnsClient buildTlsAuthenticationClient(final ApnsClientMetricsListene .setApnsServer(HOST, PORT) .setClientCredentials(p12InputStream, KEYSTORE_PASSWORD) .setTrustedServerCertificateChain(getClass().getResourceAsStream(CA_CERTIFICATE_FILENAME)) - .setEventLoopGroup(CLIENT_EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setMetricsListener(metricsListener) .build(); } @@ -132,7 +132,7 @@ protected ApnsClient buildTokenAuthenticationClient(final ApnsClientMetricsListe .setApnsServer(HOST, PORT) .setTrustedServerCertificateChain(getClass().getResourceAsStream(CA_CERTIFICATE_FILENAME)) .setSigningKey(this.signingKey) - .setEventLoopGroup(CLIENT_EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setMetricsListener(metricsListener) .build(); } diff --git a/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientBuilderTest.java b/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientBuilderTest.java index da606a97e..b46342dac 100644 --- a/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientBuilderTest.java +++ b/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientBuilderTest.java @@ -44,16 +44,16 @@ public class ApnsClientBuilderTest { private static final String KEYSTORE_PASSWORD = "pushy-test"; - private static NioEventLoopGroup EVENT_LOOP_GROUP; + private static ApnsClientResources CLIENT_RESOURCES; @BeforeAll public static void setUpBeforeClass() { - EVENT_LOOP_GROUP = new NioEventLoopGroup(1); + CLIENT_RESOURCES = new ApnsClientResources(new NioEventLoopGroup(1)); } @AfterAll public static void tearDownAfterClass() throws Exception { - EVENT_LOOP_GROUP.shutdownGracefully().await(); + CLIENT_RESOURCES.shutdownGracefully().await(); } @Test @@ -61,7 +61,7 @@ void testBuildClientWithPasswordProtectedP12File() throws Exception { // We're happy here as long as nothing throws an exception final ApnsClient client = new ApnsClientBuilder() .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST) - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setClientCredentials(new File(this.getClass().getResource(SINGLE_TOPIC_CLIENT_KEYSTORE_FILENAME).toURI()), KEYSTORE_PASSWORD) .build(); @@ -74,7 +74,7 @@ void testBuildClientWithPasswordProtectedP12InputStream() throws Exception { try (final InputStream p12InputStream = this.getClass().getResourceAsStream(SINGLE_TOPIC_CLIENT_KEYSTORE_FILENAME)) { final ApnsClient client = new ApnsClientBuilder() .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST) - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setClientCredentials(p12InputStream, KEYSTORE_PASSWORD) .build(); @@ -85,7 +85,7 @@ void testBuildClientWithPasswordProtectedP12InputStream() throws Exception { @Test void testBuildClientWithNullPassword() { assertThrows(NullPointerException.class, () -> new ApnsClientBuilder() - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setClientCredentials(new File(this.getClass().getResource(SINGLE_TOPIC_CLIENT_KEYSTORE_FILENAME).toURI()), null) .build()); } @@ -99,7 +99,7 @@ void testBuildClientWithCertificateAndPasswordProtectedKey() throws Exception { final ApnsClient client = new ApnsClientBuilder() .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST) - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setClientCredentials((X509Certificate) privateKeyEntry.getCertificate(), privateKeyEntry.getPrivateKey(), KEYSTORE_PASSWORD) .build(); @@ -117,7 +117,7 @@ void testBuildClientWithCertificateAndUnprotectedKey() throws Exception { final ApnsClient client = new ApnsClientBuilder() .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST) - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setClientCredentials((X509Certificate) privateKeyEntry.getCertificate(), privateKeyEntry.getPrivateKey(), null) .build(); @@ -133,7 +133,7 @@ void testBuildWithSigningKey() throws Exception { // We're happy here as long as nothing explodes final ApnsClient client = new ApnsClientBuilder() .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST) - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setSigningKey(signingKey) .build(); @@ -145,7 +145,7 @@ void testBuildWithSigningKey() throws Exception { void testBuildWithoutClientCredentials() { assertThrows(IllegalStateException.class, () -> new ApnsClientBuilder() - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .build()); } @@ -162,7 +162,7 @@ void testBuildWithClientCredentialsAndSigningCertificate() throws Exception { assertThrows(IllegalStateException.class, () -> new ApnsClientBuilder() - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setClientCredentials((X509Certificate) privateKeyEntry.getCertificate(), privateKeyEntry.getPrivateKey(), null) .setSigningKey(signingKey) .build()); @@ -174,7 +174,7 @@ void testBuildWithClientCredentialsAndSigningCertificate() throws Exception { void testBuildWithoutApnsServerAddress() { assertThrows(IllegalStateException.class, () -> new ApnsClientBuilder() - .setEventLoopGroup(EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setClientCredentials(new File(this.getClass().getResource(SINGLE_TOPIC_CLIENT_KEYSTORE_FILENAME).toURI()), KEYSTORE_PASSWORD) .build()); } diff --git a/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientTest.java b/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientTest.java index 9afdafaf7..5ab603a3e 100644 --- a/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientTest.java +++ b/pushy/src/test/java/com/eatthepath/pushy/apns/ApnsClientTest.java @@ -223,14 +223,14 @@ void testSendNotificationToUntrustedServer(final boolean useTokenAuthentication) cautiousClient = new ApnsClientBuilder() .setApnsServer(HOST, PORT) .setSigningKey(this.signingKey) - .setEventLoopGroup(CLIENT_EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .build(); } else { try (final InputStream p12InputStream = getClass().getResourceAsStream(MULTI_TOPIC_CLIENT_KEYSTORE_FILENAME)) { cautiousClient = new ApnsClientBuilder() .setApnsServer(HOST, PORT) .setClientCredentials(p12InputStream, KEYSTORE_PASSWORD) - .setEventLoopGroup(CLIENT_EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .build(); } } @@ -312,7 +312,7 @@ void testSendNotificationToServerWithUntrustedHostnameAndVerificationDisabled() .setApnsServer(HOST, PORT) .setTrustedServerCertificateChain(getClass().getResourceAsStream(CA_CERTIFICATE_FILENAME)) .setSigningKey(this.signingKey) - .setEventLoopGroup(CLIENT_EVENT_LOOP_GROUP) + .setApnsClientResources(CLIENT_RESOURCES) .setHostnameVerificationEnabled(false) .build();