ValidationException on Update: Validation error whilst flushing entity on AbstractPersistenceEventListener - validation

In my environment, i have grails.gorm.failOnError = true on Config.groovy.
package org.example
class Book {
String title
String author
String email
static constraints = {
title nullable: false, blank: false
email nullable: false, blank: false, unique: true //apparently this is the problem..
}
}
And, on controller, i have:
package org.example
class BookController {
def update() {
def bookInstance = Book.get(params.id)
if (!bookInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'book.label', default: 'Book'), params.id])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (bookInstance.version > version) {
bookInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'book.label', default: 'Book')] as Object[],
"Another user has updated this Book while you were editing")
render(view: "edit", model: [bookInstance: bookInstance])
return
}
}
bookInstance.properties = params
bookInstance.validate()
if(bookInstance.hasErrors()) {
render(view: "edit", model: [bookInstance: bookInstance])
} else {
bookInstance.save(flush: true)
flash.message = message(code: 'default.updated.message', args: [message(code: 'book.label', default: 'Book'), bookInstance.id])
redirect(action: "show", id: bookInstance.id)
}
}
}
To save, it's ok. But, when updating without set the title field, i get:
Message: Validation error whilst flushing entity [org.example.Book]:
- Field error in object 'org.example.Book' on field 'title': rejected value []; codes [org.example.Book.title.blank.error.org.example.Book.title,org.example.Book.title.blank.error.title,org.example.Book.title.blank.error.java.lang.String,org.example.Book.title.blank.error,book.title.blank.error.org.example.Book.title,book.title.blank.error.title,book.title.blank.error.java.lang.String,book.title.blank.error,org.example.Book.title.blank.org.example.Book.title,org.example.Book.title.blank.title,org.example.Book.title.blank.java.lang.String,org.example.Book.title.blank,book.title.blank.org.example.Book.title,book.title.blank.title,book.title.blank.java.lang.String,book.title.blank,blank.org.example.Book.title,blank.title,blank.java.lang.String,blank]; arguments [title,class org.example.Book]; default message [Property [{0}] of class [{1}] cannot be blank]
Line | Method
->> 46 | onApplicationEvent in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 895 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 918 | run . . . . . . . in ''
^ 680 | run in java.lang.Thread
At q I understand it, the problem occurs when the flush hibernate session, hibernate tries to save the object again then the exception is thrown...
When trying to save the object again, is called the book.validate () again, which makes a new query in the database to ensure the uniqueness of the email field. Right now, the Validation Exception is thrown.
But, when i removed the unique validation of email property, the update is performed normally..
My question is: This behavior is correct? Hibernate calls book.save automatically?
This is the sample project, and the steps to simulate the error are:
source: https://github.com/roalcantara/grails_app_validation_exception
grails run-app
navigate to http:// localhost: 8080/ book/book/create
create an new instance filling all fields..
then edit this instance, in: http:// localhost: 8080/ book/book/edit/1
finally, drop the 'Title' field and click on Update, then the exception is thrown..
In my environment, this behavior has occurred on grails version 2.0.3 and 2.2.1
Thanks for any help! And sorry by my poor (and shame) english.. rs..

You are essentially validating twice, first with:
bookInstance.validate()
and second with:
bookInstance.save(flush: true)
When you call bookInstance.save(flush: true) a boolean is returned. Grails takes advantage of this by default when a controller is generated, but it appears you have changed the controller Grails generated by default for some reason.
Just replace this:
bookInstance.validate()
if(bookInstance.hasErrors()) {
render(view: "edit", model: [bookInstance: bookInstance])
} else {
bookInstance.save(flush: true)
flash.message = message(code: 'default.updated.message', args: [message(code: 'book.label', default: 'Book'), bookInstance.id])
redirect(action: "show", id: bookInstance.id)
}
With this:
if( !bookInstance.save( flush: true ) ) {
render(view: "edit", model: [bookInstance: bookInstance])
return
}

Related

Grails validator doesn't detect violation

