I have and WebFlow in my controller, and simple flow-scoped service. Somewhere close to the end of my web flow, I need to validate my command object field against value I received earlier in the web flow. For this I created a simple flow-scoped service:
class EventFlowService implements Serializable {
static transactional = false
static scope = "flow"
Date getEventStartDate(){
flow.basicData.eventDate
}
}
I don't need my service anywhere else than in a command object, so I inject it to my command object, like so:
class EventRestrictionsCommand implements Serializable{
def eventFlowService
boolean onlineRegistration
Date onlineRegistrationEnd
Date onlineRegistrationStart
static constraints = {
onlineRegistrationEnd validator: {val, obj ->
if(obj.onlineRegistration){
return val > obj.onlineRegistrationStart || val <= obj.eventFlowService.getEventStartDate()
}
return null
}
}
}
The problem is that I get exception saying, that there is no flow property in my service. Is there any way I can get access to flow storage in my flow-scoped service?
I met the SAME issue before and worked it out by installing webflow plugin in GRAILS:
grails install-plugin webflow
Say, the new version of grails surports webflow well by installing webflow plugin.
Related
I want to use g.formatNumber in service, I have tried a below method, Which i got online. This is not working, its giving me the error "Cannot invoke method formatNumber() on null object", The code is below
import org.springframework.beans.factory.InitializingBean
class MyService implements InitializingBean {
boolean transactional = false
def gspTagLibraryLookup // being automatically injected by spring
def g
public void afterPropertiesSet() {
g = gspTagLibraryLookup.lookupNamespaceDispatcher("g")
assert g
}
def getFormattedNumber(){
def number = g.formatNumber(number: 5000,234 , type: "number" , maxFractionDigits: 2)
return number
}
}
How to do this.
I want to use g.formatNumber in service
Rather than jumping through the hoops you need to use a taglib within a service, it would be simpler to just use java.text.NumberFormat directly
NumberFormat format = NumberFormat.getNumberInstance()
format.maximumFractionDigits = 2
def number = format.format(5000.234)
If the service method is being called from a web request handling thread then you may wish to use the LocaleContextHolder to get the correct locale for the current web request, rather than just using the server's default.
This should work
def g = grailsApplication.mainContext.getBean('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib');
You will of course need grailsApplication injected by defining it ala
def grailsApplication
Grails 2.1.1
I can't seem to get a command object to be injected with a service so that I can use custom validator. I've tried several things, including
Grails command object data binding and
what the 2.1.1 docs on custom validator suggest, I just can't figure this one out..
Relevant Code:
class RegistrationCommand {
String username
def registrationService
static constraints = {
username validator: { val, obj ->
obj.registrationService.isUsernameUnique(val) }
}
}
class RegistrationService {
def isUsernameUnique(username){
def user = new User(username:username)
user.validate()
if(user.errors.hasFieldErrors("username")){
return false
}else{
return true
}
}
Resolved.. Issue was due to plugin.
I'm using a plugin for client side jquery validation (jquery-validation-ui-1.4.2). The command object being created by the plugin's controller wasn't getting injected with the service. The issue was reported https://github.com/limcheekin/jquery-validation-ui/issues/17 . The fix does work but has not been pushed upstream yet.
Hi there i am still very new to grails and I have not been able to figure out why this is happening.
I have a domain class:
package scheduler
class Client {
String name
static constraints = {}
}
And a controller:
package scheduler
class AdminController {
def create() {
def client = new Client(name:"John")
println client
}
}
Currently I am always getting null for client. Originally the above was a little more complex on the domain class side but I systematically dumbed it down to see if it was a problem there. I still can not get the above working.
The output is always
scheduler.Client : null
Please let me know if I need to provide anymore information.
It's not null, that's just the default output of the toString method that Grails adds. It prints the class name and the id. Since you haven't saved the instance, the id is null. If the instance was null the output would have been null, not scheduler.Client : null
If you want to see the data in the instance, use the Groovy dump() method, e.g.
def client = new Client(name:"John")
println client.dump()
You could also add a toString method that includes the name attribute, e.g.
package scheduler
class Client {
String name
String toString() { name }
}
Hello!
I am using grails jms and atmosphere plugin...
When trying to inject springSecurityService into
Jms-Atmosphere Service class, the principal/currentUser is null while there is a reference to this object (springSecurityService is not null)
//Grails Service class
class UserMessageService {
static transactional = true
static exposes = ['jms']
static destination = "queue.usermessage"
def jmsService
def springSecurityService
public def onMessage(msg) {
sleep(2000) // slow it down
log.info "sending jms mssage"
//User is null!!
User user = springSecurityService.currentUser
jmsService.send(topic:'msgevent', msg)
return null
}
}
So I am wondering...
Is it a plugin problem, or is it a problem with listening the events (As an event Listener) publicated from the jms plugin?
I have the same problem when using Atmosphere Hander as a Service using the Atmosphere plugin! In this case the atmosphere service have to be exposed to jms events also!
Please give me some ideas to deal with this... workarounds maybe... thanks
I guess there's no cookie set in your particular call. Are you using websocket? Make sure, you've got Atmosphere 1.0.0 and have the session support enabled! You will then still need to fetch the authentication from the originating request:
if(resource.writer instanceof WebsocketResponseWriter) {
AtmosphereResource resource = resource.atmosphereResource
SecurityContext sessionContext = resource.session
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY)
}
You would then need to provide the current session context with the authentication from the session context you've found. Make sure you reset the authentication once the request has been handled.
Does this help?
I'm creating a grails service that will interact with a 3rd party REST API via a Java library. The Java library requires credentials for the REST API by means of a url, username and password.
I'd like to store these credentials in configuration/Config.groovy, make them available to a service and ensure that credentials are available to the service before it requires them.
I appreciate that grailsApplication.config is available to controllers and that through a method of a service the relevant config values can be provided to the service, such as this:
package example
class ExampleController {
def exampleService
def index = { }
def process = {
exampleService.setCredentials(grailsApplication.config.apiCredentials)
exampleService.relevantMethod()
}
}
package example
import com.example.ExampleApiClient;
class ExampleService {
def credentials
def setCredentials(credentials) {
this.credentials = credentials
}
def relevantMethod() {
def client = new ExampleApiClient(
credentials.baseUrl,
credentials.username,
credentials.password
)
return client.action();
}
}
I feel this approach is slightly flawed as it depends on a controller calling setCredentials(). Having the credentials made available to the service automagically would be more robust.
Is either of these two options viable (I currently not familiar enough with grails):
Inject grailsApplication.config.apiCredentials into the service in the controller when the service is created?
Provide some form of contructor on the service that allows the credentials to be passed in to the service at instantiation time?
Having the credentials injected into the service is ideal. How could this be done?
The grailsApplication object is available within services, allowing this:
package example
import com.example.ExampleApiClient;
class ExampleService {
def grailsApplication
def relevantMethod() {
def client = new ExampleApiClient(
grailsApplication.config.apiCredentials.baseUrl
grailsApplication.config.apiCredentials.username,
grailsApplication.config.apiCredentials.password
)
return client.action();
}
}
Even though grailsApplication can be injected in services, I think services should not have to deal with configuration because it's harder to test and breaks the Single Responsibility principle. Spring, on the other side, can handle configuration and instantiation in a more robust way. Grails have a dedicated section in its docs.
To make your example work using Spring, you should register your service as a bean in resources.groovy
// Resources.groovy
import com.example.ExampleApiClient
beans {
// Defines your bean, with constructor params
exampleApiClient ExampleApiClient, 'baseUrl', 'username', 'password'
}
Then you will be able to inject the dependency into your service
class ExampleService {
def exampleApiClient
def relevantMethod(){
exampleApiClient.action()
}
}
In addition, in your Config.groovyfile, you can override any bean property using the Grails convention over configuration syntax: beans.<beanName>.<property>:
// Config.groovy
...
beans.exampleApiClient.baseUrl = 'http://example.org'
Both Config.groovy and resources.groovy supports different environment configuration.
For contexts where you can't inject the grailsApplication bean (service is not one of those, as described by Jon Cram), for example a helper class located in src/groovy, you can access it using the Holders class:
def MyController {
def myAction() {
render grailsApplication == grails.util.Holders.grailsApplication
}
}
The best options are (as from grails docs):
1 - Using Spring #Value annotation
import org.springframework.beans.factory.annotation.Value
class WidgetService {
int area
#Value('${widget.width}')
int width
def someServiceMethod() {
// this method may use the width property...
}
}
2 - Having your class implement GrailsConfigurationAware
import grails.config.Config
import grails.core.support.GrailsConfigurationAware
class WidgetService implements GrailsConfigurationAware {
int area
def someServiceMethod() {
// this method may use the area property...
}
#Override
void setConfiguration(Config co) {
int width = co.getProperty('widget.width', Integer, 10)
int height = co.getProperty('widget.height', Integer, 10)
area = width * height
}
}