いまいちだ。だめだ。
slim3でgwtやってます。とりあえずは動かしてみよう!ということで、やってます。まだできてませんがメモっときます。
できないだろうとは思いつつ (← DataStoreについてまだよく分かってません) Kindを@NotPersistentでプロパティに持って、Daoでフェッチするときに、Kind自体を検索して、そのプロパティにsetした状態のList
何がやりたいかというと、ここでやったものをslim3gwtで実現することです。非所有の関連をもったEntity二つをManageする。
画面はこんな感じ
昨日エラーになった、JDOHelperをクライアント側で使っている部分を削除。というかslim3Gwtのモデルはクライアントとサーバで共用なのでCatを変更するんです。したんです。以下のようなコード群
Cat_slim3_gwt.html
<html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Cat Manager</title> <link type="text/css" rel="stylesheet" href="Cat_slim3_gwt.css"> <script type="text/javascript" language="javascript" src="cat_slim3_gwt/cat_slim3_gwt.nocache.js"></script> </head> <body> <div class="head">CatManager</div> <div class="flame"> <div id="catcontainer" class="outer"> <div class="side_title">猫登録</DIV> </div> <BR class="clears"> <div id="kindcontainer" class="outer_right"> <div class="side_title">種類登録</DIV> </div> <BR class="clears"> </div> <!-- OPTIONAL: include this if you want history support --> <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position: absolute; width: 0; height: 0; border: 0"></iframe> </body> </html>
package kijitoraneko.demo.client; import kijitoraneko.demo.client.service.CatService; import kijitoraneko.demo.client.service.CatServiceAsync; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.RootPanel; /** * Entry point classes define <code>onModuleLoad()</code>. */ public class Cat_slim3_gwt implements EntryPoint { private final CatServiceAsync service = GWT.create(CatService.class); public void onModuleLoad() { CatView cv = new CatView(service); KindView kv = new KindView(service); RootPanel.get("catcontainer").add(cv); RootPanel.get("kindcontainer").add(kv); } }
CatView.java
package kijitoraneko.demo.client; import java.util.List; import kijitoraneko.demo.client.service.CatServiceAsync; import kijitoraneko.demo.shared.model.Cat; import kijitoraneko.demo.shared.model.Kind; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class CatView extends Composite{ private final CatServiceAsync catservice; final TextBox insertTextBox = new TextBox(); final ListBox listBox = new ListBox(); final Button insertButton = new Button("お猫登録"); final Hyperlink catsearchlink = new Hyperlink("All猫検索", ""); final Button closeCatsButton = new Button("閉じる"); final Button closeInsertButton = new Button("閉じる"); final DialogBox dialogBox = new DialogBox(); final VerticalPanel dialogVPanel = new VerticalPanel(); public CatView(CatServiceAsync proxy) { this.catservice = proxy; VerticalPanel vpanel = new VerticalPanel(); HorizontalPanel hpanel = new HorizontalPanel(); HorizontalPanel hpanel2 = new HorizontalPanel(); hpanel.add(insertTextBox); hpanel.add(listBox); hpanel.add(insertButton); hpanel2.add(catsearchlink); vpanel.add(hpanel); vpanel.add(hpanel2); dialogVPanel.setStyleName("dialogVPanel"); catsearchlink.addClickHandler(new SearchCatsHandler()); insertButton.addClickHandler(new InsertCatsHandler()); initKindListBox(); closeButtonInit(); initWidget(vpanel); } private void closeButtonInit(){ closeCatsButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { dialogVPanel.clear(); dialogBox.hide(); } }); closeInsertButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { dialogVPanel.clear(); dialogBox.hide(); insertButton.setEnabled(true); } }); } private void initKindListBox() { catservice.searchAllKind(new AsyncCallback<List<Kind>>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(List<Kind> result) { for (Kind kind : result) { listBox.addItem(kind.getName(), kind.getKey()); } } }); } class InsertCatsHandler implements ClickHandler { public void onClick(ClickEvent event) { String kindkey = listBox.getValue(listBox.getSelectedIndex()); insertCat(kindkey); } private void insertCat(String kindkey) { String catname = insertTextBox.getText(); Cat cat = new Cat(); cat.setName(catname); catservice.insertCat(cat, kindkey, new AsyncCallback<Cat>() { public void onFailure(Throwable caught) { } @Override public void onSuccess(Cat result) { Label labeltext = new Label(); labeltext.setText("登録しました"); Label label = new Label(); label.setText(result.getName()); dialogVPanel.add(labeltext); dialogVPanel.add(label); dialogVPanel.add(closeCatsButton); dialogBox.setWidget(dialogVPanel); dialogBox.center(); dialogBox.show(); } }); } } class SearchCatsHandler implements ClickHandler { public void onClick(ClickEvent event) { searchCats(); } private void searchCats() { catservice.searchAllCat(new AsyncCallback<List<Cat>>() { public void onFailure(Throwable caught) { } @Override public void onSuccess(List<Cat> result) { for (Cat cat : result) { Label name = new Label(); name.setText(cat.getName()); Label kind = new Label(); name.setText(cat.getNotpersistkind().getName()); final HorizontalPanel dialogHPanel = new HorizontalPanel(); dialogHPanel.add(name); dialogHPanel.add(kind); dialogVPanel.add(dialogHPanel); } dialogVPanel.add(closeCatsButton); dialogBox.setWidget(dialogVPanel); dialogBox.center(); dialogBox.show(); } }); } } }
KindView.java
package kijitoraneko.demo.client; import java.util.List; import kijitoraneko.demo.client.service.CatServiceAsync; import kijitoraneko.demo.shared.model.Kind; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class KindView extends Composite{ private final CatServiceAsync catService; final Button kindInsertButton = new Button("種類登録"); final Button kindSearchButton = new Button("全検索"); final Button searchByStringButton = new Button("前方検索"); final Button closekindInsertButton = new Button("閉じる"); final Button closekindSearchButton = new Button("閉じる"); final Button closesearchByStringButton = new Button("閉じる"); final TextBox insertField = new TextBox(); final TextBox frontSearchField = new TextBox(); final DialogBox dialogBox = new DialogBox(); final VerticalPanel dialogVPanel = new VerticalPanel(); public KindView(CatServiceAsync proxy) { this.catService = proxy; kindInsertButton.addStyleName("sendButton"); kindSearchButton.addStyleName("sendButton"); searchByStringButton.addStyleName("sendButton"); VerticalPanel vpanel = new VerticalPanel(); HorizontalPanel hp1 = new HorizontalPanel(); hp1.add(insertField); hp1.add(kindInsertButton); vpanel.add(hp1); HorizontalPanel hp2 = new HorizontalPanel(); hp2.add(kindSearchButton); vpanel.add(hp2); HorizontalPanel hp3 = new HorizontalPanel(); hp3.add(frontSearchField); hp3.add(searchByStringButton); vpanel.add(hp3); dialogVPanel.setStyleName("dialogVPanel"); kindInsertButton.addClickHandler(new InsertKindHandler()); kindSearchButton.addClickHandler(new SearchKindHandler()); searchByStringButton.addClickHandler(new SearchByStringHandler()); closeButtonInit(); initWidget(vpanel); } private void closeButtonInit(){ closekindSearchButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { dialogVPanel.clear(); dialogBox.hide(); kindSearchButton.setEnabled(true); } }); closesearchByStringButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { dialogVPanel.clear(); dialogBox.hide(); searchByStringButton.setEnabled(true); } }); closekindInsertButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { dialogVPanel.clear(); dialogBox.hide(); kindInsertButton.setEnabled(true); } }); } class InsertKindHandler implements ClickHandler { public void onClick(ClickEvent event) { insertKind(); } private void insertKind() { kindInsertButton.setEnabled(false); String textToServer = insertField.getText(); Kind kind = new Kind(); kind.setName(textToServer); catService.insertKind(kind, new AsyncCallback<Kind>() { public void onFailure(Throwable caught) { } public void onSuccess(Kind result) { Label labeltext = new Label(); labeltext.setText("登録しました"); Label label = new Label(); label.setText(result.getName()); dialogVPanel.add(labeltext); dialogVPanel.add(label); dialogVPanel.add(closekindInsertButton); dialogBox.setWidget(dialogVPanel); dialogBox.center(); dialogBox.show(); } }); } } class SearchKindHandler implements ClickHandler { public void onClick(ClickEvent event) { searchAllKind(); } private void searchAllKind() { kindSearchButton.setEnabled(false); catService.searchAllKind(new AsyncCallback<List<Kind>>() { public void onFailure(Throwable caught) { } public void onSuccess(List<Kind> result) { for (Kind kind : result) { Label label = new Label(); label.setText(kind.getName()); dialogVPanel.add(label); } dialogVPanel.add(closekindSearchButton); dialogBox.setWidget(dialogVPanel); dialogBox.center(); dialogBox.show(); kindSearchButton.setEnabled(true); } }); } } class SearchByStringHandler implements ClickHandler { public void onClick(ClickEvent event) { searchByString(); } private void searchByString() { String str = frontSearchField.getText(); searchByStringButton.setEnabled(false); catService.searchKindByString(str, new AsyncCallback<List<Kind>>() { public void onFailure(Throwable caught) { } public void onSuccess(List<Kind> result) { for (Kind kind : result) { Label label = new Label(); label.setText(kind.getName()); dialogVPanel.add(label); } dialogVPanel.add(closekindSearchButton); dialogBox.setWidget(dialogVPanel); dialogBox.center(); dialogBox.show(); searchByStringButton.setEnabled(true); } }); } } }
CatService.java
package kijitoraneko.demo.client.service; import java.util.List; import kijitoraneko.demo.shared.model.Cat; import kijitoraneko.demo.shared.model.Kind; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("service.s3gwt") public interface CatService extends RemoteService { List<Kind> searchAllKind(); List<Kind> searchKindByString(String str); List<Cat> searchAllCat(); Cat insertCat(Cat cat, String kindKey); Kind insertKind(Kind kind); }
CatServiceAsync.java
package kijitoraneko.demo.client.service; import java.util.List; import kijitoraneko.demo.shared.model.Cat; import kijitoraneko.demo.shared.model.Kind; import com.google.gwt.user.client.rpc.AsyncCallback; public interface CatServiceAsync { void insertKind(Kind kind, AsyncCallback<Kind> callback); void searchAllKind(AsyncCallback<List<Kind>> callback); void searchKindByString(String str , AsyncCallback<List<Kind>> asyncCallback); void searchAllCat(AsyncCallback<List<Cat>> asyncCallback); void insertCat(Cat cat, String kindKey, AsyncCallback<Cat> callback); }
CatServiceImpl.java
package kijitoraneko.demo.server.service; import java.util.List; import kijitoraneko.demo.client.service.CatService; import kijitoraneko.demo.server.dao.CatDao; import kijitoraneko.demo.server.dao.KindDao; import kijitoraneko.demo.shared.model.Cat; import kijitoraneko.demo.shared.model.Kind; public class CatServiceImpl implements CatService { KindDao kinddao = new KindDao(); CatDao catdao = new CatDao(); @Override public Kind insertKind(Kind kind) { return kinddao.makePersistentInTx(kind); } @Override public List<Kind> searchAllKind() { return kinddao.findAll(); } @Override public List<Kind> searchKindByString(String str) { return kinddao.findByString(str); } @Override public List<Cat> searchAllCat() { return catdao.findAll(); } @Override public Cat insertCat(Cat cat , String kindKey) { Kind kind = kinddao.find(kindKey); cat.setKindKey(kind); return catdao.makePersistentInTx(cat); } }
CatDao.java
package kijitoraneko.demo.server.dao; import java.util.List; import java.util.logging.Logger; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import kijitoraneko.demo.server.meta.CatMeta; import kijitoraneko.demo.shared.model.Cat; import kijitoraneko.demo.shared.model.Kind; import org.slim3.jdo.GenericDao; import org.slim3.jdo.SelectQuery; public class CatDao extends GenericDao<Cat> { private static final CatMeta catmeta = new CatMeta(); @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(CatDao.class .getName()); public CatDao() { super(Cat.class); } public CatDao(PersistenceManager pm) { super(Cat.class, pm); } @Override protected SelectQuery<Cat> from() { return new SelectQuery<Cat>(pm, catmeta.getModelClass()); } public List<Cat> findAll() { List<Cat> catlist = from().getResultList(); for (Cat cat : catlist) { cat.setNotpersistkind(JDOHelper.getPersistenceManager(cat) .getObjectById(Kind.class, cat.getKindKey())); } return catlist; } }
KindDao.java
package kijitoraneko.demo.server.dao; import java.util.List; import java.util.logging.Logger; import javax.jdo.PersistenceManager; import kijitoraneko.demo.server.meta.KindMeta; import kijitoraneko.demo.shared.model.Kind; import org.slim3.jdo.GenericDao; import org.slim3.jdo.SelectQuery; public class KindDao extends GenericDao<Kind> { private static final KindMeta kindmeta = new KindMeta(); @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(KindDao.class.getName()); public KindDao() { super(Kind.class); } public KindDao(PersistenceManager pm) { super(Kind.class, pm); } @Override protected SelectQuery<Kind> from() { return new SelectQuery<Kind>(pm, kindmeta.getModelClass()); } public List<Kind> findByString(String searchKey) { return from().where(kindmeta.name.startsWith(searchKey)).getResultList(); } }
Cat.java
package kijitoraneko.demo.shared.model; import java.io.Serializable; import javax.jdo.annotations.Extension; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.NotPersistent; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; import javax.jdo.annotations.Version; import javax.jdo.annotations.VersionStrategy; @PersistenceCapable(identityType = IdentityType.APPLICATION) @Version(strategy = VersionStrategy.VERSION_NUMBER, column = "version") public class Cat implements Serializable { private static final long serialVersionUID = 1L; @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true") private String key; @Persistent private Long version = 1L; @Persistent private String name; @Persistent private String kindKey; @NotPersistent private Kind notpersistkind; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Long getVersion() { return version; } public String getName() { return name; } public void setName(String name) { this.name = name; } /*public Kind getKind() { if (kindKey == null) { return null; } return JDOHelper.getPersistenceManager(this).getObjectById(Kind.class, kindKey); }*/ public void setKindKey(Kind kind) { if (kind == null) { kindKey = null; } kindKey = kind.getKey(); } public String getKindKey() { return kindKey; } public Kind getNotpersistkind() { return notpersistkind; } public void setNotpersistkind(Kind notpersistkind) { this.notpersistkind = notpersistkind; } }
Kind.java
package kijitoraneko.demo.shared.model; import java.io.Serializable; import javax.jdo.annotations.Extension; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; import javax.jdo.annotations.Version; import javax.jdo.annotations.VersionStrategy; @PersistenceCapable(identityType = IdentityType.APPLICATION) @Version(strategy = VersionStrategy.VERSION_NUMBER, column = "version") public class Kind implements Serializable { private static final long serialVersionUID = 1L; @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true") private String key; @Persistent private Long version = 1L; @Persistent private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Long getVersion() { return version; } }
先ほどの画面でいうと、このコードでは『All猫検索』が実行できない。このリンクを押したとき (ちなみにリンクになってるのに意味はないですGWTを思い出すための練習です) CatDao#findAll()が呼ばれます。ここにいままでCatにあった部分を実装して、@NotPersistentのプロパティにKindをセットしてクライアントに戻せばいいのかと思った。
CatDaoではちゃんとKindを取得して、Catのプロパティにセットできた。
それで、slim3のGWTServiceServlet#invokeに処理が戻って、detachCopyAllされるとCatのnotpersistkindプロパティに設定されたKindはなくなってしまう。
根本的に理解してないんだろうな。親子とかグループとか状態とかの関係でしょうかね。その辺どうもわからないな。
またじっくりとドキュメントなど読みたいと思います。