scalikeJDBCを使ってformからmysql(docker上にあるdbなのでmariaDB)にinsertしたいのですが、以下のようなエラーが出てしまいます。
Unexpected exception
ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, java.lang.NullPointerException
at controllers.SignupCustomerJson.<init>(SignupControllerSupport.scala:61)
while locating controllers.SignupCustomerJson
for the 3rd parameter of controllers.SignupController.<init> (SignupController.scala:29)
while locating controllers.SignupController
for the 4th parameter of router.Routes.<init>(Routes.scala:55)
while locating router.Routes
while locating play.api.inject.RoutesProvider
while locating play.api.routing.Router
for the 1st parameter of play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:201)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler
for the 5th parameter of play.api.DefaultApplication.<init>(Application.scala:221)
at play.api.DefaultApplication.class(Application.scala:221)
while locating play.api.DefaultApplication
while locating play.api.Application
1 error
No source available, here is the exception stack trace:
->com.google.inject.ProvisionException: Unable to provision, see the following errors:
com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1028)
com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1054)
play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:405)
play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:400)
play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:123)
play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:168)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:164)
play.utils.Threads$.withContextClassLoader(Threads.scala:21)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:164)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:131)
scala.Option.map(Option.scala:146)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:131)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:129)
scala.util.Success.flatMap(Try.scala:230)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:129)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:121)
scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
なおエラー文はこのように出ることもあります(関係なさそうなimport文をコメントアウトしたりするとメッセージが変わります)
Unexpected exception
UnsupportedOperationException: null
No source available, here is the exception stack trace:
java.lang.UnsupportedOperationException:
scalikejdbc.ConnectionPool.close(ConnectionPool.scala:337)
scalikejdbc.ConnectionPool$$anonfun$close$1.apply(ConnectionPool.scala:257)
scalikejdbc.ConnectionPool$$anonfun$close$1.apply(ConnectionPool.scala:257)
scala.Option.foreach(Option.scala:257)
scalikejdbc.ConnectionPool$.close(ConnectionPool.scala:257)
scalikejdbc.ConnectionPool$$anonfun$closeAll$1.apply(ConnectionPool.scala:268)
scalikejdbc.ConnectionPool$$anonfun$closeAll$1.apply(ConnectionPool.scala:266)
scala.collection.mutable.HashMap$$anonfun$foreach$1.apply(HashMap.scala:99)
scala.collection.mutable.HashMap$$anonfun$foreach$1.apply(HashMap.scala:99)
scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala:230)
scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:40)
scala.collection.mutable.HashMap.foreach(HashMap.scala:99)
scalikejdbc.ConnectionPool$.closeAll(ConnectionPool.scala:266)
scalikejdbc.PlayInitializer.onStop(PlayInitializer.scala:58)
scalikejdbc.PlayInitializer$$anonfun$1.apply(PlayInitializer.scala:65)
scalikejdbc.PlayInitializer$$anonfun$1.apply(PlayInitializer.scala:65)
play.api.inject.DefaultApplicationLifecycle$$anonfun$clearHooks$1$1.apply(ApplicationLifecycle.scala:94)
play.api.inject.DefaultApplicationLifecycle$$anonfun$clearHooks$1$1.apply(ApplicationLifecycle.scala:93)
scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251)
scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:249)
scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
scala.concurrent.impl.Promise$DefaultPromise.scala$concurrent$impl$Promise$DefaultPromise$$dispatchOrAddCallback(Promise.scala:280)
scala.concurrent.impl.Promise$DefaultPromise.onComplete(Promise.scala:270)
scala.concurrent.Future$class.flatMap(Future.scala:249)
scala.concurrent.impl.Promise$DefaultPromise.flatMap(Promise.scala:153)
play.api.inject.DefaultApplicationLifecycle.clearHooks$1(ApplicationLifecycle.scala:93)
play.api.inject.DefaultApplicationLifecycle.stop(ApplicationLifecycle.scala:101)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$apply$3.apply(DevServerStart.scala:147)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$apply$3.apply(DevServerStart.scala:147)
scala.Option.foreach(Option.scala:257)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:147)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:131)
scala.Option.map(Option.scala:146)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:131)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:129)
scala.util.Success.flatMap(Try.scala:230)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:129)
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:121)
scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
元のcontollerのファイルはこちらです(SignupControllerSupport.scala)import部分は全然整理がついてません・・・
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
import views.html._
import play.api.data._
import play.api.data.Forms._
import com.github.j5ik2o.spetstore.domain.model.customer._
import com.github.j5ik2o.spetstore.application.controller.{ ControllerSupport }
import com.github.j5ik2o.spetstore.application.controller.json._
import java.time.LocalDateTime
import util.control.Exception._
import java.sql.Connection
import scalikejdbc._
import scalikejdbc.SQLInterpolation._
import scalikejdbc.config._
import com.mysql.cj.jdbc.Driver
import io.circe.generic.auto._
class SignupCustomerJson @Inject() extends Controller
with LoanPattern {
// ---------------------------
// Preparing Connection Pool
// ---------------------------
// loading jdbc.properties
private val props = new java.util.Properties
props.load(classOf[CustomerJson].getClassLoader.getResourceAsStream("jdbc.properties"))
// loading JDBC driver
val jdbcDriver = props.getProperty("com.mysql.cj.jdbc.Driver")
Class.forName(jdbcDriver)
// preparing the connection pool settings
val poolSettings = new ConnectionPoolSettings(initialSize = 100, maxSize = 100)
// JDBC settings
val url = props.getProperty("jdbc:mysql://127.0.0.1:3306/spetstore?characterEncoding=utf8")
val user = props.getProperty("admin")
val passwordjdbc = props.getProperty("admin")
// create singleton(default) connection pool
ConnectionPool.singleton(url, user, passwordjdbc, poolSettings)
// named connection pool
// ConnectionPool.add('spetstore, url, user, passwordjdbc, poolSettings)
// ---------------------------
// Working with DBSession
// ---------------------------
val tableNamePrefix = "" + System.currentTimeMillis().toString.substring(8)
val customer = tableNamePrefix + "_localTx"
/** 登録 */
def insert(customerJson: CustomerJson): Unit = {
implicit val db = DB(ConnectionPool.borrow())
val status = 0
try {
using(DB(ConnectionPool.borrow())) { db =>
db.begin()
DB localTx { implicit session =>
SQL("""insert into" customer (pk, id, status, name, zipCode1 + zipCode2, prefCode, cityName, addressName, building, email, phone, loginName, password, favoriteCategoryId, version) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""").update.apply()
}
db.commit()
}
} finally { db.rollbackIfActive() }
{ db.close() }
}
}
Actionメソッドを呼び出すのはこちらからになります(SignupController.scala)
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
import views.html._
import play.api.data._
import play.api.data.Forms._
import com.github.j5ik2o.spetstore.domain.model.customer._
import com.github.j5ik2o.spetstore.application.controller.{ ControllerSupport }
import com.github.j5ik2o.spetstore.application.controller.json._
import controllers.{ SignupCustomerJson }
import play.api.i18n.{ I18nSupport, MessagesApi }
import play.api.i18n.Messages.Implicits._
import scala.util.Random
class SignupController @Inject() (val messagesApi: MessagesApi, val messagesApi2: MessagesApi, val signupCustomerJson: SignupCustomerJson) extends Controller
with play.api.i18n.I18nSupport {
val customerForm = Form(
// Userフォームマッピング
mapping(
"id" -> optional(text),
"name" -> nonEmptyText(minLength = 4),
"sexType" -> number,
"zipCode1" -> text(minLength = 3, maxLength = 3),
"zipCode2" -> text(minLength = 4, maxLength = 4),
"prefCode" -> number,
"cityName" -> text,
"addressName" -> text,
"buildingName" -> optional(text),
"email" -> text,
"phone" -> text,
"loginName" -> text,
"password" -> text,
"favoriteCategoryId" -> optional(text),
"version" -> optional(longNumber)
)(CustomerJson.apply)(CustomerJson.unapply)
)
// 入力ページを表示するAction
def signup = Action {
Ok(views.html.signup(messagesApi.toString, customerForm))
}
// 結果ページを表示するAction
def signupresult = Action { implicit request => // リクエストオブジェクトを宣言
customerForm.bindFromRequest().fold(
SignupFailure => { // バインドエラー = 入力エラーが発生した場合
Ok(views.html.signup(messagesApi.toString, SignupFailure)) // 入力画面を再表示します。
},
SignupOK => { // バインド成功 = 入力エラーがない場合
val id = Random.nextInt(1000000).toString
val signupstatus = 0
signupstatus match {
case 0 => insert(SignupOK)
}
Ok(views.html.signupresult(messagesApi2.toString, customerForm.fill(SignupOK))) // 結果画面を表示します。
}
)
}
def insert(customerForm: CustomerJson) = signupCustomerJson.insert(CustomerJson(customerForm.id, customerForm.name, customerForm.sexType, customerForm.zipCode1, customerForm.zipCode2, customerForm.prefCode, customerForm.cityName, customerForm.addressName, customerForm.buildingName, customerForm.email, customerForm.phone, customerForm.loginName, customerForm.password, customerForm.favoriteCategoryId, customerForm.version))
}
DBの初期化のファイルはこちらになります。(DBInitializer.scala)。githubに上がっていたサンプルをそのまま使わせて頂いているので手を加えていません。
package com.github.j5ik2o.spetstore.infrastructure.db
import com.typesafe.config.ConfigFactory
import scalikejdbc._, SQLInterpolation._
object DBInitializer {
def run() {
val config = ConfigFactory.load()
val driverClassName = config.getString("db.default.driver")
val url = config.getString("db.default.url")
val user = config.getString("db.default.user")
val password = config.getString("db.default.password")
Class.forName(driverClassName)
ConnectionPool.singleton(url, user, password)
DB readOnly {
implicit s =>
try {
sql"select 1 from customer limit 1".map(_.long(1)).single().apply()
} catch {
case e: java.sql.SQLException =>
DB.localTx {
implicit s =>
sql"""
DROP TABLE IF EXISTS `customer`;
""".execute().apply()
sql"""
CREATE TABLE `customer` (
`pk` BIGINT NOT NULL AUTO_INCREMENT,
`id` BIGINT NOT NULL,
`status` INT NOT NULL,
`name` VARCHAR(256) NOT NULL,
`sex_type` INT NOT NULL,
`zip_code` VARCHAR(20) NOT NULL,
`pref_code` INT NOT NULL,
`city_name` VARCHAR(256) NOT NULL,
`address_name` VARCHAR(256) NOT NULL,
`building_name` VARCHAR(256),
`email` VARCHAR(64) NOT NULL,
`phone` VARCHAR(64) NOT NULL,
`login_name` VARCHAR(64) NOT NULL,
`password` VARCHAR(64) NOT NULL,
`favorite_category_id` BIGINT,
PRIMARY KEY(`pk`),
UNIQUE(`id`)
);
""".execute().apply()
エラー一行目でコンストラクタがないと言われてる気はするんですが、いじってみたものの見当がつきません…。
4/28 大きな勘違いをしていたようで、connectionpoolの以下の一文を直しました。
val props = new java.util.Properties props.load(classOf[Settings].getClassLoader.getResourceAsStream("jdbc.properties"))
ですが今度は not found:type と言われてしまったので、
class SignupCustomerJson @Inject() extends Controller
with LoanPattern with Settings {
としてみたのですが、やはり変化はありません。
ご回答いただければ幸いです。