Scala＆gradleで独自のjarを用いる（Oracle RDS接続の場合）。

#独自のjarを使わねば、なのじゃあ。 
Scalaを使っていると、時として、mavenなどのリポジトリにないjarを用いてちょっとしたコードを書かなければならない時がある。久々にそんな機会があったので、sbtではなくgradleを使ってみて独自のjarを導入してみた。最近、gradle使ってなかったし、Oracleにけっこうはまったので備忘録を。

※　gradle入門は例えばこのあたり
https://tech-lab.sios.jp/archives/9500

# gradleにscalaを導入

はじめに、gradleをインストール。sdkmanの場合:
> sdk install gradle

対象フォルダで:
> gradle init --type scala-library

これにより、以下のようなフォルダ構成ができあがる。
（Oracle RDSに接続するコードのため、名前空間はord.rds）

```
$ tree .
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── resources
    │   └── scala
    │       └── ora
    │           └── rds
    │               └── Library.scala
    └── test
        ├── resources
        └── scala
            └── ora
                └── rds
                    └── LibrarySuite.scala
```

# build.gradleを書き換え、必要ライブラリを配置

トップ下にあるbuild.gradleを書き換える。書き換えポイントは以下、①～③

```build.gradle
apply plugin: 'scala'
apply plugin: 'application' //①gradle runできるようにする

repositories {
    jcenter()
}

dependencies {
    // Use Scala 2.12 in our library project
    implementation 'org.scala-lang:scala-library:2.12.8'

    // Use Scalatest for testing our library
    testImplementation 'junit:junit:4.12'
    testImplementation 'org.scalatest:scalatest_2.12:3.0.5'

    // Need scala-xml at test runtime
    testRuntimeOnly 'org.scala-lang.modules:scala-xml_2.12:1.1.1'

    compile fileTree(dir: 'lib', include: '*.jar') //② lib フォルダ直下のjarを全て取り込む指定
}

mainClassName = 'OracleConnectSample' //③実行したいクラス名
```
※gradleのアプリケーションプラグインについては[このあたり](http://gradle.monochromeroad.com/docs/userguide/application_plugin.html)を参考。


libフォルダを作り、必要なjarファイルを置く（ここではOracleが配布しているJDBC thinドライバー）

```
.
├── lib
│   └── ojdbc7.jar
```

# ScalaでOracle RDS接続

ただJDBC使っているだけなんだけど、忘れつつあるので...結構前の[先人のブログ](http://www.ewavesolutions.com/blog/?page_id=186)を参考に。

```scala
import java.sql.{DriverManager, Connection, Statement, ResultSet,SQLException}

object OracleConnectSample {
  val jdbcURL = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXX.ap-northeast-1.rds.amazonaws.com) (PORT=1521))(CONNECT_DATA=(SID=YYYY)))"

  val user ="ユーザー名"
  val passwd ="パスワード"

  def main(args : Array[String]) : Unit = {
    try {
        Class.forName("oracle.jdbc.driver.OracleDriver") //.newInstance()
        val con = DriverManager.getConnection(jdbcURL,user,passwd)
        try {
           val stmt = con.createStatement()
           val str ="SELECT sysdate,TO_CHAR(SYSDATE,'DY')  FROM dual" //現在時刻と曜日を取得するSQL
           val rs = stmt.executeQuery(str)
           while (rs.next()){
              println(s"${rs.getString(1)} ${rs.getString(2)}")
          }
          stmt.close()
      } catch {
         case e : SQLException => println("Database error "+e)
         case e : Throwable => {
           println("Some other exception type:")
           e.printStackTrace()
         }
      } finally {
         con.close()
      }
   } catch {
      case e : SQLException => println("Database error "+e)
      case e : Throwable => {
        println("Some other exception type:")
        e.printStackTrace()
     }
  }
 }
}
```

ポイントは、（普段Oracleに縁がない人の場合）Oracle RDS向けのJDBC接続の書き方かな。
> jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXX.ap-northeast-1.rds.amazonaws.com) (PORT=1521))(CONNECT_DATA=(SID=YYYY)))

あと、SQL文字列の最後にセミコロンを入れると、以下のエラーが出るようなので注意。
> Database error java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended

実行結果

```
$ gradle run

> Task :run
2019-02-23 14:45:30.0 SAT

BUILD SUCCESSFUL in 1s
2 actionable tasks: 1 executed, 1 up-to-date
```

オーケー、データベースの時刻もJSTとして正しいようだ。