Reputation: 2340
I have a simple JMS setup. See the following code:
class ProcessingService{
def jmsService
def theMethod(){
jmsService.send(service:'listening', value);
}
}
@Transactional
static scope = "session"
class ListeningService {
static expose = ['jms']
private int value;
def onMessage(message) {
value = message;
println "Completed ${message}"
}
int getValue(){
return value;
}
}
My question is how do I use the messages delivered from a controller?
Currently I have the following code but I'm not sure this is right since services are designed to be stateless:
class ConsumingController{
def listeningService
def method(){
while(notTimeout){
log.info(listeningService.getValue())
}
}
}
This is my first jms app so please forgive me if the answer seem obvious
Upvotes: 1
Views: 493
Reputation: 2340
An alternative that I got to work for me is using the grails-platform-core plugin using the events api.
http://grailsrocks.github.io/grails-platform-core/
and
http://grails.org/plugin/platform-core
Here's what I'm currently doing:
class ExcelService{
def processMethod(){
while(not done){
//do some processing
event("excelUpdates", completed)
}
}
}
//the controller
class ExcelProcessorService {
@grails.events.Listener
def excelUpdates(Float completed){
println "${completed}% of excel processing task completed"
}
}
I'm not sure how to push the updates to the browser yet or what to do the page is refresh (How to cancel the task) but would post update when I get it done.
Upvotes: 0
Reputation: 606
I would prefer using websockets in this case. Check http://grails.org/plugin/atmosphere
Otherwise I would suggest that you push the data to the database and check the database from the controller instead of checking the service.
Since, you experienced problems in getting atmosphere to work, I would to try to explain how I got it working.
Added a AtmosphereService class (look at the sendData method)
class AtmosphereService implements AtmosphereHandler{
static exposes = ['jms']
static transactional = false
static atmosphere = [mapping: '/atmosphere']
public void sendData(int value, long userId){
Map result = [value: value];
String broadcastChannel = "/$userId/value";
Broadcaster broadcaster = BroadcasterFactory.default.lookup(broadcastChannel, true);
broadcaster.broadcast((result as JSON) as String);
}
public void onRequest(AtmosphereResource resource) throws IOException {
try {
AtmosphereRequest req = resource.request
if (req.method.equalsIgnoreCase("GET")) {
resource.broadcaster = BroadcasterFactory.default.lookup(req.pathInfo, true);
resource.suspend();
} else if (req.method.equalsIgnoreCase("POST")) {
String stuff = req.reader.readLine().trim()
resource.broadcaster = BroadcasterFactory.default.lookup(req.pathInfo, true);
resource.broadcaster.broadcast(stuff);
}
} catch (Exception e) {
log.error("Error in Atmosphere.onRequest", e);
}
}
public void onStateChange(AtmosphereResourceEvent event) throws IOException {
AtmosphereResource r = event.resource
AtmosphereResponse res = r.response
try {
if (event.isSuspended()) {
String body = (event.message) as String;
res.writer.write( body );
switch (r.transport()) {
case TRANSPORT.JSONP:
case TRANSPORT.LONG_POLLING:
event.resource.resume()
break
default:
res.writer.flush()
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("ERROR in onStateChange", e);
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
Add the following js code to listen to the channel "/$userId/value" (Look at the request.onMessage handler)
var contentType = "application/json";
var userId = 12312;
var logLevel = 'debug';
var shared = 'true';
var transport = 'websocket';
var fallbackTransport = 'long-polling';
var socket = $.atmosphere;
var partialUpdateRequest=null;
var atmosphereUrl = BASE_HREF+'/atmosphere';
var request = { url: atmosphereUrl +"/"+userId+"/value",
contentType : contentType,
logLevel : logLevel,
shared : shared,
transport : transport,
fallbackTransport: fallbackTransport
};
request.onMessage = function (response) {
var message = response.responseBody;
try {
var json = jQuery.parseJSON(message);
// do your stuff here.
}catch (e) {
//return;
}
};
socket.subscribe(request);
Upvotes: 1