File: RESTEasy_Client_Framework.xml

package info (click to toggle)
resteasy 3.6.2-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 34,612 kB
  • sloc: java: 265,492; xml: 27,855; javascript: 405; jsp: 166; python: 101; sh: 15; sql: 3; makefile: 2
file content (924 lines) | stat: -rw-r--r-- 39,147 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
<chapter id="RESTEasy_Client_Framework">
    <title>RESTEasy Client API</title>

    <section>
        <title>JAX-RS 2.0 Client API</title>
        <para>JAX-RS 2.0 introduces a new client API so that you can make http requests to your remote RESTful web services.
        It is a 'fluent' request building API with really 3 main classes:  Client, WebTarget, and Response.  The Client
        interface is a builder of WebTarget instances.  WebTarget represents a distinct URL or URL template from which
        you can build more sub-resource WebTargets or invoke requests on.</para>
        <para>
            There are really two ways to create a Client.  Standard way, or you can use the ResteasyClientBuilder class.
            The advantage of the latter is that it gives you a few more helper methods to configure your client.
        </para>
        <programlisting>
            Client client = ClientBuilder.newClient();
            ... or...
            Client client = ClientBuilder.newBuilder().build();
            WebTarget target = client.target("http://foo.com/resource");
            Response response = target.request().get();
            String value = response.readEntity(String.class);
            response.close();  // You should close connections!

            ResteasyClient client = new ResteasyClientBuilder().build();
            ResteasyWebTarget target = client.target("http://foo.com/resource");
        </programlisting>
        <para>
            RESTEasy will automatically load a set of default providers. (Basically all classes listed in all
            META-INF/services/javax.ws.rs.ext.Providers files).  Additionally, you can manually register other providers,
            filters, and interceptors through the Configuration object provided by the method call Client.configuration().
            Configuration also lets you set various configuration properties that may be needed.
        </para>
        <para>
            Each WebTarget has its own Configuration instance which inherits the components and properties registered with
            its parent.  This allows you to set specific configuration options per target resource.  For example, username
            and password.
        </para>
        
        <para>
        One RESTEasy extension to the client API is the ability to specify that requests should be sent in "chunked" transfer mode.
        There are two ways of doing that. One is to configure an <classname>org.jboss.resteasy.client.jaxrs.ResteasyWebTarget</classname>
        so that all requests to that target are sent in chunked mode:
        </para>
        
        <programlisting>
      ResteasyClient client = new ResteasyClientBuilder().build();
      ResteasyWebTarget target = client.target("http://localhost:8081/test");
      target.setChunked(b.booleanValue());
      Invocation.Builder request = target.request();
        </programlisting>
        
        <para>
        Alternatively, it is possible to configure a particular request to be sent in chunked mode:
        </para>
        
        <programlisting>
      ResteasyClient client = new ResteasyClientBuilder().build();
      ResteasyWebTarget target = client.target("http://localhost:8081/test");
      ClientInvocationBuilder request = (ClientInvocationBuilder) target.request();
      request.setChunked(b);
        </programlisting>
        
        <para>
        Note that <classname>org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder</classname>,
        unlike <classname>javax.ws.rs.client.Invocation.Builder</classname>, is a RESTEasy class.
        </para>
        
        <para>
        <emphasis role="bold">Note. </emphasis> The ability to send in chunked mode depends on the underlying
        transport layer; in particular, it depends on which implementation of
        <classname>org.jboss.resteasy.client.jaxrs.ClientHttpEngine</classname> is being used. Currently,
        only the default implementation, <classname>ApacheHttpClient43Engine</classname>
        and the older <classname>ApacheHttpClient4Engine</classname>, both in package
        <classname>org.jboss.resteasy.client.jaxrs.engines</classname>,
        support chunked mode. See Section <link linkend='transport_layer'>Apache HTTP Client 4.x and other backends</link>
        for more information.
        </para>
    </section>
    <para>

    </para>

    <section id="proxies">
        <title>RESTEasy Proxy Framework</title>
    <para>

        The RESTEasy Proxy  Framework is the mirror opposite of the JAX-RS server-side specification. Instead of using
        JAX-RS annotations to map an incoming request to your RESTFul Web Service method, the client framework builds an
        HTTP request that it uses to invoke on a remote RESTful Web Service. This remote service does not have to be a
        JAX-RS service and can be any web resource that accepts HTTP requests.
    </para>
    <para>

        RESTEasy has a client proxy framework that allows you to use JAX-RS annotations to invoke on a remote HTTP
        resource.
        The way it works is that you write a Java interface and use JAX-RS annotations on methods and the interface. For
        example:
    </para>
    <para>

