Error in Grails for interating Nexmo plugin - grails

When I run this code:
package nexmo
class SmsControllerController {
// Inject the service
def nexmoService
def index() {
def smsResult
def callResult
try {
// Send the message "What's up?" to 1-500-123-4567
smsResult = nexmoService.sendSms("61451062006", "What's up?")
// Call the number and tell them a message
callResult = nexmoService.call("61451062006", "Have a great day! Goodbye.")
catch (NexmoException e ) {
// Handle error if failure
}
}
}
}
I get the following error message:
Error Compilation error: startup failed:
C:\nexmo-master\grails-app\controllers\nexmo\SmsController.groovy: 19: unexpected token: catch # line 19, column 13.
catch (NexmoException e ) {
^
How do I resolve this issue?

Try closing the try statement before you the catch statement.
try {
// Send the message "What's up?" to 1-500-123-4567
smsResult = nexmoService.sendSms("61451062006", "What's up?")
// Call the number and tell them a message
callResult = nexmoService.call("61451062006", "Have a great day! Goodbye.")
}
catch (NexmoException e ) {
// Handle error if failure
}

Related

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.

SpringSecurity, how to log failed attempts due to enabled==false, grails 2.5

Our authentication domain object, Operator, as boolean enabled on it.
When we set this to false, SpringSecurity + grails magically fails login attempts with the message "Sorry, your account is disabled".
We want to log such attempts. Presumably, there is some kind of listener or handler, which DOES NOT require us to implement the logic (I.e. grails just informs us that the user was rejected, not that we now have to decide if the user should be rejected or not).
We already log failed password checks, and if they fail because they had too many login attempts - we don't want it to catch those events, just the rejection due to enabled == false.
Yes, you can achieve it easily. First modify your Config.groovy so that it can redirect to a particular action on login failure:
grails.plugin.springsecurity.failureHandler.defaultFailureUrl = "/login/authfail"
// For AJAX based authentication
grails.plugin.springsecurity.failureHandler.ajaxAuthFailUrl = "/login/authfail"
Now define a LoginController with action authfail as following:
def authfail() {
String msg = ""
Exception exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
// print the kind of message you want either due to account locked, enabled = false, password expired = true and others
log.debug "User login failed due to [${exception?.message}]"
if (exception) {
if (exception instanceof AccountExpiredException) {
msg = g.message(code: "springSecurity.errors.login.expired")
} else if (exception instanceof CredentialsExpiredException) {
msg = g.message(code: "springSecurity.errors.login.passwordExpired")
} else if (exception instanceof DisabledException) {
msg = g.message(code: "springSecurity.errors.login.disabled")
} else if (exception instanceof LockedException) {
msg = g.message(code: "springSecurity.errors.login.locked")
} else {
msg = g.message(code: "springSecurity.errors.login.fail")
}
}
// redirect or respond acccordingly
}
Found a solution Solution after RTFM
MySecurityEventListener.groovy:
import org.springframework.context.ApplicationListener
import org.springframework.security.authentication.event. AuthenticationFailureDisabledEvent
class MySecurityEventListener
implements ApplicationListener<AuthenticationFailureDisabledEvent> {
void onApplicationEvent(AuthenticationFailureDisabledEvent event) {
println "DISABLED LOGGON!!!!"
}
}
Config.groovy:
grails.plugin.springsecurity.useSecurityEventListener = true
spring/resource.groovy
import com.nektan.me.bla.MySecurityEventListener
beans = {
mySecurityEventListener(MySecurityEventListener)
}
This prints the message.
However, it is not possible to access the grails services from inside the event listener, the injection does not work. We have a grails service which logs security events to the DB, which we haven't found a way to use from inside this callback.

Setting Calendar property on Domain Object

I came accross an interesting problem in my code today.
I am using Grails 2.2.0.
Here is the code
def user = lookupUserClass().get(params.id)
log.info "[update]user.subscriptionExpiryDate1: " + user.subscriptionExpiryDate
user.subscriptionExpiryDate = Calendar.getInstance();
log.info "[update]user.subscriptionExpiryDate2: " + user.subscriptionExpiryDate
if (user.subscriptionExpiryDate instanceof Calendar ) {
log.error "***** Is A Calendar Instance ***"
} else if (user.subscriptionExpiryDate instanceof String ) {
log.error "***** Is A String Instance ***"
} else {
log.error "***** Is Something else ***"
}
if (!user.save()) {
log.error "[update]Error occured saving user. Errors are: "
user.errors.each { err -> log.error err; }
render view: 'edit', model: buildUserModel(user)
return
} else {
log.info "[update]Successfully saved user"
}
subscriptionExpiryDate is a calendar property in my User object.
When I perform the save I get the following error
Failed to convert property value of type 'java.lang.String' to required type 'java.util.Calendar' for property 'subscriptionExpiryDate'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: 05/03/2013
Could anyone please explain why I would be seeing this error for the above code as nothing is standing out
This question has been resolved as per Andrew's suggestion:
Are you doing any data binding on the user object before the code you pasted? If you are binding to the subscriptionExpiryDate property, you will need a PropertyEditor to do the String -> Calendar conversion

Grails Controller - Could not catch a SocketException

When I try to catch an Exception in a controller method I could not catch SocketException. The controller action looks like:
def updateDeviceStartV1() {
try {
...
response.status = 200;
response.setContentType("application/octet-stream")
response.outputStream << responseService.encryptedResponse // byte[]
}
catch(Exception e) {
log.error "Server faced unexpected exception", e
response.status = 500;
...
}
The SocketException is thrown by line "response.outputStream << responseService.encryptedResponse" because the client unexpectedly close the connection. Nevertheless, this exception is not catched and the console receives standard exception display...
Am I doing something wrong?
I think that if the method where the exception is raised doesn't throw the exception explicitly (with a throws in the signature), it will be thrown as an UndeclaredThrowableException. Then the type in your catch just doesn't match it. Try catching SocketException instead. Or if you can just catch them all using catch(all).
Oh, take a look at this.

Getting details of the error inside a custom error page

I implemented a controller that handles HTTP error codes:
class ErrorController {
// 500
def internalserver = {
}
// 504
def timeout = {
}
// 404
def notfound = {
// just testing the values
log.debug "params: ${params}"
log.debug "response: ${response}"
log.debug "url: ${response.redirectURL}"
log.debug "object: ${response.content}"
}
// 403
def forbidden = {
}
}
Note that i already updated the UrlMappings too.
"500"(controller:'error', action:'internalserver')
"504"(controller:'error', action:'timeout')
"404"(controller:'error', action:'notfound')
"403"(controller:'error', action:'forbidden')
Is there a way to retrieve details inside each action?
i.e. for 404, the URL that was requested. for 500, the exception message or something.
looks like by simply referring to:
grails-app/views/error.gsp
will reveal all needed information.

Resources