Using java.sql.timestamp

638 views
Skip to first unread message

Evan Meagher

unread,
Nov 3, 2011, 3:21:26 AM11/3/11
to play-fr...@googlegroups.com
Is there a way to use java.sql.timestamp when saving records to MySQL? I'm using Play 1.2.3 with play-scala 0.9.1.

Whenever I try to use java.sql.timestamp, my unit tests throw NullPointerExceptions:

Internal Server Error (500) for request GET /@tests/RecipeSpec.class
Execution exception (In {module:testrunner}/app/controllers/TestRunner.java around line 67)
NullPointerException occured : null
play.exceptions.JavaExecutionException
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:229)
at Invocation.HTTP Request(Play!)
Caused by: java.lang.NullPointerException
at play.test.TestEngine$TestResults.add(TestEngine.java:171)
at org.scalatest.tools.ScalaTestRunner$.runSuiteClass(ScalaTestRunner.scala:43)
at play.scalasupport.ScalaPlugin.runTest(ScalaPlugin.scala:91)
at play.plugins.PluginCollection.runTest(PluginCollection.java:628)
at play.test.TestEngine.run(TestEngine.java:94)
at controllers.TestRunner.run(TestRunner.java:67)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:546)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:500)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:159)
... 1 more

It would seem that in this case TestEngine is null within the TestRunner class.

I found this thread, but it wasn't helpful.

I definitely don't want to resort to jank like this, so I'd really like a simple way to make use of java.sql.timestamp.

--
Evan Meagher

Guillaume Bort

unread,
Nov 3, 2011, 4:04:04 AM11/3/11
to play-fr...@googlegroups.com
You mean with Anorm? Or Hibernate?

> --
> You received this message because you are subscribed to the Google Groups
> "play-framework" group.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to
> play-framewor...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/play-framework?hl=en.
>

--
Guillaume Bort, http://guillaume.bort.fr

Evan Meagher

unread,
Nov 3, 2011, 11:59:40 PM11/3/11
to play-fr...@googlegroups.com
Anorm, I suppose. The play-scala example apps use java.util.Date, which turns into a MySQL date type, thereby losing its time component. I just want to be able to use Timestamps in my Scala code and have it stored in the db without having to jump through a bunch of hoops.

Evan Meagher

unread,
Nov 5, 2011, 8:03:20 PM11/5/11
to play-fr...@googlegroups.com
According to play-scala/src/play/db/anorm/Anorm.scala, it looks like java.util.Date objects get transformed on-the-fly to java.sql.Date's. I get the same TestRunner exceptions when trying to use java.sql.Date objects. Is it not possible to use SQL types in application code?

Evan Meagher

unread,
Nov 5, 2011, 10:10:29 PM11/5/11
to play-fr...@googlegroups.com
More info to report:

I found what I believe is a bug in TestEngine.java which is tangential to my actual issue. The unit test in question tried to calls `create()` on the model in question, which generates the following RuntimeException:

java.lang.RuntimeException: no supported constructors for type models.Recipe
at play.db.anorm.Analyser$$anonfun$50.apply(Anorm.scala:704)
at play.db.anorm.Analyser$$anonfun$50.apply(Anorm.scala:704)
at scala.Option.getOrElse(Option.scala:104)
at play.db.anorm.Analyser$class.$init$(Anorm.scala:704)
at play.db.anorm.Analyse.<init>(Anorm.scala:662)
at play.db.anorm.MParser$$anon$1.<init>(Anorm.scala:556)
at play.db.anorm.MParser$class.$init$(Anorm.scala:556)
at play.db.anorm.Convention$Magic.<init>(Anorm.scala:357)
at models.Recipe$.<init>(Recipe.scala:17)
at models.Recipe$.<clinit>(Recipe.scala)
at RecipeSpec$$anonfun$1.apply$mcV$sp(RecipeSpec.scala:15)
at RecipeSpec$$anonfun$1.apply(RecipeSpec.scala:12)
at RecipeSpec$$anonfun$1.apply(RecipeSpec.scala:12)
at org.scalatest.FlatSpec$$anon$2.apply(FlatSpec.scala:2563)
at org.scalatest.Suite$class.withFixture(Suite.scala:1509)
at RecipeSpec.withFixture(RecipeSpec.scala:8)
at org.scalatest.FlatSpec$class.runTest(FlatSpec.scala:2560)
at RecipeSpec.org$scalatest$BeforeAndAfterEach$$super$runTest(RecipeSpec.scala:8)
at org.scalatest.BeforeAndAfterEach$class.runTest(BeforeAndAfterEach.scala:167)
at RecipeSpec.runTest(RecipeSpec.scala:8)
at org.scalatest.FlatSpec$$anonfun$org$scalatest$FlatSpec$$runTestsInBranch$1.apply(FlatSpec.scala:2485)
at org.scalatest.FlatSpec$$anonfun$org$scalatest$FlatSpec$$runTestsInBranch$1.apply(FlatSpec.scala:2474)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:61)
at scala.collection.immutable.List.foreach(List.scala:45)
at org.scalatest.FlatSpec$class.org$scalatest$FlatSpec$$runTestsInBranch(FlatSpec.scala:2473)
at org.scalatest.FlatSpec$class.runTests(FlatSpec.scala:2687)
at RecipeSpec.runTests(RecipeSpec.scala:8)
at org.scalatest.Suite$class.run(Suite.scala:1804)
at RecipeSpec.org$scalatest$FlatSpec$$super$run(RecipeSpec.scala:8)
at org.scalatest.FlatSpec$class.run(FlatSpec.scala:2758)
at RecipeSpec.run(RecipeSpec.scala:8)
at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:59)
at org.scalatest.tools.ScalaTestRunner$.run(ScalaTestRunner.scala:61)
at org.scalatest.tools.ScalaTestRunner$.runSuiteClass(ScalaTestRunner.scala:17)
at play.scalasupport.ScalaPlugin.runTest(ScalaPlugin.scala:91)
at play.plugins.PluginCollection.runTest(PluginCollection.java:628)
at play.test.TestEngine.run(TestEngine.java:94)
at controllers.TestRunner.run(TestRunner.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:546)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:500)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:159)
at play.server.PlayHandler$NettyInvocation.execute(PlayHandler.java:220)
at play.Invoker$Invocation.run(Invoker.java:265)
at play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:200)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)

This RuntimeException bubbles up into an ExceptionInInitializerError, whose `getMessage` method returns null. `ScalaTestRunner.runSuiteClass` sets `result.error` equal to this null message and passes the result to TestResults.add, which throws a NullPointException when calling `result.error.startsWith`.

This still doesn't explain why Anorm doesn't support java.sql.{Date, Timestamp}. The fundamental exception here complains that a valid constructor doesn't exist, which isn't true:

// Scala constructor.
case class Recipe(
  id: Pk[Long],
  title: String,
  authorId: Long,
  createdAt: Date,
  body: String
)

# SQL evolution.
CREATE TABLE Recipe (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    title varchar(255) NOT NULL,
    authorId bigint(20) NOT NULL,
    createdAt date NOT NULL,
    body text NOT NULL,
    FOREIGN KEY (authorId) REFERENCES User(id),
    PRIMARY KEY (id)
);
Reply all
Reply to author
Forward
0 new messages