<programlisting>
public interface SimpleClient
{
   @GET
   @Path("basic")
   @Produces("text/plain")
   String getBasic();

   @PUT
   @Path("basic")
   @Consumes("text/plain")
   void putBasic(String body);

   @GET
   @Path("queryParam")
   @Produces("text/plain")
   String getQueryParam(@QueryParam("param")String param);

   @GET
   @Path("matrixParam")
   @Produces("text/plain")
   String getMatrixParam(@MatrixParam("param")String param);

   @GET
   @Path("uriParam/{param}")
   @Produces("text/plain")
   int getUriParam(@PathParam("param")int param);
}</programlisting>
    </para>
    <para>

        RESTEasy has a simple API based on Apache HttpClient. You generate a proxy then you can invoke methods on the
        proxy. The invoked method gets translated to an HTTP request based on how you annotated the method and posted to
        the server. Here's how you would set this up:
    </para>
    <para>

        <programlisting>
            Client client = ClientBuilder.newClient();
            WebTarget target = client.target("http://example.com/base/uri");
            ResteasyWebTarget rtarget = (ResteasyWebTarget)target;

            SimpleClient simple = rtarget.proxy(SimpleClient.class);
            client.putBasic("hello world");
        </programlisting>
        Alternatively you can use the RESTEasy client extension interfaces directly:
        <programlisting>
            ResteasyClient client = new ResteasyClientBuilder().build();
            ResteasyWebTarget target = client.target("http://example.com/base/uri");

            SimpleClient simple = target.proxy(SimpleClient.class);
            client.putBasic("hello world");
        </programlisting>

    </para>
    <para>

        @CookieParam works the mirror opposite of its server-side counterpart and creates a cookie header to send to the
        server. You do not need to use @CookieParam if you allocate your own javax.ws.rs.core.Cookie object and pass it
        as
        a parameter to a client proxy method. The client framework understands that you are passing a cookie to the
        server
        so no extra metadata is needed.
    </para>
    <para>
     The framework also supports the JAX-RS locator pattern, but on the client side.  So, if you have a method annotated only with @Path, that proxy method
     will return a new proxy of the interface returned by that method.
    </para>
    <section id="Custom_client-side_responses">
        <title>Abstract Responses</title>

        <para>

            Sometimes you are interested not only in the response body of a client request, but also either the response
            code and/or response headers. The Client-Proxy framework has two ways to get at this information
        </para>
        <para>


        </para>
        <para>

            You may return a javax.ws.rs.core.Response.Status enumeration from your method calls:
        </para>
        <para>

            <programlisting>
@Path("/")
public interface MyProxy {
   @POST
   Response.Status updateSite(MyPojo pojo);
}
            </programlisting>
        </para>
        <para>

            Internally, after invoking on the server, the client proxy internals will convert the HTTP response code into
            a
            Response.Status enum.
        </para>
        <para>


        </para>
        <para>

            If you are interested in everything, you can get it with the javax.ws.rs.core.Response class:
        </para>
        <para>

            <programlisting>
@Path("/")
public interface LibraryService {

