DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • OWASP TOP 10 API Security Part 2 (Broken Object Level Authorization)
  • Protecting Go Applications: Limiting the Number of Requests and Memory Consumption
  • The Future of Rollouts: From Big Bang to Smart and Secure Approach to Web Application Deployments
  • Mitigate the Risks of Poor Performing Cloud Apps

Trending

  • A Keycloak Example: Building My First MCP Server Tools With Quarkus
  • My Dive into Local LLMs, Part 2: Taming Personal Finance with Homegrown AI (and Why Privacy Matters)
  • Deploying LLMs Across Hybrid Cloud-Fog Topologies Using Progressive Model Pruning
  • Vibe Coding: Conversational Software Development — Part 1 Introduction
  1. DZone
  2. Coding
  3. Languages
  4. Jax-RS 2 and LongPolling based Chat Application

Jax-RS 2 and LongPolling based Chat Application

By 
Altuğ Altıntaş user avatar
Altuğ Altıntaş
·
Jun. 28, 13 · Interview
Likes (0)
Comment
Save
Tweet
Share
7.5K Views

Join the DZone community and get the full member experience.

Join For Free

longpolling ; also known as reverse ajax or comet, is a push method that operates seamlessly in javascript aided web browsers.

although advanced push techniques such as sse and websocket with html 5 are already available, either these technologies are still in the process of development or they are not supported entirely by web browsers, longpolling and similar techniques be in demand.

in longpolling technique, the web browser makes a request to the server, and this request is suspended on the server until a ready response ( resource ) is founded. the pending http request is sent back to the available source web browser when a response is obtained. the web browser transmits a new polling message as soon as it gets the http response, and this process repeats itself until a new http response is ready..

jax-rs-async

from time to time, the failure of the pending polling request originating from server, web browser or current network environment can also be a matter. in this case, web browser takes the error information from the server, sent a request once more and then the polling starts again.

in longpolling technique, xmlhttprequest object which is a javascript object can be used on the web browser side. forthcoming asyncronousresponse objects with jax-rs 2 can be used on the server side in terms of flexibility and convenience.

now, i would like to share with you a chat application instance that contains the association of longpolling technique and jax-rs 2 within java ee 7 .

dependent library

chat application can easily operate on a servlet container, but available container environment must comply with the standard servlet 3 because jax-rs 2 uses forthcoming asynchronous handlers together with servlet 3 on the container.

<dependency>  
 <groupid>org.glassfish.jersey.containers</groupid>  
 <artifactid>jersey-container-servlet</artifactid>  
 <version>2.0</version>  
</dependency>

note:

  • jersey is the reference implementer library of the standard jax-rs. http://jersey.java.net/
  • jetty 9 or tomcat 7 can be used for the servlet 3 support .

entry point of the chat application (rest endpoint)

@applicationpath("app")  
public class app extends application {  
  
@override  
public set<class<?>> getclasses() {  
  
set<class<?>> sets=new hashset<>();  
sets.add(chat.class);  
return sets;  
  
}  
}  

the above application class type object that is wrapped with @applicationpath notation contains the entry point of the chat application. the defined chat class into the hashset is described as a rest resource belonging to the chat application.

chat resource

@path("/chat")  
public class chat {  
  
final static map<string, asyncresponse> waiters = new concurrenthashmap<>();  
final static executorservice ex = executors.newsinglethreadexecutor();  
  
@path("/{nick}")  
@get  
@produces("text/plain")  
public void hangup(@suspended asyncresponse asyncresp, @pathparam("nick") string nick) {  
  
waiters.put(nick, asyncresp);  
}  
  
@path("/{nick}")  
@post  
@produces("text/plain")  
@consumes("text/plain")  
public string sendmessage(final @pathparam("nick") string nick, final string message) {  
  
ex.submit(new runnable() {  
@override  
public void run() {  
set nicks = waiters.keyset();  
for (string n : nicks) {  
// sends message to all, except sender  
if (!n.equalsignorecase(nick))  
waiters.get(n).resume(nick + " said that: " + message);  
}  
}  
});  
  
return "message is sent..";  
}  
}  

asyncresponse type parameter that is found as a parameter on hangup(..) method defines the longpolling response object which will be suspended on the server. while asyncresponse type objects can be provided from jax-rs environment automatically, these suspended objects can be submitted to the user (web browser) as a response  at any time. the second parameter [ @pathparam("nick") string nick ] found on the hangup(..) method obtains the user nick name which is sent to the method on the url.

the information about suspended asyncresponse objects belong to which user is needed subsequently. concurrenthashmap that is a structure of a concurrent map can be used for this purpose. in this way,each nick -> asyncresponse object that is sent to thehangup(..) method will be kept under record.