Given a simple domain class, with a start hour and end hour, where the end hour should always be a greater value than start hour:
class Daypart {
...
Integer startHour
Integer endHour
static constraints = {
...
startHour inList: (0..23)
endHour inList: (0..23), validator: { val, obj ->
return (val > obj.startHour)
}
}
}
When using 20 for start hour and 4 for end hour, validation should fail. On a brand new instance that calls the save() action, validation works as expected.
When editing an existing instance and calling update(), validation rules are ignored, and .validate() returns true, even with setting start hour to -32 (the property with a simple constraint, not even a custom validation routine.) I've made sure to .clearErrors() before calling .validate() in the update block to no avail. Any ideas on what's going on here?
Edit: Adding update block
def update(Daypart dc) {
dc.clearErrors()
dc.validate()
println ("Got errors? ${dc.hasErrors()}")
try {
if (dc.hasErrors()) {
flash.error ="Invalid parameters."
redirect resource: "campaign/daypart", action: "edit", id: dc.id, campaignId: dc.campaign.id
return
}
dc.save(flush: true)
flash.success = "Updated campaign ${dc.campaign.id}."
redirect(controller: 'campaign', action: 'index')
}
catch (DaypartException de) {
flash.message = de.message
redirect resource: "campaign/daypart", action: "edit", id: de.daypart.id, campaignId: de.daypart.campaign.id
}
}
}
Remove dc.clearErrors(), which removes all validate errors from your Daypart instance.

Grails plugin returning invalid stream header error

I have a Grails app that uses a plugin I have created. Both use Spring-security-core plugin.
My plugin has a domain class, controller and views. Data to display is selected from a line drawn on a map. The data returned is displayed in a list at the bottom of the browser window. I have created a link on one of the fields that is supposed to show the selected record.
When I click this link, however I get the following error:
| Error 2014-05-27 16:14:11,415 [http-bio-8082-exec-6] ERROR errors.GrailsExceptionResolver - StreamCorruptedException occurred when processing request: [GET] /test/bridge/show/661
invalid stream header: 8401FE00. Stacktrace follows:
Message: invalid stream header: 8401FE00
Line | Method
->> 802 | readStreamHeader in java.io.ObjectInputStream
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 299 | <init> in ''
| 55 | show . . . . . . in RIMS.bridge.BridgeController
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter . . . . in grails.plugin.cache.web.filter.AbstractFilter
| 53 | doFilter in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
| 49 | doFilter . . . . in grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter
| 82 | doFilter in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 1145 | runWorker . . . in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 724 | run . . . . . . in java.lang.Thread
The code that fails is where I attempt to get the data with the ID in the following action:
#Secured(["hasRole('ROLE_MAP_USER')"])
def show(Long id) {
println "ID: ${id}"
def princObj = springSecurityService?.principal
log.debug "User: ${princObj}"
def bridgeInstance = RIMS.bridge.Bridge.get(id)
if (!bridgeInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'bridge.label', default: 'Bridge'), id])
redirect(action: "list")
return
}
render(plugin: "nhvr", view:"show", model: [bridgeInstance: bridgeInstance])
}
The returned user, retured at log.debug "User: ${princObj}" is correct and has the required role.
I am not sure how to proceed. Can anyone suggest what to try?
Here is the code for the Bridge class:
package RIMS.bridge
class Bridge {
String bridgeNo
String roadNo
BigDecimal linkNo
BigDecimal chng
String travelDirectionCode
BigDecimal northing
BigDecimal easting
String overUnderCode
Date dateActive
Date dateArchived
String tranUser
Date tranDateTime
String tranType
Serializable obj
String cwayCode
String constructed
static hasMany = [
bridgeClearances: BridgeClearance,
bridgeCulverts: BridgeCulvert,
bridgeDimensions: BridgeDimension,
bridgeDrawings: BridgeDrawing,
bridgeDucts: BridgeDuct,
bridgeHydraulics: BridgeHydraulic,
bridgeMaintenances: BridgeMaintenance,
bridgeMiscellaneouses: BridgeMiscellaneous,
bridgeParts: BridgePart,
bridgeServices: BridgeService,
bridgeSpans: BridgeSpan,
bridgeSubstructures: BridgeSubstructure,
bridgeSuperstructures: BridgeSuperstructure]
static mapping = {
id generator: "assigned"
version false
}
static constraints = {
bridgeNo maxSize: 10
roadNo nullable: true, maxSize: 5
linkNo nullable: true
chng nullable: true
travelDirectionCode maxSize: 10
northing nullable: true
easting nullable: true
overUnderCode maxSize: 10
dateArchived nullable: true
tranUser maxSize: 30
tranType maxSize: 6
obj nullable: true
cwayCode nullable: true, maxSize: 4
constructed nullable: true, maxSize: 3
}
def locateByBridgeNo(String bridgeNo){
println "locating by no: ${bridgeNo}"
withCriteria{
eq('bridgeNo', bridgeNo)
}
}
static listActiveBridges(){
withCriteria(){
isNull('dateArchived')
}
}
static listBridgesByBridgeNo(String bridgeNo){
withCriteria(){
eq('bridgeNo', bridgeNo)
}
}
String toString(){
return "${bridgeNo} Road: ${roadNo}, Link: ${linkNo}, chainage: ${chng}"
}
}