   @GET
   @Produces("application/xml")
   Response getAllBooks();
}</programlisting>
        </para>
     </section>
     
    <section id="Response_proxies">
        <title>Response proxies</title>
        <para>
           A further extension implemented by the RESTEasy client proxy framework is the "response proxy facility",
           where a client proxy method returns an interface that represents the information
           contained in a <classname>javax.ws.rs.core.Response</classname>. Such an interface must be annotated with
           <classname>@ResponseObject</classname> from package <classname>org.jboss.resteasy.annotations</classname>,
           and its methods may be further annotated with <classname>@Body</classname>, <classname>@LinkHeaderParam</classname>,
           and <classname>@Status</classname> from the same package,  as well as <classname>javax.ws.rs.HeaderParam</classname>.
           Consider the following example.
        </para>
        
        <programlisting>
   @ResponseObject
   public interface TestResponseObject {
      
      @Status
      int status();

      @Body
      String body();

      @HeaderParam("Content-Type")
      String contentType();
      
      ClientResponse response();
   }

   @Path("test")
   public interface TestClient {
   
      @GET
      TestResponseObject get();
   }

   @Path("test")
   public static class TestResource {

      @GET
      @Produces("text/plain")
      public String get() {
         return "ABC";
      }
   }
        </programlisting>
        
        <para>
           Here, <classname>TestClient</classname> will define the client side proxy for <classname>TestResource</classname>.
           Note that <methodname>TestResource.get()</methodname> returns a <classname>String</classname> but the proxy
           based on <classname>TestClient</classname> will return a <classname>TestResponseObject</classname> on a 
           call to <methodname>get()</methodname>:
        </para>

        <programlisting>
      Client client = ClientBuilder.newClient();
      TestClient ClientInterface = ProxyBuilder.builder(TestClient.class, client.target("http://localhost:8081")).build();
      TestResponseObject tro = ClientInterface.get();
        </programlisting>
        
        <para>
           The methods of <classname>TestResponseObject</classname> provide access to various pieces of information about the
           response received from <methodname>TestResponse.get()</methodname>. This is where the annotations on those methods
           come into play. <methodname>status()</methodname> is annotated with <classname>@Status</classname>, and a call to
           <methodname>status()</methodname> returns the HTTP status. Similarly, <methodname>body()</methodname> returns the
           returned entity, and <methodname>contentType()</methodname> returns the value of the response header Content-Type:
        </para>
        
        <programlisting>
      System.out.println("status: " + tro.status());
      System.out.println("entity: " + tro.body());
      System.out.println("Content-Type: " + tro.contentType());
        </programlisting>
        
        <para>
           will yield
        </para>

        <programlisting>
status: 200
entity: ABC
Content-Type: text/plain;charset=UTF-8        
        </programlisting>
        
        <para>
           Note that there is one other method in <classname>TestResponseObject</classname>, <methodname>response()</methodname>,
           that has no annotation. When RESTEasy sees a method in an interface annotated with <classname>@ResponseObject</classname>
           that returns a <classname>javax.ws.rs.core.Response</classname> (or a subclass thereof), it will return a
           <classname>org.jboss.resteasy.client.jaxrs.internal.ClientResponse</classname>. For example,
        </para>
        
        <programlisting>
      ClientResponse clientResponse =  tro.response();
      System.out.println("Content-Length: " + clientResponse.getLength());
        </programlisting>
        
        <para>
           Perhaps the most interesting piece of the response proxy facility is the treatment of methods 
           annotated with <classname>@LinkHeaderParam</classname>. Its simplest use is to assist in 
           accessing a <classname>javax.ws.rs.core.Link</classname> returned by a resource method. For 
           example, let's add
        </para>
        
        <programlisting>
      @GET
      @Path("/link-header")
      public Response getWithHeader(@Context UriInfo uri) {
         URI subUri = uri.getAbsolutePathBuilder().path("next-link").build();
         Link link = new LinkBuilderImpl().uri(subUri).rel("nextLink").build();
         return Response.noContent().header("Link", link.toString()).build();
      }
        </programlisting>
        
        <para>
           to <classname>TestResource</classname>, add
        </para>
        
        <programlisting>
       @GET
       @Path("link-header")
       ResponseObjectInterface performGetBasedOnHeader();
        </programlisting>
        
        <para>
           to <classname>ClientInterface</classname>, and add
        </para>
        
        <programlisting>
       @LinkHeaderParam(rel = "nextLink")
       URI nextLink();
        </programlisting>
        
        <para>
           to <classname>ResponseObjectInterface</classname>. Then calling       
        </para>
        
        <programlisting>
      ResponseObjectInterface obj = ClientInterface.performGetBasedOnHeader();
      System.out.println("nextLink(): " + obj.nextLink());
        </programlisting>
        
        <para>
           will access the <classname>LinkHeader</classname> returned by <methodname>TestResource.getWithHeader()</methodname>:
        </para>
        
        <programlisting>
