Grails + Spock: NullPointerException when doing addTo* on an embedded hasMany field - grails

I have domain class:
class MarketCommoditiesConfiguration extends MarketConfiguration {
static mapWith = "mongo"
static hasMany = ['commodities': Commodity]
static embedded = ['commodities']
...
Doing save after addToCommodities throws the following exception.
| java.lang.NullPointerException
at org.grails.datastore.mapping.model.types.Association.getInverseSide(Association.java:71)
at org.grails.datastore.mapping.engine.NativeEntryEntityPersister.handleEmbeddedInstance(NativeEntryEntityPersister.java:1254)
at org.grails.datastore.mapping.engine.NativeEntryEntityPersister.handleEmbeddedInstance(NativeEntryEntityPersister.java:1215)
at org.grails.datastore.mapping.engine.NativeEntryEntityPersister.handleEmbeddedToMany(NativeEntryEntityPersister.java:1188)
at org.grails.datastore.mapping.engine.NativeEntryEntityPersister.persistEntity(NativeEntryEntityPersister.java:1077)
at org.grails.datastore.mapping.engine.NativeEntryEntityPersister.persistEntity(NativeEntryEntityPersister.java:1138)
at org.grails.datastore.mapping.engine.EntityPersister.persist(EntityPersister.java:160)
at org.grails.datastore.mapping.core.AbstractSession.persist(AbstractSession.java:522)
at org.grails.datastore.gorm.GormInstanceApi.doSave(GormInstanceApi.groovy:194)
at org.grails.datastore.gorm.GormInstanceApi.save_closure5(GormInstanceApi.groovy:162)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:161)
at com.apposit.terra.connect.service.MarketService.addCommodityToMarket(MarketService.groovy:248)
at com.apposit.terra.connect.service.MarketServiceSpec.Test addCommodityToMarket creates a new next month configuration if current month's configuration doesn't exist(MarketServiceSpec.groovy:164)

Putting Keyword inside #Mock annotation solved it. http://grails.1312388.n4.nabble.com/Grails-MongoDb-embedded-collection-causes-nullpointerexception-td4644098.html contains more involved discussion.
I know this is super-old, but a Google search led me here whilst
facing the same issue. Make sure that you have added #Mock(User) to
your unit test class. In my case, I had multiple levels of embedded
domain classes, and each of them had to be mocked.
- clarkdustin

Related

Object Id set as null when saving - AjaxDependencySelection

