grails jms onMessage receives message text?? not Message - grails

I have this in my listener service (following doc):
#Queue(name='queue.web.dev')
def onMessage(Message msg) {
println "DEBUG msgCorrelationID :"+msg.getJMSCorrelationID()
}
but on receiving message, I got error:
"No signature of method: java.lang.String.getJMSCorrelationID()"
If I try adding Message to onMessage args like:
def onMessage(Message msg)
I got error:
java.lang.NoSuchMethodException: MessageListenerService$$EnhancerBySpringCGLIB$$4bfa7a63.onMessage(java.lang.String)
Looks to me that onMessage is getting String message text. Is that true? How can I get whole jms.Message then?

Don't know if this is still open but you have to take the object out of the message yourself ..
def messageContents = ((ObjectMessage) message).getObject()
Is that what your looking for ?

Remove the default message converter
jms {
containers {
standard {
messageConverter = null
}
}
}
Check grails jms docs here

Related

Reuse Serilog Templates

Sometimes I need to save the log message to a database.
Getting redundant code like this.
public async Task Timeout(StartSendTradeSaga state, IMessageHandlerContext context)
{
var msg = $"Stale trade: Trade {Data.TradeId} has been awaiting reply for more than one hour";
Log.Error("Stale trade: Trade {TradeId} has been awaiting reply for more than one hour", Data.TradeId);
Data.LogStatus = LogStatus.Error;
Data.LogMessage = msg;
if (Data.SaharaLogId != -1)
{
await SaveLog();
MarkAsComplete();
}
else
{
throw new Exception("Unable to write log to database - missing audit trail id");
}
}
To create the msg I use string interpolation and in the next line I log using the Serilog template syntax.
I log to EleaticSearch in json format. So, I can't use interplolation here.
Looking for suggestions on how to only write the message once.

Use pipeline method in jenkins class