nextlink: http://localhost:8081/test/link-header/next-link
        </programlisting>
        
        <para>
           Last but not least, let's add
        </para>
        
        <programlisting>
      @GET
      @Produces("text/plain")
      @Path("/link-header/next-link")
      public String getHeaderForward() {
         return "forwarded";
      }
        </programlisting>
        
        <para>
           to <classname>TestResource</classname> and
        </para>
        
        <programlisting>
       @GET
       @LinkHeaderParam(rel = "nextLink")
       String followNextLink();
        </programlisting>
        
        <para>
           to <classname>ResponseObjectInterface</classname>. Note that, unlike
           <methodname>ResponseObjectInterface.nextLink()</methodname>, <methodname>followNextLink()</methodname>
           is annotated with <classname>@GET</classname>; that is, it qualifies as (the client proxy to) a resource
           method. When executing <methodname>followNextLink()</methodname>, RESTEasy will retrieve the value
           of the <classname>Link</classname> returned by <methodname>TestResource.getWithHeader()</methodname>
           and then will make a GET invocation on the <classname>URL</classname> in that <classname>Link</classname>.
           Calling
        </para>
        
        <programlisting>
      System.out.println("followNextLink(): " + obj.followNextLink());
        </programlisting>
        
        <para>
           causes RESTEasy to retrieve the <classname>URL</classname> http://localhost:8081/test/link-header/next-link
           from the call to <methodname>TestResource.getWithHeader()</methodname> and then perform a GET on it,
           invoking <methodname>TestResource.getHeaderForward()</methodname>:
        </para>
        
        <programlisting>
followNextLink(): forwarded
        </programlisting>
        
        <para><emphasis role="bold">Note.</emphasis> This facility for extracting a <classname>URL</classname>
        and following it is a step toward supporting the Representation State Transfer principle of HATEOAS.
        For more information, see
        <ulink url="http://shop.oreilly.com/product/0636920028925.do">RESTful Java with JAX-RS 2.0, 2nd Edition</ulink>
        by Bill Burke.
        </para>
    </section>
    
    <section id="ClientURI">
      <title>Giving client proxy an ad hoc URI</title>
      
      <para>
          Client proxies figure out appropriate URIs for targeting resource methods by looking at <classname>@Path</classname> 
          annotations in the client side interface, but it is also possible to pass URIs explicitly to the proxy through the
          use of the <classname>org.jboss.resteasy.annotations.ClientURI</classname> annotation. For example, let 
          <classname>TestResource</classname> be a client side interface and <classname>TestResourceImpl</classname> a server resource:
      </para>
      
      <programlisting>
   @Path("")
   public interface TestResource {
      
      @GET
      @Path("dispatch")
      public String dispatch(@ClientURI String uri);
   }
   
   @Path("")
   public static class TestResourceImpl {
      
      @GET
      @Path("a")
      public String a() {
         return "a";
      }
      
      @GET
      @Path("b")
      public String b() {
         return "b";
      }
   }
      </programlisting>
      
      <para>
          Calling <methodname>TestResource.dispatch()</methodname> allows specifying a specific URI for accessing a resource method. In the
          following, let BASE_URL be the address of the <classname>TestResourceImpl</classname> resource.
      </para>
      
      <programlisting>
   private static String BASE_URL = "http://localhost:8081/";
   ...
   public void test() throws Exception
   {
      ResteasyClient client = new ResteasyClientBuilder().build();
      TestResource proxy = client.target(BASE_URL).proxy(TestResource.class);
      String name = proxy.dispatch(BASE_URL + "a");
      System.out.println("name: " + name);
      name = proxy.dispatch(BASE_URL + "b");
      System.out.println("name: " + name);
      client.close();
   }
      </programlisting>
      
      <para>
          Then passing "http://localhost:8081/a" and "http://localhost/b" to <methodname>dispatch()</methodname> invokes
          <methodname>TestResourceImp.a()</methodname> and <methodname>TestResourceImpl.b()</methodname> respectively, yielding
          the output
      </para>
      
      <programlisting>