the second method of the chat class sendmessage(..) can be accessed with http /post method and operates as restful method which derives chat messages from the web browser.

when users submit a chat message with the knowledge of nick name to the server, sendmessage(..) restful method obtains this information from the method parameters, and this information is being transacted as asynchronous through the executorservice object. of course a simple thread can be used instead of executorservice object that is used in here.

just as new thread( new runnable(){ … } ).start(); . the key issue here is the running of the sent message at the background and to prevent the interruption of default /post request, more precisely, to prevent the waiting of message information made push to all users.

the nick -> asyncresponse pair that is filled in the previous hangup(..) method in the concurrenthashmap is consumed into the runnable task object which is found in the sendmessage(..) method, and this chat message is transmitted to all suspended asyncresponse objects except the user itself. the resume() method included in the asyncresponse objects allows the @suspended response object to respond. that is to say, ( suspend ) before, and then ( resume ) when chat message resource become ready.

html components

<!doctype html>  
<html>  
<head>  
<title></title>  
<meta charset="utf-8">  
</head>  
<body>  
<span></span>  
<table>  
<tr class="nick">  
    <td>nick:</td>  
    <td><input id="nick"/></td>  
</tr>  
<tr>  
    <td>message:</td>  
    <td><textarea id="message" disabled="disabled"></textarea></td>  
</tr>  
</table>  
<button>post</button>  
<ul></ul>  
<script src="resources/jquery-1.9.1.js" type="text/javascript"></script>  
<script type="text/javascript" src="resources/chat.js"></script>  
</body>  
</html>  

in the above html page, there are a nick input object, a text area object where the message will be entered and an html button where the message will be sent and these are lined in an html table object. the textarea is made as disabled initially because it is expected to enter the nick name firstly from the user when the application is started. when the user sends the first request (nick name), unchangeable state of this field is modified and is made message writable. also, when nick name is sent to the server (i.e. when the first polling request is made), html table row element which is a class type (
<tr>
) is hidden.

chat application is required to provide xmlhttprequest objects and http requests as asynchronous. in this application we will benefit from jquery ajax library which facilitates these operations and uses xmlhttprequest objects in the background. in addition to jquery dependence, there is a chat.js script that was written by us in the project.

chat.js

// the polling function must be called once,  
//it will call itself recursively in case of error or performance.  
var poolit = function () {  
$.ajax({  
    type: "get",  
    url: "/app/chat/" + $("#nick").val(), // access to the hangup(..) method  
    datatype: "text", // incoming data type text  
    success: function (message) {  
        // the message is added to the <li/> element when it is received.  
        $("ul").append("<li>" + message + "</li>");  
        poolit(); // link to the re-polling when a message is consumed.  
    },  
    error: function () {  
        poolit(); // start re-polling if an error occurs.  
    }  
});  
}  
  
// when the submit button is clicked;  
$("button").click(function () {  
  
if ($(".nick").css("visibility") === "visible") { // if <tr> line is visible;  
    $("textarea").prop("disabled", false); // able to enter data  
    $(".nick").css("visibility", "hidden"); // make <tr> line invisible;  
    $("span").html("chat started..");  // information message  
  
    // polling operation must be initiated at a time  
    poolit();  
}  
else  // if it is not the first time ;  
    $.ajax({  
        type: "post", // http post request  
        url: "/app/chat/" + $("#nick").val(),// access to the sendmessage(..) method.  
        datatype: "text", // incoming data type -> text  
        data: $("textarea").val(), // chat message to send  
        contenttype: "text/plain", // the type of the sent message  
        success: function (data) {  
  
            $("span").html(data); // it writes [message is sent..] if successful.  
  
            // blink effect  
            $("span").fadeout('fast', function () {  
                $(this).fadein('fast');  
            });  
        }  
    });  
});  

testing the application

because the jetty 9.0.0.rc2 plugin is included in the pom.xml configuration file of the application, the application can be easily run with

> mvn jetty:run-war
command. the application can be accessed at http://localhost:8080/ after above goal run.

you can access source code and live example follow the next url => http://en.kodcu.com/2013/06/jax-rs-2-and-longpolling-based-chat-application/

application Object (computer science) Requests

Opinions expressed by DZone contributors are their own.

Related

  • OWASP TOP 10 API Security Part 2 (Broken Object Level Authorization)
  • Protecting Go Applications: Limiting the Number of Requests and Memory Consumption
  • The Future of Rollouts: From Big Bang to Smart and Secure Approach to Web Application Deployments
  • Mitigate the Risks of Poor Performing Cloud Apps

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: