S-JIS[2010-09-12/2010-09-23] �ύX����

Slim3

Slim3�́AGoogle App Engine for Java�iGAE/J�j�p��MVC�t���[�����[�N�B
�O���[�o���g�����U�N�V�����������鑼�ABigtable�ւ̃A�N�Z�X��JDO/JPA��葬���炵���B


Slim3�̃C���X�g�[��

Slim3��Eclipse����B
���AEclipse�̃v���O�C���̂悤�Ȍ`���ł͂Ȃ��̂ŁA�g���j���[����V�K�v���W�F�N�g��Slim3�̃v���W�F�N�g���쐬����h�̂ł͂Ȃ��B
Slim3�̃u�����N�v���W�F�N�g���_�E�����[�h���Ă��āAEclipse�ɃC���|�[�g����B

�Q�l�F Slim3 ���{��T�C�g(�����)���u�����N�v���W�F�N�g�̓���

  1. �u�����N�v���W�F�N�g�̈ꗗ�̃y�[�W���J���B�i��ԏオ��ԐV�����j
  2. Slim3�̃u�����N�v���W�F�N�g���_�E�����[�h����B�i2010-09-12���_��slim3-blank-1.0.5.zip���ŐV�j
  3. Eclipse3.6�̃��[�N�X�y�[�X�ɃC���|�[�g����B
    1. ���j���[�o�[�́u�t�@�C��(F)�v���u�C���|�[�g(I)�v�Łu�C���|�[�g�v�_�C�A���O���J���B
    2. �u��ʁv�ˁu�����v���W�F�N�g�����[�N�X�y�[�X�ցv��I�����āu���ցv
    3. �u�A�[�J�C�u�E�t�@�C���̑I��(A)�v��I��ŁA�_�E�����[�h����slim3-blank-1.0.5.zip�̏ꏊ���w�肷��B
    4. �u�����v�{�^���������ƁA�v���W�F�N�g���C���|�[�g�����B
    5. �C���|�[�g���ꂽ�v���W�F�N�g���́uslim3-blank�v�ƂȂ��Ă���̂ŁA�K�X�ύX����B
  4. Eclipse�̐ݒ���s���B�i�u�����N�v���W�F�N�g�̓����ɏ����Ă���ʂ�j
  5. war/WEB-INF/web.xml��ҏW����B
    �v�f�� �ҏW���e
    context-param <param-name>slim3.rootPackage</param-name> param-value�̒l���������g�p����p�b�P�[�W���ɂ���B
    �Ⴆ�΁ujp.hishidama.gae.slim3.ex1�v
    servlet
    servlet-mapping
    <servlet-name>GWTServiceServlet</servlet-name> �R�����g�A�E�g���O���B
  6. ���̑��A�u�����N�v���W�F�N�g�̓����ɏ����Ă���ݒ���s���B

�v���W�F�N�g�����s�i�u���s�v���uWeb�A�v���P�[�V�����v�j����ƁA�uDevelopment Mode�v�Ƃ����r���[���J���B
�����ɕ\������Ă���uhttp://127.0.0.1:8888/index.html?gwt.codesvr=127.0.0.1:9997�v���u���E�U�[�ŊJ���ƁA�ŏ��ɁuGoogle Web Toolkit Developer Plugin�v�̃C���X�g�[�����v�������B
GwtDevPluginSetup.exe���_�E�����[�h���Ď��s���ăC���X�g�[������B

�ēx�uhttp://127.0.0.1:8888/index.html?gwt.codesvr=127.0.0.1:9997�v���J���ƁA�u���E�U�[��͐^�����̉�ʂ��\������邾���B�iGwtDevPlugin��ActiveX�̎��s�͋��‚��Ă����j
Eclipse�́uDevelopment Mode�v�r���[�ɂ́uModule main has been loaded�v�Ƃ������b�Z�[�W���\�������B

���̎��_�Łuhttp://127.0.0.1:8888/index.html�v�ɃA�N�Z�X����ƁA�uWeb�y�[�W����̃��b�Z�[�W�v�Ƃ����^�C�g���̃G���[�_�C�A���O���\�������B���͂́uGWT module 'main' may need to be (re)compiled�v�B
�������ꂽindex.html�������JavaScript�����s���Ă��邾���̂悤�Ȃ̂ŁA�p�����[�^�[�����ŊJ���z��ł͂Ȃ��̂��낤�B


���[�U�[�C���^�[�t�F�[�X�̍쐬

���[�U�[�����̉�ʁi�\����������͂��Ă�������肷��j���쐬���Ă݂�B
�i���������̕��@�́ASlim3�Ƃ�������GAE/J�̎������@�̂悤�ȋC������B
 Slim3��MVC�A�‚܂�Controller��JSP���g�����@�̏ꍇ�A���̃��[�U�[�C���^�[�t�F�[�X�͕s�v�����H�j

�Q�l�F Slim3 ���{��T�C�g(�����)�����[�U�[�C���^�[�t�F�C�X�̍쐬

  1. ���j���[�o�[�́u�t�@�C��(F)�v���uUiBinder�v�ŁuNew UiBinder�v�_�C�A���O���J���B
  2. �u���O(M)�v��Main�Ɠ���āu�����v�{�^��
  3. ����ƁA�usrc/�w��p�b�P�[�W/�v�̉���Main.java��Main.ui.xml�������B

�������ꂽMain.java�F

package jp.hishidama.gae.slim3.ex1.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;

public class Main extends Composite {

	private static MainUiBinder uiBinder = GWT.create(MainUiBinder.class);

	interface MainUiBinder extends UiBinder<Widget, Main> {
	}

	@UiField
	Button button;

	public Main(String firstName) {
		initWidget(uiBinder.createAndBindUi(this));
		button.setText(firstName);
	}

	@UiHandler("button")
	void onClick(ClickEvent e) {
		Window.alert("Hello!");
	}

}

�������ꂽMain.ui.xml�F

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
	xmlns:g="urn:import:com.google.gwt.user.client.ui">
	<ui:style>
		.important {
			font-weight: bold;
		}
	</ui:style>
	<g:HTMLPanel>
		Hello,
		<g:Button styleName="{style.important}" ui:field="button" />
	</g:HTMLPanel>
</ui:UiBinder>

Slim3�����[�U�[�C���^�[�t�F�C�X�̍쐬�y�[�W�ɏ�����Ă�����̂Ƃ͓��e���قȂ��Ă��邪�A�����ƃo�[�W�����Ⴂ�̏��ׂ��낤�B


�����āAMainEntryPoint.java���A��������Main�N���X���Ăяo���悤�C������B

MainEntryPoint.java�F

package jp.hishidama.gae.slim3.ex1.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;

public class MainEntryPoint implements EntryPoint {

	public void onModuleLoad() {
		RootPanel.get().add(new Main("hishidama"));
	}
}

���Ȃ݂ɁuonModuleLoad()�v�̓C���^�[�t�F�[�X�Ő錾����Ă��郁�\�b�h�̎��������A@Override�A�m�e�[�V�����͕t���Ȃ��B
�Ȃ��Ȃ�ASlim3�̃u�����N�v���W�F�N�g��JDK1.5�����ɂȂ��Ă��邩��B


�u���E�U�[�Łuhttp://127.0.0.1:8888/index.html?gwt.codesvr=127.0.0.1:9997�v���J���i���邢�͊��ɊJ���Ă����̂�������X�V/�����[�h����j�ƁAMain.ui.xml�̓��e��HTML�ɕϊ�����ĕ\�������B

���̃{�^���������ƁA�uHello!�v�Ƃ����_�C�A���O���\�������B


Main.java��Main.ui.xml�͂��݂��ɖ��ڂȊ֌W�ɂ���B

Main.java
public class Main extends Composite {
�`
	@UiField
	Button button;

	// �R���X�g���N�^�[
	public Main(String firstName) {
		initWidget(uiBinder.createAndBindUi(this));
		button.setText(firstName);
	}

	@UiHandler("button")
	void onClick(ClickEvent e) {
		Window.alert("Hello!");
	}
}
Main.ui.xml
	<g:HTMLPanel>
		Hello,
		<g:Button styleName="{style.important}" ui:field="button" />
	</g:HTMLPanel>

Main�N���X�̒���button�Ƃ������O�̃t�B�[���h�i�����o�[�ϐ��j������B
Main()�R���X�g���N�^�[�̒���button.setText()���s�����Ƃɂ��A�{�^���̃e�L�X�g���Z�b�g���Ă���B���ꂪ��ʕ\�����ɕ\������Ă���B

Main.ui.xml�́ug:Button�v�Ƃ����v�f���A�{�^���𐶐����Ă���B
�����́uui:field�v�Ƃ��������̒l�́AMain.java�́u@UiField�v�A�m�e�[�V������t�����t�B�[���h�̕ϐ����ƈ�v���Ă���K�v������B

�܂��AMain#onClick()�́u@UiHandler�v�A�m�e�[�V�����̒l���AMain.ui.xml��ui:field�ŕt����ꂽ���O�ƈ�v���Ă���K�v������B

�Ⴆ�΁ubutton�v�Ƃ������O��ʂ̖��O�ɕς�����������A��L��4�ӏ��S�Ă𓯂����O�ɕς���K�v������B
Main�N���X�̃t�B�[���h�������ς���ƁA�u���̖��O��Main.ui.xml�ɖ����v�Ƃ����|�̃G���[��Eclipse��ɕ\�������B
������Main.ui.xml��ui:field�̒l��ς���ƁAMain#onClick()�ɕt���Ă���u@UiHandler�v�A�m�e�[�V�����̒l���uMain.ui.xml�ɖ����v�Ƃ����G���[����������B
�A������ӏ��̃G���[�`�F�b�N��������Ƃ���Ă���̂͂������B


Controller�ɂ���ʑJ��

Slim3�ł́A��ʑJ�ڂ�Controller�ɂ���Đ��䂷��B
�u�����N�v���W�F�N�g�ɓ����Ă���build.xml�ɂ���āAController�N���X��jsp�t�@�C���̐��`�𐶐����邱�Ƃ��o����B

build.xml�́ugen-controller�v�����s����ƁA�p�X�i���s����URL�̈ꕔ�j����͂���_�C�A���O���J���B
�����Ƀp�X����͂���ƁA����ɊY������Controller�N���X��jsp�t�@�C�������������B
Controller�N���X�́A����JSP��\������ׂɎg�p�����iJSP�̕\���O�iJSP�ւ̃t�H���[�h�O�j�ɌĂ΂��j�B

�p�X ���������t�@�C�� �A�N�Z�X����URL
���[�J���i�e�X�g�j �C���^�[�l�b�g�i�{�ԁj
/ war/index.jsp
src/�`/server/controller/IndexController.java
test/�`/server/controller/IndexControllerTest.java
http://localhost:8888/
http://localhost:8888/index
http://aid.appspot.com/
http://aid.appspot.com/index
/aaa/ war/aaa/index.jsp
src/�`/server/controller/aaa/IndexController.java
test/�`/server/controller/aaa/IndexControllerTest.java
http://localhost:8888/aaa/
http://localhost:8888/aaa/index
http://aid.appspot.com/aaa/
http://aid.appspot.com/aaa/index
/aaa/bbb war/aaa/bbb.jsp
src/�`/server/controller/aaa/BbbController.java
test/�`/server/controller/aaa/BbbControllerTest.java
http://localhost:8888/aaa/bbb http://aid.appspot.com/aaa/bbb

�������ꂽIndexController.java�F

package jp.hishidama.gae.slim3.ex1.server.controller;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;

public class IndexController extends Controller {

	@Override
	public Navigation run() throws Exception {
		return forward("index.jsp");	��index.jsp�փt�H���[�h����悤�L�q����Ă���
	}
}

����index.jsp�ɃA�N�Z�X����ɂ́A�uhttp://localhost:8888/�v���u���E�U�[�ŊJ���B
jsp�ɂ͒��ڃA�N�Z�X�ł��Ȃ��悤�ɂȂ��Ă���̂ŁA�uhttp://localhost:8888/index.jsp�v��403 FORBIDDEN�ɂȂ�B

���������[�U�[�C���^�[�t�F�[�X�̍쐬�iMainEntryPoint�̍쐬�j�ɂ����index.html��p�ӂ��Ă����ꍇ�A������̕����D�悳��A��������index.jsp�͎g�p����Ȃ��B
���������āAindex.html���폜���Ă����K�v������B�i���邢�̓��l�[�����Ă����j
Main.java�EMain.ui.xml�A�‚��ł�MainEntryPoint.java���i�‚܂�client�p�b�P�[�W���ƑS���j�폜���Ă����Ă����v�Ȃ悤���B
�v���W�F�N�g�̃v���p�e�B�[�́uGoogle�v���uWeb�c�[���L�b�g�v�́u�G���g���[�E�|�C���g�E���W���[���v��Main���폜����΁AMain.gwt.xml���s�v�ɂȂ�B[2010-09-19]
�܂��Awar/main/���폜�ł���B�i�G���g���[�|�C���g����`����Ă���ƁA����ɍ����j


�A���J�[�^�O

�����N�ɂ���ĕʂ̉�ʂ֑J�ڂ�����ɂ́Aa�v�f�i�A���J�[�^�O�j��href�����Łuf:url�v�֐����L�q����B[/2010-09-17]

<a href="${ f:url('/aaa/') }">�J�ڂ���</a>

�uf�v�́u<%@taglib prefix="f" uri="http://www.slim3.org/functions"%>�v�ɂ���Đ錾����Ă���ASlim3���񋟂���֐��̐ړ����B
�uf:url�v�͑��΃p�X��URL���G���R�[�h���Ă����B

�J�ڌ� �J�ڐ� �L�q�� ���l
�ǂ�����ł� war/aaa/index.jsp
<a href="${ f:url('/aaa/') }">�J�ڂ���</a>
<a href="${ f:url('/aaa/index') }">�J�ڂ���</a>
�u/�v����n�߂�ƁA���̃T�C�g���̐�΃p�X�����B
�u/�v�ŏI���ƁAindex���ȗ����ꂽ�����B
war/*.jsp war/aaa/index.jsp
<a href="${ f:url('aaa/') }">�J�ڂ���</a>
<a href="${ f:url('aaa/index') }">�J�ڂ���</a>
�u/�v����n�߂Ȃ��ƁA���΃p�X�B
war/aaa/*.jsp war/aaa/bbb.jsp
<a href="${ f:url('/aaa/bbb') }">�J�ڂ���</a>
<a href="${ f:url('bbb') }">�J�ڂ���</a>
����f�B���N�g���[���̃y�[�W�ւ̑J�ځB
war/aaa/*.jsp war/aaa/index.jsp
<a href="${ f:url('/aaa/index') }">�J�ڂ���</a>
<a href="${ f:url('index') }">�J�ڂ���</a>
<a href="${ f:url('./') }">�J�ڂ���</a>
����f�B���N�g���[����index.jsp�ւ̑J�ځB
war/aaa/*.jsp war/index.jsp
<a href="${ f:url('/') }">�J�ڂ���</a>
<a href="${ f:url('../') }">�J�ڂ���</a>
<a href="${ f:url('../index') }">�J�ڂ���</a>
�z�[���y�[�W�i�g�b�v�y�[�W�j�ւ̑J�ځB

���͉��

������́i�o�^�j�����ʂ����ɂ́Aform�v�f��jsp�t�@�C���ɋL�q����B[2010-09-17]

�Q�l�F Slim3 ���{��T�C�g(�����)���t�H�[���̍쐬

<form method="post" action="${ f:url('inputAction') }">
<p><input type="text" ${ f:text("foo") }/></p>
<p><input type="submit" value="�o�^"/></p>
</form>

input�v�f�ɂ́Af:text�Ef:hidden�Ƃ������A�����̈ꕔ�𐶐�����Slim3�̊֐����p�ӂ���Ă���B
������type="submit"�͓��ɉ����p�ӂ���Ă��Ȃ��̂ŁA���̂܂�HTML���L�q����B
�iStruts����HTML�̃^�O�����̂܂ܒu��������J�X�^���^�O���p�ӂ���Ă������ASlim3�͂��������T�O�ł͂Ȃ��悤���j

���̂܂܂œ��̓G���A�͕\�������B
�������T�u�~�b�g�i�o�^�j�{�^���������ƁA404 NOT_FOUND�̃G���[�ɂȂ�Bform�^�O��action�����Ŏw�肵��URI�̏���������ĂȂ����瓖�R�O�O�G


�Ȃ��A�����l��^�������ꍇ�́A����JSP�ƃy�A�ɂȂ��Ă���Controller�̒��Œl���Z�b�g���Ă��΂����B

public class InputController extends Controller {

	@Override
	public Navigation run() throws Exception {
		requestScope("foo", "�����l");

		return forward("input.jsp");
	}
}

���͂��ꂽ�t�H�[�����󂯎�鏈�����쐬����B

�u�����N�v���W�F�N�g�ɓ����Ă���build.xml�́ugen-controller-without-view�v�����s����ƁAController�N���X���������B�ijsp�t�@�C���͍���Ȃ��j
�uaaa/inputAction�v�Ƃ����p�X�ɂ��Ă����ƁA�usrc/�`/server/controller/aaa/InputActionController.java�v�ƃe�X�g�p�\�[�X���o����B

package jp.hishidama.gae.slim3.ex1.server.controller.aaa;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;

public class InputActionController extends Controller {

	@Override
	public Navigation run() throws Exception {
		return null;			�������P��null��Ԃ������i�J�ڐ悪�����j
	}
}

���̐e�N���X�ł���Controller�ɂ́Arequest�Ƃ����t�B�[���h����`����Ă���B
�����ɂ��̓��e��\�����Ă݂悤�B

package jp.hishidama.gae.slim3.ex1.server.controller.aaa;

import java.util.logging.Logger;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.util.RequestMap;

public class InputActionController extends Controller {
	private final static Logger LOG = Logger.getLogger(InputActionController.class.getName());

	@Override
	public Navigation run() throws Exception {
		RequestMap rm = new RequestMap(request);
		LOG.info(rm.toString());

		return null;
	}
}

RequestMap�Ƃ����̂́ASlim3�ŗp�ӂ���Ă��郆�[�e�B���e�B�[�BHashMap���p�����Ă���B
����Œ������Ă݂�ƁA���̉�ʂœ��͂��ꂽ�l�Ɩ��O�������Ă���̂�������B
�i�‚��łɁuslim3.�v�Ŏn�܂�v���p�e�B�[�������‚������Ă���悤���B���͉�ʂł͂������������O�͎g�p���Ȃ������ǂ������j

�Ȃ��Arun()��null��Ԃ��Ɛ^��������ʂ��\������邾���Ȃ̂ŁA�ʂ̉�ʂɑJ�ڂ���悤�ɂ��Ă����B
gen-controller�œo�^������ʁi/aaa/complete�j������Ă����āA�����փ��_�C���N�g����̂��ǂ������B

		 return redirect(basePath + "complete");

���āASlim3�̏ꍇ�ADB�o�^�Ȃǂ̏����́u�T�[�r�X�v�N���X�ōs���悤���B
�Ȃ̂ŁAService�N���X���쐬���AController����Service���Ăяo���悤�ɂ���B

�u�����N�v���W�F�N�g�ɓ����Ă���build.xml�́ugen-service�v�����s����ƃN���X���i�̈ꕔ�j����͂���_�C�A���O���J���B
�����ɃN���X���i�̈ꕔ�j����͂���ƁAService�N���X�Ƃ��̃e�X�g�N���X�������B
�Ⴆ�΁uaaa.MyService�v�Ɠ��͂���Ɓusrc/�`/server/service/aaa/MyService.java�v�������B

�������ꂽMyService.java�F

package jp.hishidama.gae.slim3.ex1.server.service.aaa;

public class MyService {

}

���g�͉��������̂ŁO�O�G�A�����Ń��\�b�h��lj�����B

package jp.hishidama.gae.slim3.ex1.server.service.aaa;

import java.util.Map;
import java.util.logging.Logger;

public class MyService {
	private final static Logger LOG = Logger.getLogger(MyService.class.getName());

	public void regist(Map<String, Object> input) {
		LOG.info(input.toString());
	}
}

�C������InputActionController.java�F

package jp.hishidama.gae.slim3.ex1.server.controller.aaa;

import jp.hishidama.gae.slim3.ex1.server.service.aaa.MyService;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.util.RequestMap;

public class InputActionController extends Controller {

	private MyService service = new MyService();

	@Override
	public Navigation run() throws Exception {
		service.regist(new RequestMap(request));

		return null;
	}
}

���Ȃ݂�Controller�̃C���X�^���X�̓��N�G�X�g���ɍ����i�}���`�X���b�h�ŌĂ΂�Ȃ��j�悤�Ȃ̂ŁA�t�B�[���h�ɃC���X�^���X���������Ă��悢�B


Slim3�ŁiGAE�́jDB�Ƀf�[�^��o�^�i�ۑ��j����ׂɂ́A�u���f���v�N���X���g�p����B
���f���Ƃ́A�v�����JavaBeans�i�t�B�[���h�ɒl��ێ����A�Z�b�^�[�E�Q�b�^�[���\�b�h�Őݒ�E�擾����j�B
���f���̃C���X�^���X�Ƀf�[�^���Z�b�g���A��������̂܂�GAE��DB�ɕۑ�����B
�iModel�̐�����Slim3 ���{��T�C�g(�����)���f�[�^�N���X�̒�`�j

�u�����N�v���W�F�N�g�ɓ����Ă���build.xml�́ugen-model�v�����s����ƃN���X���i�̈ꕔ�j����͂���_�C�A���O���J���B
�����ɃN���X���i�̈ꕔ�j����͂���ƁAModel�N���X�Ƃ��̃e�X�g�N���X�A���ꂩ��Meta�Ƃ����N���X�������B
�Ⴆ�΁uaaa.Data�v�Ɠ��͂���Ɓusrc/�`/shared/model/aaa/Data.java�v�usrc/�`/server/meta/aaa/DataMeta.java�v�������B

�������ꂽData.java�̈ꕔ�F

package jp.hishidama.gae.slim3.ex1.shared.model.aaa;

import java.io.Serializable;

import com.google.appengine.api.datastore.Key;

import org.slim3.datastore.Attribute;
import org.slim3.datastore.Model;

@Model(schemaVersion = 1)
public class Data implements Serializable {

	private static final long serialVersionUID = 1L;
	@Attribute(primaryKey = true)
	private Key key;

	@Attribute(version = true)
	private Long version;
	/**
	 * Returns the key.
	 *
	 * @return the key
	 */
	public Key getKey() {
		return key;
	}
�`
}

GAE�Ƀf�[�^��o�^����ۂɂ́A�L�[�ƃo�[�W�������K�{�̂悤���B�Ȃ̂ŁA����Ɋւ���t�B�[���h�ƃZ�b�^�[�E�Q�b�^�[���\�b�h�������ŗp�ӂ���Ă���B

�����ɁA�����ŕK�v�Ƃ���t�B�[���h�ƃZ�b�^�[�E�Q�b�^�[���\�b�h��lj�����B
���̍ۂ̖��O�i�Z�b�^�[�E�Q�b�^�[���\�b�h�̖��O�A������v���p�e�B�[���j�́A���͌�JSP�iinput�v�f��name�����j�ɍ��킹�Ă����B
�������邱�Ƃɂ���āASlim3�̃��[�e�B���e�B�[���g���Ēl�̃R�s�[���ȒP�Ɏ����ł��邩��B

	private String foo;
�`
	/**
	 * @return foo
	 */
	public String getFoo() {
		return foo;
	}

	/**
	 * @param foo
	 *	�Z�b�g���� foo
	 */
	public void setFoo(String foo) {
		this.foo = foo;
	}

���t�B�[���h��Z�b�^�[�E�Q�b�^�[�͎����Œlj�����K�v�����邪�A����ɂ����Meta�N���X�������I�ɏ��������B

���̃��f���N���X���g����DB�ɓo�^���郍�W�b�N�́AService�N���X�ɋL�q����B
�i�g�����U�N�V�����̒��ŗ�O����������ƁA�����I�Ƀ��[���o�b�N�����炵���j

import org.slim3.datastore.Datastore;
import org.slim3.util.BeanUtil;
import com.google.appengine.api.datastore.Transaction;

import jp.hishidama.gae.slim3.ex1.shared.model.aaa.Data;

public class MyService {

	public Data regist(Map<String, Object> input) {
		Data data = new Data();
		BeanUtil.copy(input, data);

		Transaction tx = Datastore.beginTransaction();
		Datastore.put(data);
		tx.commit();

		return data;	//�l��Ԃ��Ă���̂́A�e�X�g���ɃL�[���擾��������
	}
}

�C������MyServiceTest.java�F

public class MyServiceTest extends AppEngineTestCase {
�`
	@Test
	public void regist() {
		Map<String, Object> input = new HashMap<String, Object>();
		input.put("foo", "Hello");

		Data data = service.regist(input);

		Data stored = Datastore.get(Data.class, data.getKey());
		assertThat(stored.getFoo(), is("Hello"));
	}
}

�\����ʁi�ꗗ�\����ʁj

DB�ɓo�^���ꂽ�l�̈ꗗ��\�������ʂ�����Ă݂�B[2010-09-18]
��ʂɕ\������l�́A����jsp��\������ׁiJSP�ւ̑J�ڑO�j�ɌĂ΂��Controller�ŗp�Ӂirequest�I�u�W�F�N�g�ɃZ�b�g�j����B

�Q�l�F Slim3 ���{��T�C�g(�����)���‚Ԃ₫�̈ꗗ�\��

��������aaa/list.jsp���C���������́F

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="f" uri="http://www.slim3.org/functions"%>
�`
<c:forEach var="e" items="${dataList}">
${f:h(e.foo)}<br>
</c:forEach>
�`

��������ListController.java���C���������́F

	@Override
	public Navigation run() throws Exception {
		List<Data> dataList = new ArrayList<Data>();
		{
			Data g1 = new Data(); g1.setFoo("abc");    dataList.add(g1);
			Data g2 = new Data(); g2.setFoo("������"); dataList.add(g2);
		}
		requestScope("dataList", dataList);

		return forward("list.jsp");
	}

�ŁA���ۂɂ�Service�N���X�̕���DB����f�[�^���擾���郁�\�b�h��p�ӂ��āA������Ăяo���B


ListController.java�F

	private MyService service = new MyService();
�`
	@Override
	public Navigation run() throws Exception {
		List<Data> dataList = service.getList();
		requestScope("dataList", dataList);

		return forward("list.jsp");
	}

�C������MyService.java�F

import org.slim3.datastore.Datastore;

import jp.hishidama.gae.slim3.ex1.shared.model.aaa.Data;

public class MyService {

	private DataMeta meta = new DataMeta();
�`
	public List<Data> getList() {
		return Datastore.query(meta).sort(meta.foo.asc).asList();
	}
}

Datastore.query()��ModelQuery�Ƃ����N���X��Ԃ��B
ModelQuery#sort()�Ń\�[�g���ڂ��w�肷��B���̎w��̎d���͖ʔ����ȁB
���ɂ�ModelQuery#filter()�Ńt�B���^�[�����iSQL�Ō���WHERE�����j���w��ł���悤���B
�Ō��ModelQuery#asList()���ĂԂ��Ƃɂ����DB�A�N�Z�X���s����B


�폜�@�\

�ꗗ�\������ɍ폜�@�\��lj����Ă݂�B[2010-09-23]

���݂̃f�[�^�ꗗ�̉E���ɍ폜�����N��u���B���̃����N���N���b�N����ƁA���̍s���폜�����B

list.jsp�F

<table border="1">
	<tr>
		<th>�^�C�g��</th>
		<th>���e</th>
		<th>�쐬��</th>
		<th>�폜</th>
	</tr>
<c:forEach var="e" items="${dataList}">
	<tr>
		<td>${f:h(e.title)}</td>
		<td>${f:h(e.content)}</td>
		<td><fmt:formatDate value="${e.createDate}" pattern="yyyy-MM-dd" /></td>
		<c:set var="deleteUrl" value="delete?key=${f:h(e.key)}&amp;version=${e.version}" />
		<td><a href="${f:url(deleteUrl)}" onclick="return confirm('�폜���Ă����ł����H')">�폜</a></td>
	</tr>
</c:forEach>
</table>

DeleteController.java�F

package jp.hishidama.gae.slim3.ex1.server.controller.aaa;

import jp.hishidama.gae.slim3.ex1.server.meta.aaa.DataMeta;
import jp.hishidama.gae.slim3.ex1.server.service.aaa.MyService;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
public class DeleteController extends Controller {

	private DataMeta  meta    = DataMeta.get();
	private MyService service = new MyService();

	@Override
	public Navigation run() throws Exception {
		service.delete(asKey(meta.key), asLong(meta.version));

		return redirect("list"); //�ꗗ�\����ʂɖ߂�
	}
}

MyService.java�F

public class MyService {

	private DataMeta meta = new DataMeta();
�`
	public void delete(Key key, Long version) {
		Transaction tx = Datastore.beginTransaction();
		Data data = Datastore.get(tx, meta, key, version);
		Datastore.delete(tx, data.getKey());
		Datastore.commit(tx);
	}
}

�܂��Acontroller�p�b�P�[�W������AppRouter�Ƃ����N���X�������URL�}�b�s���O��ύX���Ă����ƁA�ʂ�URI�`���udelete/�L�[/�o�[�W�����v�ō폜���w�肷�邱�Ƃ��o����B

list.jsp�F

		<c:set var="deleteUrl" value="delete/${f:h(e.key)}/${e.version}" />
		<td><a href="${f:url(deleteUrl)}" onclick="return confirm('�폜���Ă����ł����H')">�폜</a></td>

AppRouter.java�F

package jp.hishidama.gae.slim3.ex1.server.controller;

import org.slim3.controller.router.RouterImpl;

public class AppRouter extends RouterImpl {

	/** �R���X�g���N�^�[ */
	public AppRouter() {
		addRouting(
			"/{app}/delete/{key}/{version}",
			"/{app}/delete?key={key}&version={version}"
		);
	}
}

�u/aaa/delete/�L�[/�o�[�W�����v�Ƃ������N�G�X�g������ƁA�u/aaa/delete?key=�L�[&version=�o�[�W�����v�Ƃ����`�ɒu�������Ă���Controller���Ăяo�����悤�ɂȂ�B


���t����

Slim3�iGAE�j�ł͓��t�͕W�����ň�����̂ŁA���{���ԁiJST�j�Ƃ���Ă���B[2010-09-18]
�����f�[�^�Ƃ��Ă͂���ł����Ƃ��Ă��A�\������ۂ͓��{�l�Ƃ��Ă͓��{���Ԃ̕����s���������񂶂�Ȃ����Ǝv���B

JSP�ŕ\������ۂ�Date�^�̒l��ϊ����Ă��B �iSlim3��GAE�̋@�\�ł͂Ȃ��AJSTL�̓��t�t�H�[�}�b�g���g�p����j

<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<fmt:formatDate value="${createDate}" pattern="yyyy-MM-dd HH:mm:ss" timeZone="JST"/>
<fmt:setTimeZone value="JST"/>
<fmt:formatDate value="${createDate}" pattern="yyyy-MM-dd HH:mm:ss z"/>

�����iValidation�j

Slim3�ł́A�ȒP�ȃo���f�[�V�����t���[�����[�N���񋟂���Ă���B[2010-09-18]

�Q�l�F Slim3 ���{��T�C�g(�����)���o���f�[�V����

���͂��󂯕t����Controller�̒��Œl���`�F�b�N���A�G���[����������G���[��ʂ֑J�ڂ���B

�C������InputActionController.java�F

�`
import org.slim3.controller.validator.Validators;
�`
public class InputActionController extends Controller {
�`
	@Override
	public Navigation run() throws Exception {
		if(!validate()){
			return forward("input");	//�G���[���N�����ꍇ�̑J�ڐ�B�����ł͌��̓��͉��
		}

		service.regist(new RequestMap(request));

		return redirect(basePath + "complete");
	}

	boolean validate() {
		Validators v = new Validators(request);

		v.add("foo", v.required());
		v.add("bar", v.required(), v.maxlength(100));
		v.add("zzz", v.required(), v.integerType(), v.longRange(1, Integer.MAX_VALUE));

		return v.validate();
	}
}

Validators�̃C���X�^���X�����ۂ�request��n���Ă���̂ŁA�������W�b�N��g�ݍ��ނ̂�Controller�N���X�ł����A�Ǝv���B

v.add()�̑�1�����ɓ��͉�ʂ̊e���ڂ̖��O�i<input name="foo">�Ƃ��j���w�肵�A��2�����ȍ~�ɂ͐������e���w�肷��B
required()���K�{�`�F�b�N�Amaxlength()���ő啶�����`�F�b�N�AintegerType()�͐����`�F�b�N�AlongRange()�͔͈̓`�F�b�N�ƁA��ϕ�����Ղ��B

�G���[�����������v.validate()��false��Ԃ��B
�܂��AController#errors�iv.getErrors()�ŕԂ����̂Ɠ����C���X�^���X�j�̒��ɃG���[���b�Z�[�W���Z�b�g�����B


�G���[���b�Z�[�W��\������ɂ́A�ȉ��̂悤�ɋL�q����B
�i�����ł͌��̓��͉�ʂɃG���[���b�Z�[�W��\������z��j

�C������input.jsp�F

<head>
�`
<style type="text/css">
input.err { background-color: pink; }
span.err  { color: red; }
</style>
</head>
<%-- �G���[���b�Z�[�W���܂Ƃ߂ĕ\������� --%>
<c:if test="${not empty errors}">
<ul>
<c:forEach var="e" items="${f:errors()}">
<li><span class="err">${f:h(e)}</span></li>
</c:forEach>
</ul>
</c:if>
<%-- �•ʂ̃G���[���b�Z�[�W��\������� --%>
foo�F
<input type="text" ${ f:text("foo") } class="${f:errorClass('foo', 'err')}"/>
<c:if test="${not empty errors.foo}"><span class="err">�G���[�F${f:h(errors.foo)}</span></c:if>
<br>
bar�F
<input type="text" ${ f:text("bar") } class="${f:errorClass('bar', 'err')}"/>
<c:if test="${not empty errors.bar}"><span class="err">�G���[�F${f:h(errors.bar)}</span></c:if>
<br>
zzz�F
<input type="text" ${ f:text("zzz") } class="${f:errorClass('zzz', 'err')}"/>
<c:if test="${not empty errors.zzz}"><span class="err">�G���[�F${f:h(errors.zzz)}</span></c:if>

����ŁAfoo�Ebar�Ezzz���K�{�`�F�b�N�G���[�ɂȂ�ƈȉ��̂悤�ȃ��b�Z�[�W���\�������B

  • foo�͕K�{�ł��B
  • bar�͕K�{�ł��B
  • zzz�͕K�{�ł��B
foo�F �G���[�Ffoo�͕K�{�ł��B
bar�F �G���[�Fbar�͕K�{�ł��B
zzz�F �G���[�Fzzz�͕K�{�ł��B

�G���[���b�Z�[�W�ɂ̓G���[�̏o�����ږ����o�͂���邪�A�����ID���\�������̂͂��܂�ǂ��Ȃ��B
src/application_ja.properties�Ɂulabel.���ږ��v�Ƃ����G���g���[��������ƁA���̖��O�ŕ\�������悤�ɂȂ�B

src/application_ja.properties�F

�`
label.foo=�Ӂ[
label.bar=�o�[
lbael.zzz=���₷��
  • �Ӂ[�͕K�{�ł��B
  • �o�[�͕K�{�ł��B
  • ���₷��͕K�{�ł��B
foo�F �G���[�F�Ӂ[�͕K�{�ł��B
bar�F �G���[�F�o�[�͕K�{�ł��B
zzz�F �G���[�F���₷��͕K�{�ł��B

�܂��Aapplication_ja.properties���́uvalidator.�v�Ŏn�܂�v���p�e�B�[�̕���������������΁A�G���[���b�Z�[�W�S�ʂ�Ǝ��ɒ�`���邱�Ƃ��o����B

validator.required={0}�͕K�{�ł��B
validator.byteType={0}�̓o�C�g�łȂ���΂����܂���B
validator.shortType={0}�͒Z�����łȂ���΂����܂���B
validator.integerType={0}�͐����łȂ���΂����܂���B
validator.longType={0}�͒������łȂ���΂����܂���B
validator.floatType={0}�͒P���x�����łȂ���΂����܂���B
validator.doubleType={0}�͔{���x�����łȂ���΂����܂���B
validator.numberType={0}�͐��l({1})�ł͂���܂���B
validator.dateType={0}�͓��t({1})�ł͂���܂���B
validator.minlength={0}�̒������ŏ��l({1})�����ł��B
validator.maxlength={0}�̒������ő�l({1})�𒴂��Ă��܂��B
validator.range={0}��{1}��{2}�̊ԂłȂ���΂����܂���B
validator.regexp={0}���s���ł��B

�������W�b�N�̕��Ō•ʂɃG���[���b�Z�[�W���w�肷�邱�Ƃ��o����B
�i�������A���̏ꍇ�ɂ�{0}��{1}�Ƃ����������̒u���͎g���Ȃ��̂Œ��Ӂj

�C������InputActionController.java�F

public class InputActionController extends Controller {
�`
	boolean validate() {
		Validators v = new Validators(request);

		v.add("foo", v.required("foo�͕K�{�₪��"));
		v.add("bar", v.required("bar�͕K�{��"), v.maxlength(100, "bar��100�𒴂��Ă���"));
		v.add("zzz", v.required("�����͕K�{����"), v.integerType("zzz��������Ȃ��c"), v.longRange(1, Integer.MAX_VALUE, "zzz���͈͊O"));

		return v.validate();
	}
}
  • foo�͕K�{�₪��
  • bar�͕K�{��
  • �����͕K�{����
foo�F �G���[�Ffoo�͕K�{�₪��
bar�F �G���[�Fbar�͕K�{��
zzz�F �G���[�F�����͕K�{����

HTTP�Z�b�V����

GAE��HTTP�Z�b�V�������g�p����ɂ́Aappengine-web.xml��ݒ肵�Ă����K�v������B[2010-09-19]

war/WEB-INF/appengine-web.xml�F

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
�`
	<sessions-enabled>true</sessions-enabled>	�c�f�t�H���g��false
</appengine-web-app>

Slim3�̏ꍇ�AController�N���X�ł́irequest�Ɠ��l�ɁjsessionScope()�Ƃ������\�b�h���p�ӂ���Ă���̂ŁA�l�̐ݒ�E�擾�ɂ͂�����g���̂��֗��B


GAE�֖߂� / Java�֖߂� / �Z�p�����֖߂�
���[���̑��M��F�Ђ�����

�@

�@

�@

�@

�@

�@

�@

�@

�@

�@

�@

�@

�@

�@

�@

�@