Saving of grails domain object with an attribute type object fails - spring

I'm trying to save a domain object with grails 2.3.3 But it is not saved. How can I save it and why is it not saving?
The domain code:
package berg
import nl.jappieklooster.Log
class FieldValue {
Object value
public String toString(){
Log.debug "Field value: {0}", value
return value.toString()
}
static constraints = {
}
}
The code that saves:
// an extract from the bootsrap file
def init = { servletContext ->
def blueFV = new FieldValue(value: Color.blue)
def smallFV = new FieldValue(value: "small")
def fieldVals = [blueFV, smallFV]
saveData(fieldVals,berg.FieldValue)
}
public void saveData(List list, Class type){
def wholeList = type.list() ?: []
println("Started with adding the "+type.getName()+" classes.")
int saved = 0;
int failed = 0;
if(!wholeList){
list.each{ i ->
if(i.validate()){
i.save(flush:true, failOnError: true)
saved++
}
else{
println("! - - - Warning: '"+i.toString()+"' could not be created! - - - !")
failed++
}
}
if(failed > 0)//if one fails, let the message appear more clearly
println(".v.v.")
println("When saving the "+type.getName()+" classes: "+saved+" were saved, "+failed+" failed to be saved.")
if(failed > 0)
println(".^.^.")
}
}
The entire value column does not show up in the database

Related

Wren class does not implement a field

I'm trying to learn how to use Dome and Wren. To do this I've started working on a simple Flappy Bird clone.
The problem I'm having is that I get the error message
Bird does not implement bird_idle
It then points to line 63 in my main class which is shown below:
class Main {
resources=(value){ _resources = value }
bird=(value){ _bird = value }
construct new() {
_resources = Resources.new()
_bird = Bird.new(_resources.birdIdle, _resources.birdFlap, _resources.obstacleTile.width * 2, _resources.obstacleTile.height * 4, 10, 4)
}
init() {}
update() {}
draw(alpha) {
Canvas.cls()
Canvas.draw(_bird.bird_idle, _bird.center.x, _bird.center.y) <-- this is line 63
}
}
var Game = Main.new()
Since I'm new to Wren I don't quite understand what this means seeing as if you look at my bird class below, I should be implementing bird_idle. So what am I doing wrong?
class Bird {
bird_idle=(value){ _bird_idle = value } <-- Right?
bird_flap=(value){ _bird_flap = value }
center=(value){ _center = value }
gravity=(value){ _gravity = value }
force=(value){ _force = value }
velocity=(value){ _velocity = value }
velocityLimit=(value){ _velocityLimit = value }
isGameRunning=(value){ _isGameRunning = value }
construct new(idle, flap, horizontalPosition, verticalPosition, drag, jumpForce) {
_bird_idle = idle
_bird_flap = flap
_center = Vector.new(horizontalPosition + (idle.width * 0.5), verticalPosition + (idle.height*0.5))
_gravity = drag
_force = jumpForce
_velocityLimit = 1000
_isGameRunning = true
}
jump() {
_velocity = -_force
}
isTouchingCeiling() {
var birdTop = _center.y - (_bird_idle.height * 0.5)
if(birdTop < 0) {
return true
}
return false
}
isTouchingGround() {
var birdBottom = _center.y + (_bird_idle.height * 0.5)
if(birdBottom > height) {
return true
}
return false
}
}
You forgot to add the getter:
class Bird {
construct new(idle) {
_bird_idle = idle
}
bird_idle=(value){_bird_idle = value }
bird_idle{_bird_idle} // You need this if you want to access the field _bird_idle.
}
var my_bird = Bird.new("Idle")
my_bird.bird_idle = "Not Idle"
System.print(my_bird.bird_idle) // Output: Not Idle

cant able to test file extension on test class?

