jersey
  1. jersey
  2. JERSEY-2447

Asynchronous Processing for Jersey MVC

    Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      As the server-side Java industry matures, Java EE is gradually moving into the realm of very high throughput, low latency systems. One important technique in supporting such systems is better asynchronous processing capabilities. To this end, I want to make sure Jersey MVC can support something like the following:

      @Path("order")
      @GET
      @Produces({"text/html"})
      @Template(name = "order.facelet")
      public void orderDetails(@QueryParam("id") Long id, 
                               @Suspended AsyncResponse asyncResponse) {
          ...
          // Do possibly high-latency work, possibly in a non-blocking fashion, freeing up the request thread.
          asyncResponse.resume(order); // When ready, produce the response that is processed through the template, possibly on a completely separate thread.  
          ...
      }
      

      Reading the current Jersey MVC docs, I am not sure if this will work and I have not tried.

      Do let me know if anything needs to be explained further - I am happy to help.

      Please note that these are purely my personal views and certainly not of Oracle's as a company.

        Activity

        Hide
        Michal Gajdos added a comment -

        Hi Reza,

        based on my experience this use-case works (without facelets of course - they're not supported). I tried similar thing last week and it works like a charm.

        @GET
        @Template(name = "/template.mustache")
        public void get(@QueryParam("limit") @DefaultValue("-1") final int limit,
                        @Suspended final AsyncResponse response) {
        
            final Client client = ClientBuilder
                    .newClient()
                    .register(RomeProvider.class)
                    .register(LoggingFilter.class);
        
            final SortedSet<Entry> entries = Sets.newTreeSet();
        
            Observable
                    .from(uris)
                    .parallel(uriObservable -> uriObservable.map(uri -> client.target(uri).request().get(SyndFeed.class)))
                    .subscribe(
                            feed -> {
                                entries.addAll(feed.getEntries().stream().map(Entry::new).collect(Collectors.toList()));
                            },
                            response::resume,
                            () -> {
                                response.resume(
                                        entries.stream().limit(limit == -1 ? entries.size() : limit).collect(Collectors.toList()));
                            }
                    );
        }
        

        Let me know if you want some specifics or if I can close the issue.

        Show
        Michal Gajdos added a comment - Hi Reza, based on my experience this use-case works (without facelets of course - they're not supported). I tried similar thing last week and it works like a charm. @GET @Template(name = "/template.mustache" ) public void get(@QueryParam( "limit" ) @DefaultValue( "-1" ) final int limit, @Suspended final AsyncResponse response) { final Client client = ClientBuilder .newClient() .register(RomeProvider.class) .register(LoggingFilter.class); final SortedSet<Entry> entries = Sets.newTreeSet(); Observable .from(uris) .parallel(uriObservable -> uriObservable.map(uri -> client.target(uri).request().get(SyndFeed.class))) .subscribe( feed -> { entries.addAll(feed.getEntries().stream().map(Entry:: new ).collect(Collectors.toList())); }, response::resume, () -> { response.resume( entries.stream().limit(limit == -1 ? entries.size() : limit).collect(Collectors.toList())); } ); } Let me know if you want some specifics or if I can close the issue.
        Hide
        reza_rahman added a comment -

        Cool! You can close the issue if you want. I would suggest that a blog entry on this could be very interesting. If you do decide to blog about it, please do let me know so I can feature it on The Aquarium .

        Show
        reza_rahman added a comment - Cool! You can close the issue if you want. I would suggest that a blog entry on this could be very interesting. If you do decide to blog about it, please do let me know so I can feature it on The Aquarium .
        Hide
        Michal Gajdos added a comment -

        Thanks, closing as invalid. I'll try to come up with a blog entry.

        Show
        Michal Gajdos added a comment - Thanks, closing as invalid. I'll try to come up with a blog entry.

          People

          • Assignee:
            Unassigned
            Reporter:
            reza_rahman
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: