heroku java

53
Kazuyuki Kawamura 日本Springユーザグループ

Upload: kaz-kawamura

Post on 20-Nov-2014

7.271 views

Category:

Technology


0 download

DESCRIPTION

Heroku上でJavaアプリケーションを動かすためのチュートリアル。Spring Rooを使ったSpring MVCのサンプルもあり。データストアとして、PostgreSQL、Database.comにも対応

TRANSCRIPT

Page 1: Heroku java

Kazuyuki Kawamura 日本Springユーザグループ

Page 2: Heroku java

www.heroku.com

Page 3: Heroku java

今日はJavaユーザ会のCCC

Page 4: Heroku java

Cloud Application Platform

Page 5: Heroku java

  herokuの新しいスタック   サポートする言語とフレームワーク

  Ruby   Rails 3   Sinatra

  Node.js   express

  Clojure   Ring

  Java   Spring   Play!

  Python   Django

  Scala

Page 6: Heroku java

  スタックのソフトウェアバージョン   OS: Ubuntu Server 10.04   Ruby: MRI 1.9.2   Bundler: 1.1pre   Node.js: 0.4.7   NPM: 1.0.6   JVM: OpenJDK 6

Page 7: Heroku java
Page 8: Heroku java
Page 9: Heroku java

  前提条件 (ローカルマシン)   JDKとMavenがインストールされている   gitがインストールされている

http://code.google.com/p/git-osx-installer/downloads/list?can=3

  herokuのコマンドラインクライアントがインストールされている (バージョン 2.1.0以上) gem install heroku

Page 10: Heroku java

  アプリケーションを書く   pom.xmlに依存するライブラリを定義   ローカルでテスト   herokuへデプロイ

Page 11: Heroku java

public  class  HelloWorld  extends  HttpServlet  {          @Override          protected  void  doGet(HttpServletRequest  req,  HttpServletResponse  resp)                          throws  ServletException,  IOException  {                  resp.getWriter().print("Hello  from  Java!\n");          }  

       public  static  void  main(String[]  args)  throws  Exception{                  Server  server  =  new  Server(Integer.valueOf(System.getenv("PORT")));                  ServletContextHandler  context  =                            new  ServletContextHandler(ServletContextHandler.SESSIONS);                  context.setContextPath("/");                  server.setHandler(context);                  context.addServlet(new  ServletHolder(new  HelloWorld()),"/*");                  server.start();                  server.join();                }  }

Page 12: Heroku java

<?xml  version="1.0"  encoding="UTF-­‐8"?>  <project  xmlns="http://maven.apache.org/

POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0  http://maven.apache.org/maven-­‐v4_0_0.xsd">  

   <modelVersion>4.0.0</modelVersion>      <groupId>foo</groupId>      <version>1.0-­‐SNAPSHOT</version>      <name>helloheroku</name>      <artifactId>helloheroku</artifactId>      <packaging>jar</packaging>  

<properties>          <java.version>1.6</java.version>          <jetty.version>              7.4.4.v20110707          </jetty.version>      </properties>  

   <dependencies>  

<!-­‐-­‐  Jetty  -­‐-­‐>          <dependency>              <groupId>                  org.eclipse.jetty              </groupId>              <artifactId>                  jetty-­‐webapp              </artifactId>              <version>${jetty.version}</version>          </dependency>          <dependency>              <groupId>org.mortbay.jetty</groupId>              <artifactId>                  jsp-­‐2.1-­‐glassfish              </artifactId>              <version>2.1.v20100127</version>          </dependency>      </dependencies>  

Page 13: Heroku java

   <build>          <plugins>              <plugin>                  <groupId>                      org.apache.maven.plugins</groupId>                  <artifactId>maven-­‐compiler-­‐plugin                      </artifactId>                  <version>2.3.2</version>                  <configuration>                      <source>${java.version}</source>                      <target>${java.version}</target>                  </configuration>              </plugin>              <plugin>                  <groupId>org.codehaus.mojo</groupId>                  <artifactId>appassembler-­‐maven-­‐plugin                      </artifactId>                  <version>1.1.1</version>                  <configuration>                      <assembleDirectory>target                          </assembleDirectory> <generateRepository>false                          </generateRepository>  

                 <programs>                          <program>                              <mainClass>                                  HelloWorld                              </mainClass>                              <name>webapp</name>                          </program>                      <programs>                  </configuration>                  <executions>                      <execution>                          <phase>package</phase>                          <goals>                              <goal>assemble</goal>                          </goals>                      </execution>                  </executions>              </plugin>          </plugins>      </build>  </project>  

Page 14: Heroku java

  プロセスモデル   Procfileとherokuのプロセス管理コマンド

  Procfile   heroku上のwebまたはworker dynoで実行されるコマンドを定義

  ローカルで実行   mvn install

  export REPO=$HOME/.m2/repository   foreman start

web: sh target/bin/webapp

12:20:54 web.1 | 2011-10-17 12:20:54.047:INFO::jetty-7.4.4.v20110707 12:20:54 web.1 | 2011-10-17 12:20:54.153:INFO::started o.e.j.s.ServletContextHandler{/,null} 12:20:54 web.1 | 2011-10-17 12:20:54.192:INFO::Started [email protected]:5000 STARTING

prereq: gem install foreman

Page 15: Heroku java

  herokuへデプロイ   .gitignoreを作成

  gitにアプリケーションを格納 git init

git add .

git commit –m “init”

target

Page 16: Heroku java

  herokuへデプロイ   cedar stack上にアプリケーションを作成 heroku create --stack cedar Enter your Heroku credentials. Email: [email protected] Password: Creating quiet-lightning-477... done, stack is cedar http://quiet-lightning-477.herokuapp.com/ | [email protected]:quiet-lightning-477.git Git remote heroku added

Page 17: Heroku java

  herokuへデプロイ   コードのデプロイ git push heroku master Counting objects: 6, done. Delta compression using up to 2 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 629 bytes, done. Total 6 (delta 0), reused 0 (delta 0) -----> Heroku receiving push -----> Node.js app detected -----> Vendoring node 0.4.7 -----> Installing dependencies with npm 1.0.8 [email protected] ./node_modules/express ├── [email protected] ├── [email protected] └── [email protected] Dependencies installed -----> Discovering process types Procfile declares types -> web -----> Compiled slug size is 3.2MB -----> Launching... done, v4 http://quiet-lightning-477.herokuapp.com deployed to Heroku

To [email protected]:quiet-lightning-477.git * [new branch] master -> master

Page 18: Heroku java

  heroku プロセス管理コマンド   プロセスの実行数を変更

heroku ps:scale web=1

  プロセスのステータスを確認 heroku ps

  ログを確認 heroku logs

Process State Command ------------ ------------------ ------------------------------ web.1 idle for 158h sh target/bin/webapp

Scaling web processes... done, now running 1

2011-07-18T05:33:23+00:00 app[web.1]: Listening on 13725 2011-07-18T05:33:42+00:00 heroku[web.1]: State changed from starting to up

Page 19: Heroku java
Page 20: Heroku java
Page 21: Heroku java

  サンプルプログラム   Rooを利用して作成   DBにデータを格納するSpring MVCを利用したWebアプリケーション

  Pizza Shop http://www.springsource.org/roo/guide?w=beginning

  作成したサンプルをHerokuで実行するように変更

Page 22: Heroku java

project --topLevelPackage com.sample.pizzashop   Mavenを利用してビルド   AspectJを利用している

Page 23: Heroku java

persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY

  JPAの初期設定   persistence.xmlやSpringの設定などを追加

Page 24: Heroku java

  作成するエンティティ   Topping – トッピング   Base – 生地   Pizza – ピザ   PizzaOrder – ピザの注文

entity --class ~.domain.Topping --testAutomatically field string --fieldName name --notNull --sizeMin 2

entity --class ~.domain.Base --testAutomaticallyfield string --fieldName name --notNull --sizeMin 2

Page 25: Heroku java

entity --class ~.domain.Pizza –testAutomatically field string --fieldName name --notNull --sizeMin 2

field number --fieldName price --type java.lang.Floatfield set --fieldName toppings --type ~.domain.Topping field reference --fieldName base --type ~.domain.Base

Page 26: Heroku java

entity --class ~.domain.PizzaOrder --testAutomaticallyfield

string --fieldName name --notNull --sizeMin 2 field string --fieldName address --sizeMax 30 field number --fieldName total --type java.lang.Float field date --fieldName deliveryDate --type java.util.Date field set --fieldName pizzas --type ~.domain.Pizza

Page 27: Heroku java

web mvc setup web mvc all --package ~.web

Page 28: Heroku java

perform tests   テストの実行

perform eclipse   Eclipse関連のファイルの作成

Page 29: Heroku java

  ひとまず実行 mvn jetty:run http://localhost:8080/pizzashop へアクセス

Page 30: Heroku java

  herokuへデプロイ   .gitignoreを作成

  gitにアプリケーションを格納 git init

git add .

git commit –m “init”

  herokuにデプロイ git push heroku master

target

Page 31: Heroku java
Page 32: Heroku java
Page 33: Heroku java

  Herokuが提供するデータベースはPostgreSQL   Shared Databaseは5MBまで無償で利用可能   有料オプションもあり

  DATABASE_URL環境変数にDBへの接続情報が格納されている

Page 34: Heroku java

  データベース関連の設定   DBとしてPostgreSQLを利用するように設定

以下をRooで実行 persistence setup --provider HIBERNATE --database POSTGRES

  Spring設定ファイル(src/main/resources/META-INF/spring/applicationContext.xml)の編集 <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource"> <property name="driverClassName" value="org.postgresql.Driver"/> <property name="url" value="#{systemEnvironment['DATABASE_URL'].replaceAll( 'postgres://(.*):(.*)@(.*)', 'jdbc:postgresql://$3?user=$1&amp;password=$2') }"/> </bean> <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> <property name="persistenceUnitName" value="persistenceUnit"/> <property name="dataSource" ref="dataSource"/> </bean>

Page 35: Heroku java

  データベース関連の設定   persistence.xml(src/main/resources/META-INF/

persistence.xml)の編集 <?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence …⋯> <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.datanucleus.jpa.PersistenceProviderImpl</provider> <properties> <property name="datanucleus.autoCreateSchema" value="false"/> <property name="datanucleus.storeManagerType" value="rdbms"/> <property name="datanucleus.ConnectionURL” value="jdbc:postgresql://localhost:5432"/> <property name="datanucleus.ConnectionUserName" value=""/> <property name="datanucleus.ConnectionPassword" value=""/> <property name="datanucleus.autoCreateTables" value="true"/> …⋯ </properties> </persistence-unit> </persistence>

Page 36: Heroku java

  起動用のjettyの追加 pom.xmlに以下を追加 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.3</version> <executions> <execution> <phase>package</phase> <goals><goal>copy</goal></goals> <configuration> <artifactItems> <artifactItem> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-runner</artifactId> <version>7.5.1.v20110908</version> <destFileName>jetty-runner.jar</destFileName> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin>

Page 37: Heroku java

  サービス起動用の設定 Procfileを作成

  ローカルで起動   環境変数DATABASE_URLを設定

export DATABASE_URL=postgres://demo:demo@localhost/demo   サービスを起動

foreman start → http://locahost:5000/

web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war

Page 38: Heroku java

  herokuへデプロイ   gitにアプリケーションを格納 git add .

git commit –m “Support PostgreSQL”

  herokuにデプロイ git push heroku master

Page 39: Heroku java
Page 40: Heroku java

  www.database.com   native cloud database service

  RESTやSOAPのAPIを通してデータにアクセス   OAuth、SAMLを用いて認証

