|
40 | 40 | package org.glassfish.jersey.grizzly.connector; |
41 | 41 |
|
42 | 42 | import javax.ws.rs.client.Client; |
| 43 | +import javax.ws.rs.client.Invocation; |
43 | 44 | import javax.ws.rs.core.Configurable; |
44 | 45 | import javax.ws.rs.core.Configuration; |
45 | 46 |
|
| 47 | +import org.glassfish.jersey.client.ClientConfig; |
| 48 | +import org.glassfish.jersey.client.ClientRequest; |
46 | 49 | import org.glassfish.jersey.client.Initializable; |
47 | 50 | import org.glassfish.jersey.client.spi.Connector; |
48 | 51 | import org.glassfish.jersey.client.spi.ConnectorProvider; |
| 52 | +import org.glassfish.jersey.internal.util.Property; |
49 | 53 |
|
50 | 54 | import com.ning.http.client.AsyncHttpClient; |
| 55 | +import com.ning.http.client.AsyncHttpClientConfig; |
| 56 | +import com.ning.http.client.RequestBuilder; |
51 | 57 |
|
52 | 58 | /** |
53 | 59 | * Connector provider for Jersey {@link Connector connectors} that utilize |
|
86 | 92 | * @since 2.5 |
87 | 93 | */ |
88 | 94 | public class GrizzlyConnectorProvider implements ConnectorProvider { |
| 95 | + /** |
| 96 | + * A {@link GrizzlyConnectorProvider.RequestCustomizer request customizer} instance to be used to customize the |
| 97 | + * request. |
| 98 | + * |
| 99 | + * The value MUST be an instance implementing the {@link GrizzlyConnectorProvider.RequestCustomizer} SPI. |
| 100 | + * <p> |
| 101 | + * A default value is not set (is {@code null}). |
| 102 | + * </p> |
| 103 | + * <p> |
| 104 | + * The name of the configuration property is <tt>{@value}</tt>. |
| 105 | + * </p> |
| 106 | + * |
| 107 | + * @see #register(Invocation.Builder, GrizzlyConnectorProvider.RequestCustomizer) |
| 108 | + * @see org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider.RequestCustomizer |
| 109 | + */ |
| 110 | + @Property |
| 111 | + static final String REQUEST_CUSTOMIZER = "jersey.config.grizzly.client.request.customizer"; |
| 112 | + |
| 113 | + private final AsyncClientCustomizer asyncClientCustomizer; |
| 114 | + |
| 115 | + /** |
| 116 | + * A customization SPI for the async client instance underlying Grizzly connectors. |
| 117 | + * <p> |
| 118 | + * An implementation of async client customizer can be |
| 119 | + * registered in a {@code GrizzlyConnectorProvider} |
| 120 | + * {@link GrizzlyConnectorProvider#GrizzlyConnectorProvider(GrizzlyConnectorProvider.AsyncClientCustomizer) constructor}. |
| 121 | + * When a connector instance is then created, the customizer is invoked to update the |
| 122 | + * {@link com.ning.http.client.AsyncHttpClientConfig.Builder underlying async client configuration builder} before the actual |
| 123 | + * configuration instance is built and used to create the async client instance. |
| 124 | + * The customizer thus provides a way how to configure parts of the underlying async client SPI that are not directly |
| 125 | + * exposed in the {@code GrizzlyConnectorProvider} API. |
| 126 | + * </p> |
| 127 | + * |
| 128 | + * @see org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider.RequestCustomizer |
| 129 | + * @since 2.10 |
| 130 | + */ |
| 131 | + public static interface AsyncClientCustomizer { |
| 132 | + /** |
| 133 | + * Customize the underlying asynchronous client configuration builder. |
| 134 | + * <p> |
| 135 | + * The configuration builder instance instance returned from the method will be subsequently used to build the |
| 136 | + * configuration object that configures both the {@link com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider} |
| 137 | + * Grizzly async client provider} as well as the underlying {@link com.ning.http.client.AsyncHttpClient async HTTP |
| 138 | + * client} instance itself. |
| 139 | + * </p> |
| 140 | + * <p> |
| 141 | + * Note that any JAX-RS and Jersey specific configuration updates on the configuration builder happen before this method |
| 142 | + * is invoked. As such, changes made to the configuration builder may override or cancel the effect of the JAX-RS and |
| 143 | + * Jersey specific configuration changes. As such any configuration changes should be made with care and implementers |
| 144 | + * should be aware of possible side effect of their changes. |
| 145 | + * </p> |
| 146 | + * |
| 147 | + * @param client JAX-RS client for which the connector is being created. |
| 148 | + * @param config JAX-RS configuration that was used to initialize connector's configuration. |
| 149 | + * @param configBuilder Async HTTP Client configuration builder that has been initialized based on the JAX-RS |
| 150 | + * configuration. |
| 151 | + * @return Async HTTP Client builder instance to be used to configure the underlying Grizzly provider and async HTTP |
| 152 | + * client instance. Typically, the method returns the same {@code configBuilder} instance that has been passed into |
| 153 | + * the method as an input parameter, but it is not required to do so. |
| 154 | + */ |
| 155 | + public AsyncHttpClientConfig.Builder customize(final Client client, |
| 156 | + final Configuration config, |
| 157 | + final AsyncHttpClientConfig.Builder configBuilder); |
| 158 | + } |
| 159 | + |
| 160 | + /** |
| 161 | + * A customization SPI for the async client request instances. |
| 162 | + * |
| 163 | + * A request customizer can be used to configure Async HTTP Client specific details of the request, which are not directly |
| 164 | + * exposed via the JAX-RS, Jersey or Grizzly connector provider API. |
| 165 | + * <p> |
| 166 | + * Before a request is built and sent for execution, a registered request customizer |
| 167 | + * implementation can update the Async HTTP Client {@link com.ning.http.client.RequestBuilder request builder} used |
| 168 | + * to build the request instance ultimately sent for processing. |
| 169 | + * An instance of the request customizer can be either {@link #register(ClientConfig, RequestCustomizer) registered globally} |
| 170 | + * for all requests by registering the customizer in the Jersey client configuration, or it can be individually |
| 171 | + * {@link #register(Invocation.Builder, RequestCustomizer) registered per request}, by registering it into a specific |
| 172 | + * invocation builder instance. In case of a conflict when one instance is registered globally and another per request, the |
| 173 | + * per request registered customizer takes precedence and the global customizer will be ignored. |
| 174 | + * </p> |
| 175 | + * |
| 176 | + * @see org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider.AsyncClientCustomizer |
| 177 | + * @see #register(org.glassfish.jersey.client.ClientConfig, GrizzlyConnectorProvider.RequestCustomizer) |
| 178 | + * @see #register(Invocation.Builder, GrizzlyConnectorProvider.RequestCustomizer) |
| 179 | + * @since 2.10 |
| 180 | + */ |
| 181 | + public static interface RequestCustomizer { |
| 182 | + /** |
| 183 | + * Customize the underlying Async HTTP Client request builder associated with a specific Jersey client request. |
| 184 | + * <p> |
| 185 | + * The request builder instance returned from the method will be subsequently used to build the actual Async HTTP Client |
| 186 | + * request instance sent for execution. |
| 187 | + * </p> |
| 188 | + * <p> |
| 189 | + * Note that any JAX-RS and Jersey specific request configuration updates on the request builder happen before this |
| 190 | + * method is invoked. As such, changes made to the request builder may override or cancel the effect of the JAX-RS and |
| 191 | + * Jersey specific request configuration changes. As such any request builder changes should be made with care and |
| 192 | + * implementers should be aware of possible side effect of their changes. |
| 193 | + * </p> |
| 194 | + * |
| 195 | + * @param requestContext Jersey client request instance for which the Async HTTP Client request is being built. |
| 196 | + * @param requestBuilder Async HTTP Client request builder for the Jersey request. |
| 197 | + * @return Async HTTP Client request builder instance that will be used to build the actual Async HTTP Client |
| 198 | + * request instance sent for execution. Typically, the method returns the same {@code requestBuilder} instance that |
| 199 | + * has been passed into the method as an input parameter, but it is not required to do so. |
| 200 | + */ |
| 201 | + public RequestBuilder customize(final ClientRequest requestContext, final RequestBuilder requestBuilder); |
| 202 | + } |
| 203 | + |
| 204 | + /** |
| 205 | + * Create new Grizzly Async HTTP Client connector provider. |
| 206 | + */ |
| 207 | + public GrizzlyConnectorProvider() { |
| 208 | + this.asyncClientCustomizer = null; |
| 209 | + } |
| 210 | + |
| 211 | + /** |
| 212 | + * Create new Grizzly Async HTTP Client connector provider with a custom client configuration customizer. |
| 213 | + * |
| 214 | + * @param asyncClientCustomizer Async HTTP Client configuration customizer. |
| 215 | + * @since 2.10 |
| 216 | + */ |
| 217 | + public GrizzlyConnectorProvider(final AsyncClientCustomizer asyncClientCustomizer) { |
| 218 | + this.asyncClientCustomizer = asyncClientCustomizer; |
| 219 | + } |
| 220 | + |
89 | 221 | @Override |
90 | 222 | public Connector getConnector(Client client, Configuration config) { |
91 | | - return new GrizzlyConnector(client, config); |
| 223 | + return new GrizzlyConnector(client, config, asyncClientCustomizer); |
92 | 224 | } |
93 | 225 |
|
94 | 226 | /** |
@@ -124,4 +256,41 @@ public static AsyncHttpClient getHttpClient(Configurable<?> component) { |
124 | 256 |
|
125 | 257 | throw new IllegalArgumentException(LocalizationMessages.EXPECTED_CONNECTOR_PROVIDER_NOT_USED()); |
126 | 258 | } |
| 259 | + |
| 260 | + /** |
| 261 | + * Register a request customizer for a single request. |
| 262 | + * |
| 263 | + * A registered customizer will be used to customize the underlying Async HTTP Client request builder. |
| 264 | + * <p> |
| 265 | + * Invoking this method on an instance that is not configured to use Grizzly Async HTTP Client |
| 266 | + * connector does not have any effect. |
| 267 | + * </p> |
| 268 | + * |
| 269 | + * @param builder JAX-RS request invocation builder. |
| 270 | + * @param customizer request customizer to be registered. |
| 271 | + * @return updated Jersey client config with the Grizzly |
| 272 | + * {@link org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider.RequestCustomizer} attached. |
| 273 | + */ |
| 274 | + public static Invocation.Builder register(Invocation.Builder builder, RequestCustomizer customizer) { |
| 275 | + return builder.property(REQUEST_CUSTOMIZER, customizer); |
| 276 | + } |
| 277 | + |
| 278 | + /** |
| 279 | + * Register a request customizer for a all requests executed by a client instance configured with this client config. |
| 280 | + * |
| 281 | + * A registered customizer will be used to customize underlying Async HTTP Client request builders for all requests created |
| 282 | + * using the Jersey client instance configured with this client config. |
| 283 | + * <p> |
| 284 | + * Invoking this method on an instance that is not configured to use Grizzly Async HTTP Client |
| 285 | + * connector does not have any effect. |
| 286 | + * </p> |
| 287 | + * |
| 288 | + * @param config Jersey client configuration. |
| 289 | + * @param customizer Async HTTP Client configuration customizer. |
| 290 | + * @return updated JAX-RS client invocation builder with the Grizzly |
| 291 | + * {@link org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider.RequestCustomizer RequestCustomizer} attached. |
| 292 | + */ |
| 293 | + public static ClientConfig register(ClientConfig config, RequestCustomizer customizer) { |
| 294 | + return config.property(REQUEST_CUSTOMIZER, customizer); |
| 295 | + } |
127 | 296 | } |
0 commit comments