简体   繁体   中英

Multiple servlet request not able to call JMS object's method

I have a JMS object appended to request object and in the doPost() method, the object's get method is being called to get current topic data which will be sent to client in response continuously.

On another user request concurrently, I do not see in the doPost() method, the get message being called or rather am receiving empty/null string from the call.

How to make the method be responsive for concurrent requests/users.

On Debug: While debugging in eclipse, I sometimes see that both threads receive getMessage data alternatively.

<jms:listener-container connection-factory="connectionFactory" task-executor="jmsTaskExecutor" destination-type="topic" concurrency="5">    
    <jms:listener destination="abc.topic" ref="abc" method="receive" />     
</jms:listener-container>

<bean name="jmsTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="2"/>
    <property name="maxPoolSize" value="50"/>       
    <property name="threadNamePrefix" value="some-queue-thread"/>
</bean>

<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="pubSubDomain" value="true"/>
</bean>


@Component("abc")
public class abc {

private String msg;

public synchronized void receive(String msg){       
    this.msg = msg;     
}


public synchronized String getMessage(){        
    return msg;     
}
}

@Component
@Controller
public class ForwardController extends ServletForwardingController
{   
@Autowired
abc topicObject;

@Override   
@RequestMapping("/xyzPath")
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {       
        request.setAttribute("autowired", topicObject);
        request.getRequestDispatcher("/xyz").forward(request, response);
    }        
return null;
}   

@WebServlet("/xyz")
public class xyz extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) {

abc topicObject =  request.getAttribute("autowired");

while(true){        
    System.out.println("start"+Thread.currentThread.getId());
    String msg = topicObject.getMessage();
    response.getWriter.write(msg);
    System.out.println("stop"+Thread.currentThread.getId());
  }
 }
}

What is the right way to call topicObject.getMessage() concurrently

Remove the @Async annotation. I'm not sure what you intended it to do, but it doesn't do that.

From the Javadoc :

However, the return type is constrained to either void or Future .

And from the Spring framework documentation :

The @Async annotation can be provided on a method so that invocation of that method will occur asynchronously. In other words, the caller will return immediately upon invocation and the actual execution of the method will occur in a task that has been submitted to a Spring TaskExecutor.

In other words, with @Async, the code is not executed immediately but later on another thread, but it returns immediately. So for your getMessage , you have provided a return type that is not supported and leads to undefined behaviour (random even, in your case).

For the receive method, this is also not what you want, because it will defer assignment to message .

Solution: Remove both @Async annotations, and make both methods synchronized so that you correctly publish the change to the message variable which makes it visible in all threads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM