Wildfly 8とHibernate OGMでMongoDBにJPA
前回からの続き的内容。
RESTの受け口が作れたので、今度はそれを永続化するところに挑戦。
永続化と言えばDBなので、MySQLとかでもいんだけれども、せっかくなのでMongoDBに永続化することにしてみます。
Javaなので、APIは当然JPAです!って、MongoDBとかってJPA対応したクライアントとかあるのだろうか?と思って探していたら、Hibernate OGMというのを使うとできるらしいということが分かった。
んで、これはどうやらWildfly 8.2にはデフォルトでは含まれていないもののようだということも分かった。
ダウンロードしてきてmodulesに登録してもいいのだけれど、お試しなのでwarに抱き込んでやることにします。
pom.xml
warに抱き込むことにしたのでdependencyにscopeをcompileで追加してやります。
resteasyはJPAには関係なくて、テストする時用のJAX-RSクライアントです。
<dependency> <groupId>org.hibernate.ogm</groupId> <artifactId>hibernate-ogm-mongodb</artifactId> <version>4.1.0.CR1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>3.0.10.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <version>3.0.10.Final</version> <scope>test</scope> </dependency>
Entity
エンティティクラスはこんな感じ。
@Entity public class Todo implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid", strategy = "uuid2") private String id; @Column private String title; @Column private boolean done; // setter/getterは省略
GeneratedValueのところが少しはまりポイントでした。
何もつけないとエラーになったので、色々調べて上の書き方に落ち着きました。
persistence.xml
ほぼサンプルから拾ったまんま。
<persistence-unit name="mongoUnit" transaction-type="JTA"> <!-- Use Hibernate OGM provider: configuration will be transparent --> <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider> <class>com.github.chanko.jpa.Todo</class> <properties> <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" /> <property name="hibernate.ogm.datastore.provider" value="mongodb" /> <property name="hibernate.ogm.datastore.host" value="192.168.33.11" /> <property name="hibernate.ogm.datastore.port" value="27017" /> <property name="hibernate.ogm.datastore.database" value="todo" /> </properties> </persistence-unit>
直接ホストを指定してるけれど、wildflyのdatasourceに設定してそれを参照するようなやり方は見つけらなかった。ここはイマイチなところ。
EJB
JPAエンティティはEJBから扱ってやることにします。
JPAにしたのでこちらは特にいつも通りで変わったことはしておりません。
@Stateless @Named public class TodoBean { @PersistenceContext private EntityManager em; public void register(String title, boolean done) { Todo todo = new Todo(); todo.setTitle(title); todo.setDone(done); em.persist(todo); } }
JAX-RS
リクエストの受け口を作っておきます。
引数や戻りのクラス構造はご想像ください。
@Path("todo") public class TodoService { @Inject private TodoBean todoBean; @PUT @Path("register") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Result register(TodoParam param) { try { todoBean.register(param.getTitle(), param.isDone()); Result r = new Result(); r.setResult("success"); r.setCount(1); return r; } catch (Throwable t) { Result r = new Result(); r.setResult("failure"); r.setCount(-1); return r; } } }
JAX-RSクライアント
あとはこのサービスを呼んでやればOKです。
JUnitから実行したりできるので、JAX-RSのクライアントを使って呼び出すことにします。
Client client = ClientBuilder.newClient(); Response res = client .target(new URI("http://localhost:8080/chanko-angularjs/rs/todo/register")) .request(MediaType.APPLICATION_JSON) .put(Entity.json(Json.createObjectBuilder() .add("title", "hoge").add("done", true).build() .toString()));
結果
無事に登録されました。
> db.Todo.find() { "_id" : "23cb7f5b-1bfa-49d4-b0a2-281479201004", "title" : "hoge", "done" : true }