My code receives the message from the queue multiple time, I want to receive it only one time. How can I do it?

yigibm

I am new, so my question is relatively easy, I guess.

I am using Websphere Application Server platform and default JMS provider to send and receive message from queue. This is how my app looks like:

enter image description here

Saytime is my main servlet which reroute my code to a .jsp file. The "Produce" button sends the app following code and generate the message written in box:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String queueName = "jms/helloqueue";
    Context jndiContext = null;
    QueueConnectionFactory queueConnectionFcatory = null;
    QueueConnection queueConnection = null;
    QueueSession queueSession = null;
    QueueSender queueSender = null;
    Queue queue = null;
    TextMessage textMessage = null;
    response.setContentType("text/html");
    request.setCharacterEncoding("UTF-8"); // To information the that you may use Unicode characters
    response.setCharacterEncoding("UTF-8");
    String txt = request.getParameter("text");
   
    try {
        Properties initialProperties = new Properties();
        initialProperties.put(InitialContext.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
        initialProperties.put(InitialContext.PROVIDER_URL, "iiop://localhost:2810");
        jndiContext = new InitialContext(initialProperties);
    } catch (NamingException e) {
        e.printStackTrace();
        System.exit(1);
    }
    try {
        queueConnectionFcatory = (QueueConnectionFactory) jndiContext.lookup("jms/helloqcf");
        queue = (Queue) jndiContext.lookup(queueName);
    } catch (NamingException e) {
        e.printStackTrace();
        System.exit(1);
    }
    try {
        queueConnection = queueConnectionFcatory.createQueueConnection();
        queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
        queueSender = queueSession.createSender(queue);
        textMessage = queueSession.createTextMessage();
        
        textMessage.setText(txt);
        queueSender.send(textMessage);
        
    } catch (JMSException e) {
        System.out.println("JMS Exception occured: "+ e.getMessage());
    } finally {
        if(queueConnection != null){
            try{
                Thread.sleep(6000);
                queueConnection.close();
            } catch(Exception e){}
        }
    }
    RequestDispatcher rd = request.getRequestDispatcher("saytime");
    rd.forward(request,response);
}

The "Receive" button sends my app to following servlet code and receives the message from queue:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String queueName = "jms/helloqueue";
    Context jndiContext = null;
    QueueConnectionFactory queueConnectionfactory = null;
    QueueConnection queueConnection = null;
    QueueSession queueSession = null;
    QueueReceiver queueReceiver = null;
    Queue queue = null;
    String text = null;

    try {
        Properties initialProperties = new Properties();
        initialProperties.put(InitialContext.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
        initialProperties.put(InitialContext.PROVIDER_URL,"iiop://localhost:2810");
        jndiContext = new InitialContext(initialProperties);
    } catch (NamingException e) {
        System.out.println("JNDI exception occured: " + e.getMessage());
        System.exit(1);
    }

    try {
        queueConnectionfactory = (QueueConnectionFactory) jndiContext.lookup("jms/helloqcf");
        queue = (Queue) jndiContext.lookup(queueName);
    } catch (NamingException e) {
        System.exit(1);
    }
    try {
        queueConnection = queueConnectionfactory.createQueueConnection();
        queueSession = queueConnection.createQueueSession(true,Session.AUTO_ACKNOWLEDGE);
        queueReceiver = queueSession.createReceiver(queue);
        //queueReceiver.setMessageListener(listener);
        queueConnection.start();
        text = queueReceiver.receive().toString();
        
    } catch(JMSException e) {
        System.out.println("Exception occured: "+ e.getMessage());
    } finally {
        if (queueConnection != null) {
            try {
                queueConnection.close();
            } catch (JMSException e) {
            }
        }
    }

    if(text != null) {
        request.setAttribute("message", text.toString());
    }
    RequestDispatcher rd = request.getRequestDispatcher("saytime");
    rd.forward(request,response);
}

After that I print the message with this little code in my .jsp file:

<%
String getValues = (String) request.getAttribute("message");
%>
<%
if (getValues != null) {
    out.println("<p>" + getValues + "</p>");
} else {
    out.println("<p> There is no message </p>");
}
%>

The problem is this: I am able to take my produced message, but the button continues to receive the message till the count on JMSXDeliveryCount hit 5. Mostly JMSXDeliveryCount start with 1 and total I can receive the message 5 times. I want to receive it only once and then message to disappear.

Additionally, I want to know how I can print only my message. I print with additional details like you see in the picture. If it's possible, I don't want that.

I tried to limit redelivery number, but I am unable to come up with right code I guess. Also, I tried to use different acknowledgement mode but, it did not work either.

I got really confused with it, some help would be perfect. Thanks.

Justin Bertram

The problem is you're creating the consumer's session as transacted. See this line:

queueSession = queueConnection.createQueueSession(true,Session.AUTO_ACKNOWLEDGE);

The acknowledgement mode will be ignored since the session is transacted (i.e. you're passing true in the first parameter). This is noted in the documentation which states:

If transacted is set to true then the session will use a local transaction which may subsequently be committed or rolled back by calling the session's commit or rollback methods. The argument acknowledgeMode is ignored.

Therefore, you should either acknowledge the message and commit the session manually, e.g.:

Message message = queueReceiver.receive();
text = message.toString();
message.acknowledge();
queueSession.commit();

Or you should use a non-transacted session and allow the message to be auto-acknowledged according to the acknowledgement mode, e.g.:

queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

Typically transacted sessions are only used when multiple operations (i.e. send and receive) need to be combined together atomically. Since you're only consuming a single message here I would recommend you just use a non-transacted session.

Also, you will eventually want to cache the javax.jms.Connection or perhaps use a connection pool rather than creating a connection, session, & producer/consumer for every message. This is an anti-pattern and should be avoided whenever possible.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How can I flush/empty my UART(RX) each time before I receive a new message?

my code do my print statement for many times ,I want to do it just for one time

How can I read one message at a time from /var/mail

How can i drag and drop multiple widgets at the same time i can drag my labels but want to drag them at the same time

How can I execute some part of code at time that I want?

How can I queue up URLSession.DataTaskPublisher requests so that only one is made at a time?

Python server: How can I continously queue tasks while making sure only one at a time is processed

How do I create a queue system that can be modified in execution time while there are processes launched from this queue

I want to make this code specific to only one role, how can I do it?

i want to toggle between two functions this code works only one time but i want to make it work each time i click

How do I make my multiple choice code written in CSS & JS to only select one option? Currently I can select both

How to I modify my code so I can search for multiple inputs(from the same column) at the same time in Python

If I have multiple clients subscribed to a pusher channel, can I have only one of them receive the message?

How i can show a toast message only one time per click for the current activity

How can I make it so that only one of the draggable objects in my game can be moved at a time?

can I get a data from file only one time in my gem similar to config/initializers in rails?

I want to show a Message to Internet Explorer (10 -11) Only and show it one time a day

How can I make my email show only one time per email?

How do I get my angularjs factory to only fetch http data one time?

How do I tell my graph coloring problem program to only assign color 1 one time?

flutter videoPlayerController.addListener() listening multiple times. how can i listen only one time?

Multiple Adobe Analytic tools in Adobe DTM - how do I only have one fire at a time?

How can i have my code print more than one graph at a time?

Do I need to change source code of my website every time I want to update contents?

How do I return only one element from at a time and and int from range in python for loop

How can I use my local time as the only reference of `ntpd`?

Function is running multiple time as per CPU core(CPU cores = 4 in my case). How can I run function only 1 time?

How can i make one thread out of several run for maximum time(minimum time in waiting queue)?

How can I move only one turtle at a time?