visuaforce page:
<apex:page sidebar="false" controller="UploadOpportunityScheduleLineItem123">
<apex:form >
<apex:sectionHeader title="Upload data from CSV file"/>
<apex:pagemessages />
<center>
<apex:inputFile value="{!contentFile}" filename="{!nameFile}" />
<apex:commandButton action="{!ReadFile}" value="Upload File" id="theButton" style="width:70px;"/>
<br/> <br/>
</center>
</apex:form>
</apex:page>
apex:
public with sharing class UploadOpportunityScheduleLineItem123{
// Global variables
public string nameFile{get;set;}
Public Id parentId{get;set;}
public Blob contentFile{get;set;}
List<account> lstScheduleToUpdate = new List<account>();
public account objSchedule{get;set;}
//String array for taking csv data by line.
String[] filelines = new String[]{};
//set for storing all id's from csv.
set<String> opptoupload{get;set;}
//Main constructor
public UploadOpportunityScheduleLineItem123()
{
//Initalizing required objects.
objSchedule = new account();
opptoupload = new set<String>();
}
//Method to read file content and check extension and file format.
public Pagereference ReadFile()
{
parentId=Apexpages.currentPage().getParameters().get('ParentId');
//If without selecting csv file you clicked on upload it will give error message.
if(nameFile == null)
{
ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.ERROR,'You should select csv file to upload');
ApexPages.addMessage(errormsg);
return null;
}
//Taking file extension.
String extension = nameFile.substring(nameFile.lastIndexOf('.')+1);
//Checking if file extension is .csv.
if(extension == 'csv' ||extension == 'CSV')
{
nameFile =blobToString( contentFile,'ISO-8859-1');
//Spliting by new line
filelines = nameFile.split('\n');
//Spliting values by (,) for checking coloumn size
for (Integer i=1;i<filelines.size();i++){
String[] inputconvalues = new String[]{};
inputconvalues = filelines[i].split(',');
account b = new account();
b.name= inputconvalues[0];
b.billingcountry = inputconvalues[1];
b.billingcity = inputconvalues[2];
lstScheduleToUpdate.add(b);
}
//Checking if list is not empty then updating.
if(lstScheduleToUpdate.Size()>0)
{
insert lstScheduleToUpdate;
}
ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.info,'Batches File uploaded successfully');
ApexPages.addMessage(errormsg);
return null;
}
//If file is not csv type then it will give error message.
else
{
ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.ERROR,'File type should be csv type');
ApexPages.addMessage(errormsg);
return null;
}
}
public static String blobToString(Blob input, String inCharset){
String hex = EncodingUtil.convertToHex(input);
System.assertEquals(0, hex.length() & 1);
final Integer bytesCount = hex.length() >> 1;
String[] bytes = new String[bytesCount];
for(Integer i = 0; i < bytesCount; ++i)
bytes[i] = hex.mid(i << 1, 2);
return EncodingUtil.urlDecode('%' + String.join(bytes, '%'), inCharset);
}
}
test class :
#IsTest(SeeAllData=true)
private class testexceltoaccount
{
static testmethod void testLoadData() {
StaticResource testdoc = [Select Id,Body from StaticResource where name ='testMethodCSVUpload1'];
UploadOpportunityScheduleLineItem123 testUpload = new UploadOpportunityScheduleLineItem123();
testUpload.contentFile= testdoc.Body;
testUpload.ReadFile();
}
}
Cant able to cross this section of code in code coverage :
String extension = nameFile.substring(nameFile.lastIndexOf('.')+1);
//Checking if file extension is .csv.
if(extension == 'csv' ||extension == 'CSV')
{
I tried many possible to cross code coverage but still it is at that point .Please help me in this regard.
Thanks in advance
When we use apex:inputFile on VF page and upload any file, then name of file is automatically update field into the field specified in filename attribute, but when you are writing test class you only specifying content of file
testUpload.contentFile= testdoc.Body;
You should add name in nameFile global variable manually
testUpload.nameFile= 'test.csv';
#IsTest(SeeAllData=true)
private class testexceltoaccount
{
static testmethod void testLoadData() {
StaticResource testdoc = [Select Id,Body,Name from StaticResource where name ='testMethodCSVUpload1'];
UploadOpportunityScheduleLineItem123 testUpload = new UploadOpportunityScheduleLineItem123();
testUpload.contentFile= testdoc.Body;
testUpload.nameFile= 'test.csv';
testUpload.ReadFile();
}
}

GRAILS - GORM : DuplicateKeyException during saving a new object

I use GORM to back occurrences in a database, from an excel file.
new ExcelBuilder(excelFile.inputStream).eachLine([labels: true, sheet: 0]) {
if (cell(0)) {
def nameA = cell(0)
def nameB = cell(1)
def a = Chapitre.findByNom(nameA)
def code = cell(2)
def designation = cell(3)
if (code == null || nameA == null || nameB == null) {
flash.messages << "error"
} else if (!Chapitre.findByNom(nameA)) {
flash.messages << "error"
} else if ( Rubrique.where{nom == nameB && chapitre == a}.list().size() == 0) {
flash.messages << "error"
} else if(Object.where{rubrique == Rubrique.findByNom(nameB) && c == code && d == designation}.count() > 0){
flash.messages << "error"
} else {
def b = Rubrique.findByNom(nameB)
def isNew = false;
Object.withNewSession {session2->
def object = Object.findOrCreateByCode(code)
if(object.designation == null)
isNew = true;
object.rubrique = b
object.d= (designation == null)?"":designation
// try {
rowCount += object.save()? 1 : 0
// } catch(ValidationException) {
// if(isNew)
// rowCount++;
// log.info("ErreuRRRRRRRRrrrRRrrRrRRrrrrRrrrRrrrRrrrr")
// }
}
}
}
currentLine++
}
flash.messages << "${rowCount} ligne create or update"
An update will break any worries, the course of the lines of file continue and database recording is effective.
However when it comes to inserting a new object, I get an Exception:
org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session:[fen.NuisanceType#2202];
nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
The registration of the object in question is effective , but the error raised off the path of the file.
When i uncommented the try and catch I bypasses the error and so all my copies of each file are created in the database .
I thus found a way around my worries, but I do not find it very clean and i come to you to try to understand my problem.
Without further information hard to give any clear answers. Is this code back in a service?(very much doubt it since it has flash.message pointing to controller doing all of it.) Try making it into a service and transactional then maybe you could look at removing withNewTransaction call.
You can read more about error created here:
Grails - DuplicateKeyException
Review comment:
"Well, that problem occurs when you are initializing a class new ClassD with an id or unique property manually, when there is another already in the session. So, you should try to get that entity first (that's what findOrCreateWhere does, but if you use an id you need to use get) and then use the instance found or create a new one for the update"
Hibernate Error: a different object with the same identifier value was already associated with the session
You code tidied up and running from service: (issues may go away) since I have also cleaned up the duplicated finds you were doing:
class TestService {
static transactional=true
def saveRecord() {
def results=[]
new ExcelBuilder(excelFile.inputStream).eachLine([labels: true, sheet: 0]) {
if (cell(0)) {
def nameA = cell(0)
def nameB = cell(1)
def code = cell(2)
def designation = cell(3)
def a = Chapitre.findByNom(nameA)
def b = Rubrique.where{nom == nameB && chapitre == a}
def c = Object.where{rubrique == b && c == code && d == designation}
if (!code||!nameA||!nameB||!a||!b||!c) {
results << "Error saving ${nameA} ${nameB} ${code}"
} else {
//boolean isNew = false
def object = Object.findOrSaveWhere(code:code)
if(object) {
if (!object.designation) {
rowCount++
results << "Record ${object} has no designation ? new Record?"
}
object.rubrique = b
object.d = designation ?: ''
object.save()
results << "Record ${object.id} is saved"
} else {
/*
* Could not save or find code:code now create a new object:
* object = new Object(code:code, rubrique:rubrique: d: designation ?: '').save()
*
*/
}
}
}
currentLine++
}
results << "${rowCount} ligne create or update"
return results
}
}

How to Change Controller Name and function name URL in Grails 2.2.2?

I am trying to change my controller name and method name in grails
e.g :abc.com/newUser/viewUser/4
i want to convert in below format
e.g :abc.com/new-user/view-user/4
Or
e.g :abc.com/new_user/view_user/4
for that i wrote a code :
package customize
import grails.web.UrlConverter
import org.apache.commons.lang.StringUtils
class CustomUrlConverter implements UrlConverter {
private static final String GRAILS_EXTENSION = '_'
String toUrlElement(String propertyOrClassName) {
if (StringUtils.isBlank(propertyOrClassName)) {
return propertyOrClassName
} else {
String[] r = propertyOrClassName.split("(?=\\p{Upper})");
String lowerPropertyOrClassName = propertyOrClassName.toLowerCase();
println r.length + "size()";
String extendedPropertyOrClassName="";
if(r.length > 1){
for(int i=0; i < r.length;i++){
extendedPropertyOrClassName = extendedPropertyOrClassName + r[i].toLowerCase()
if(i+1 < r.length ){
extendedPropertyOrClassName =addGrailsExtension(extendedPropertyOrClassName);
}
}
}else{
extendedPropertyOrClassName = propertyOrClassName.toLowerCase()
}
return extendedPropertyOrClassName
}
}
private String addGrailsExtension(String propertyOrClassName) {
if (propertyOrClassName.endsWith(GRAILS_EXTENSION)) {
return propertyOrClassName
} else {
return propertyOrClassName + GRAILS_EXTENSION
}
}
}
In Config.groovy
grails.web.url.converter = 'hyphenated'
// grails-app/conf/spring/resources.groovy
beans = {
"${grails.web.UrlConverter.BEAN_NAME}"(com.myapplication.MyUrlConverterImpl)
}
In this when i am trying to get all character in small letter like below Url
e.g :abc.com/newuser/viewuser/4
its working fine
But when i add underscore in between two character like below Url
e.g :abc.com/new_user/view_user/4
Its gives an error 404..
Please Help me out. If you have any other option to change URL also welcome..
Thank you
One of the easiest way to achieve your requirement is UrlMappings.groovy
"/new_user/view_user/$id"(controller: 'newUser', action: 'viewUser')

How to play the drop failed animation in ScalaFX/JavaFX 2?

In ScalaFX if I drop a TreeCell onto a control other than the containing TreeView then a short animation is played showing the dragged item returning to its original position.
The same happens if I drop the TreeCell outside of the application - e.g. onto the desktop.
If I drop the TreeCell onto the containing TreeView in a location that shouldn't be accepted I want the same animation to play, but setting:
event.dropCompleted = false
isn't enough to produce this effect.
Is there a way to play the drop failed animation from inside the TreeCell's onDragDropped event handler?
Edit
Added code sample as requested. Drag an entry and drop it outside the control and you will see the drop failed animation. Drag an entry and drop it below the list and the animation doesn't play. The question is how to make the animation play in the second case.
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.scene.paint.Color
import scalafx.scene.layout.Pane
import scalafx.Includes._
import scalafx.scene.input.{TransferMode, DataFormat, DragEvent, MouseEvent}
import scalafx.scene.control._
import javafx.scene.control.{TreeItem => jfxTreeItem}
import java.nio.ByteBuffer
import java.util
import scalafx.beans.value.ObservableValue
class StringRootItem(text: String) extends TreeItem[String](text) {
override def toString() = text
}
class StringTreeItem(text: String) extends TreeItem[String](text) {
override def toString() = text
}
object DragAndDropControl {
def apply(rootNodeName: String, entries: List[String]): DragAndDropControl = {
val rootItem = new StringRootItem(rootNodeName)
rootItem.setExpanded(true)
val children = rootItem.getChildren
entries.foreach(entry => {
children.add(new StringTreeItem(entry))
})
new DragAndDropControl(rootItem)
}
}
class DragAndDropControl(rootItem: StringRootItem) extends TreeView[String](rootItem) {
showRoot = false
cellFactory = (tree: TreeView[String]) => {
new StringDragAndDropCell(tree)
}
object StringDragAndDropCell {
val customFormat: DataFormat = new DataFormat("string.entry.custom")
var transferItem: TreeItem[String] = null
def toBuffer(entry: String): ByteBuffer = ByteBuffer.allocate(10)
def fromBuffer(buffer: ByteBuffer): String = null
}
class StringDragAndDropCell(tree: TreeView[String]) extends TreeCell[String] {
import StringDragAndDropCell._
private var stringEntry: String = null
onDragDetected = (event: MouseEvent) => {
val db = startDragAndDrop(TransferMode.MOVE)
import scala.collection.JavaConversions._
if ((treeItem ne null) && (treeItem.value ne null) && (treeItem.value.getValue ne null)) {
transferItem = treeItem.value
val content: Map[javafx.scene.input.DataFormat, AnyRef] = Map(customFormat.delegate -> toBuffer(transferItem.value()))
val contentMap: util.Map[javafx.scene.input.DataFormat, AnyRef] = mapAsJavaMap(content)
db.setContent(contentMap)
}
event.consume()
}
onDragOver = (event: DragEvent) => {
val db = event.getDragboard
if (db.hasContent(customFormat))
event.acceptTransferModes(TransferMode.MOVE)
event.consume()
}
onDragDone = (event: DragEvent) => {
if (event.transferMode == TransferMode.MOVE)
event.dragboard.clear()
event.consume()
}
onDragDropped = (event: DragEvent) => {
val db = event.getDragboard
var success = false
if (db.hasContent(customFormat))
success = stringEntry ne null
if (success)
if (event.gestureSource != event.delegate.getGestureTarget) {
treeItem().getParent.getChildren.removeAll(transferItem)
treeItem().getParent.getChildren.add(index(), transferItem)
}
event.dropCompleted = success
event.consume()
}
/*
* Change handler for the treeItem property.
*
* The treeItem property is set by JavaFX after construction and at any time when the cell is recycled for UI virtualization.
*
* The text property must be updated when the treeItem is set in order for the cell to render correctly (without this the cell will appear blank.)
*/
super.treeItem.onChange((observable: ObservableValue[jfxTreeItem[String], jfxTreeItem[String]], oldValue: jfxTreeItem[String], newValue: jfxTreeItem[String]) => {
if (newValue ne null) {
stringEntry = newValue.getValue
text = stringEntry
}
else
stringEntry = null
})
override def toString(): String = {
if (stringEntry == null)
null
else
s"ScalaFX string tree cell ${stringEntry.toString}"
}
}
}
object TestDragAndDrop extends JFXApp
{
println("javafx.runtime.version: " + System.getProperties.get("javafx.runtime.version"))
println("java.runtime.version: " + System.getProperties.get("java.runtime.version"))
stage = new JFXApp.PrimaryStage {
title = "Test Drag and Drop"
width = 600
height = 472
scene = new Scene {
fill = Color.LIGHTGREEN
root = new Pane {
content = DragAndDropControl("Numbers", List("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"))
}
}
}
}

Resources