I would like to make a resilient slack notification class for my Jenkins instance.
Currently I just call the slackSend function from the Jenkins slack plugin. However if the call to slack fails, so does my build. This means I have a very hard dependency on Slack that I am not ok with.
I have managed to get the code to work but it is rather ugly and I would like to know if there is a better way to do this.
Firstly I have class defined in src/something/slack/slackHandler.groovy
The code looks a little like this:
package something.slack
public class slackHandler {
private String threadId = ""
private String channelName = ""
private Boolean silent = false
private Closure sender
private Logger logger
public silence(Boolean trigger) {
this.silent = trigger
}
public sendMessage(String msg) {
if (threadId == "") {
def (slackResponse, ok) = this.sendMessageTo(this.channelName, msg)
if (!ok) {
// We have tried to send a on channel. But the send failed so we can not determine the threadId.
// We should at this point store the messages and try send it again on the next call to slack.
return
}
this.setThreadId(slackResponse.threadId)
} else {
def (slackResponse, ok) = this.sendMessageTo(this.threadId, msg)
if (!ok){
// We tried to send on a threadId, it failed. We have the threadId so we can leave the slackResponse alone.
// We should at this point store the messages and try send it again on the next call to slack.
return
}
}
}
public sendMessageTo(String channel, String msg) {
return this.trySend(channel, msg)
}
private trySend(String to, String msg) {
if (this.silent) {
return [[threadId: "nothing"], true]
}
try {
return [sender(to, msg), true]
} catch (e) {
// These do not work :(
println("There wasn an error sending the slack message. Error $e")
println("Message being sent: $msg")
return [null, false]
}
}
}
This is the part I'm not happy about. To use the above code I need to create and pass a closure to send the messages to slack because the slackSend function is not available inside my class. I can not find out how to give it the ability to use this function or access the slack class. The println calls are also not showing up in the Jenkins console which is a problem for this class as the fallback is to log to the console. This makes me think that I am missing some sort of context that I need to give my class.
This is how I currently use the class:
def slackSender = new slackHandler(
[
channelName:"rd-bots",
sender: {to, msg -> return slackSend(channel: to, message: msg)}
]
)
slackSender.sendMessage("Hello :wave:")
Can someone please tell me if the is a way to pass on the context or if what I have done is the only way? Also why don't the println calls appear in the Jenkins log?
You can include a try-catch in your pipeline code around your call to your slack handler.
Here's the documentation for catchError: https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#catcherror-catch-error-and-set-build-result-to-failure
I think it should look something like this in a pipeline:
#Library('shared-lib#main')_
pipeline{
agent any
options {
timestamps()
}
environment {
Custom_Variables = 'stuff'
}
stages{
stage ('blah') {
steps {
catchError{
def slackSender = new slackHandler(
[
channelName:"rd-bots",
sender: {to, msg -> return slackSend(channel: to, message: msg)}
]
)
slackSender.sendMessage("Hello :wave:")
}
}
}
}
}
After a bit of digging and looking at different questions for other things where context is needed I managed to find an answer.
When running in Jenkins the this value will give the context of your running environment. You can pass that on to something else.
Code updated to look like this:
public class slackHandler {
private String threadId = ""
private String channelName = ""
private Boolean silent = false
private ctx
public silence(Boolean trigger) {
this.silent = trigger
}
public setThreadId(String id) {
this.threadId = id
}
public sendMessage(String msg) {
if (threadId == "") {
def (slackResponse, ok) = this.sendMessageTo(this.channelName, msg)
if (!ok) {
// We have tried to send a on channel. But the send failed so we can not determine the threadId.
// We should at this point store the messages and try send it again on the next call to slack.
return
}
this.setThreadId(slackResponse.threadId)
} else {
def (slackResponse, ok) = this.sendMessageTo(this.threadId, msg)
if (!ok){
// We tried to send on a threadId, it failed. We have the threadId so we can leave the slackResponse alone.
// We should at this point store the messages and try send it again on the next call to slack.
return
}
}
}
public sendMessageTo(String channel, String msg) {
return this.trySend(channel, msg)
}
private trySend(String to, String msg) {
if (this.silent) {
return [[threadId: "nothing"], true]
}
def slackResponse = ctx.slackSend(channel: to, message: msg)
if (slackResponse != null) {
return [slackResponse, true]
} else {
ctx.echo("There was an error sending slack message sent: $msg")
return [null, false]
}
}
}
Used like this:
import com.proquoai.slack.slackHandler
def slackSender = new slackHandler(
[
channelName:"trashroom10120123",
ctx: this
]
)
node ('docker') {
stage('Send Slack Messages') {
slackSender.sendMessage("Hello :wave:")
slackSender.sendMessage("It's running :go_dance:")
}
stage('Send out of band messages') {
slackSender.sendMessageTo("rd-bots", ":ship-it:")
}
}
As a side note, the slackSend function appears to swallow the error and simply doesn't return a slackResponse. Therefore using a try/catch block didn't actually help in determining if slack sending failed.

Spray.IO Stop http server with Http.Unbind

