Hello again. I have other problem with upgrade old...
# questions
a
Hello again. I have other problem with upgrade old version to 4.0.4
Copy code
Error: Could not find or load main class grails.plugin.json.view.JsonViewCompiler
I try to set version by version to fit it into 4.0.4
Copy code
jsonViewsVersion=2.0.3
and
Copy code
classpath "org.grails.plugins:views-gradle:$jsonViewsVersion"

...
implementation "org.grails.plugins:views-json:$jsonViewsVersion"
    implementation "org.grails.plugins:views-json-templates:$jsonViewsVersion"
but nothing works. I don’t want to upgrade gradle version now to use 2.1.*. Why I can’t find a version. Is it possible there is a good one…? Don’t think so…
s
What is your reasoning behind only upgrading to Grails 4.0.4?
a
I need to show them it is possible, asap 😄 then move to 7 with all major changes. They told me it’s not possible, few guys tried and failed and we should stay with 3.3.10… they have big clients with lots of data.. and lots of money.. and as usual - features, features, features. I told them we need to spend some time to make system more stable and up to date because it’s harder and harder to keep it alive. And it’s not possible to do this forever…
😂 1
j
Try something like
Copy code
buildscript {
    dependencies {
        classpath "org.grails.plugins:views-gradle:2.0.4"
        // ... other classpath deps like grails-gradle-plugin, etc.
    }
}
dependencies {
    implementation "org.grails.plugins:views-json:2.0.4"
    // If you use templates (e.g., GeoJSON support), add:
    // implementation "org.grails.plugins:views-json-templates:2.0.4"
    // ... other dependencies
}
// Ensure the plugin is applied after core Grails plugins
apply plugin: "org.grails.grails-web"
apply plugin: "org.grails.plugins.views-json"
a
I think old grails plugins are tricky. I back to compile in gradle instead of dependencies and it works
@James Fredley I tested your solution before and failed
I think grails in version 4.0.4 is more restricted.. I try to test controller with
ControllerUnitTest
have something like this
Copy code
void "migration"() {
        given:
        setSecurityContext()
        MigrationCmd cmd = new MigrationCmd()
        cmd.with {
            target = randomUUID()
            source = randomUUID()
        }

        controller.migrationService = mockMigrationService

        when:
        controller.migrate(cmd)

        then:
        response.status == 200

        and:
        1 * mockMigrationService.migrate(_)
    }
and controller
Copy code
@RolesAllowed(value = [some roles])
def migrate(MigrationCmd cmd) {
    if (!cmd.validate()) {
        validationRespond(cmd)
        return
    }

    try {
        migrationService.migrate(cmd)
        ok()
    } catch (Exception e) {
        cmd.errors.reject('migrationFailed')
        validationRespond(cmd)
    }
}
with controller Trait with method
Copy code
void validationRespond(def validatableObj, boolean shouldValidate = false) {
        if (validatableObj == null) {
            notFound()
            return
        }

        if (validatableObj.metaClass.respondsTo(validatableObj, 'validate')) {
            if (shouldValidate) {
                validatableObj?.validate()
            }
            if (validatableObj?.hasErrors()) {
                respond(validatableObj.errors)
            } else {
                // Cant validate, just respond
                respond(validatableObj)
            }
        } else {
            // Non-validatable object passed in, just respond with it.
            respond(validatableObj)
        }
    }
I added `
Copy code
messageSource.addMessage('migrationFailed', request.locale, 'Migration failed.')
but have an error
Copy code
Error rendering view: No message found under code 'migrationFailed' for locale 'en'.
grails.views.ViewException: Error rendering view: No message found under code 'migrationFailed' for locale 'en'.
i think this is not the same instance of message source in controller and in view renderer (in test). Is it possible? Any solution for this? I have plenty of this. i dont want to rewrite all to integration or functional
s
Break point at
migrate
and have a look at the
cmd
object. See the
errors
to find your error codes.
It should work like you do it
a
i have an error view
Copy code
/**
 * Renders validation errors according to vnd.error: <https://github.com/blongden/vnd.error>
 */
model {
    Errors errors
}

response.status UNPROCESSABLE_ENTITY

json {
    Errors errorsObject = (Errors) this.errors
    def allErrors = errorsObject.allErrors
    int errorCount = allErrors.size()
    if (errorCount == 1) {
        def error = allErrors.iterator().next()
        message messageSource.getMessage(error, locale)
    } else {
        total errorCount
        _embedded {
            errors(allErrors) { ObjectError error ->
                message messageSource.getMessage(error, locale)
            }
        }
    }
}
I added to test all 4 codes from cmd debug In view we have
messageSource.getMessage(error, locale)
so I stop in AbstractMessageSource and there is no messages
image.png
I didn’t do any setup for messageSource in test. It just implements
implements ControllerUnitTest<>
and then
messageSource.addMessage
in test
I found it!! 😄
Copy code
def stup() {    
        def resolver = applicationContext.getBean('jsonSmartViewResolver', JsonViewResolver)
        if (resolver.templateEngine) {
            resolver.templateEngine.messageSource = messageSource
        }
        ...
    }
s
@Artur Czocher great. Good find. If you have lots of tests with gson views I can suggest a helper trait like:
Copy code
@SelfType(ControllerUnitTest)
trait JsonViewResolverHelper {

     void attachMessageSource() {
         def resolver = applicationContext.getBean('jsonSmartViewResolver', JsonViewResolver)
          resolver.templateEngine?.messageSource = messageSource
     }

}
and in your spec:
Copy code
void setup() {
       attachMessageSource()
    }