GWTのRPCで、特定のフィールドは送受信したくないとき

GWTのRPCで、特定のフィールドは送受信したくないときは、クラスのフィールドにtransient修飾子をつけるとよい。
アノテーションをつけて抑制する方法とかもありそうだけどわからなかった。

なお、クライアント - サーブレット間で送受信したいが、データベースには保存したくないフィールドは
@Attribute(persistent=false)
のようにアノテーションをつける

使用例

//データモデルにコンポジットパターンとリスナーパターンを使用するとき。
@Model(schemaVersion = 1)
public abstract class Composite implements Serializable{

@Attribute(primaryKey = true)
private Key key;

@Attribute(version = true)
private Long version;

//データベースにComposite役の参照関係を保存するとき
//Composite役をデータベースに直接保存するとデータ容量がすごいことになる。
//Composite役への参照はサーブレット - クライアント間で送受信するが、
//データベースには保存しない。
@Attribute(persistent=false)
protected List<Composite> childrenList = new ArrayList<Composite>(); //子要素のリスト

//データベース内で子要素との関連を保持するためのリスト
//本当はInverseModelListRefを使った方がいいかも。
@Attribute(unindexed=true)
private List<Key> childrenKeyList = new ArrayList<Key>();

//オブザーバパターンのためのリスナー
// RPCでサーバに送ろうとすると、リスナー側のパネルまでサーバに送ってしまい、NotSerializableExceptionがでる。
@Attribute(persistent=false)
transient protected List<ItemListener> _listeners = new ArrayList<ItemListener>();

//(後略)

}

データベース - サーブレット - クライアント間のデータ送受信の抑制

○:送受信する!  ×:抑制

クラスのフィールドにtransient修飾子をつける フィールドに @Attribute(persistent=false) アノテーションをつける
DB
× ×
Servlet
× ×
Client

Windows環境にMeteorをインストール

Windows向けの公式インストーラがあるようだ。

Meteor の

「On Windows? Download the official Meteor installer here.」

からダウンロードする。

GWTでサーバを使用せずにZipファイルをクライアントへ保存

外部JavaScript(JS)ライブラリとJSNIを使って実装する。FileSaverとJSZipを利用する。

Shift_JISは扱えません!!

  • 使用するjsライブラリ
  • war/js に使用するJSファイルを入れておく
  • htmlファイルでJSファイルをリンクしておくのも忘れずに
  • javaファイルでは、JSNIで外部JSライブラリにアクセス($wndを忘れずに)。JSNI内部ではjava.util.Mapが使えないようなので、JSONObjectを使用する。
  • JSONObjectを使うために、.gwt.xmlファイルにinheritsを追加する必要がある。

参考
gwt - Java Hashmap and Mutlidimensional array type sig in JSNI? - Stack Overflow
eligrey/FileSaver.js · GitHub
JSZip



 *.html

(前略)
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link type="text/css" rel="stylesheet" href="/css/global.css" />
    <script language="javascript" src="js/jszip.js"></script>
    <script language="javascript" src="js/FileSaver.js"></script>
</head>

(後略)

 *.java

        public void onModuleLoad() {

            Button save = new Button("保存");
            save.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    //JSONObject がMap代わりに使える
                    JSONObject obj = new JSONObject();
                    for (int i = 0; i < 3; i++) {
                        obj.put("k"+i, new JSONString("v"+i));
                    }
                    JavaScriptObject jsObj = obj.getJavaScriptObject();
                    saveAsZip(jsObj);
                }
            });

        RootPanel.get().add(save);
    }

    /**
     * @param fileMap
     *            key:ファイル名 value:ファイル内容
     * @return
     */
    private native boolean saveAsZip(JavaScriptObject fileMap) /*-{
		var zip = new $wnd.JSZip();

		for (key in fileMap) {
			zip.file(key + ".txt", fileMap[key]);
		}
		var blob = zip.generate({
			type : "blob"
		});
		$wnd.saveAs(blob, "text.zip");
		return true;
    }-*/;

*.gwt.xml

<module>
	<inherits name="com.google.gwt.user.User" />
	<inherits name="com.google.gwt.user.theme.standard.Standard" />
	<inherits name="com.google.gwt.json.JSON" />

	<entry-point class="(エントリーポイントクラス)" />
	<source path="client" />
</module>

GWTをSuper Dev ModeでデバッグするときGWTで書いたページが更新されていない

 GWTデバッグするために、SuperDevModeでローカルサーバを立ち上げ、デバッグしたいWebページにアクセスしたが、ページの内容が古いままのとき。もしくは、ページにアクセスしてもGWTコンパイルが始まらないとき。

 いったんローカルサーバを終了 ⇒ GWTコンパイル ⇒ 再度ローカルサーバ起動・開発中Webページにアクセス

とすれば、今後WebページにアクセスするたびにGWTコンパイルが実行されるはず。

FlowPanelの要素にPanelを追加しても浮動化してくれない

GWTを使用していて、FlowPanelの要素にPanelを追加しても浮動化してくれないとき。

追加する要素を<span></span>で囲み、CSSでfloat属性を指定すればよい

