Artur Czocher
12/16/2025, 12:05 AMError: 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
jsonViewsVersion=2.0.3
and
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…sbglasius
12/16/2025, 7:43 AMArtur Czocher
12/16/2025, 9:58 PMJames Fredley
12/20/2025, 2:21 AMbuildscript {
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"Artur Czocher
12/20/2025, 11:12 AMArtur Czocher
12/20/2025, 11:12 AMArtur Czocher
12/20/2025, 11:20 AMControllerUnitTest
have something like this
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
@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
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 `
messageSource.addMessage('migrationFailed', request.locale, 'Migration failed.')
but have an error
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'.Artur Czocher
12/20/2025, 11:24 AMsbglasius
12/20/2025, 4:23 PMmigrate and have a look at the cmd object. See the errors to find your error codes.sbglasius
12/20/2025, 4:23 PMArtur Czocher
12/20/2025, 7:41 PM/**
* 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 messagesArtur Czocher
12/20/2025, 7:42 PMArtur Czocher
12/20/2025, 7:44 PMimplements ControllerUnitTest<> and then messageSource.addMessage in testArtur Czocher
12/21/2025, 6:55 AMdef stup() {
def resolver = applicationContext.getBean('jsonSmartViewResolver', JsonViewResolver)
if (resolver.templateEngine) {
resolver.templateEngine.messageSource = messageSource
}
...
}sbglasius
12/21/2025, 7:16 PM@SelfType(ControllerUnitTest)
trait JsonViewResolverHelper {
void attachMessageSource() {
def resolver = applicationContext.getBean('jsonSmartViewResolver', JsonViewResolver)
resolver.templateEngine?.messageSource = messageSource
}
}
and in your spec:
void setup() {
attachMessageSource()
}