Grails & Nexmo plugin - grails

I'm getting errors in Grails integrating Nexmo plugin. The file where the errors occured is 'NexmoService.groovy' as follows:
package grails.plugin.nexmo
import groovyx.net.http.HTTPBuilder
import org.springframework.context.i18n.LocaleContextHolder as LCH
import static groovyx.net.http.ContentType.URLENC
import static groovyx.net.http.Method.POST
class NexmoService {
def grailsApplication
def messageSource
def sendSms(String to, String text, String from=config?.sms?.default_from) throws NexmoException {
if (!to || !text || !from) {
throw new NexmoException(getMessage("nexmo.sms.error.missing.param"))
}
def http = new HTTPBuilder(config?.endpoint)
def requestBody = [to: to, text: text, from: from, api_key: config?.api?.key, api_secret: config?.api?.secret]
http.request(POST) {
uri.path = "/sms/${config?.format}"
send(URLENC, requestBody)
response.success = { resp, data ->
def message = data?.messages[0]
def statusCode = message?.status
if (statusCode != "0") {
def error = getMessage("nexmo.sms.status.${statusCode}", [message?."error-text"], getMessage("nexmo.sms.error.default"))
throw new NexmoException(error)
}
log.info(getMessage("nexmo.sms.success"))
return [status: message?.status, id: message?."message-id"]
}
response.failure = { resp, data ->
def error = getMessage("nexmo.sms.error.response", [resp?.status], getMessage("nexmo.sms.error.default"))
throw new NexmoException(error)
}
}
}
def call(String to, String text, String from="") throws NexmoException {
if (!to || !text) {
throw new NexmoException(getMessage("nexmo.call.error.missing.param"))
}
def http = new HTTPBuilder(config?.endpoint)
def requestBody = [to: to, text: text, from: from, api_key: config?.api?.key, api_secret: config?.api?.secret]
http.request(POST) {
uri.path = "/tts/${config?.format}"
send(URLENC, requestBody)
response.success = { resp, data ->
def statusCode = data?.status
if (statusCode != "0") {
def error = getMessage("nexmo.call.status.${statusCode}", [data?."error-text"], getMessage("nexmo.call.error.default"))
throw new NexmoException(error)
}
log.info(getMessage("nexmo.call.success"))
return [status: data?.status, id: data?."call-id"]
}
response.failure = { resp, data ->
def error = getMessage("nexmo.call.error.response", [resp?.status], getMessage("nexmo.call.error.default"))
throw new NexmoException(error)
}
}
}
private ConfigObject getConfig() {
return grailsApplication.config?.nexmo
}
private String getMessage(String code, List args=[], String defaultMessage="") {
if (messageSource.resolveCode(code, LCH.locale)) {
return messageSource.getMessage(code, args.toArray(), LCH.locale)
}
return defaultMessage
}
}
The errors are below:
| Error Compilation error: startup failed:
C:\nexmo-master\grails-app\services\grails\plugin\nexmo\NexmoService.groovy:
3: unable to resolve class groovyx.net.http.HTTPBuilder # line 3,
column 1. import groovyx.net.http.HTTPBuilder ^
C:\nexmo-master\grails-app\services\grails\plugin\nexmo\NexmoService.groovy:
6: unable to resolve class groovyx.net.http.ContentType # line 6,
column 1. import static groovyx.net.http.ContentType.URLENC ^
C:\nexmo-master\grails-app\services\grails\plugin\nexmo\NexmoService.groovy:
7: unable to resolve class groovyx.net.http.Method # line 7, column
1. import static groovyx.net.http.Method.POST ^
3 errors

You do not have http-builder library in classpath. Look at this post for instructions to import this library. How to import groovyx.net.http or http://www.groovy-lang.org/mailing-lists.html#nabble-td3995735

Related

GroovyDynamicMethodsInterceptor