name: a
name: b
      </programlisting>
    </section>
    
    <section id="Sharing_interfaces">
        <title>Sharing an interface between client and server</title>
        <para>
            It is generally possible to share an interface between the client and server. In this scenario, you just
            have your JAX-RS services implement an annotated interface
            and then reuse that same interface to create client proxies to invoke on the client-side.
        </para>

    </section>
    </section>
    
    
    

   
   <section id="transport_layer">
     <title>Apache HTTP Client 4.x and other backends</title>

       <para>
           Network communication between the client and server is handled by default in RESTEasy.
           The interface between the RESTEasy Client Framework and the network
           is defined by RESTEasy's <code class="classname">ClientHttpEngine</code> interface.
           RESTEasy ships with multiple implementations of this interface.
       </para>
       <para>
           The default
           implementation is <code class="classname">ApacheHttpClient43Engine</code>, which uses
           version 4.3 of the <code class="classname">HttpClient</code> from the Apache
           <code class="classname">HttpComponents</code> project.
           <code class="classname">ApacheHttpClient4Engine</code> is an implementation that
           uses the pre-Apache 4.3 version, to provide backward compatibility.
           RESTEasy automatically selects one of these two
           <code class="classname">ClientHttpEngine</code> implementations based upon the
           detection of the Apache version.
       </para>
       <para>
           <code class="classname">ApacheHttpAsyncClient4Engine</code>, instead, is built on top
           of <emphasis>HttpAsyncClient</emphasis> (still from the Apache
           <emphasis>HttpComponents</emphasis> project) with internally dispatches requests
           using a non-blocking IO model.
       </para>
       <para>
           <code class="classname">JettyClientEngine</code> is built on top
           of <emphasis>Eclipse Jetty</emphasis> HTTP engine, which is possibly an interesting
           option for those already running on the Jetty server.
       </para>
       <para>
           Finally,
           <code class="classname">InMemoryClientEngine</code> is
           an implementation that dispatches requests to a server in the same JVM and
           <code class="classname">URLConnectionEngine</code> is an implementation that uses
           <code class="classname">java.net.HttpURLConnection</code>.
       </para>

       <table frame="topbot">
           <tgroup cols="2" rowsep="1" colsep="1">
               <thead>
                   <row>
                       <entry>RESTEasy ClientHttpEngine implementations</entry>
                       <entry></entry>
                   </row>
               </thead>
               <tbody>
                   <row>
                       <entry>ApacheHttpClient43Engine</entry>
                       <entry>Uses HttpComponents HttpClient 4.3 api</entry>
                   </row>
                   <row>
                       <entry>ApacheHttpClient4Engine</entry>
                       <entry>Uses HttpComponents HttpClient pre-4.3 api</entry>
                   </row>
                   <row>
                       <entry>ApacheHttpAsyncClient4Engine</entry>
                       <entry>Uses HttpComponents HttpAsyncClient</entry>
                   </row>
                   <row>
                       <entry>JettyClientEngine</entry>
                       <entry>Uses Eclipse Jetty</entry>
                   </row>
                   <row>
                       <entry>InMemoryClientEngine</entry>
                       <entry>Dispatches requests to a server in the same JVM</entry>
                   </row>
                   <row>
                       <entry>URLConnectionEngine</entry>
                       <entry>Uses java.net.HttpURLConnection</entry>
                   </row>
               </tbody>
           </tgroup>
       </table>

       <para>
           The RESTEasy Client Framework can also be customized.  The user can provide
           their own implementations of
           <code class="classname">ClientHttpEngine</code> to the
           <code class="classname">ResteasyClient</code>.
       </para>

       <programlisting>