I have an app built on spray 1.3.3 and I'm trying to stop http server by sending message.
Official documentation says:
Stopping. To explicitly stop the server, send an Http.Unbind command to
the HttpListener instance (the ActorRef for this instance is available
as the sender of the Http.Bound confirmation event from when the
server was started).
Here is how i the start server:
(IO(Http) ? Http.Bind(httpListener, interface = iface, port = port)).map {
case m: Http.Bound => println(s"Success $iface:$port")
case fail : Http.CommandFailed => println(s"Bad try :(")
}
I tried to send message Http.Unbind to httpListener but with no success. Seems to be it's not that actor
May be i need to extract somehow sender ref of Http.Bound message? But how?
Here is my httpListener's head:
class MyHttpListener extends HttpServiceActor {
import context.dispatcher
def receive = runRoute(
path("shutdown") {
get {
actors.httpListener ! Http.Unbind
complete("Stopping server")
}
}
Anyway, i just want to send http request to /shutdown and have my application be down
The sender of the Bound message should be the Spray listener, so when receiving that message you can capture it.
You did not post your full actor so this is a little different but I hope this helps.
class MyStarter extends Actor {
// this will be the listener
var myListener: ActorRef = _
override def preStart(): Unit = {
implicit val system = context.system
IO(Http) ! Http.Bind(...)
}
override def receive: Receive = {
case msg: Bound =>
// when you receive the Bound message it was sent by the listener
myListener = sender()
...
case ... => ...
}
}

Unable to print error message in foreach in magento admin

Hi i have added a new mas action in the sales order grid which allow create batch invoices.
For this my controler file is
<?php
class Iclp_Batchupdate_IndexController extends Mage_Adminhtml_Controller_Action
public function batchinvoiceAction ()
{
$already = " already ";
$refererUrl = $this->getRequest()->getServer('HTTP_REFERER');
$this->loadLayout();
$this->renderLayout();
$orderIds = explode(",",$this->getRequest()->getParam('order_ids'));
foreach ($orderIds as $orderIdss) {
$order = Mage::getModel('sales/order')->load($orderIdss);
//echo $orderIdss ."<br/>";
//echo "already ".$order->getStatusLabel();
try
{
if(!$order->canInvoice())
{
echo Mage::getSingleton('core/session')->addError($orderIdss.$already.$order->getStatusLabel());
}
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice();
if (!$invoice->getTotalQty()) {
Mage::throwException(Mage::helper('core')->__('Cannot create an invoice without products.'));
}
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_ONLINE);
$invoice->register();
$transactionSave = Mage::getModel('core/resource_transaction')->addObject($invoice)->addObject($invoice->getOrder());
$transactionSave->save();
$order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true)->save();
//echo "Invoice are created";
}
catch (Mage_Core_Exception $e) {
}
}
//A Success Message
Mage::getSingleton('core/session')->addSuccess("Some success message");
//A Error Message
Mage::getSingleton('core/session')->addError("Some error message");
//A Info Message (See link below)
Mage::getSingleton('core/session')->addNotice("This is just a FYI message...");
//These lines are required to get it to work
session_write_close();
$this->getResponse()->setRedirect($refererUrl);
}
}
every thing is working fine but the problem is it is not printing the error message in foreach in above code
if(!$order->canInvoice())
{
echo Mage::getSingleton('core/session')->addError($orderIdss.$already.$order->getStatusLabel());
}
but the bottom error message are displayed properly. MOreover if i extend the class with front-action than it also prints the foreach messages. Please suggest where i am doing the mistake
You should add your errors and messages to admintml/session and not to core/session when you are in adminhtml. That should display the message correctly. You shouldn't need session_write_close();. There is also no need to echo the message, that should be handled automatically by Magento after the redirect.
There is also no need to call $this->loadLayout(); and $this->renderLayout(); because you are redirecting at the end.
Finally, regarding the redirect, you should not read the referrer yourself, Magento can to that for you more reliably. Just use the $this->_redirectReferer(); method instead of $this->getResponse()->setRedirect($refererUrl);.

How to retrieve exact reason of the error from async HttpRequest?

I am trying to figure out how to find out exact reason of (async) HttpRequest (from 'dart:html') failure, and, to be honest, I am a bit lost here.
The onError callback receives only HttpRequestProgressError object, which doesn't have anything useful, and the HttpRequest object itself has "status" set to "0" in case of failure, even console shows "Failed to load resource" with no details.
What I want is to know the exact reason - like "connection refused" or "host name not resolved".
Is this possible at all?
Thank you!
Unfortunately, there is no property to report the error as detailed as you'd like. The reason is that JavaScript doesn't support this.
There are the properties status and statusText on the HttpRequest object (which you could get from your HttpRequestProgressEvent with evt.target, but those represent HTTP status codes. Every other error has the status code 0 - request failed. This could be anything, and the only place to look at is the browser's console, because this is an Exception thrown by the browser.
If your request was synchronous, you could surround the send() with a try-catch. If your request is async, this won't work.
See here
#library('Request');
#import('dart:html');
#import("dart:json");
typedef void RequestHandler(String responseText);
typedef void ErrorHandler(String error);
class ResourceRequest {
XMLHttpRequest request;
RequestHandler _callbackOnSuccess;
ErrorHandler _callbackOnFailure;
ResourceRequest.openGet(String url, RequestHandler callbackOnSuccess, [ErrorHandler callbackOnFailure])
: request = new XMLHttpRequest(),
_callbackOnSuccess = callbackOnSuccess,
_callbackOnFailure = callbackOnFailure {
request.open("GET", url, async : true);
request.on.loadEnd.add((XMLHttpRequestProgressEvent e) => onLoadEnd(e));
}
void send() {
request.send();
}
void onLoadEnd(XMLHttpRequestProgressEvent event) {
if (request.readyState == 4 && request.status == 200) {
_callbackOnSuccess(request.responseText);
} else if (_callbackOnFailure != null) {
_callbackOnFailure(request.statusText);
}
}
}

Resources