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
Related
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
I am trying to make it so that no matter what function of my controller is accessed, if the session has been nulled, it goes back to the log in page after you click ok on a modal that pops up saying the session has expired but I can't quite get it to work. Here are the first few methods of this controller:
def beforeInterceptor = {
[action:this.&checkSession()]
}
def checkSession() {
if (!session.user) {
render text: """<script type="text/javascript"> alert('Session expired. Please log in again.'); window.location.href = data.url;</script>""",
contentType: 'js'
}
}
def index() {
redirect (action: customerLogin)
}
def customerLogin = {
selectedBatch = null
}
def authenticate = {
def user = null
def possibleUsersList = User.findAllWhere(user_name: params.username)
possibleUsersList.each {
if (bcryptService.checkPassword(params.password, it.user_password))
user = it
}
if (user) {
session.user = user
greetingName = user.user_name
render(contentType: 'text/json') {
[success: true, url: createLink(controller: 'customer', action: 'custMainPage')]
}
}
else {
//def messages = ResourceBundle.getBundle('messages')
//def errorstring = bundle.getString("fatcaone.login.error")
//println "Login error: " + ${errorstring}
render (contentType: 'text/json') {
//["message": '<p>code=fatcaone.login.error</p>']
["message": '<p>Login or Password incorrect.</p>']
}
}
}
def logout = {
if (session.user != null) {
flash.message = "Goodbye ${session.user.fullName}"
session.user = null
}
redirect(action: customerLogin)
}
beforeInterceptor has been removed from Grails 3.0.
See https://github.com/grails/grails-core/issues/635 for a discussion of this.
Given that you want to keep your code as it is do:
def beforeInterceptor = {
[action:this.&checkSession()]
}
private def checkSession() {
if (!session.user) {
flash.error = 'Session expired. Please log in again.'
redirect(action: customerLogin)
return false
}
}
def index() {
redirect (action: customerLogin)
}
def customerLogin = {
selectedBatch = null
}
def authenticate = {
def user = null
def possibleUsersList = User.findAllWhere(user_name: params.username)
possibleUsersList.each {
if (bcryptService.checkPassword(params.password, it.user_password))
user = it
}
if (user) {
session.user = user
greetingName = user.user_name
render(contentType: 'text/json') {
[success: true, url: createLink(controller: 'customer', action: 'custMainPage')]
}
}
else {
//def messages = ResourceBundle.getBundle('messages')
//def errorstring = bundle.getString("fatcaone.login.error")
//println "Login error: " + ${errorstring}
render (contentType: 'text/json') {
//["message": '<p>code=fatcaone.login.error</p>']
["message": '<p>Login or Password incorrect.</p>']
}
}
}
def logout = {
if (session.user != null) {
flash.message = "Goodbye ${session.user.fullName}"
session.user = null
}
redirect(action: customerLogin)
}
And in your login page add:
<g:if test="${flash.error}">
<script type="text/javascript">
alert('${flash.error}');
</script>
</g:if>
Check this
def checkSession() {
if (session == null || session["loginId"] == null) {
render text: """<script type="text/javascript"> alert('Session expired. Please log in again.'); window.location.href = "${createLink(controller: 'test',action: 'logout')}";</script>""",
contentType: 'js';
return false;
}
}
I've some troubles with my loginfilter in grails. If there is no session, it redirects me to the login page, but it blocks the css.
class LoginFilters {
def filters = {
loginCheck(controller: '*', action: '*') {
before = {
println("USER: "+session.user)
println("ActionName: "+actionName)
println("Controller: "+controllerName)
if (session.user == null) {
println("Redirecting to Loginpage")
render(view: '/index');
return true
}else{
return true
}
}
}
}
}
Where is my problem?
I need this to render a part of it in a controller like:
class MessageController {
def index = {
def messageMap = listAlli18nMessages() // the question
render (contentType: "text/xml") {
messageMap {key, message ->
..
}
}
}
}
Finally I found an answer - override the default Grails messageSource:
class ExtendedPluginAwareResourceBundleMessageSource extends PluginAwareResourceBundleMessageSource {
Map<String, String> listMessageCodes(Locale locale) {
Properties properties = getMergedProperties(locale).properties
Properties pluginProperties = getMergedPluginProperties(locale).properties
return properties.plus(pluginProperties)
}
}
In grails-app/conf/spring/resources.groovy:
beans = {
messageSource(ExtendedPluginAwareResourceBundleMessageSource) {
basenames = "WEB-INF/grails-app/i18n/messages"
}
}
Corresponding controller code:
class MessageController {
def messageSource
def index = {
def messageMap = messageSource.listMessageCodes(request.locale)
render (contentType: "text/xml") {
messageMap {key, message ->
..
}
}
}
}
The approach you are taking doesn't look to be possible based on the API docs for PluginAwareResourceBundleMessageSource. This will get you close to a solution
class MessageController {
def messageSource
def index = {
Locale locale = new Locale('en');
List codes = ['default.paginate.prev','default.paginate.next','default.boolean.true','default.boolean.false']
def messageMap = messagesForCodes(codes,locale)
render (contentType: "text/xml") {
messageMap {key, message ->
..
}
}
}
private def messagesForCodes(codes, locale){
Map messages = [:]
codes.each{code->
messages[code] = messageSource.getMessage(code,null,locale)
}
messages
}
}
Are there in any idioms in grails which help us with saving domain objects ?
For example
i may want to do something like
if(candidate.hasErrors || !candidate.save)
{
candidate.errors.each {
log it
}
However i do not want to spread the logic across all the places i do domainObject.save.
I also do not want seperate class like say repo to which I pass this domainObject and put in this logic
Thanks
Sudarshan
Here's a service method that I've used to validate and save, but log resolved validation messages on failure. It's helpful to use this instead of just println error or log.warn error since the toString() for error objects is very verbose and you just want to see what would be displayed on the GSP:
class MyService {
def messageSource
def saveOrUpdate(bean, flush = false) {
return validate(bean) ? bean.save(flush: flush) : null
}
boolean validate(bean) {
bean.validate()
if (bean.hasErrors()) {
if (log.isEnabledFor(Level.WARN)) {
def message = new StringBuilder(
"problem ${bean.id ? 'updating' : 'creating'} ${bean.getClass().simpleName}: $bean")
def locale = Locale.getDefault()
for (fieldErrors in bean.errors) {
for (error in fieldErrors.allErrors) {
message.append("\n\t")
message.append(messageSource.getMessage(error, locale))
}
}
log.warn message
}
bean.discard()
return false
}
return true
}
And here's an example in a controller:
class MyController {
def myService
def actionName = {
def thing = new Thing(params)
if (myService.saveOrUpdate(thing)) {
redirect action: 'show', id: thing.id
}
else {
render view: 'create', model: [thing: thing]
}
}
}
Edit: It's also possible to add these methods to the MetaClass, e.g. in BootStrap.groovy:
class BootStrap {
def grailsApplication
def messageSource
def init = { servletContext ->
for (dc in grailsApplication.domainClasses) {
dc.metaClass.saveOrUpdate = { boolean flush = false ->
validateWithWarnings() ? delegate.save(flush: flush) : null
}
dc.metaClass.validateWithWarnings = { ->
delegate.validate()
if (delegate.hasErrors()) {
def message = new StringBuilder(
"problem ${delegate.id ? 'updating' : 'creating'} ${delegate.getClass().simpleName}: $delegate")
def locale = Locale.getDefault()
for (fieldErrors in delegate.errors) {
for (error in fieldErrors.allErrors) {
message.append("\n\t")
message.append(messageSource.getMessage(error, locale))
}
}
log.warn message
delegate.discard()
return false
}
return true
}
}
}
}
This depends on a 'log' variable being in scope, which will be true in any Grails artifact. This changes the controller usage slightly:
class MyController {
def actionName = {
def thing = new Thing(params)
if (thing.saveOrUpdate()) {
redirect action: 'show', id: thing.id
}
else {
render view: 'create', model: [thing: thing]
}
}
}
As a metaclass method it may make more sense to rename it, e.g. saveWithWarnings().