Page 41: Heroku java

  http://forcedotcom.github.com/java-sdk/   Javaアプリケーションからdatabase.comにアクセスするためのモジュール   API Connector   JPA Provider (datanucleusベース)   Oauthによる認証/認可   Spring Securityプラグイン   自動コード生成モジュール (既存のオブジェクトからEntityを自動生成)

Page 42: Heroku java
Page 43: Heroku java

  データベース関連の設定   JPAプロバイダとしてDatanucleusを利用するように設定 (databaseは何でも良い) 以下をRooで実行 persistence setup --provider DATANUCLEUS_2 --database POSTGRES

Page 44: Heroku java

  pom.xmlを変更   database.com SDKをdependencyに追加

  datanucleusのバージョンの変更

<dependency> <groupId>com.force.sdk</groupId> <artifactId>force-jpa</artifactId> <version>22.0.7-BETA</version> </dependency>

<dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-core</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-jpa</artifactId> <version>2.1.7</version> </dependency>

プラグインのdependencyも要変更

Page 45: Heroku java

  persistence.xml(src/main/resources/META-INF/persistence.xml)の変更 <?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" …⋯> <persistence-unit name="forceDatabase"> <provider>com.force.sdk.jpa.PersistenceProviderImpl</provider> <properties> <property name="datanucleus.autoCreateSchema" value="true" /> <property name="datanucleus.storeManagerType" value="force" /> <property name="datanucleus.validateTables" value="false" /> <property name="datanucleus.validateConstraints" value="false" /> <property name="datanucleus.Optimistic" value="false" /> <property name="datanucleus.datastoreTransactionDelayOperations" value="true"/> <property name="datanucleus.jpa.addClassTransformer" value="false" /> <property name="datanucleus.cache.level2.type" value="none" /> <property name="datanucleus.detachAllOnCommit" value="true" /> <property name="datanucleus.copyOnAttach" value="false" /> </properties> </persistence-unit> </persistence>

Page 46: Heroku java

  Spring設定ファイル(src/main/resources/META-INF/spring/applicationContext.xml)の変更

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="forceDatabase" /> </bean>

<bean id="forceService" class="com.force.sdk.connector.ForceServiceConnector"> <property name="connectionName" value="forceDatabase"/> </bean>

Page 47: Heroku java

  Entityの変更   Database.comの制限

  IDはStringでなければいけない

  VersionフィールドはlastModifiedDateにマッピング

@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private String Base.id;

@Version @Column(name = "lastModifiedDate") @Temporal(TemporalType.TIMESTAMP) private Calendar Base.version;

Base_Roo_Entity.aj

Base_Roo_Entity.aj

Page 48: Heroku java

  Entityの変更   Database.comの制限

  ManyToManyは未サポート  要件に合わせて、OneToMany、ManyToOneに変更する  中間テーブル用のEntityを作成する

  上記変更に合わせ、以下も修正   テストクラス   Webのコントローラクラス

Page 49: Heroku java

  環境変数の設定   database.comのコネクタは、FORCE_<コネクション名>_URL環境変数で指定された接続先に接続   コネクション名は、JPAであればpersistence-unitの名前

export FORCE_FORCEDATABASE_URL="force://[email protected]&password=passwd"

  ローカルで実行 mvn jetty:run

Page 50: Heroku java

  環境変数の設定 heroku config:add FORCE_FORCEDATABASE_URL="force://[email protected]&password=passwd"

  デプロイ git add .

git commit -m "Support Database.com"

git push heroku master

  ログを確認 heroku logs

  Webブラウザでアプリケーションにアクセス heroku open

Page 51: Heroku java
Page 52: Heroku java

  addons.heroku.com

Page 53: Heroku java

  Java on heroku   heroku上でJavaアプリケーションを動かすことができる

  gitを利用してデプロイ   Mavenを利用してビルド   Java EEではない

  データソース   herokuで提供されるDBはPostgreSQL   database.comなど外部のツールとも連携可能   herokuのAdd-onによって様々なデータソースが利用可能