has a behavior I can not understand.
I have 2 domain class, i'm using this names to illustrate the problem, Foo and Bar that is:
[Foo]
class Foo {
String value1
}
[Bar]
class Bar {
String value1
static belongsTo = [foo: Foo]
}
Now im my controller i have this:
def createBar = {
def foo = foo.get(params['foo_id'].toLong()) //this is a hidden field in form
def bar = new Bar()
bindData(bar, params, [exclude:['foo']])
bindData(bar, foo, [include:['foo']] //This not work!
//bar.foo = foo //This works fine!
bar.save()
}
When i save using just bindData the controller throws TransientObjectException saying the Foo is unsaved, but when i use the second form, the actions works fine, and saves the domain without exceptions.
Why this happens? I not understand, because for me, the bindValue() and the bar.foo is the same behavior.
I'm not using dbCreate in my app, only validate, this is the representations of the tables:
[Foo]
id (PK)
value1 (varchar)
[Bar]
id (PK)
value2 (varchar)
foo_id (FK)
I'm using grails 2.2.3
Thanks.
There are all sorts of problems with your code.
You're passing the instance of foo to the excludes, also the method name is bindData not bindValue:
bindValue(bar, params, [exclude:[foo]])
This should be
bindData(bar, params, [exclude:['foo']])
Related
I have a Foo class which is SUT and a Bar class, which is its collaborator. Foo calls run(List<Object> values) on the Bar with "expectedList" as an argument. Then, Foo will add a few more elements to this List so that its state will be different from what it was at the time of calling run(). Here's my test case.
#Test
public void testFoo() {
Bar collaborator = spy(new Bar());
Foo sut = new Foo(collaborator);
verify(collaborator).run(expectedList);
}
Note that the collaborator is actually a spy object rather than a mock. This test case will fail because even though run() was called with an argument equal to expectedList, it was modified since and its current value no longer equals expectedList. However, this is the way it is supposed to work, so I'm wondering if there's a way to have Mockito store the snapshot of parameters when a method is called and verify them based on these values rather than the most recent values.
Use an Answer to check the value of the argument when the method is called. You can either throw an AssertionError within the Answer if the value is wrong, or you can store the value, and do your assertion at the end.
The answer of Dawood ibn Kareem worked for me but I lacked an example, also I use Kotlin and Mockito-Kotlin, so my solution is like this:
class Foo(var mutable: String)
interface Bar {
fun run(foo: Foo)
}
#Test fun `validate mutable parameter at invocation`() {
val bar = mock<Bar>()
var valueAtInvocation: String? = null
whenever(bar.run(any())).then {
val foo = it.arguments.first() as Foo
valueAtInvocation = foo.mutable // Store mutable value as it was at the invocation
Unit // The answer
}
val foo = Foo(mutable = "first")
bar.run(foo)
valueAtInvocation isEqualTo "first"
foo.mutable = "second"
bar.run(foo)
valueAtInvocation isEqualTo "second"
}
valueAtInvocation will represent the value of the mutable property foo.mutable at the last invocation of bar.run(foo). Should also be possible to do assertions within the then {} block.
You can't call verify() on an object that is not a mock. Is this what you meant?
Bar collaborator = mock(Bar.class);
Foo sut = spy(new Foo(collaborator));
verify(collaborator).run(expectedList);
Why don't you try using argument capture to acquire the value of expected list when it was run and then you can compare it.
ArgumentCaptor<List> listCaptor = ArgumentCaptor.forClass(List.class);
verify(collaborator).run(listCaptor.capture());
assertEquals(expectedList, argument.getValue());
I'm trying to use Jackson to read JSON that looks like this:
{
api: {
version: "1.0"
},
list: [
{ // actually
foo: "foo", // x.phoo: "foo"
bar: "mane", // x.barr: "mane"
baz: "padme", // y.bazz: "padme"
qux: "hum" // y.quux: "hum"
},
...
]
}
I have the entire JSON string. All I really need is the list of objects, each of which contains the values for keys {foo bar baz quz}. How would you go about this? I don't know whether to use JsonNodes and navigate through the tree, or whether I can get to the list and then use ObjectMapper to map each list item to an object.
There is an additional hitch. The keys don't actually come is as foo bar baz qux, but as x.phoo x.barr y.bazz y.quux, and I want foo bar baz qux as the field names in the objects that get created. I'm hoping to use ObjectMapper's setPropertyNamingStrategy method for that.
You could create an object representing the whole JSON document.
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyJsonDocument {
private List<Foo> foos; // just declare this one field, the rest will get ignored
...
}
and use ObjectMapper to read the whole thing.
As for the field names,
#JsonNaming(MyXDroppingPropertyNamingStrategy.class)
public class Foo {
...
should work a charm.
I've done something like this recently, and here's my quick-and-dirty solution.
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> record = mapper.readValue( jsonString ,Map.class);
Map<String,Object>[] list = (Map<String, Object>[]) record.get("list");
/* Retrieve keyset (should be foo, bar, baz, qux) */
Set<String> keys = list[0].keySet();
/* Retrieve value of foo */
String foo = list[0].get("foo").toString();
This depends on a lot of generic object types and casting to be able to use the "list" object as an array of Maps. A more robust solution would be to an explicit class structure that mirrors the structure of your json, and pull in the json with the essentially the same code, but processing the result is simpler.
MyRecordClass record = mapper.readValue( jsonString ,MyRecordClass.class);
String foo = record.list[0].foo;
This second method depends on good mapping between your class's component variable names and your json's field names. Also on the structure matching. In general, I wouldn't bother with this unless I was going to use these record objects enough to make up for the time I've spent creating the classes.
Castle Windsor passes the registered concrete type to Controller's constructors. A typical implementation (no pun intended) is:
private readonly IDepartmentRepository _deptsRepository;
public DepartmentsController(IDepartmentRepository deptsRepository)
{
if (deptsRepository == null)
{
throw new ArgumentNullException("deptsRepository");
}
_deptsRepository = deptsRepository;
}
I need to pass the ctor a second parameter, if possible, so that I can pass that val on to the Repository constructor (I know: tramp data alert, but I don't know if there's a straightforward way around it:
public DepartmentsController(IDepartmentRepository deptsRepository, int DBInstance)
{
if (deptsRepository == null)
{
throw new ArgumentNullException("deptsRepository");
}
_deptsRepository = deptsRepository(DBInstance);
}
REPOSITORY
public DepartmentRepository(int dbInst)
{
string connStr = string.Format("Phoo{0}Bar", dbInst);
using (var conn = new OleDbConnection(connStr))
{
using (var cmd = conn.CreateCommand())
{
. . .
Is it possible to tweak what Castle Windsor sends to the Controller constructor this way? If so, how?
AND/BUT: For this to be of any value (to me, anyway), I need to be able to get the int val (that will be passed to the Controller) from the URL the client sends. IOW, if the client asks the server for data via:
http://locohost:4242/Platypus/GetAll/1
I need to pass a "1" as the second argument to PlatypusController.
If the user asks the server for data via:
http://locohost:4242/Platypus/GetAll/42
I need to pass a "42" as the second argument to PlatypusController.
etc.
This is what I did to solve my Controller/Repository data context Dilemma:
0) Added a database context argument to the Controller's routing attribute. IOW, this:
[Route("api/HHSUsers/GetAll")]
...got changed to this:
[Route("api/HHSUsers/GetAll/{dbContext=03}")]
1) Passed that database context arg to the Repository. To wit, this:
return _hhsusersrepository.GetAll();
...got changed to this:
return _hhsusersrepository.GetAll(dbContext);
...so that the Controller method is now:
[Route("api/HHSUsers/GetAll/{dbContext=03}")]
public IEnumerable<HHSUsers> GetAllHHSUsersRecords(int dbContext)
{
return _hhsusersrepository.GetAll(dbContext);
}
2) Changed the corresponding method in the Repository interface from:
IEnumerable<HHSUsers> GetAll();
...to this:
IEnumerable<HHSUsers> GetAll(string dbContext);
3) Changed the Repository method from this:
public HHSUsersRepository()
{
// All the data is loaded here in the ctor
}
public IEnumerable<HHSUsers> GetAll()
{
return hhsusers;
}
....to this:
public IEnumerable<HHSUsers> GetAll(string dbContext)
{
LoadHHSUsers(dbContext);
return hhsusers;
}
private void LoadHHSUsers(int dbContext)
{
string connStr = string.Format("Foo{0}Bar", dbContext);
// The same as previously from this point on, except that this:
// using (var conn = new OleDbConnection(#"Foo Bar Phoo Bar etc"...
// becomes:
// using (var conn = new OleDbConnection(connStr))
4) Tack the dbcontext val to the end of the URL when calling the method, so that it is this:
http://localhost:28642/api/HHSUsers/GetAll/42
...instead of this:
http://localhost:28642/api/HHSUsers/GetAll
If the data context to use is "03" I can omit the dbcontext arg from the URL, as 03 is the default value I set when I appended "=03" to the Controller's "dbContext" routing attribute arg.
I know some fancy-pants propeller-heads will find fault with this for some reason (for one reason because of the tramp data going here and there and everywhere like a hobo on steroids), but my response is the same as that of an athlete who is getting trash-talked by an opposing player and yet whose team is winning: just point at the scoreboard. IOW, this works for me, so that's pretty much all I care about. Style points are for runway models and, again, fancy-pants propeller-heads (AKA Star-Bellied Sneeches (as opposed to us plain
cats with the unstarred bellies)); see "The perfect is the enemy of the good."
This simple way has that self-same benefit -- of being (relatively) simple to grok and, thus, modify/refactor as necessary. Inelegant? Sure, but so was Joe Kapp.
Here is a Model
import org.bson.types.ObjectId
class Foo{
ObjectId id
String name
}
And here an action
def action = {
render(status:200, contentType:"application/json") {
['foo' : Foo.get(params.id)]
}
}
The action will return something like this
{"foo":{"class":"Foo","id":{"class":"org.bson.types.ObjectId","inc":340737392,"machine":-2019394572,"new":false,"time":1299107672000},"name":"fooName"]}
My question is, how can I send in the json the toString of the ObjectId, I don't want this
"id":{"class":"org.bson.types.ObjectId","inc":340737392,"machine":-2019394572,"new":false,"time":1299107672000}
I want something more like
"id":18893828183
I know I can select the parameters I want like:
def foo = Foo.get(params.id)
['foo' : 'Foo' :[id:foo.id.toString(), name:foo.name]]
But I don't want to declare always what I want to return as json, I want to return all the object, Foo.get(params.id).encodeAsJSON()...
Is there a way to override encodeAsJSON()
I already tried to add this
class Foo{
....
static transients : ['idStr']
def getIdStr(){
return this.id.toString()
}
....
}
But it's ignored in the encodeAsJSON()
I even tried this
class Foo{
....
def toJSON(){
def obj = this.encodeAsJSON()
def json = new JsonSlurper().parseText(obj);
json.idString = this.id.toString()
return json.toString()
}
...
}
this "works", but no....
because after this
render(status:200, contentType:"application/json") {
['foo' : Foo.get(params.id).toJSON()]
}
the render encode the json, so everything is "escaped"....
So what do you think is the solution, with a builder always defining what I want to return?
Hope, I made my question clear....
I'll start with the builder, hope you can give me another simpler / cleaner solution...
Thanks
edit
I just did a method that returns the object as a map so now I do something like this
render(status:200, contentType:"application/json") {
['foo' : getFooAsMap(Foo.get(params.id))]
}
Register this objectMarshaller at Bootstarp.groovy and it will work like a charm
import grails.converters.JSON
import org.bson.types.ObjectId
JSON.registerObjectMarshaller(ObjectId) {
return it.toStringMongod()
}
If you're going to be JSON-encoding your domain classes out to the web, I wonder if ObjectId might not be the best choice? The GORM/MongoDB integration allows you to use any type for the id. You could just declare it as a String type (which can be assigned as a toString of an ObjectId if you like to use that for its randomness) and then you don't need to worry about this mess. Any performance/scalability problems from this could be analysed/dealt with later, but I wouldn't expect there to be any unless it's a very large app.
Use GStrings in your map and you will get a numeric value for your ObjectId.
E.g.
render ["foo":"$foo.id"] as JSON
You can do this too:
def domainObj = YourDomainClass.get(params.id)
Map props = [:]
def domain = new DefaultGrailsDomainClass(YourDomainClass.class)
domain.properties.each{
props[it.name] = domainObj[it.name]
}
props["id"] = domainObj.id.toString()
render props as JSON
Or better yet, make it reusable. Put this closure someplace handy:
def mongoObjectResponse = {dobj ->
Map props = [:]
def domain = new DefaultGrailsDomainClass(YourDomainClass.class)
domain.properties.each{
props[it.name] = dobj[it.name]
}
props["id"] = dobj.id.toString()
// I like to leave room in my responses for messages and such
message = ""
obj = props
}
Then call like this from your controller:
return render(contentType: "text/json") {
mongoObjectResponse.delegate = delegate
mongoObjectResponse(domainObj)
}
Just define your domain class as
class Foo {
String id
String name
}
Instead of ObjectId
I have a class Foo with a field UpdateMe of type Confirmation as described below..
public class Foo
{
public Confirmation UpdateMe{get;set;}
public int BarInt{get;set}
}
public enum Confirmation
{
N = 0,
Y = 1
}
I have a whitelist that has UpdateMe, and runs the following way...
[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
public ActionResult Update(Foo foo)
{
if(ModelState.IsValid)
{
//this is the Foo as it exists in the backend..using Linq2Sql read/record behavior
Foo existingFoo = _Service.GetFoo();
string[] whitelist = { "UpdateMe" };
UpdateModel(existingFoo, whitelist);
//do persistence stuff down here...
}
}
the model is bound just fine, the incoming Foo has whatever UpdateMe value I set, however the UpdateModel procedure is not updating the property.
This has been ridiculously simplified, but rest assured the UpdateModel is working for other properties coming through the action.
Any idea why this particular public property is not updating?
Ok, heres the scoop.
The issue is that the field was mapped to a checkbox. When not writing the checkbox using an HtmlHelper it was not propagating into the ModelState, and therefore not being included in the UpdateModel.
When I switched to using an HtmlHelper, the ModelState was then including the checkbox value regardless of being selected(desired)...however this brought back the ugliness of mapping an enum type to a checkbox.