List of String throws ClassCastException when using gson with rest profile in Grails - gson

When I try to render List of Strings with GSON and Grails Rest profile app, I am getting
java.lang.ClassCastException: _info_app_name__schemaImporter_index_gson$_run_closure1 cannot be cast to grails.plugin.json.builder.StreamingJsonBuilder$StreamingJsonDelegate
My Controller class is as below
class SchemaImporterController {
static responseFormats = ['json']
def index() {
def data = [:]
data.stringList = [
'One',
'Two',
'Three',
'Four
] as ArrayList<String>
return data
}
}
and my GSON index view is as below
model{
List<String> stringList
}
json{
informationList stringList.each { String str ->
singleEntry str
}
}
I also tried different variations when declaring model variables like,
List stringList,
ArrayList
But its returning same error everytime I do this. Any idea why ? Just to note here that its working fine when I render other domain classes.

I found the culprit. I was using each when iterating over the list. I removed it and made my GSON view like below and it started working fine.
model{
List<String> stringList
}
json{
informationList stringList, { String str ->
singleEntry str
}
}

Related

How to get two attributes of a model in the same HTML file

Code
#RequestMapping(value = "/cars", params = "request")
public String showSomeAmountCars(HttpServletRequest request, Model model) {
String count = request.getParameter("count");
int parsedCount = Integer.parseInt(count);
model.addAttribute("someCars", carService.getCars(parsedCount));
return "cars";
}
In the method showSomeAmountCars I get some number of cars using parameter in URL link.
In the method showAllCars I get the whole list of cars.
Expected behavior
if I request /cars, then I get the list of cars from the HTML file
if I request /cars?count = 2, then I get the list of two cars from the same HTML file
Question
How can I get the two added attributes in the HTML file and make sure they don't conflict?
You can have an optional request parameter like this:
#GetMapping("/cars")
public String showSomeAmountCars(#RequestParam(name = "cars", required = false) Integer count, Model model) {
if( count == null ) {
model.addAttribute("cars", carService.getCars());
} else {
model.addAttribute("cars", carService.getCars(count));
}
return "cars";
}

unable to query child properties in OData with Web Api