参考:
Simplifying GWT Markup with HTML Widgets « TurboManage



Main.java

public class Gwt_tmp implements EntryPoint {
	
	private static final int COUNT = 10;

	public void onModuleLoad() {

		VerticalPanel mainPanel = new VerticalPanel();
		RootPanel.get().add(mainPanel);

		mainPanel.addStyleName("contents");
		{
			mainPanel.add(new Label("ボタンをFlowPanelに追加"));
			FlowPanel fp = new FlowPanel();
			fp.setWidth("800px");
			mainPanel.add(fp);
			fp.clear();
			for (int i=0; i<COUNT; i++)
		    {
				Button item= new Button("button"+i);
				item.setWidth("100px");
		        fp.add(item);
		    }
			
		}
		mainPanel.add(new HTML("<hr>"));[f:id:black-skin:20150315175347p:plain]
		{
			mainPanel.add(new Label("VerticalPanelはFlowPanelでも横配置できない"));
			FlowPanel fp = new FlowPanel();
			mainPanel.add(fp);
			for (int i = 0; i < COUNT; i++) {
				VerticalPanel item = new VerticalPanel();
				item.setStyleName("name-" + i);
				item.add(new Label("title" + i));
				item.add(new Button("ボタン"));
				fp.add(item);
			}

		}
		

		mainPanel.add(new HTML("<hr>"));
		{
			mainPanel.add(new Label("<span>で囲み、floatを指定"));
			FlowPanel fp = new FlowPanel();
			fp.setWidth("800px");
			mainPanel.add(fp);
			fp.clear();
			for (int i=0; i<COUNT; i++)
		    {
				VerticalPanel item = new VerticalPanel();
				item.setWidth("150px");
				item.setStyleName("name-" + i);
				item.add(new Label("title" + i));
				item.add(new Button("ボタン"));
		        fp.add(new FloatSpanItemWidget(item));
		    }
			
		}
	}
}

FloatSpanItemWidget.java


import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

public class FloatSpanItemWidget extends SimplePanel
{
    public FloatSpanItemWidget()
    {
        super((Element) Document.get().createSpanElement().cast());
        addStyleName("float");
    }
 
    public FloatSpanItemWidget(String s)
    {
        this();
        getElement().setInnerText(s);
    }
 
    public FloatSpanItemWidget(Widget w)
    {
        this();
        this.add(w);
    }
}
<!--(中略)-->
.float{
float: left;
}

f:id:black-skin:20150315175705p:plain

DecoratorPanelを使ったが、padding,border,marginが反映されなかったとき

ちょっとはまったので。
以下の内容が記述されたCSSファイルが読み込まれるように自分で設定すること。
たとえば、decoratorPanel.cssという名前のファイルにして読み込む

decoratorPanel.css

.gwt-DecoratorPanel {

}
.gwt-DecoratorPanel .topCenter,
.gwt-DecoratorPanel .bottomCenter {
background: url(images/hborder.png) repeat-x;
}
.gwt-DecoratorPanel .middleLeft,
.gwt-DecoratorPanel .middleRight {
background: url(images/vborder.png) repeat-y;
}
.gwt-DecoratorPanel .topLeftInner,
.gwt-DecoratorPanel .topRightInner,
.gwt-DecoratorPanel .bottomLeftInner,
.gwt-DecoratorPanel .bottomRightInner {
width: 5px;
height: 5px;
zoom: 1;
}
.gwt-DecoratorPanel .topLeft {
background: url(images/corner.png) no-repeat 0px 0px;
-background: url(images/corner_ie6.png) no-repeat 0px 0px;
}
.gwt-DecoratorPanel .topRight {
background: url(images/corner.png) no-repeat -5px 0px;
-background: url(images/corner_ie6.png) no-repeat -5px 0px;
}
.gwt-DecoratorPanel .bottomLeft {
background: url(images/corner.png) no-repeat 0px -5px;
-background: url(images/corner_ie6.png) no-repeat 0px -5px;
}
.gwt-DecoratorPanel .bottomRight {
background: url(images/corner.png) no-repeat -5px -5px;
-background: url(images/corner_ie6.png) no-repeat -5px -5px;
}
html>body .gwt-DecoratorPanel {
}
* html .gwt-DecoratorPanel .topLeftInner,
* html .gwt-DecoratorPanel .topRightInner,
* html .gwt-DecoratorPanel .bottomLeftInner,
* html .gwt-DecoratorPanel .bottomRightInner {
width: 5px;
height: 5px;
overflow: hidden;
}

 
参考
DecoratorPanel (GWT Javadoc)
Showcase of GWT Features

slim3 使用時にEGITでチェックアウトできないとき

 slim3はModelのmetaファイルを作成するためにATP (Annotation Processing)を使用している。ATPを有効にしたままだとEGITでCheckOutしようとしたときに、変更を破棄するかを聞いてくるダイアログが何回も出てきてCheckOutできない。CheckOutするためには

 メニューバーの Project -> Properties -> Java Compiler -> Annotation Processing

の中にある、「enable annotation processing」のチェックをはずす。