is there anyway to use GroovyDynamicMethodsInterceptor in grails 3.0.17.
if not , what can I use instead?
this is part of my code ClinicianService.groovy :
package org.imedcom.server.provider
import org.codehaus.groovy.grails.web.metaclass.GroovyDynamicMethodsInterceptor
import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod
import grails.web.databinding.DataBinder
import org.imedcom.server.core.command.ClinicianCommand
import org.imedcom.server.core.command.CreateClinicianCommand
import org.imedcom.server.core.exception.ClinicianException
import org.imedcom.server.model.*
import org.springframework.transaction.annotation.Transactional
#Transactional
class ClinicianService {
def springSecurityService
def passwordService
ClinicianService() {
GroovyDynamicMethodsInterceptor i = new GroovyDynamicMethodsInterceptor(this)
i.addDynamicMethodInvocation(new BindDynamicMethod())
}
Clinician createClinician(CreateClinicianCommand command) {
def clinicianInstance = new Clinician(command.properties)
clinicianInstance.user = new User(command.properties)
clinicianInstance.user.enabled = true
if (!clinicianInstance.user.validate()) {
clinicianInstance.user.errors.fieldErrors.each {
clinicianInstance.errors.rejectValue("user.${it.field}", it.code, it.arguments, it.defaultMessage)
}
}
if (clinicianInstance.user.save(flush: true) && clinicianInstance.save(flush: true)) {
updateRoleLinks(command.roleIds, clinicianInstance)
updatePatientGroupLinks(command.groupIds, clinicianInstance)
}
return clinicianInstance
}
def updatePatientGroupLinks(List<Long> groupIds, Clinician clinician) {
def oldPatientGroups = Clinician2PatientGroup.findAllByClinician(clinician)*.patientGroup
def newPatientGroups = PatientGroup.findAllByIdInList(groupIds)
newPatientGroups.each { patientGroup ->
Clinician2PatientGroup.link(clinician, patientGroup)
}
def obsoletePatientGroups = oldPatientGroups - newPatientGroups
obsoletePatientGroups.each {
Clinician2PatientGroup.unlink(clinician, it)
}
}
def updateRoleLinks(List<Long> roleIds, Clinician clinician) {
UserRole.removeAll(clinician.user, true)
Role.findAllByIdInList(roleIds).each { role ->
def userRole = new UserRole(user: clinician.user, role: role)
if (!userRole.save()) {
throw new ClinicianException("clinician.could.not.assign.clinician.rights", userRole.errors)
}
}
}
}
and this is my ClinicianController.grroy where I also use
``def clinicianService```
import grails.plugin.springsecurity.annotation.Secured
import org.imedcom.server.core.command.CreateClinicianCommand
import org.imedcom.server.model.Clinician
import org.imedcom.server.model.Clinician2PatientGroup
import org.imedcom.server.core.command.ClinicianCommand
import org.imedcom.server.core.model.types.PermissionName
import org.springframework.dao.DataIntegrityViolationException
#Secured(PermissionName.NONE)
class ClinicianController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def clinicianService
def passwordService
def springSecurityService
def authenticationManager
#Secured(PermissionName.CLINICIAN_CREATE)
def create() {
if (!params.cleartextPassword) {
params.cleartextPassword = passwordService.generateTempPassword()
}
def command = new CreateClinicianCommand()
bindData(command, params, ["action", "controller"])
[cmd: command]
}
#Secured(PermissionName.CLINICIAN_CREATE)
def save(CreateClinicianCommand command) {
if (!command.validate()) {
render(view: "create", model: [cmd: command])
return;
}
def clinicianInstance = clinicianService.createClinician(command)
if (!clinicianInstance.hasErrors()) {
flash.message = message(code: 'default.created.message', args: [message(code: 'clinician.label'), clinicianInstance.firstName])
redirect(action: "show", id: clinicianInstance.id)
} else {
render(view: "create", model: [cmd: command])
}
}
}
and I am also using the clinicianService in other controllers too.
this all was in grails 2.4.4.
If what you want to do is invoke data binding from a Grails Service there are a few ways to do that. One is to implement DataBinder.
import grails.web.databinding.DataBinder
class SomeService implements DataBinder {
def serviceMethod(someMap) {
def obj = new SomeClass()
bindData obj, params
obj
}
}
Another option is to inject the data binder into your service:
import org.grails.databinding.SimpleMapDataBindingSource
class SomeService {
def grailsWebDataBinder
TestObject getNewTestObject(Map someMap) {
def obj = new SomeClass()
grailsWebDataBinder.bind obj, someMap as SimpleMapDataBindingSource
obj
}
}

Logging Http request and response body

I am trying to figure out how to log every request and its associated response that comes into my application. Currently I have created a Grails interceptor that captures the request and response. The issue that I keep running into is if I log the request body before it reaches the controller then the resource is consumed by my logger and request body is null. So I tried logging the request body after it's been processed by the controller. The problem with that is then the input stream is closed and I can no longer access it.
this is my interceptor:
import grails.plugin.springsecurity.SpringSecurityService
import javax.servlet.ServletRequest
class HttpLoggingInterceptor {
SpringSecurityService springSecurityService
HttpLoggingService httpLoggingService
HttpLoggingInterceptor() {
match(controller: "*")
}
boolean before() {
httpLoggingService.logRequest(request, response, springSecurityService.principal)
true
}
}
This is the httpLoggingService:
import grails.transaction.Transactional
import org.apache.commons.io.IOUtils
import org.springframework.security.core.userdetails.User
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletRequestWrapper
import javax.servlet.http.HttpServletResponse
import java.nio.charset.StandardCharsets
#Transactional
class HttpLoggingService {
static final String CR = "\r\n"
def logRequest(HttpServletRequestWrapper request, HttpServletResponse response, User user) {
log.debug("REQUEST:${CR}" +
"Request URL: ${request?.method} ${request?.requestURL}${CR}" +
"Request QueryString: ${request?.queryString}${CR}" +
"Request Body : ${getRequestBody(request)}" +
"Request Client IP: ${request?.remoteAddr}${CR}" +
"Request User: ${getUserInfo(user)}${CR}" +
"Request Headers: ${getRequestHeaders(request)}${CR}" +
"Request Query String Parameters: ${getRequestParameters(request)}${CR}" +
"Response Status: ${response?.status}${CR}" +
"Respones Body: ${getResponseBody(response)}" +
"Response Properties: ${response?.properties}${CR}" +
"Response Headers: ${getResponseHeaders(response)}${CR}" +
CR
)
}
private String getUserInfo(User user) {
String userInfo = null
if (user instanceof CipUserDetails) {
userInfo = "${user?.username} [${user?.fullName}] - ${user?.authorities[0]?.role}"
}
userInfo
}
private String getRequestBody(HttpServletRequestWrapper request) {
String requestBody = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8)
requestBody
}
private String getRequestParameters(HttpServletRequest request) {
Map parameterMap = request?.parameterMap
String parameterString = ""
for (String name : request?.parameterNames) {
parameterString += "${CR} ${name}=${parameterMap?.get(name)}"
}
parameterString
}
private String getRequestHeaders(HttpServletRequest request) {
String parameterString = ""
for (String name : request.headerNames) {
parameterString += "${CR} ${name}=${request?.getHeader(name)}"
}
parameterString
}
private String getResponseHeaders(HttpServletResponse response) {
String parameterString = ""
for (String name : response?.headerNames) {
parameterString += "${CR} ${name}=${response?.getHeader(name)}"
}
parameterString
}
}
Could someone please help me figure out how to do this?

How to properly implement load balancer healthcheck for Grails

I'm working with a Grails 2 application that is deployed to Amazon AWS which uses a software load balancer (ELB). The problem we are having is that the grails application instances are added to the load balancer before the application is fully initialized. It's the resources plugin specifically which serves static assets like javascript, css, images, etc.
The load balancer makes an http request to a 'healthcheck' URL.
GET '/myapp/lbcheck'
LoadBalancerController.groovy:
package myapp
class LoadBalancerController {
def healthService
def healthcheck() {
response.contentType = 'text/plain'
try {
healthService.checkDatabase()
render(status: 200, text: "Up")
}
catch(Exception ex) {
log.error("Error with database healthcheck " + ex)
render(status: 503, text: "Down")
}
}
}
HealthSerivce.groovy
package myapp
import groovy.sql.Sql
class HealthService {
def dataSource
// Either returns true, or throws an Exception
def checkDatabase() {
Sql sql = new Sql(dataSource)
sql.rows("SELECT 429")
sql.close()
return true
}
}
The SQL query clearly isn't enough. It seems like we need to check some other kind of property in the framework to determine that it has been initialized.
You could try setting setting a field on your healthService bean to true inside of BootStrap.groovy. I think that's run after Grails is fully initialized.
package myapp
import groovy.sql.Sql
class HealthService {
def dataSource
def initializationComplete = false
// Either returns true, or throws an Exception
def checkDatabase() {
Sql sql = new Sql(dataSource)
sql.rows("SELECT 429")
sql.close()
return true
}
}
inside BootStrap.groovy:
class BootStrap {
def healthService
def init = { servletContext ->
healthService.initializationComplete = true
}
}
in your LoadBalancerController.groovy:
def healthcheck() {
response.contentType = 'text/plain'
def healthy = false
try {
healthy = healthService.with {
initializationComplete && checkDatabase()
}
}
catch(Exception ex) {
log.error("Error with database healthcheck " + ex)
}
if (healthy) {
render(status: 200, text: "Up")
} else {
render(status: 503, text: "Down")
}
}

Inject services to src/groovy in Grails 3.0.9

I am trying to create an EndPoint file. So I created a file with name ServerEndPointDemo.groovy
package com.akiong
import grails.util.Environment
import grails.util.Holders
import javax.servlet.ServletContext
import javax.servlet.ServletContextEvent
import javax.servlet.ServletContextListener
import javax.servlet.annotation.WebListener
import javax.websocket.EndpointConfig
import javax.websocket.OnClose
import javax.websocket.OnError
import javax.websocket.OnMessage
import javax.websocket.OnOpen
import javax.websocket.Session
import javax.websocket.server.PathParam
import javax.websocket.server.ServerContainer
import javax.websocket.server.ServerEndpoint
import javax.websocket.EncodeException
import javax.servlet.annotation.WebListener
import java.util.concurrent.CopyOnWriteArraySet
#WebListener
#ServerEndpoint(value="/chat/test/{username}")
public class ServerEndPointDemo implements ServletContextListener {
private static HashMap<String, String> usersMap = new HashMap<String, String>();
private static final Set<ServerEndPointDemo> connections = new CopyOnWriteArraySet<>();
private String username
private Session session
#OnOpen
public void handleOpen(Session session,#PathParam("username") String user){
System.out.println("-------------------------------------");
System.out.println(session.getId() + " has opened a connection");
println "user = "+user
connections.add(this);
this.username = user
this.session = session
addUserToMap(username,session.getId())
try{
def ctx = Holders.applicationContext
chatService = ctx.chatService
}
catch (Exception e){
println "e = "+e
}
}
#OnClose
public void handleClose(Session session){
System.out.println("Session " +session.getId()+" has ended");
}
#OnMessage
public String handleMessage(String message,Session session){
chatService.saveSessionAdminJava(session.getId())
}
#OnError
public void handleError(Throwable t){
println "error ~"
}
private void sendMessageToAll(String message){
println "session.size() = "+sessions.size()
for(Session s : sessions){
try {
s.getBasicRemote().sendText(message);
println "sent to session = "+s.getId()
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
`
I tried to use this code for calling a method from service:
try {
def ctx = Holders.applicationContext
chatService = ctx.chatService
} catch (Exception e) {
println "e = " + e
}
This is my service:
package com.akiong.services
import com.akiong.maintenance.Chat
class ChatService {
def serviceMethod() {
}
def saveSessionAdminJava(def sessionJava) {
println "jaln!!!"
def chatInstance = Chat.findByIsAdmin("1")
chatInstance.sessionJava = sessionJava
chatInstance.save(failOnError: true)
}
}
But after I tried to run this code, I'm getting this error:
Error : groovy.lang.MissingPropertyException: No such property: chatService for
class: com.akiong.ServerEndPointDemo
Anyone know how to call a method from service to file in src/groovy?
So here is the problem. The code you written is correct for injecting service:
try {
def ctx = Holders.applicationContext
chatService = ctx.chatService
} catch (Exception e) {
println "e = "+e
}
But the chatService is not defined anywhere in your class. So even if your handleOpen method is invoked there must be MissingPropertyException being thrown but since you have handled the top level Exception class (which should never be encouraged) that exception from your handleOpen method got suppressed.
Now, later in your handleMessage method, the same problem is occurring again of chatService being undefined and hence you are getting the exception you posted in your question.
So, you know the answer now :-) Simply define the chatService in your ServerEndPointDemo class.
Update:
public class ServerEndPointDemo implements ServletContextListener {
private static HashMap<String, String> usersMap = new HashMap<String, String>();
private static final Set<ServerEndPointDemo> connections = new CopyOnWriteArraySet<>();
private String username
private Session session
def chartService // Initialize here
// rest of your code
}
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
class MyClass{
private static final log = LogFactory.getLog(this)
def ctx = AH.application.mainContext
def authService=ctx.authService
def method(){
log.debug "into MyClass method"
}
}

HTTP Status 404 - Grails

I was trying to get into "http://localhost:8080/Twillio/smsService/index" from Grails view.
and I get errors like below.
HTTP Status 404 - "/WEB-INF/grails-app/views/smsService/index.gsp" not found.
My codes used for SmsServiceController.groovy is below.
package twillio
class SmsServiceController {
def index () {}
def smsService
def twilioHttpEndpointBean
def read = { withFormat { html {} } }
def create = { SendSmsCommand cmd ->
def validMessage = cmd.validate();
log.debug "Incoming message is ${validMessage ? 'valid' : 'invalid'}"
log.debug "Format is ${request.format}"
withFormat {
json {
if (validMessage) {
def smsResponse
try {
smsResponse = smsService.send(cmd.destination, cmd.message)
render(contentType: "application/json") {
result(success: true)
}
} catch (Exception e) {
render(contentType: "application/json", status: 500) {
result(success: false, message: e.message)
}
}
} else {
render(contentType: "application/json", status: 500) { result(success: false) }
}
}
}
}
}
class SendSmsCommand {
String destination
String message
static constraints = {
message(size: 1..140)
}
}
You have to place an index.gsp at grails-app/views/smsService/index.gsp

Resources