So I decided to use AjaxDependencySelection Plugin for Grails, and it has proven to be very useful. However, I am trying to implement autoComplete boxes, and it does not seem to be saving the object id when using an Autocompleted selection. Here is my implementation in my gsp
<g:selectPrimary id="template" name="template"
domain='dms.nexusglobal.Template'
searchField='templateName'
collectField='id'
domain2='dms.nexusglobal.Tag'
bindid="template.id"
searchField2='tagName'
collectField2='id'
hidden="hiddenNew"
noSelection="['': 'Please choose Template']"
setId="tag"
value="${documentPartInstance?.template}"/>
<g:selectSecondary id="tag" name="tag"
domain2='dms.nexusglobal.Subtag'
bindid="tag.id"
searchField2='subtagName'
collectField2='id'
autocomp="1"
noSelection="['': 'Please choose Tag']"
setId="subtag"
value="${documentPartInstance?.tag}"/>
<g:autoCompleteSecondary id="subtag" name="subtagId"
domain='dms.nexusglobal.Subtag'
primarybind='tag.id'
hidden='tag'
hidden2='hidden5'
searchField='subtagName'
collectField='id'
value='${documentPartInstance?.subtag}'/>
<input type=hidden id="hidden5" name="subtagId" value="${documentPartInstance?.subtag}"/>
However, everytime I save it, I am presented with this error Column 'subtag_id' cannot be null . Here is my domain class definition for Subtag
class Subtag {
static scaffold = true
String subtagName
static belongsTo = [tag : Tag]
public Subtag()
{
}
public Subtag(String s)
{
subtagName = s
}
static constraints = {
}
String toString(){
subtagName
}
}
Tag hasMany subtags as well
It seems to be creating new Subtag instances when using the autoselect box (as an error shows up saying Could not find matching constructor for:packagename.Subtag(java.lang.String) Although this is a feature I am looking to implement in my application at later stages (being able to create new Subtags on the fly when creating a document Part), right now, all I would like to be able to do is just choose from my already existing subtags.
When I add in a string constructor, it comes back with the error that Column subtag_id cannot be null
I have developed it so will try help you through your issue.
The problem is that you are trying to push a value from selectSecondary and update the elementId of g:autocomplete which is actually a seperate entity.
I will update the plugin with a new method, need to test it out first.. Also take a look at g:selectAutoComplete. Although this method would only work if your secondary was the primary task... so no good in that case either..
hang on and look out for 0.37 release
Released 0.37 documentation on how to do such a thing here: https://github.com/vahidhedayati/ajaxdependancyselection/wiki/from-selection-to-autocomplete---how-to

Basic problems to use Vaadin 7 + Grails 2.3 (Persistence, domain class design, get Hibernate Session)

I'm using Vaadin 7 + Grails 2.3, there is some questions
My domain classes
class Base {
private static final Date NULL_DATE = new Date(0)
Date createdAt = NULL_DATE;
Date updatedAt = NULL_DATE;
def beforeInsert(){
createdAt = new Date();
updatedAt = new Date();
}
def beforeUpdate(){
updatedAt = new Date();
}
static mapping = {
autoTimestamp true
}
}
abstract class Person extends Base{
String name;
String name2;
String phone1;
String phone2;
static constraints = {
name2 nullable:true
phone1 nullable:true
phone2 nullable:true
}
}
class Customer extends Person {
double credit;
}
THE PROBLEMS
PROBLEM 1
In my Vaadin class UI, if I try this
class MyUI extends UI {
#Override
protected void init(VaadinRequest vaadinRequest) {
Customer customer = new Customer()
customer.name="RODRIGO"
customer.save()
}
}
Show this error
Servlet.service() for servlet [VaadinServlet 0] in context with path [/AgileWeb] threw exception [com.vaadin.server.ServiceException: groovy.lang.MissingPropertyException: No such property: name for class: agileweb.Customer
Possible solutions: all] with root cause
Message: No such property: name for class: agileweb.Customer
Possible solutions: all
there is no "name" property? The class Customer extends Person that has this property.
PROBLEM 2
If I try this
Customer customer = new Customer()
Customer.setName("RODRIGO")
Customer.save()
Show thos error : Message: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
I have seach about this error but I didn't understand to fix it, maybe I'm new with Grails
PROBLEM 3 - ACTUALLY IS A QUESTION
I know that I can use BeanItemContainer, just from List object, that is possible with no problem, but BeanItemContainer is not lazy load, I'd like to use HbnContainer addon (https://vaadin.com/directory#addon/hbncontainer) becase it just need a hibernate session, so How Can I get the "Hibernante session", is there any example and how to do it?
PROBLEM 4 - ACTUALLY IS A QUESTION (AGAIN)
Following this tutorial https://vaadin.com/wiki/-/wiki/Main/Vaadin%20on%20Grails%20-%20Database%20access
It works to save object in the database, but the questions
- Is it really necessary to create a service for each domain class? I have read that it's recomend to put domain logical in the services, I agree with this, but what about simple domain that no need any logical?
so, is there possible to create something like DAO for services? is there any service design to avoid repeted code just to save objects?
I know that are many questions but I think these questions are the same of others, I really want to use Vaadin + Grails to enjoy the better of both, but is not easy to me at the moment!
Before I start answering your question, let me question you domain model. Base class is generally fine, but I want to talk about Person and Customer. You may have good reasons why you picked up inheritance, but please think of composition. Maybe you could have Person that contains a reference to an enum, that states type of the person. You could start here with that: http://en.wikipedia.org/wiki/Composition_over_inheritance
I think you have a typo there. Call save() method on 'customer' not 'Customer', which is a class
When there is a request coming to Grails application, it opens a session and the session is available during that request. There is not this kind of behavior like that in Vaadin. You need to put it into a Service. Yes, you can make generic service to save an object
class GenericService { def save(def domain) { domain.save(failOnError:true) }}
You can get the session factory like this
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
def ctx = AH.application.mainContext
def sessionFactory = ctx.sessionFactory
or
ApplicationContext applicationContext = grailsApplication.mainContext
ConfigurableLocalSessionFactoryBean factory = applicationContext.getBean('&sessionFactory')
As I wrote, you could create GenericService or a service per domain object. Just to keep in mind that GenericService should only save an object and contain no other logic that would be specific for a domain object.

grails removeFrom not working in Integration Test

All of this is on Grails 2.2.3.
I have two classes in a One-to-many relationship, and a service which removes a list of ids
class Box {
String name
static hasMany = [items:ItemDomain]
static constraints = {
items(nullable:true)
}
}
and
class ItemDomain { String name Box box
static belongsTo = Box
static constraints = {
name(blank:false,unique:['box'], maxSize:127)
box(nullable:false) } }
In the service, here's the problem section:
def itemsToDelete = params.itemsToDelete //List of DB ids
List<ItemDomain> items= []
items.addAll(box.items) //Copy the list to avoid concurrent mod exception
for(ItemDomain item : items)
{
if(itemsToDelete.contains(item.id))
{
box.removeFromItems(item)
item.delete()
}
box.save(flush: true)
}
This works fine when running the application, but from integration testing it fails with
InvalidDataAccessApiUsageException: deleted object would be re-saved by cascade (remove deleted object from associations)
If I take out the flush, and eventually it will fail with:
Field error in object 'mypackage.ItemDomain' on field 'box': rejected value [null];
Adding logging, I see the size of box.items before entering the loop is the same as it is after exiting the loop, printing the items in the loop before and after shows that the item.box field for the deleted items changes to null. I've tried messing with the cascade mapping in the parent class... I'm at a loss as to whether I'm doing something wrong or if this is an issue with integration testing. The only similar issues I found were against grails 1.1 and had no resolution in the threads that I found.
I appreciate any feedback.
So, not surprisingly, I was doing something wrong. It turns out that my equals() and hashCode() implementations on the ItemDomain class were including a field that was never supposed to change, but due to requirements creep, was now changing and the methods never got updated properly.

Groovy:Apparent variable xyz was found in a static scope but doesn't refer to a local variable, static field or class. Possible causes:

I am getting this "error" in an Spring Tool Suite for all of my domain classes. Its not really an error, because it compiles fine. But it's masking real compile errors, how can I get rid of it ? They are in the same package, so I dont need the import, if I add the import it says it can't find the class...
So the following code produce a red x
Groovy:Apparent variable 'ExampleB' was found in a static scope but doesn't refer to a local variable, static
field or class. Possible causes:
package domain.com.so;
class ExampleA {
static belongsTo = [exampleB: ExampleB]
static constraints = {
}
}
And this code produces a simpilar error:
Groovy:Apparent variable 'ExampleA' was found in a static scope but doesn't refer to a local variable, static field
or class. Possible causes:
package domain.com.so;
class ExampleB {
static hasMany = [exampleAs: ExampleA]
static constraints = {
}
}
Normally when STS complains something like this I run
grails clean
and
grails compile --refresh-dependencies
This happens quite often when I'm making changes to static members and the dynamic reloading is enabled while running the application. I find I have to delete and re-add the project to the workspace. It's almost like the metadata for the project gets in a "stuck" state of when the error occurred during run-time.

Beginner Groovy

I'm following the code examples in 'The Definitive Guide to Grails' by Graeme Keith Rocher, and have come across a rather unusual stumbling block.
Essentially, 2 domain classes exist - Bookmark & Tag.
Bookmark:
class Bookmark {
static hasMany = [tags:Tag]
URL url
String title
String notes
Date dateCreated = new Date()
}
Tag:
class Tag{
static belongsTo= Bookmark
Bookmark bookmark
String name
}
I'm instructed to launch the Grails Console (is this the same as the groovy console)and create a new object as follows.
def b = new Bookmark(url: new URL('http://grails.org/'), title:'Grails', notes:'Groovy')
This results in:
Result: Bookmark : null
According to the book, GORM automatically provides an implementation of an addTag method. So I code...
b.addTag( new Tag(name: 'grails'))
Only to get whammed with the error message:
Exception thrown: No such property: b for class: ConsoleScript1
groovy.lang.MissingPropertyException: No such property: b for class: ConsoleScript1 at ConsoleScript1.run(ConsoleScript1:2)
The author hasn't accounted for this in the book. I was wondering if anyone could help me out?
Thanks.
Are you reading the 1st edition of the book? If so it's quite outdated. The add* methods have been deprecated since 0.5. It was replaced by addTo* so do this instead:
b.addToTags( new Tag(name: 'grails'))
Assuming your code example shouldn't have Bookmarks defined twice (copy and paste error?) and Tag might look like this:
class Tag {
String name
}
The groovy console is not the same as the grails console. To access the grails console, type grails console in your application directory - you should get a Java GUI app. It's possible that the example will work then because grails add some stuff to the standard Groovy.
Also, your problem isn't the addTag method, but the item b that you defined which cannot be found. Try entering the whole script into the console at once and executing it, instead of executing it line by line.

Resources