1

I have been trying to bind my android multiform data to the play framework form binding. But right now its seems to be complaining that the Date format binding failed. Any help would be really greatly appreciated!

The format I am currently sending over from the android app is "yyyy-MM-dd"

Things if have tried:

  • Tried to set my own date format in the "application.conf" to date.format=yyyy-MM-dd
  • Tried to set the the java.util.Date format manually.

    val format = new java.text.SimpleDateFormat("yyyy-MM-dd")
      format.format(new java.util.Date())
    

Here is Http data mapping i receive from Android retrofit. I did a println on the "request.body.dataParts"

Map(stock -> List(11), productname -> List(pleasework), price -> List(11.0), userid -> List(test), brand -> List(nike), condition -> List(New (with defects)), date -> List("2015-09-20"), category -> List(Shoe), ean -> List(e0ee9583-fb10-43c1-80f3-c1725251adfc), sold -> List(true))

Error message Play Framework is complaining:

Binding Failed
List(FormError(date,error.date,List()))

Play Framework Controller Code:

val format = new java.text.SimpleDateFormat("yyyy-MM-dd")
      format.format(new java.util.Date())
      val userForm = Form(
        mapping(
          "ean" -> text,
          "date" -> of(dateFormat),
          "sold" -> boolean,
          "productname" -> text,
          "userid" -> text,
          "price" -> of(doubleFormat),
          "stock" -> number,
          "brand" -> text,
          "category" -> text ,
          "condition" -> text
        )(Product.apply)(Product.unapply)
      )

    def multiuploaddata  = Action(parse.multipartFormData) {
       implicit request =>

     userForm.bindFromRequest()(request).fold (
            errFrm =>{
              println("Binding Failed")
              println(errFrm.errors)
            },
            userData => {
              println("Success bind: " + userData.ean)
            }
          )
    }
      Ok("Receive MultiImage is okay!")
  }

Android Retrofit Interface Code:

@Multipart
@POST("/multiuploaddata")
void updateProductImageData(@Part("ean") String ean,
                            @Part("date") Date date,
                            @Part("sold") boolean sold,
                            @Part("productname") String productname,
                            @Part("userid") String userid,
                            @Part("price") double price,
                            @Part("stock") int stock,
                            @Part("brand") String brand,
                            @Part("category") String category,
                            @Part("condition") String condition
,  @PartMap Map<String, TypedFile> Files, Callback<Photo> callback);

Android Fragment onClickListener:

mDoneButton = (Button) v.findViewById(R.id.done_button);
    mDoneButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
// Calling the retrofit Interface to send Data and Images over to server
 service.updateProductImageData(mProduct.getId().toString(),
                    mProduct.getDate(), mProduct.isSold(), mProduct.getProductName(),
                    mProduct.getUserId(), mProduct.getPrice(), mProduct.getStock(), mProduct.getBrand(), mProduct.getCategory()[0],
                    mProduct.getCondition()[0], files, new retrofit.Callback<Photo>() {
                @Override
                public void success(Photo photo, Response response) {
                    Log.d(TAG, "SUCCESS UPLOAD MULTI IMAGE!!! " + response);
                }

                @Override
                public void failure(RetrofitError error) {

                }
            });
Jone45
  • 11
  • 1
  • try this https://github.com/square/retrofit/issues/291. this link has helped me to resolve my date issue. given link is just hint. – Mohammad Tauqir Sep 20 '15 at 04:08
  • Thanks alot for the link! i will try out : ) – Jone45 Sep 20 '15 at 05:22
  • Hi Haito, thanks for your advise. does it mean that the best way to send "date" data over from android to play framework is to use epoch? I did a search and found that there is 2 recommended method "epoch" and "pathbinder" http://stackoverflow.com/questions/30078615/what-is-the-ideal-way-to-send-a-date-parameter-over-a-get-request-in-play-framew – Jone45 Sep 20 '15 at 10:02

1 Answers1

0

I end up following Haito suggestion to convert the dates into epoch long values and send it over to play framework. so right now after retrieving the Date value from the play framework i will need to convert it back to a Date and do my own formatting.

val datetime = new Date(1442802362000L)

Updated Play framework code:

val userForm1 = Form(
mapping(
  "ean" -> text,
  "date" -> longNumber, <--- change to long instead of date
  "sold" -> boolean,
  "productname" -> text,
  "userid" -> text,
  "price" -> of(doubleFormat),
  "stock" -> number,
  "brand" -> text,
  "category" -> text ,
  "condition" -> text
)(Product1.apply)(Product1.unapply)
)

Android Fragment code:

service.updateProductImageData2(mProduct.getId().toString(),
                    // Convert the date value into long
                    mProduct.getDate().getTime(), mProduct.isSold(), mProduct.getProductName(),
                    mProduct.getUserId(), mProduct.getPrice(), mProduct.getStock(), mProduct.getBrand(), mProduct.getCategory()[0],
                    mProduct.getCondition()[0], files, new retrofit.Callback<Photo>() {
                        @Override
                        public void success(Photo photo, Response response) {
                            Log.d(TAG, "SUCCESS UPLOAD MULTI IMAGE!!! " + response);
                        }

                        @Override
                        public void failure(RetrofitError error) {

                        }
                    });

I actually did dig out the DateFormat and Parsing Function and try to modify it. But I guess i am still quite new to scala and couldn't get it to work.

One thing i did find it strange is that for the def dateParse(data: String) Function. If I pass in the value "2015-09-02" it will work. But if the value is taken from it's function parameter it will work. I did a println on the "data" parameter and it is the same "2015-09-02" but i just won't work.

// This will work
def dateParse(data: String) = {formatter.parseDateTime("2015-09-02").toDate}

// This will not work
def dateParse(data: String) = {formatter.parseDateTime(data).toDate}

The code for the parsing and dateFormat function:

private def parsing[T](parse: String => T, errMsg: String, errArgs: Seq[Any])(key: String, data: Map[String, String]): Either[Seq[FormError], T] = {
stringFormat.bind(key, data).right.flatMap { s =>
  println("The Data is: " + data("date"))
  scala.util.control.Exception.allCatch[T]
    .either(parse(s))
    .left.map(e => Seq(FormError(key, errMsg, errArgs)))
}
}

def dateFormat(pattern: String, timeZone: TimeZone = TimeZone.getDefault): Formatter[Date] = new Formatter[Date] {

val jodaTimeZone = org.joda.time.DateTimeZone.forTimeZone(timeZone)
val formatter = org.joda.time.format.DateTimeFormat.forPattern(pattern).withZone(jodaTimeZone)
def dateParse(data: String) = {formatter.parseDateTime(data).toDate}

override val format = Some(("format.date", Seq(pattern)))

def bind(key: String, data: Map[String, String]) = parsing(dateParse, "error.date", Nil)(key, data)

def unbind(key: String, value: Date) = Map(key -> formatter.print(new org.joda.time.DateTime(value).withZone(jodaTimeZone)))
}
Jone45
  • 11
  • 1