reports in jasper grails - grails

My controller action is
def jasper () {
def emp = Employee.findAll()
chain(controller:'jasper', action:'index', model:[data:emp],params:params)
}
and in my jrxml file i have following fields: name, lastname, gender, phone
I want to write a query that would have data only of name and lastname but with same jrxml file then my action would be
def jasper () {
def emp = Employee.executeQuery("select a.name a.lastname from Employee a ")
chain(controller:'jasper', action:'index', model:[data:emp],params:params)
}
This do not print only name and lastname in my report rather gives NoSuchMethodException. How to do this?

I don't think that the second query result could be a replacement of the first since the structure of the result is completely different.
In the first case you will get a List<Employee>, while in the second case you get an List<Object[]>.
You could rework your Jasper report to expect List<Object[]> and use select a.name, a.lastname, a.gender, a.phone from Employee a for the first scenario. In this case, you could safeguard the report agains the possible null values so that the report works well with the second, more limited result set.

Related

What is the correct syntax for projection of a child property in a System.Linq.Dynamic.Core Select

I am using System.Linq.Dynamic.Core v 1.2.24 to create a dynamic select statement when querying SQL Server via Entity Framework. This is sitting behind a GraphQL API and the intention is to make the database query as efficient as possible - only query the database for the requested columns.
I have the projection working for the type being enumerated but that type has a child property which also needs projection.
I have created a simple Fiddle to demonstrate this .
https://dotnetfiddle.net/nvU7DB
In the example I am querying a Person collection and Person has a property Address. I am successfully projecting the Person properties but can't figure out how to project the Address properties. I have not been able to find any examples of this.
This dynamic linq string will bring back all properties of Address:
"new Person(Id, FirstName, Address)"
but I want to do a projection on Address to just populate Id and City for example.
I was thinking the string might look like this
"new Person(Id, FirstName, new Address(Id, City)"
but this results in "Unhandled exception. Type 'Address' not found (at index 37)"
Without the 'new':
"new Person(Id, FirstName, Address(Id, City))"
which results in "Unhandled exception. No property or field 'City' exists in type 'Person' (at index 38)".
To clarify what I'm trying to do, this is what the projection would look like in C# code:
var projectedPeople = people.Select(
e => new Person() {
Id = e.Id,
FirstName = e.FirstName,
Address = new Address(){
Id = e.Address.Id,
City = e.Address.City
}
});
Any help or insights would be appreciated.
For anyone picking this up later, the solution was as follows
string dynamicSelect = "new Person(Id, FirstName, new Address(it.Address.Id, it.Address.AddressLine1, it.Address.City) as Address)";
ParsingConfig parsingConfig = new ParsingConfig(){ResolveTypesBySimpleName = true};
IEnumerable result = (IEnumerable)peopleQueryable.Select(parsingConfig, dynamicSelect);

Querying over nested assets in Hyperledger Composer

I want to write a specific query for my Hyperledger Composer app. Below, I have 2 assets and a transaction. Asset1 has a field called contents, which is an array of type Asset2. The associated code is below:
namespace org.acme.biznet
asset Asset1 identified by Asset1Id {
o String Asset1Id
--> Asset2[] contents
}
asset Asset2 identified by Asset2Id {
o String Asset2Id
}
transaction Transact {
--> Asset1 asset1
}
I want to select all instances of Transact where the associated Asset1 has a specified Asset2 inside. The closest solution I came to the query below, which did not work.
query GetTransactionsThatHaveAsset2 {
description: ""
statement:
SELECT org.acme.biznet.Transact
WHERE (asset1.contents CONTAINS (Asset2Id == _$propId))
}
The thing is, I have also written the query below.
query GetAsset1sThatHaveAsset2 {
description: ""
statement:
SELECT org.acme.biznet.Asset1
WHERE (contents CONTAINS (Asset2Id == _$propId))
}
This query behaves as intended, but it's selecting over Asset1. I want to select over Transact. How would I write this query?
no, you can't presently nest the query like you propose, nested named queries are not currently implemented in Composer (CouchDB is not a relational DB, and hence Composer query language can't translate the nested query presently to be translated to CouchDB) 2) Transact is a transaction - it contains a relationship identifier(s) you defined in your model, not the nested data stored in the related asset. You would have to define a query that searches for all transactions that matches the asset1 identifier field you passed to the trxn - then in your code, you can check transact.asset1.contents contains the 'something' (passed in to the trxn too?) using a javascript match - quite straightforward). Alternatively, you could use the REST API filters (loopback filters as opposed to queries) where (form your app code) you can resolve the relationships of transaction (Transact) back to asset1 (and its contents) using the REST call with filter eg
{"where":{"asset1":"resource:org.acme.net.Asset1#1"}, "include":"resolve"} . Hope this helps, maybe its nesting you're looking for exclusively..
In my case, I have these assets
// Define assets
asset Product identified by productId {
o String productId
o String description
o String serialNumber
o String modelNumber
o String status // TRANSFERED, RECEIVED, RECLAMED
o DateTime joinTime
--> Trader previousOwner
--> Trader currentOwner
--> Trader newOwner
}
// Trade, moves product from to a new owner.
transaction Trade {
--> Product product
--> Trader newOwner
o String trade_type
}
Executing a trade transaction results in the record:
{
"$class": "org.sp.network.Trade",
"product": "resource:org.sp.network.Product#123",
"newOwner": "resource:org.sp.network.Trader#6694",
"trade_type": "Trade",
"transactionId": "e39a86ed4748a3ab73b5e9c023f6bb0ca025098af09b8b5b2dca8f5f7ef0db67",
"timestamp": "2019-06-13T12:04:20.180Z"
}
And to query all Trade transactions that contain a product is
query ProductPath{
description: "Selete all Trade transactions for a specific ProductId"
statement:
SELECT org.sp.network.Trade
WHERE (_$productId==product)
}
Using the rest server: the value of _$productId is resource:org.sp.network.Product#123

