0

I'm trying to create a simple application so that I'll get familiar with grails. What the app does is a CRUD of profit and date. And I used date as the primary key.

I'm done with the add and read and I'm now working on the delete part.

This is sample db

> ---------------------------- 
>|   date       |   profit  |
> ---------------------------- 
>| 2015-08-01   |  4.45678  | 
>| 2015-08-02   |  76.45678 |
>| 2015-08-03   |  567      | 
>| 2015-08-04   |  6789.60  |
> ----------------------------

This is the error message:

URI /SampleGrailsApp/dailyProfit/delete/2015-08-10%2000:00:00.0 Class org.hibernate.TypeMismatchException Message Provided id of the wrong type for class samplegrailsapp.DailyProfit. Expected: class java.util.Date, got class java.lang.Long

This is the controller

package samplegrailsapp

import java.text.DateFormat
import java.text.SimpleDateFormat

class DailyProfitController {
    def scaffold = DailyProfit
    def index() { 
        list()
    }

    def save() {
       // Date myDate = params.date('test', 'yyyy-MM-dd');
        params.date_month = (Integer.parseInt(params.date_month)<10)? "0" + params.date_month : params.date_month
        params.date_day = (Integer.parseInt(params.date_day)<10)? "0" + params.date_day : params.date_day
        params.date = params.date_year + "-" + params.date_month + "-" + params.date_day
        def dailyProfit = new DailyProfit(params)
        println params.toString()
        dailyProfit.save()
        list()
        //render(view:"profitTable")

    }

    def list(){
        def dailyProfit = DailyProfit.list()
        render view:"profitTable",  model: [dailyProfit : dailyProfit]
    }


    def delete(Date date){
        def dailyProfit = DailyProfit.get(date)
        dailyProfit.delete(flush: true)
        list()
    }
}

HTML file is

<table class="table table-hover table-bordered">
<thead>
<tr>
<th>Date</th>
<th>Profit</th>
<th>Delete?</th>
</tr>
</thead>
<tbody> 
<g:each in="${dailyProfit}" var="dp">
<tr>
<td><g:formatDate format="yyyy-MM-dd" date="${dp.date}"/></td>
<td>
<g:formatNumber number="${dp.profit}" type="currency" currencyCode="PHP" format="###.##" />
</td>
<td>
<g:form controller="dailyProfit" action="delete" id="${dp.date}">
<g:actionSubmit value="Delete" >
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</g:actionSubmit>    
</g:form>
</td>
</tr>
</g:each>
</tbody>
</table>

This is DailyProfit.groovy

package samplegrailsapp

import java.text.DateFormat
import java.text.SimpleDateFormat
import org.grails.databinding.BindingFormat
class DailyProfit {
    @BindingFormat('yyyy-MM-dd')
    Date date;
    double profit; 

    static constraints = {
        date (blank:false, nullable:false, validator: {value, object ->
           DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
           Calendar cal  = Calendar.getInstance();
           cal.setTime(new Date());
           cal.set(Calendar.HOUR_OF_DAY, 0);
           cal.set(Calendar.MINUTE, 0);
           cal.set(Calendar.SECOND, 0);
           cal.set(Calendar.MILLISECOND, 0);
            if((cal.getTime().before(value) )){
                return false;
            } 
        })
        profit (blank:false, nullable:false, validator: {value, object ->
                if (!value.toString().matches(/^([1-9]{1}[0-9]*\.{0,1}\d{0,5}|0\.[0-9]{1,2}|0|\.[0-9]{1,5})$/) ) return false;
        })     
    }

    static mapping = {
        version false
        //id generator:'assigned', name:'date'
        id column: 'date', name: 'date', generator: 'assigned'
    }

    /*def beforeInsert() {
        id = date
    }*/
}

As you can see, I used this format for the date yyyy-MM-dd before it is written in the table. Now for the delete button which is located in the last column of the table, when I pass it to the action, it gets the raw format, not this yyyy-MM-dd and that's probably why I get the mismatch error. The question is what can I do so I can edit the date before it is passed to the delete action? or is there another way to delete a data? Thank you.