ClientHttpEngine myEngine = new ClientHttpEngine() {
    protected SSLContext sslContext;
    protected HostnameVerifier hostnameVerifier;


    @Override
    public ClientResponse invoke(ClientInvocation request) {
        // implement your processing code and return a
        // org.jboss.resteasy.client.jaxrs.internal.ClientResponse
        // object.
    }

    @Override
    public SSLContext getSslContext() {
       return sslContext;
    }

    @Override
    public HostnameVerifier getHostnameVerifier() {
       return hostnameVerifier;
    }

    @Override
    public void close() {
       // do nothing
    }
};

ResteasyClient client = new RESTEasyClientBuilder().httpEngine(myEngine).build();
       </programlisting>

       <para>
           RESTEasy and <classname>HttpClient</classname> make reasonable default decisions so
           that it is possible to use the client framework without ever referencing
           <classname>HttpClient</classname>. For some applications it may be necessary to drill
           down into the <classname>HttpClient</classname> details.
           <classname>ApacheHttpClient43Engine</classname> and
           <classname>ApacheHttpClient4Engine</classname> can
           be supplied with an instance of
           <classname>org.apache.http.client.HttpClient</classname> and an instance of
           <classname>org.apache.http.protocol.HttpContext</classname>, which can carry
           additional configuration details into the <classname>HttpClient</classname> layer.

       </para>
           <classname>HttpContextProvider</classname>
           is a RESTEasy provided interface through which a custom
           <classname>HttpContext</classname> is supplied to
           <classname>ApacheHttpClient43Engine</classname> and
           <classname>ApacheHttpClient4Engine</classname>.
       <para>

       <programlisting>
package org.jboss.resteasy.client.jaxrs.engines;

import org.apache.http.protocol.HttpContext;

public interface HttpContextProvider {
   HttpContext getContext();
}
       </programlisting>

       </para>

       <para>
           Here is an example of providing a custom HttpContext
       </para>

       <programlisting>
DefaultHttpClient httpClient = new DefaultHttpClient();
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient,
   new HttpContextProvider() {
           @Override
           public HttpContext getContext() {
              // Configure HttpClient to authenticate preemptively
              // by prepopulating the authentication data cache.
              // 1. Create AuthCache instance
              AuthCache authCache = new BasicAuthCache();
              // 2. Generate BASIC scheme object and add it to the local auth cache
              BasicScheme basicAuth = new BasicScheme();
              authCache.put(getHttpHost(url), basicAuth);
              // 3. Add AuthCache to the execution context
              BasicHttpContext localContext = new BasicHttpContext();
              localContext.setAttribute(ClientContext.AUTH_CACHE, authCache);
              return localContext;
           }
});
       </programlisting>

    <section id="http_redirect">
      <title>HTTP redirect</title>
      <para>
         The <classname>ClientHttpEngine</classname> implementations based on Apache
         <classname>HttpClient</classname> support HTTP redirection.
         The feaure is disabled by default and has to be enabled by users explicitly:
         <programlisting>
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine();
engine.setFollowRedirects(true);
Client client = new ResteasyClientBuilder().httpEngine(engine).build();
     </programlisting>
      </para>
    </section>

    <section id="apache_pre_4_3">
        <title>Apache HTTP Client pre-4.3 APIs</title>
     <para>
         The Apache pre-4.3 <classname>HttpClient</classname> implementation uses
         <classname>org.apache.http.impl.conn.SingleClientConnManager</classname>
         to manage a single socket and allows
         <classname>org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager</classname>
         to replace <classname>SingleClientConnManager</classname> for multithreaded applications.
         <classname>SingleClientConnManager</classname> manages a single socket at any given time and
         supports the use case in which one or more invocations are made serially
         from a single thread.
     </para>

     <para>
        Here is an example of replacing the <classname>SingleClientConnManager</classname>
        with <classname>ThreadSafeClientConnManager</classname> in
        <classname>ApacheHttpClient4Engine</classname>.
     </para>
     <programlisting>
