I am in trouble with one point in Grails 3.3.11 and I need help.
I am developing a rest-api in grails 3.3.11, but I can't use message source for i18n in service. It only works in my controller.
message = messageSource.getMessage('documentProperties.notFound', [partId,jsonRequestDoc.get("typeId")] as Object[], LocaleContextHolder.locale)
When I do that above, I receive this in service.
Cannot invoke method getMessage() on null object
My messageSource is defined in the beginning of my service class as below:
@Autowired
def messageSource
In order to resolve this, I manually created a service constructor which receives message source from the controller.
class CmbIdService {
public CmbIdService(def messageSource){
this.messageSource = messageSource
}
}
It was working as expected, but when I started running my integration tests, I noticed that Grails did not know how to instantiate my service considering the presence of the constructor. This the message I receive when I run the Grails Integration tests.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cmbIdService': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'java.lang.Object' available: more than one 'primary' bean found among candidates... continue.
Could anyone help me. I don't know what to do. I need to use message source for internacionalization. And I need to do that in service, not only in the controller. And my tests need to continue working.
Thanks!
Alfredo
Instead of this...
class CmbIdService {
public CmbIdService(def messageSource){
this.messageSource = messageSource
}
}
Do this...
class CmbIdService {
def messageSource
}
If that class is defined in grails-app/services/[whatever your package is]/CmbIdService.groovy
, then an instance will automatically be created for you, added to the application context as a bean, and that instance will be subjected to autowire-by-name.
EDIT
Comments below suggest that the OP is still getting an NPE. I have provided a working example at https://github.com/jeffbrown/dnunesmessagesource.
package dnunesmessagesource
import org.springframework.context.i18n.LocaleContextHolder
class CmbIdService {
def messageSource
String getCustomMessage() {
messageSource.getMessage('my.custom.message', [] as Object[], LocaleContextHolder.locale)
}
}
package dnunesmessagesource
class DemoController {
CmbIdService cmbIdService
def index() {
String message = cmbIdService.customMessage
[customMessage: message]
}
}
my.custom.message=This Is My Custom Message
model {
String customMessage
}
json {
message customMessage
}
That all appears to work as designed.
$ http :8080/demo
HTTP/1.1 200
Content-Language: en-US
Content-Type: application/json;charset=UTF-8
Date: Wed, 31 Mar 2021 18:31:37 GMT
Transfer-Encoding: chunked
X-Application-Context: application:development
{
"message": "This Is My Custom Message"
}