Querying in Hyperledger Composer

When I try to make the query:
query PapersFromAPoll
{
description: "retrieve all the papers from a poll"
statement:
SELECT org.acme.democracity.Paper
WHERE(poll.pollId == _$id)
}
I am not able to get any rows, here is the fragment where I make this query:
return query('PapersFromAPoll',{id : count.poll.pollId})
It is strange because when I erase the WHERE statement and I make a simple query without any parameters it works perfectly.
Paper and Poll in model.cto file:
asset Paper identified by paperId {
o String paperId
o String[] fields
--> Poll poll //Paper related with a poll
}
asset Poll identified by pollId {
o String pollId
o Ask[] asks
}
query PapersFromAPoll
{
description: "retrieve all the papers from a poll"
statement:
SELECT org.acme.democracity.Paper
WHERE(poll == _$pollId)
}
So you can filter by the Poll asset by giving a reference to that Poll asset. When you try to query with the pollId it will have to be a reference to the resource resource:org.acme.democracity.Poll#{insert_id}

Grails - Convert String data to Date

Lets say, i have a "Book" class with field "availableOn"(as shown below).
class Book {
String availableOn;
}
The fields holds values
"All days" or
String representation of a date. For example "13/06/2012"
How can i get all Books that are available within next two days? The below code would throw an exception ("java.util.Date cannot be cast to java.lang.String")
def books = c.list(){
between('availableOn', new Date(), new Date() + 2)
}
PS : Am working on a legacy DB, and so am not suppose to change the schema :(
I think there are 2 problems which the between statement will have:
availableOn cannot be converted to a Date for comparison when its value is All days
Even when availableOn has a date value in it, it is not converted to a Date for the comparison
I'd try something along the lines of this:
def now = new Date()
def books = Book.findAllByAvailableNotEqual("All days").findAll { book ->
Date.parse('dd/MM/yyyy', book.availableOn) > now && Date.parse('dd/MM/yyyy', book.availableOn) < now+2
}
Clearly, this can be done in a nicer way (adding some methods to the domain class for example), but this should illustrate my idea...
I don't have a criteria based solution, but you can try something like this:
Book.executeQuery(
"select book from Book book where book.availableOn = :availableOn or to_date(book.availableOn, :format) between (:startDate, :endDate) ",
[availableOn:"All days", format: "dd/MM/yyyy", startDate: startDate, endDate:endDate])
The problem with my solution is that this query becomes DB dependent. to_date is an Oracle function. You may want to alter this to fit your database
You can use format on a date to get desired string format of it.
new Date().format('dd/MM/yyyy')
And your criteria would get modified to
def books = c.list(){
def todayDateStr = new Date().format('dd/MM/yyyy')
def twoDaysAfterTodayDateStr = (new Date()+2).format('dd/MM/yyyy')
or{
between('availableOn', todayDateStr, twoDaysAfterTodayDateStr)
eq 'availableOn', 'All Days'
}
}
Test if the str comparison works, otherwise other ways has to be used. Sending from phone, excuse my typos.
UPDATE
The above would fail in peculiar cases when dates are like "01/01/2013" and "07/11/2011".
Alternatively, you can use sqlRestriction but in that case it gets tightly coupled with the underlying database. Something like this can be done if Oracle db is used:
def books = c.list(){
def todayDateStr = new Date().format('dd/MM/yyyy')
def twoDaysAfterTodayDateStr = (new Date()+2).format('dd/MM/yyyy')
or{
sqlRestriction "to_date(available_on, 'DD/MM/YYYY') between to_date(todayDateStr, 'DD/MM/YYYY') and to_date(twoDaysAfterTodayDateStr, 'DD/MM/YYYY')"
eq 'availableOn', 'All Days'
}
}

AutoIncrement fields other than Id in grails

I'm new to Grails. I have a field in my domain object which I define as an String.
String ponum
When i click first time on create page ,the "ponum" field has to display 0001 and later it has to save in database.And When i click on second time the "ponum" field has to display 0002 and later it has to save in database.Everytime i click on create page "ponum" field has to autoincrement and save it database.I google ,but i did not get any document.
thanks
As things get an id anyway (assuming your using a regular rdbms with standard id genaerator), why not just pretend there's a variable ponum which is based on the id?
Just add a getter to your domain class:
class Page {
String getPonum() {
String.format( "%04d", id )
}
}
According to this answer, it is not possible to use hibernate generators (those used for ids) to do that. If you really need to use Hibernate generators, a workaround is described in the answer as well.
In your case, you could use an interceptor to generator your ponum property when inserting a new object:
class Yours {
int ponum
def beforeInsert() {
def lastPonum = Book.list([sort: 'ponum', order:'desc', max: 1])
if(lastPonum)
ponum = (lastPonum.pop().ponum as int) + 1 as String
else
ponum = '0'
}
}

Resources