ClientConnectionManager cm = new ThreadSafeClientConnManager();
HttpClient httpClient = new DefaultHttpClient(cm);
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
     </programlisting>
     
     <para>
         For more information about HttpClient (4.x), see the documentation
         at <ulink url="http://hc.apache.org/httpcomponents-client-ga/tutorial/html/">
         http://hc.apache.org/httpcomponents-client-ga/tutorial/html/</ulink>.
     </para>
     
     <para>
         <emphasis role="bold">Note.</emphasis> It is important to understand
         the difference between "releasing" a connection and "closing" a
         connection.  <emphasis role="bold">Releasing</emphasis> a connection
         makes it available for reuse.  <emphasis role="bold">Closing</emphasis>
         a connection frees its resources and makes it unusable.
     </para>
     <para>
         <classname>SingleClientConnManager</classname> manages
         a single socket, which it allocates to at most a single invocation
         at any given time.  Before that socket can be reused, it has to be
         released from its current use, which can occur in one of two ways.  If
         an execution of a request or a call on
         a proxy returns a class other than <classname>Response</classname>,
         then RESTEasy will take care of releasing the connection.  For example,
         in the fragments
     </para>
     
     <programlisting>
WebTarget target = client.target("http://localhost:8081/customer/123");
String answer = target.request().get(String.class);
     </programlisting>
     
     <para>
         or
     </para>
     
     <programlisting>
ResteasyWebTarget target = client.target("http://localhost:8081/customer/123");
RegistryStats stats = target.proxy(RegistryStats.class);
RegistryData data = stats.get();
     </programlisting>
     
     <para>
        RESTEasy will release the connection under the covers.  The only counterexample is the case
        in which the response is an instance of <classname>InputStream</classname>, which must
        be closed explicitly.
     </para>
     
     <para>
         On the other hand, if the result of an invocation is an instance of
         <classname>Response</classname>, then Response.close() method must be used to released the connection.
     </para>
     
     <programlisting>
WebTarget target = client.target("http://localhost:8081/customer/123");
Response response = target.request().get();
System.out.println(response.getStatus());
response.close();
     </programlisting>
     
     <para>
         You should probably execute this in a try/finally block.  Again, releasing a connection only makes it available
         for another use. <emphasis role="bold">It does not normally close the socket.</emphasis>
     </para>
         
     <para>
         On the other hand,
         <methodname>ApacheHttpClient4Engine.finalize()</methodname> will close any open
         sockets, but only if it created the <classname>HttpClient</classname> it has been
         using.  If an <classname>HttpClient</classname> has been passed into the
         <classname>ApacheHttpClient4Executor</classname>, then the user is responsible
         for closing the connections:
     </para>
     
     <programlisting>