Symfony2 Constraints\email not found

I installed a email validator for a newsletter form in Symfony2. Locally everything works fine, but if I upload the whole folder to my webhosting i get the following error message:
Fatal error: Class 'Symfony\Component\Validator\Constraints\email' not found in /home/donacico/public_html/spendu/donaci14/vendor/symfony/symfony/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php on line 64
My validation yml looks like this:
# src/Dbe/DonaciBundle/Resources/config/validation.yml
Dbe\DonaciBundle\Entity\Newsletter:
properties:
email:
- email:
message: The email "{{ value }}" is not a valid email.
checkMX: true
Dbe\DonaciBundle\Entity\Contact:
properties:
email:
- email:
message: The email "{{ value }}" is not a valid email.
checkMX: true
And here is the action of the create controller:
/**
* Creates a new Newsletter entity.
*
*/
public function createAction(Request $request) {
$entity = new Newsletter();
$form = $this -> createCreateForm($entity);
$form -> handleRequest($request);
if ($form -> isValid()) {
$em = $this -> getDoctrine() -> getManager();
$em -> persist($entity);
$em -> flush();
$this -> get('session') -> getFlashBag() -> add('newsletterSubscribed', 'Thank you for subscribing!');
}
return $this -> render('DbeDonaciBundle:UnderConstruction:index.html.twig', array('entity' => $entity, 'form' => $form -> createView(), ));
}
Also in the config.yml file I have validation enabled:
framework:
validation: { enable_annotations: true }
Any idea what could cause this error?
If you work on a linux system its case sensitive.
'Symfony\Component\Validator\Constraints\email'
to
'Symfony\Component\Validator\Constraints\Email'
otherwise the autoloader can't find the file and the class.
It really was a error case of case sensitive, but I corrected the wrong one.
src/DbeDonaciBundle/Resources/config/validation.yml
Dbe\DonaciBundle\Entity\Newsletter:
properties:
email:
- Email :
message: The email "{{ value }}" is not a valid email.
checkMX: true

Grails + hibernate + controller sessionFactory null object?

