My current problem right now is the custom object marshaller that I created since grails 2.4.5 to grails 3.3.0 is not working on grails 4.0.0. Grails 4 respond the domain model by default not the custom made I create.
Below are the codes I have. Please review and if you find theres something wrong please do let me know guys, I will be glad if you can help me with this.
ResponseSender.groovy
package com.problem.solve.common
import org.springframework.http.HttpStatus
trait ResponseSender {
void sendResponse() {
render status: HttpStatus.NO_CONTENT
}
void sendResponse(def responseData) {
respond (responseData)
}
void sendResponse(HttpStatus status, def responseData) {
response.status = status.value()
respond (responseData)
}
}
This ResponseSender.groovy trait is implemented on the controller.
MarshallerInitializer.groovy
package com.problem.solve.marshaller
class MarshallerInitializer {
CustomObjectMarshallers customObjectMarshallers
void initialize() {
customObjectMarshallers.register()
}
}
this MarshallerInitializer.groovy will be called when bootstrap initialize.
package com.problem.solve.marshaller
class CustomObjectMarshallers {
List marshallers = []
void register() {
marshallers.each {
it.register()
}
}
}
This CustomObjectMarshallers.groovy will going to register all marshallers.
UserMarshaller.groovy
package com.problem.solve.marshaller.marshalls
import com.problem.solve.security.User
import grails.converters.JSON
class UserMarshaller {
void register() {
JSON.registerObjectMarshaller(User) { User user ->
return [
id: user.id,
fullName: user.fullName,
username: user.username,
emailAddress: user.emailAddress,
roles: user.authorities.authority,
dateCreated: user.dateCreated,
lastUpdated: user.lastUpdated,
_entityType: 'User'
]
}
}
This UserMarshaller.groovy is a sample domain model that I want to convert from domain model to json response.
resources.groovy
import com.problem.solve.marshaller.CustomObjectMarshallers
import com.problem.solve.marshaller.MarshallerInitializer
import com.problem.solve.marshaller.marshalls.*
// Place your Spring DSL code here
beans = {
customObjectMarshallers(CustomObjectMarshallers) {
marshallers = [
new UserMarshaller()
]
}
marshallerInitializer(MarshallerInitializer) {
customObjectMarshallers = ref('customObjectMarshallers')
}
}
The problem with this setup is not working on grails 4, but this setup are working with grails 2.4.5 and grails 3.3.0.
I really need your help guys.
Thank you so much :)
I solve this marshaller problem by creating DomainModelResponseDto as respond domain model.
Example:
class UserResponseDto {
String id
String username
String email
UserResponseDto(User user) {
id = user.id
username = user.username
email = user.email
}
}
I have another solution to this problem. The marshaller is working the problem is the views. I have to delete the views that are generated when creating a domain class and all is working perfectly with the current marshaller and setup.
Related
I'm upgrading an existing application from Grails 2.4.4 to Grails 4.0.10 and I'm trying to test the logout code that works in the Grails 2.4.4 app now. However, when I call findAllByUsername after deleting all the tokens for that user, GORM returns apparently stale data.
To test this, I tried
AuthenticationToken.list().find { it.username == username }, and it returns null. However, AuthenticationToken.findAllByUsername(username) returns the 3 records that were just deleted.
How can I prevent findAllByUsername from returning stale data in this unit test?
package us.cloudcard.api
import grails.testing.gorm.DataTest
import grails.testing.gorm.DomainUnitTest
import groovy.time.TimeCategory
import spock.lang.Specification
class AuthenticationTokenSpec extends Specification implements DomainUnitTest<AuthenticationToken>, DataTest {
def setup() {
[AuthenticationToken, Photo, Person].each { mockDomain(it) }
}
def "test logout"() {
setup:
String username = "bacon"
[username, "eggs", "biscuits", "gravy", username, "hashbrowns", username].each {
new AuthenticationToken(username: it).save(validate: false)
}
when:
List<AuthenticationToken> tokensForUser = AuthenticationToken.findAllByUsername(username)
AuthenticationToken.deleteAll(tokensForUser, flush: true)
then:
AuthenticationToken.list().find { it.username == username } == null // this passes
AuthenticationToken.findAllByUsername(username).empty // this fails
}
}
Back in Grails 2.x world I could create multiple dataSources in an environment:
development {
dataSource {
...
}
dataSource_new {
...
}
}
and reference them in the controller:
def db = new SQL(dataSource_new)
and everything worked awesome. In Grails 3.x, everything is not awesome:
development:
dataSource:
...
dataSource_new:
...
and calling
def db = new SQL(dataSource_new)
throws:
Ambiguous method overloading for method groovy.sql.Sql#
Anyone have success with this (or can point out what's changed that I've missed)?
Tried mapping in domain with no luck:
class abc {
String ...
static mapping = {
datasource: ['DEFAULT', 'dataSource_new']
}
throws:
Ambiguous method overloading for method groovy.sql.Sql#<init>. Cannot resolve which method to invoke for [null] due to overlapping prototypes between: [interface java.sql.Connection] [interface javax.sql.DataSource]
I work with multiply datasources in Grails 3.x like following:
assuming you have configuration:
development {
dataSources {
dataSource {
url = 'your_url'
password = 'psw'
...
}
second {
url = 'you_url_2'
password = 'psw2'
...
}
}
So in a service you will have mapped data source like this:
dataSource_second
And to create Sql instance you will need to do the following:
def sql = new Sql(dataSource_second)
It works in Grails 3.0.11.
Hope it will help.
In official docs you can find an example for injecting datasource into service:
https://grails.github.io/grails-doc/latest/guide/single.html#multipleDatasources
class DataService {
static datasource = 'lookup'
void someMethod(...) {
//…
}
}
or into command:
http://grails.github.io/grails-doc/latest/guide/upgrading.html
import grails.dev.commands.*
import javax.sql.*
import groovy.sql.*
import org.springframework.beans.factory.annotation.*
class RunQueryCommand implements ApplicationCommand {
#Autowired
DataSource dataSource
boolean handle(ExecutionContext ctx) {
def sql = new Sql(dataSource)
println sql.executeQuery("select * from foo")
return true
}
}
Moreover look at this thread and quoted examples: https://github.com/grails/grails-core/issues/701
Grails 2.4.x here.
I have a requirement that all the methods of all my Grails services, generated by grails create-service <xyz>, be "wrapped"/intercepted with the following logic:
try {
executeTheMethod()
} catch(MyAppException maExc) {
log.error(ExceptionUtils.getStackTrace(maExc))
myAppExceptionHandler.handleOrRethrow(maExc)
}
Where:
log.error(...) is the SLF4J-provided logger you get when you annotate your class with the #Slf4j annotation; and
ExceptionUtils is the one from org.apache.commons:commons-lang3:3.4; and
myAppExceptionHandler is of type com.example.myapp.MyAppExceptionHandler; and
This behavior exists (or has the option to exist in the event that it needs to be explicitly called somehow) for each method defined in a Grails service
So obviously this wrapper code needs to include import statements for those classes as well.
So for example if I have a WidgetService that looks like this:
class WidgetService {
WidgetDataService widgetDataService = new WidgetDataService()
Widget getWidgetById(Long widgetId) {
List<Widget> widgets = widgetDataService.getAllWidgets()
widgets.each {
if(it.id.equals(widgetId)) {
return it
}
}
return null
}
}
Then after this Groovy/Grails/closure magic occurs I need the code to behave as if I had written it like:
import groovy.util.logging.Slf4j
import org.apache.commons.lang3.exception.ExceptionUtils
import com.example.myapp.MyAppExceptionHandler
#Slf4j
class WidgetService {
WidgetDataService widgetDataService = new WidgetDataService()
MyAppExceptionHandler myAppExceptionHandler = new MyAppExceptionHandler()
Widget getWidgetById(Long widgetId) {
try {
List<Widget> widgets = widgetDataService.getAllWidgets()
widgets.each {
if(it.id.equals(widgetId)) {
return it
}
}
return null
} catch(MyAppException maExc) {
log.error(ExceptionUtils.getStackTrace(maExc))
myAppExceptionHandler.handleOrRethrow(maExc)
}
}
}
Any ideas as to how I might be able to achieve this? I'm worried that a pure Groovy closure might interfere somehow with whatever Grails is doing to its services under the hood at runtime (since they are all classes that don't explicitly extend a parent class).
Here is what I was trying to pin point in my comment:
package com.example
import groovy.util.logging.Log4j
#Log4j
trait SomeTrait {
def withErrorHandler(Closure clos) {
try {
clos()
} catch(Exception e) {
log.error e.message
throw new ApplicationSpecificException(
"Application Specific Message: ${e.message}"
)
}
}
}
Service class:
package com.example
class SampleService implements SomeTrait {
def throwingException() {
withErrorHandler {
throw new Exception("I am an exception")
}
}
def notThrowingException() {
withErrorHandler {
println "foo bar"
}
}
}
Test:
package com.example
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(SampleService)
class SampleServiceSpec extends Specification {
void "test something"() {
when:
service.throwingException()
then:
ApplicationSpecificException e = thrown(ApplicationSpecificException)
e.message == "Application Specific Message: I am an exception"
}
void "test something again"() {
when:
service.notThrowingException()
then:
notThrown(Exception)
}
}
Here is the sample app.
Grails 3.0.9 but it should not matter. this is applicable for Grails 2.4.*
You can intercept the calls to your Service class methods either using MetaInjection or Spring AOP. So you don't have to write closure in each Service class. You can look into this blog that explains both the approaches with examples.
I have a secured grails application with the spring security plugin and right now I am trying to do some tests with the login process with no success till now. Has anybody an idea of what is the problem?
This is my LoginPage.groovy
package pages.login
import geb.Page
class LoginPage extends Page {
static url = "login/auth"
static at = {
title ==~ /Login/
}
static content = {
loginForm { $("form") }
username { $("input", type:"text", name:"j_username") }
password { $("input", type:"password", name:"j_password") }
loginButton{ $("input", type:"submit", value:"Login") }
}
}
And this is the test using junit4:
import geb.junit4.GebReportingTest
import pages.copyright.*
import pages.login.LoginPage
import org.junit.Test
class CopyrightCRUDTests extends GebReportingTest {
#Test
void doSomeCrud() {
to LoginPage
at LoginPage
$("form").j_username() << "admin"
$("form").j_password() << "XXXXX"
loginButton.click()
to AuthenticatedPage
at AuthenticatedPage
}
}
The AuthenticatedPage is a page which needs authentication, but in this moment it is imposible to be authenticated using geb. Does anybody know anything about this issue?
Thanks in advance!
Try rewriting doSomeCrud() as follows:
to LoginPage
loginForm.j_username = 'admin'
loginForm.j_password = 'XXXXX'
loginButton.click()
waitFor { at AuthenticatedPage }
I don't know if this will help you since you are not using Spock, but I had a few issues with login as well (can't remember exactly what though)
I eventually found this code that I put in a spec extending GebSpec.
This gets called before each of the tests requiring a login:
def setupSpec() {
Browser.drive {
go baseUrl
$("form.login").with {
username = System.getenv("APP_USERNAME")
password = System.getenv("APP_PASSWORD")
}
$("input[name='submit']").click()
}
}
It doesn't seem like much, but the use of 'with' on the form worked for me.
I am working through a Grails tutorial from InfoQ called Getting Started With Grails, Second Edition, and I am trying to add a custom codec to a unit test. My environment is Grails 1.3.7 and Groovy 1.7.8.
So the codec is SHACodec.groovy, and it lives in grails-app/utils. The contents are:
import java.security.MessageDigest
class SHACodec{
static encode = {target->
MessageDigest md = MessageDigest.getInstance('SHA')
md.update(target.getBytes('UTF-8'))
return new String(md.digest()).encodeAsBase64()
}
}
The codec works just fine when I log into the app. It's being used for a password field in my UserController.authenticate()
def authenticate = {
def user =
User.findByLoginAndPassword(params.login, params.password.encodeAsSHA())
if(user){
session.user = user
flash.message = "Hello ${user.login}!"
redirect(controller:"race", action:"list")
}else{
flash.message = "Sorry, ${params.login}. Please try again."
redirect(action:"login")
}
}
When I add this to a unit test, the following error displays:
No such property: SHACodec for class:
racetrack.UserControllerTests
groovy.lang.MissingPropertyException:
No such property: SHACodec for class:
racetrack.UserControllerTests at
racetrack.UserControllerTests.testAuthenticate(UserControllerTests.groovy:39)
The test is:
package racetrack
import org.codehaus.groovy.grails.plugins.codecs.*
import grails.test.*
class UserControllerTests extends ControllerUnitTestCase {
protected void setUp() {
super.setUp()
String.metaClass.encodeAsSHA = {->
SHACodec.encode(delegate)
}
}
protected void tearDown() {
super.tearDown()
}
void testAuthenticate(){
def jdoe = new User(login:"jdoe", password:"password".encodeAsSHA())
mockDomain(User, [jdoe])
controller.params.login = "jdoe"
controller.params.password = "password"
controller.authenticate()
assertNotNull controller.session.user
assertEquals "jdoe", controller.session.user.login
controller.params.password = "foo"
controller.authenticate()
assertTrue controller.flash.message.startsWith(
"Sorry, jdoe")
}
I found two different recommendations so far.
First, call the codec directly from the test:
SHACodec codec = new SHACodec()
codec.encode("password")
Second, use an integration test instead of a unit test.
The results were the same for each option. What is the small thing I am missing?
Thanks in advance for your time!
you are not importing your codec--you are importing the default grails codecs. You just need to make the import for the codec in the test match the exact package path of where the codec lives. If you are using an IDE, let it try to import the codec for you...
Use the loadCodec method of the GrailsUnitTestCase. It's very simple. See the example bellow:
import grails.test.*
import org.codehaus.groovy.grails.plugins.codecs.HTMLCodec
class SomeTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
loadCodec(HTMLCodec)
}
protected void tearDown() {
super.tearDown()
}
void testSomething() {
assertEquals "<p>Hello World</p>", "<p>Hello World</p>".encodeAsHTML()
}
}
The answer from #hvgotcodes is correct, but you also need to add the grails-app/utils folder to your Java Build Path before the import works (at least that's what I needed to do with SpringSource Eclipse IDE).