HttpClient httpClient = new DefaultHttpClient();
ApacheHttpClient4Engine executor = new ApacheHttpClient4Engine(httpClient);
...
httpClient.getConnectionManager().shutdown();
     </programlisting>
     
     <para>
         Note that if <classname>ApacheHttpClient4Engine</classname> has created its own
         instance of <classname>HttpClient</classname>, it is not necessary to wait
         for <methodname>finalize()</methodname> to close open sockets.  The
         <classname>ClientHttpEngine</classname> interface has a <methodname>close()</methodname>
         method for this purpose.
     </para>

    <para>
        Finally, if your javax.ws.rs.client.Client class has created the engine automatically for you, you should
        call Client.close() and this will clean up any socket connections.
    </para>
    </section>

    <section id="apache_4_3">
        <title>Apache HTTP Client 4.3 APIs</title>
        <para>
            The Apache 4.3 <classname>HttpClient</classname> implementation uses
            <classname>org.apache.http.impl.conn.BasicHttpClientConnectionManager</classname>
            to manage a single socket and
            <classname>org.apache.http.impl.conn.PoolingHttpClientConnectionManager</classname>
            to service connection requests from multiple execution threads.
            RESTEasy's <classname>ClientHttpclientBuilder43</classname> and
            <classname>ApacheHttpClient43Engine</classname>
            uses them as well.
        </para>
    </section>

    <section id="apache_asynch">
        <title>Asynchronous HTTP Request Processing</title>
        <para>
            RESTEasy's default async engine implementation class is
            <emphasis>ApacheHttpAsyncClient4Engine</emphasis>.  It can be set as the active
            engine by calling method <emphasis>useAsyncHttpEngine</emphasis> in
            <emphasis>ResteasyClientBuilder</emphasis>.
        </para>
        <programlisting>
    Client asyncClient = new ResteasyClientBuilder().useAsyncHttpEngine()
                             .build();
    Future&lt;Response&gt; future = asyncClient
                             .target("http://locahost:8080/test").request()
                             .async().get();
    Response res = future.get();
    Assert.assertEquals(HttpResponseCodes.SC_OK, res.getStatus());
    String entity = res.readEntity(String.class);
        </programlisting>
        <sect2>
            <title>InvocationCallbacks</title>
            <para>
                InvocationCallbacks are called from within the io-threads and thus must not block or else
                the application may slow down to a halt. Reading the response is safe because the response
                is buffered in memory, as are other async and in-memory client-invocations that submit-calls
                returning a future not containing Response, InputStream or Reader.
            </para>
            <programlisting>
   final CountDownLatch latch = new CountDownLatch(1);
   Future&lt;String&gt; future = nioClient.target(generateURL("/test")).request()
         .async().get(new InvocationCallback&lt;String&gt;()
                {
                   @Override
                   public void completed(String s)
                   {
                      Assert.assertEquals("get", s);
                      latch.countDown();
                      throw new RuntimeException("for the test of it");
                   }

                   @Override
                   public void failed(Throwable error)
                   {
                   }
                });
   String entity = future.get();
   Assert.assertEquals("get", entity);
            </programlisting>
            <para>
                InvocationCallbacks may be called seemingly "after" the future-object returns. Thus, responses
                should be handled solely in the InvocationCallback.
            </para>
            <para>
                InvocationCallbacks will see the same result as the future-object and vice versa. Thus, if the
                invocationcallback throws an exception, the future-object will not see it. This is the
                reason to handle responses only in the InvocationCallback.
            </para>

        </sect2>

        <sect2>
            <title>Async Engine Usage Considerations</title>
            <para>
                Asynchronous IO means non-blocking IO utilizing few threads, typically at most as many
                threads as number of cores.  As such, performance may profit from fewer thread switches
                and less memory usage due to fewer thread-stacks. But doing synchronous, blocking IO (the
                invoke-methods not returning a future) may suffer, because the data has to be transferred
                piecewise to/from the io-threads.
            </para>
            <para>
                Request-Entities are fully buffered in memory, thus <emphasis>HttpAsyncClient</emphasis>
                is unsuitable for very large uploads.  Response-Entities are buffered in memory, except
                if requesting a Response, InputStream or Reader as Result. Thus for large downloads or
                COMET, one of these three return types must be requested, but there may be a performance
                penalty because the response-body is transferred piecewise from the io-threads. When
                using InvocationCallbacks, the response is always fully buffered in memory.
            </para>
        </sect2>
    </section>

    <section id="jetty_client">
        <title>Jetty Client Engine</title>
        <para>
            As a drop in replacement, RESTEasy allows selecting a Jetty 9.4+ based HTTP engine.
            The Jetty implementation is newer and lessl tested, but if may end up being a good choice
            when relying on Jetty as server side already.  The Jetty Server can even share execution
            resources with Client libraries if you configure them to use e.g. the same QueuedThreadPool.
        </para>
        <para>
            The Jetty engine is enabled by adding a dependency to the <emphasis>org.jboss.resteasy:resteasy-client-jetty</emphasis>
            artifact to the Maven project; then the client can be built as follows:
        </para>
        <programlisting>
   ResteasyClient client = new ResteasyClientBuilder().clientEngine(
      new JettyClientEngine(new HttpClient())).build();
        </programlisting>
    </section>

   </section>
   

</chapter>