user3714598
  • 1,733
  • 5
  • 28
  • 45
  • Maybe you need this one: http://stackoverflow.com/questions/2871977/binding-a-grails-date-from-params-in-a-controller?lq=1 – user711189 Aug 11 '15 at 07:03
  • how about changing the statement to find `dailyProfit` to this - `def dailyProfit = DailyProfit.findByDate(date)` – tusar Aug 11 '15 at 07:04
  • @geo I already have that in my domain class, but it seems that it isn't working, by the way I also post the domain class. Thanks :) – user3714598 Aug 11 '15 at 07:13
  • @tusar Hi, here's the result URI /SampleGrailsApp/dailyProfit/delete/2015-08-09%2000:00:00.0 Class java.lang.NullPointerException Message Cannot invoke method delete() on null object ... its weird that it says null but the uri has a value. Could you check if I've done something wrong with the html? Thank you. – user3714598 Aug 11 '15 at 07:19
  • 1
    @user3714598 , I think there is a problem with parsing the `date`. Thats why the `dailyProfit` object was not found. Can you also format the parameter `id="${dp.date}"` to `id="${dp.date.format("yyyy-MM-dd")}"` in GSP so that it can be parsed correctly when supplied with parameters. Because currently the parameter is passed in a different format (e.g. `2015-08-09%2000:00:00.0` as you got in the log). – tusar Aug 11 '15 at 08:54
  • @tusar the date was parsed correctly as seen here **URI /SampleGrailsApp/dailyProfit/delete/2015-08-10 Class java.lang.NullPointerException Message Cannot invoke method delete() on null object** but I still have an error which is the null pointer. I also made additional checking, I tried to print the value of date inside the delete function and the output is this **Wed Aug 12 10:02:41 CST 2015** which is weird because I chose an aug-10 data. Could you think of other possible way to fix this? Thanks – user3714598 Aug 12 '15 at 02:27

3 Answers3

1

Your delete controller method is expecting a parameter named date, yet your form is not providing one. Instead the form is providing a parameter named id. To fix the form, add a hidden field with the name date and value ${dp.date}. That will map the DailyProfit's primary key, date, to the date parameter in your controller method.

Emmanuel Rosa
  • 9,697
  • 2
  • 14
  • 20
  • Yey! Thank you! It did fix my problem but may I ask if is it possible to pass a parameter without using the hidden field? Thanks :) – user3714598 Aug 12 '15 at 02:58
  • 1
    Yes. The form tag has a params attribute which expects a Map. You can set the value to ${[date: dp.date]} – Emmanuel Rosa Aug 12 '15 at 03:05
0

I think your error was happen before that delete(Date date) method, because that parameter is obviously a Date not Long.

But if you want to override PreDelete event, you can override application event on grails by implementing ApplicationListener<AbstractPersistenceEvent> and register that class in resources.groovy. Then you can interrupt PreDelete like below

@Override
    void onApplicationEvent(AbstractPersistenceEvent event) {

            switch (event.eventType) {
                \\case EventType.PostInsert:
                \\    break
                \\case EventType.PreUpdate:
                \\    break
                case EventType.PreDelete:
                    onPreDelete(event as PreDeleteEvent)
                    break
            }
    }

def onPreDelete(PreDeleteEvent event, final User user) {
        def domain = event.entityObject
        if(!domain instance of YourDomainClass)
            return
        //edit date in your domain before delete here
    }
Angga
  • 2,305
  • 1
  • 17
  • 21
0

In general i would say, specify a date format and the use,

Date.format(dateFormatter, value)

to get the value parsed as a date. For example,

class DailyProfitController {
   //point of interest
   String dateFormat = "yyyy-MM-dd"

   def save() {
    // Date myDate = params.date('test', 'yyyy-MM-dd');
    params.date_month = (Integer.parseInt(params.date_month)<10)? "0" + params.date_month : params.date_month
    params.date_day = (Integer.parseInt(params.date_day)<10)? "0" + params.date_day : params.date_day

    //another point of interest
    params.date = Date.parse(dateFormat, params.date_year + "-" + params.date_month + "-" + params.date_day)
    def dailyProfit = new DailyProfit(params)
    println params.toString()
    dailyProfit.save()
    list()
    //render(view:"profitTable")

}
ivanorone
  • 450
  • 4
  • 17