http://phillyspring.ning.com/forum/topics/july-meeting-springsource-roo
위 url에 있는 발표 자료를 간략하게 정리해 봤다.
1. Roo란 ?
spring & java 환경을 위한 RAD(Rapid Application Development) 플랫폼
- domain-centric design of database entities
- Auto-scaffolding of UI elements
- Builds a full stack Spring web application
- Target build process managed by Maven
java, spring 환경에서 개발할 때 많은 xml 설정을 상당 부분 CoC(Convention over Configuration)으로 변경한 프레임워크.
2. Roo 개발 절차
Roo는 grails/rails 처럼 커맨드 라인 쉘을 제공한다.
이 쉘을 이용해서
- 메이븐으로 빌드되는 프로젝트를 생성
- roo와 개발툴에서의 변경이 서로 동기화되는 round-trip을 제공한다.
- 특정 기능을 제공하기 위해 aspect를 사용한다.
- aspect를 관련된 클래스 파일에 위빙한다.
3. 사용된 기술들
AspectJ ITD(Inter-Type Declarations)
- maven/eclipse에서 aspectj 컴파일러를 사용한다.
- roo 어노테이션된 클래스에 컴파일 타임에 코드(aspect에 구현된)를 추가한다.
Roo 커맨드 쉘
- 훌룡한 빌드 환경을 생성/유지한다.
- 동적으로 .aj 파일을 생성하고, web UI scaffold를 제공한다.
4. Creating a roo project
- 디렉토리 생성하기
- 해당 디렉토리에서 roo 쉘 실행
- create project 명령 수행
flibbity-floo:roo-demo krimple$ roo
____ ____ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / / / /
/ _, _/ /_/ / /_/ /
/_/ |_|\____/\____/ 1.0.0.M1 [rev 64]
Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
roo> create project -topLevelPackage com.chariot.demo.roodemo
Created /Users/krimple/svn-projects/...roodemo/pom.xml
Created SRC_MAIN_JAVA
Created SRC_MAIN_RESOURCES
Created SRC_TEST_JAVA
Created SRC_TEST_RESOURCES
Created SRC_MAIN_WEBAPP
Created SRC_MAIN_RESOURCES/applicationContext.xml
Created SRC_MAIN_WEBAPP/WEB-INF
Created SRC_MAIN_WEBAPP/WEB-INF/roodemo-servlet.xml
Created SRC_MAIN_WEBAPP/WEB-INF/web.xml
Created SRC_MAIN_WEBAPP/WEB-INF/jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/index.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/urlrewrite.xml
5. Installing JPA
'install jpa' 명령을 사용해서 Open JPA, Hibernate, EclipseLink 중 하나의 persistence F/W를 설치한다.
roo> install jpa -provider HIBERNATE -database MYSQL
Created SRC_MAIN_RESOURCES/META-INF
Created SRC_MAIN_RESOURCES/META-INF/persistence.xml
Created SRC_MAIN_RESOURCES/database.properties
please enter your database details in src/main/resources/database.properties
Managed SRC_MAIN_RESOURCES/applicationContext.xml
Managed ROOT/pom.xml
6. Adding a Persistent JPA Entity
‘new persistent class’ 명령을 사용해서 새로운 도메인 클래스를 설정한다.
후에 'add field' 명령을 사용해서 필드를 추가할 수 있다.
roo> new persistent class jpa -name ~.Conference
Created SRC_MAIN_JAVA/com/chariot/roodemo
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_Plural.aj
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_Entity.aj
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_Configurable.aj
7. What Got Created?
지금까지의 작업을 수행했다면 Roo는 아래와 같은 파일들을 생성했을 것이다.
- Conference.java - the file you edit, containing Roo annotations and your properties
- Conference_Roo_Configurable.aj - adds @Configurable to the entity
- Conference_Roo_Entity.aj - Adds all JPA persistence methods, an id, and a version
- Conference_Roo_JavaBean.aj - Adds getters/ setters for all of your private properties
8. Setting up JPA fields
필드나 관계를 추가할 수 있다. 이러한 필드들은 물리적으로 자바 파일에 추가된다. 또 추가된 필드들을 위한 support 메소드들이 자동으로 wired된다.
roo> add field string name
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj
roo> add field string description
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj
roo> add field date jpa -type java.util.Date -fieldName created
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj
9. Building a Relationship
roo> new persistent class jpa -name ~.domain.Conference
roo> add field string -fieldName conferenceName -notNull -sizeMin 1 -sizeMax 40
roo> add field date jdk -type java.util.Date -notNull -fieldName startDate
roo> add field date jdk -type java.util.Date -notNull -fieldName endDate
roo> new persistent class jpa -name ~.domain.ConferenceSession
roo> add field string -notNull -fieldName title -sizeMax 80
roo> add field reference jpa -fieldName conference -type com.chariot.demo.contrack.domain.Conference
roo> add field set jpa -element ~.domain.ConferenceSession -fieldName session -class com.chariot.demo.contrack.domain.Conference
10. Entity Validation
JSR-303 annotation에 의해 entity를 validate할 수 있다.
@NotNull, @Nullable, @Size, @DecimalMin, @DecimalMax, etc...
자동 생성되는 Controller에는 이러한 Bean Validation API를 통해 validation을 호출하는 코드가 포함된다.
javax.validation.Validation.
buildDefaultValidatorFactory().getValidator().
validate(conference))
11. Validation Examples
@Size(min = 5, max = 30, message = "Please enter a name between {min} and {max} characters.")
private String name;
@Size(min = 10, max=2048, message = "{description.required}")
private String description;
@Temporal(TemporalType.TIMESTAMP)
@Column(insertable=true, updatable=false)
@NotNull
private Date created;
12. Configuring logging
roo> configure logging -level TRACE
Created SRC_MAIN_RESOURCES/log4j.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/web.xml
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
#Updated at Tue Jun 09 09:21:45 EDT 2009
#Tue Jun 09 09:21:45 EDT 2009
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.rootLogger=TRACE, stdout, R
log4j.appender.R.File=application.log
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.R=org.apache.log4j.RollingFileAppender
13. Generating a Controller
roo> new controller automatic -name com.chariot.roodemo.domain.ConferenceController
Created SRC_MAIN_JAVA/com/chariot/roodemo/domain/ConferenceController.java
Created SRC_MAIN_JAVA/com/chariot/roodemo/domain/ConferenceController_Roo_Controller.aj
Created SRC_MAIN_WEBAPP/images
Created SRC_MAIN_WEBAPP/images/banner-graphic.png
Created SRC_MAIN_WEBAPP/images/springsource-logo.png
Created SRC_MAIN_WEBAPP/images/list.png
Created SRC_MAIN_WEBAPP/images/show.png
Created SRC_MAIN_WEBAPP/images/create.png
Created SRC_MAIN_WEBAPP/images/update.png
Created SRC_MAIN_WEBAPP/images/delete.png
Created SRC_MAIN_WEBAPP/styles
Created SRC_MAIN_WEBAPP/styles/roo.css
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/header.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/footer.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/includes.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/dataAccessFailure.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/uncaughtException.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/list.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/show.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/create.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/update.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/menu.jsp
Managed SRC_MAIN_WEBAPP/WEB-INF/jsp/menu.jsp
19. Example Aspect: show
In ConferenceController_Roo_Controller.aj:
@org.springframework.web.bind.annotation.RequestMapping(
value = "/conference/{id}", method = org.springframework.web.bind.annotation.RequestMethod.GET)
public java.lang.String ConferenceController.show(
@org.springframework.web.bind.annotation.PathVariable("id") Long id,
org.springframework.ui.ModelMap modelMap) {
if (id == null) throw new IllegalArgumentException("An Identifier is required");
modelMap.addAttribute("conference", com.chariot.roodemo.domain.Conference.findConference(id));
return "conference/show";
}
Uses findConference in Conference_Roo_Entity.aj
public static com.chariot.roodemo.domain.Conference Conference.findConference(java.lang.Long id) {
if (id == null) throw new IllegalArgumentException(
"An identifier is required to retrieve an instance of Conference");
javax.persistence.EntityManager em = new Conference().entityManager;
if (em == null) throw new IllegalStateException(
"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects
library?)");
return em.find(Conference.class, id);
}
20. Get it working!
mvn jetty:run이나 mvn tomcat:run을 통해서 웹 어플리케이션을 실행할 수 있다.
Hit the webapp url and get a menu of choices
21. IDE Support
Roo는 SpringSource Tool Suite(STS)를 사용하면 보다 편하게 사용할 수 있다. STS는 다음과 같은 편의를 제공한다.
- AJDT AspectJ editing support is very good
- Roo Console available via Right-click if installed
하지만 STS 사용시 mvn eclipse:eclipse를 빈번하게 수행해야 하고, F5를 자주 눌러야 한다.
이런 불편은 eclipse에서 mvn eclipse:eclipse를 external command로 등록하고 수행 후에 프로젝트를 refresh하도록 설정하면 해결된다.
22. Resources
Roo JIRA: http://jira.springframework.org/browse/ROO
Roo Forum: http://forum.springsource.org/forumdisplay.php?f=67