views:

82

answers:

4

For our grails application, I've written a method that lets you upload a CSV file full of contacts, and it will parse the file and create contacts out of the data. I've used a test file of my own (hard-coding which fields mean what) and it works great.

But of course I can't leave the field references hard-coded like that, so my next step is to show the user a screen letting them map the columns in their file to our database fields (columns A and B hold names, column C holds e-mail, etc).

My question: what's the best way to temporarily store the data I extract in the first part, so it can be used at the end of the second? A domain class would seem like the logical choice, but I haven't found a graceful way to do this at all. Hibernate doesn't seem to be fond of 2D string arrays, and to implement it in an OO fashion would require several domain classes (ImportedCsv, CsvRow). Is that acceptable to have several top-level domain classes for such a small and temporary process?

I'm a bit of a grails newbie, so I'm not sure what's hackish and what's graceful. What would you do?

A: 

Store the data in the session object. You can store most arbitrary data such as arrays of strings or hash maps in session. It will last as long as the user is using the web app with a timeout period of something like 30 minutes although this can be increased or decreased as required. Once the user stops using the web app there session will time out and expire. If you don't need to keep the data around after the user is done with your application this is probably the easiest way.

Jared
+1  A: 
upload the file in the first action
store a blob in db 
parse the columns out display ui to map column to fields 
second action read the blob from db, create new domain objects, delete blob from db

i think storing the csv file in the session might lead to some problems.

Aaron Saunders
A: 

The first thing that came to mind when reading your question was Grails Web Flows. These are based on the Spring Web Flow project and make it quite easy to implement wizard-style view sequences. Think of them as a state machine. You can also save state between "steps" in the flow using the flow scope.

Daniel Rinser
flow scope is request with a session ref. Saving huge data in those scopes will kill the application performance if not cleaned propely. I think using web-flow just for a two step op is quite overengineered
Sammyrulez
A: 

I would agree with Aaron Saunders and say that you should store it in the database. This will allow you to save the users state in case their session times out.

Use a multi-part form to upload the file, then get the file out like this:

def uploadedFile = request.getFile( 'image' )
csvDomainInstance.csvFile = uploadedFile.bytes

Your domain object might look like this:

class ContactCsvFile {
  byte[] csvFile
  static constraints = {
    csvFile( nullable:true, maxSize:2097152 ) //2MB
  }
}

Then to read it out, do something like this (not tested):

def file = new File()
file.setBytes( csvDomainInstance.csvFile )
def csvText = file.getText()
Javid Jamae