I am new to using hibernate and grails. I have multiple java objects that I need to persist. To learn how it works I'm using a simple example of an employee class. Its in my src/java with the corresponding xml mappings with it. I think I need to make a session instance from my session factory, and I do not know what I'm doing wrong. I followed a tutorial for setting up hibternate hibernate tut and tried to translate it for grails. Any thoughts?
package com.turingpages.Matrix.view
import org.springframework.dao.DataIntegrityViolationException
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
class MatrixController {
def ctx = AH.application.mainContext
def sessionFactory = ctx.sessionFactory
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
...
def create() {
def session = sessionFactory.currentSession
Transaction tx = null;
Integer employeeID = null;
try{
tx = session.beginTransaction();
Employee employee = new Employee("fname", "lname", 100);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
My stack trace:
ERROR errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [POST] /turingpages/matrix/create
Cannot get property 'currentSession' on null object. Stacktrace follows:
Message: Cannot get property 'currentSession' on null object
Line | Method
->> 33 | create in com.turingpages.Matrix.view.MatrixController$$ENvP7skK
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread
There's no reason you should be writing code like that with Grails. If you really need to manage the transaction in a controller, you should do it this way.
def create() {
Integer employeeID = null;
Employee.withTransaction { status ->
Employee employee = new Employee(firstName: "fname", lastName: "lname", noIdea: 100);
employee.save()
if (employee.hasErrors()) {
status.setRollbackOnly()
}
}
return employee.id;
}
That said, when dealing with a single Domain like this, you don't really need to worry about it at all:
def create() {
Employee employee = new Employee(firstName: "fname", lastName: "lname", noIdea: 100);
employee.save(flush: true)
[employee: employee] // generally you want to pass the object back to a view this way
// deal with errors in the domain on the view
}
And even better would be to use a Service class. But that can be your homework assignment.
You need to move the code
def ctx = AH.application.mainContext
def sessionFactory = ctx.sessionFactory
into the method create(), or replace it with
def sessionFactory
However, Grails provides a withTransaction method to serve your purpose in a simpler way:
def create() {
Employee.withTransaction{ status ->
Employee employee = new Employee("fname", "lname", 100).save()
.....
if (employee.id) {
return employee.id
}
else {
status.setRollbackOnly()
}
}
}

Sorry, we were not able to find a user with that username and password

I installed the Spring Security core plug-in 1.2.7.3 on Grails 2.1.1, ran the s2-quickstart command, and then initialized the initial user and roles in the bootstrap.groovy, but I still cannot login. Text of the relevant piece of BootStrap.groovy follows:
if (SecRole.count == 0) {
def fUserRole = SecRole.findByAuthority('ROLE_FlowUser') ?: new SecRole(authority: 'ROLE_FlowUser').save(failOnError: true, flush: true)
def fAdminRole = SecRole.findByAuthority('ROLE_FlowAdmin') ?: new SecRole(authority: 'ROLE_FlowAdmin').save(failOnError: true, flush: true)
def bf = SecUser.findByUsername('bill') ?: new SecUser(
username: 'bill',
password: 'eagle',
firstName: 'bill',
lastName: 'fly',
email: 'bill.fly#baylorhealth.edu',
accountExpired: false,
accountLocked: false,
passwordExpired: false,
enabled: true
).save(failOnError: true, flush: true)
if (!bf.authorities.contains(fAdminRole)) {
SecUserSecRole.create bf, fAdminRole, true
}
if (!bf.authorities.contains(fUserRole)) {
SecUserSecRole.create bf, fUserRole, true
}
}
I am not encrypting the password in bootstrap, as seems to be the answer to most of the questions of this type. All four records are getting written to the database tables, but of course, I cannot tell if the password is encrypted correctly. My initial controller has the following annotation ahead of the class statement:
#Secured(['IS_AUTHENTICATED_FULLY'])
Also, I added the following to the config.groovy:
// Added by the Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'cocktail.SecUser'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'cocktail.SecUserSecRole'
grails.plugins.springsecurity.authority.className = 'cocktail.SecRole'
grails.plugins.springsecurity.password.algorithm = 'SHA-256'
Your password may be encoded two times (problem may occure if you are using multi datasources).
Try this :
class User {
...
transient bEncoded = false
...
protected void encodePassword() {
if (!bEncoded ) {
password = springSecurityService.encodePassword(password);
bEncoded = true;
}
}
}
My guess is the authorities.contains check is failing because of missing hashCode and equals methods in your role class. But if there are no roles (your 1st check) then the user wouldn't have any granted, so you can just remove those checks:
SecUserSecRole.create bf, fAdminRole, true
SecUserSecRole.create bf, fUserRole, true
If that doesn't fix it, it's most likely a password encoding issue - add debug logging for Spring Security and it should show you why it's failing; add debug 'org.springframework.security' in your log4j block in Config.groovy
p.s. if (SecRole.count == 0) { should be if (SecRole.count() == 0) { or just if (!SecRole.count()) {

Resources