I am using odata and attempting to filter queries on the properties of a child class.
I am using MongoDb to store a series of object and am wanting to query these objects using OData. The objects are auto generated from xml so there is some annoying inheritance, the basic object scenario is below.
public class Container {
public Parent Property {get; set;}
}
public class Parent {}
public class Child : Parent {
public StringWrapper Value {get; set;}
}
public class StringWrapper {
public string Value {get; set;}
}
So I have made the Container into an entity and made a controller which has the code:
public ContainerController : ODataController {
public PageResult<Container> Get(ODataQueryOptions<Container> queryOptions) {
IQueryable<Container> containers = mongoRepo.All();
var filteredContainers = queryOptions.ApplyTo(containers)
as IQueryable<Container>;
return new PageResult<Container>(filteredContainers,
Request.GetNextPageLink(),
Request.GetInlineCount());
}
}
I am then querying this with the uri:
http://...Container?$filter=Property/NS.Child/Value/Value eq 'example'
If I throw a break point after applying the queryoptions and look at the IQueryable.Expression it gives the result:
value(MongoDB.Driver.Linq.MongoQueryable`1[NS.Container])
.Where($it => (IIF((IIF((($it.Property As Child) == null), null, ($it.Property As Child).Value) == null), null, ($it.Property As Child).Value.Value) == value(System.Web.Http.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty))
when this is then resolved I get the following error
Unable to determine the serialization information for the expression: .
Edit
I tried implementing this basic case without using the mongo db and the same query works fine. I then tried a test with the mongo C# driver for using .where with the As method this resulted in the same error.
I found the query
queryable.Where(
it => (it.Property is Child && ((Child)it.Properties).Value.Value == "example"));
works correctly and was wondering if there is a way to get the query into this form from the same uri or alternatively get the C# driver for mongodb to convert as queries into this form?
Can you try this instead,
var filteredContainers = queryOptions.ApplyTo(containers,
new ODataQuerySettings
{
EnableConstantParameterization = false,
HandleNullPropagation = HandleNullPropagationOption.False
});
?

how to unit test controller when automapper is used?

here's my controller
[POST("signup")]
public virtual ActionResult Signup(UserRegisterViewModel user)
{
if (ModelState.IsValid)
{
var newUser = Mapper.Map<UserRegisterViewModel, User>(user);
var confirmation = _userService.AddUser(newUser);
if (confirmation.WasSuccessful)
return RedirectToAction(MVC.Home.Index());
else
ModelState.AddModelError("Email", confirmation.Message);
}
return View(user);
}
here's my unit test:
[Test]
public void Signup_Action_When_The_User_Model_Is_Valid_Returns_RedirectToRouteResult()
{
// Arrange
const string expectedRouteName = "~/Views/Home/Index.cshtml";
var registeredUser = new UserRegisterViewModel { Email = "newuser#test.com", Password = "123456789".Hash()};
var confirmation = new ActionConfirmation<User>
{
WasSuccessful = true,
Message = "",
Value = new User()
};
_userService.Setup(r => r.AddUser(new User())).Returns(confirmation);
_accountController = new AccountController(_userService.Object);
// Act
var result = _accountController.Signup(registeredUser) as RedirectToRouteResult;
// Assert
Assert.IsNotNull(result, "Should have returned a RedirectToRouteResult");
Assert.AreEqual(expectedRouteName, result.RouteName, "Route name should be {0}", expectedRouteName);
}
Unit test failed right here.
var result = _accountController.Signup(registeredUser) as RedirectToRouteResult;
when I debug my unit test, I got following error message: "Missing type map configuration or unsupported mapping."
I think its because configuration is in web project, not the unit test project. what should I do to fix it?
You need to have the mapper configured, so in your test class set up, not the per-test setup, call the code to set up the mappings. Note, you'll also probably need to modify your expectation for the user service call as the arguments won't match, i.e, they are different objects. Probably you want a test that checks if the properties of the object match those of the model being passed to the method.
You should really use an interface for the mapping engine so that you can mock it rather than using AutoMapper otherwise it is an integration test not a unit test.
AutoMapper has an interface called IMappingEngine that you can inject into your controller using your IoC container like below (this example is using StructureMap).
class MyRegistry : Registry
{
public MyRegistry()
{
For<IMyRepository>().Use<MyRepository>();
For<ILogger>().Use<Logger>();
Mapper.AddProfile(new AutoMapperProfile());
For<IMappingEngine>().Use(() => Mapper.Engine);
}
}
You will then be able to use dependency injection to inject AutoMapper's mapping engine into your controller, allowing you to reference your mappings like below:
[POST("signup")]
public virtual ActionResult Signup(UserRegisterViewModel user)
{
if (ModelState.IsValid)
{
var newUser = this.mappingEngine.Map<UserRegisterViewModel, User>(user);
var confirmation = _userService.AddUser(newUser);
if (confirmation.WasSuccessful)
return RedirectToAction(MVC.Home.Index());
else
ModelState.AddModelError("Email", confirmation.Message);
}
return View(user);
}
You can read more about this here: How to inject AutoMapper IMappingEngine with StructureMap
Probably it is cool to abstract mapping into MappingEngine.
Sometimes I use following approach to IOC Automapper
In IOC builder:
builder.RegisterInstance(AutoMapperConfiguration.GetAutoMapper()).As<IMapper>();
where GetAutoMapper is:
public class AutoMapperConfiguration
{
public static IMapper GetAutoMapper()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<OrderModelMapperProfile>();
cfg.AddProfile<OtherModelMapperProfile>();
//etc;
});
var mapper = config.CreateMapper();
return mapper;
}
}
And finally in Controller ctor
public MyController(IMapper mapper)
{
_mapper = mapper;
}

Visualforce 'Conversion Error setting value' -- binding problem with selectCheckboxes

I am getting a 'Conversion error setting value' when I try to save a record in my controller extension. The page looks the way I would expect, but when I select one or more checkboxes, it gives my that error. I'm not seeing what the error is here. Thanks for the help.
The page:
<apex:pageBlockSectionItem >
<apex:OutputLabel value="Assigned Areas of Coverage" for="books" />
<apex:selectCheckboxes value="{!selectedBooks}"
layout="pageDirection" id="books">
<apex:selectOptions value="{!options}" />
</apex:selectCheckboxes>
</apex:pageBlockSectionItem>
The controller:
public String[] selectedBooks {get; set;}
public List<SelectOption> options
{
get
{
List<SelectOption> result = new List<SelectOption>();
List<String> optionNames = bookNames(books);
optionNames.sort();
for(String n : optionNames){
if(!blacklist.contains(n)){
result.add(new SelectOption(n, n));
}
}
return result;
}
}
private List<Book__c> books
{
get
{ if (books == null){
books = [select Id, Name from Book__c];
}
return books;
}
set;
}
private List<String> bookNames(List<Coverage__c> coverage)
{
List<String> result = new List<String>();
for(Coverage__c c : coverage){
result.add(c.Book__r.Name);
}
return result;
}
private List<String> bookNames(List<Book__c> books)
{
List<String> result = new List<String>();
for(Book__c b : books){
result.add(b.Name);
}
return result;
}
private List<Id> bookIDs(List<String> bookNames)
{
List<Id> result = new List<Id>();
Set<String> bookNamesSet = new Set<String>(bookNames);
for(Book__c b : books){
if(bookNamesSet.contains(b.Name)){
result.add(b.Id);
}
}
return result;
}
I think you have to post more code and it's not clear what exactly you wish to achieve:
What's your actual "command" function, I don't see any <apex:commandButton action="{!fun}" ... > and not a single function from the controller looks like "public void fun()" or "public PageReference fun()" - I especially mean the part about taking no input arguments.
Your code does not compile, I've replaced Book__c with Account and Coverage with Contact, but for example the "blacklist" variable in
if(!blacklist.contains(n)){
is undefined. I can assume that this is same as "result", but you know... garbage in, garbage out. We might need just the part you've omitted ;) Also - can you replicate the problem using standard Salesforce objects so it's easier to test for us?
"selectedBooks" is read in the page but you never set value? Not even to the simplest selectedBooks = new String[]... The uninitialized variable a is solution to similar problem discussed on Salesforce message board.
Just a random thought - for bookIDs() function you might be better using Map<Id, Book__c> or Map<Id, String>. The first one can even be instantiated directly from [SELECT Id, Name FROM Book] if you need it. You want set of IDs - use the keySet() method afterwards. You want a list of books - use the values().

NHibernate: HasMany components and Where/Contains clause

I'm trying to work out how to create a query using Linq to NHibernate.
I have two classes like this:
public class Foo
{
private ISet<Bar> _bars = new HashedSet<Bar>();
public virtual ISet<Bar> Bars
{
get { return _bars; }
set { _bars = value; }
}
}
public class Bar
{
public string Name { get; set; }
public string Color { get; set; }
}
Foo's Bar collection is mapped as a one-to-many component collection.
Now I want to run a query that should look something like this:
var myBar = new Bar { Name = "test", Color = "testColor" };
var matchingFoos = Session.Linq<Foo>
.Where(foo => foo.Bars.Contains(myBar),
new BarEqualityComparer())
.ToList();
I am not sure if this is correct, but whenever I run this query I get a NullReferenceException from inside a method called NHibernate.Linq.Visitors.WhereArgumentsVisitor.GetCollectionContainsCriteria method.
Could anyone help me out with an alternative means of running this query?
The BarEqualityComparer will be the point of failure for sure. There is no simple way for the provider to translate custom class to an SQL statement.

Resources