티스토리 툴바


자바에서 착각하기 쉬운 것들

2010/04/21 23:51 | Posted by Royalvip

http://blog.naver.com/jsharp83?Redirect=Log&logNo=110034118340

We were building a new web application recently, and being in a position to influence the development, I promptly chose to use theMaven2 web application directory structure. Spring is now our web application framework of choice, so that was a given. We have also had very good results with Tiles in our legacy web application, thanks to the efforts of one of my colleagues, so we also wanted to use Tiles here. I had set up a web application at my previous job to work with Spring and Tiles about 3 years ago, but the details were hazy, and the Tiles integration in our legacy application uses some proprietary components, so I decided to figure this out afresh for this project. Surprisingly, there does not seem to be much documentation about Spring/Tiles integration on the web, but I was able to build an example by piecing together information from various sources, which I describe here. Hopefully, the information will help someone in a similar situation.

We start off with a standard Spring application, with the web.xml containing a reference to the Spring DispatcherServlet, as shown below. The web.xml file lives in src/main/webapp/WEB-INF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
      http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<servlet>
<servlet-name>myapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet><servlet-mapping> <servlet-name>myapp</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app>

The myapp-servlet.xml referenced by the web.xml above. The myapp-servlet.xml also lives in src/main/webapp/WEB-INF and is shown below. The myapp-servlet.xml sets up the TilesConfigurer with the location of the tiles configuration file (tiles-def.xml), sets up the Tiles view resolver, and specifies the URL mappings to the respective Spring controllers. It also imports non-web bean definitions from the applicationContext.xml in src/main/resources. This is a personal preference, since I like to be able to unit test the non-web components using JUnit, and breaking this up into a separate configuration file makes this easier.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/util 
       http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<import resource="classpath:applicationContext.xml" />
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles-def.xml</value>
</list>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="requestContextAttribute" value="requestContext"/>
<property name="viewClass"
value="org.springframework.web.servlet.view.tiles.TilesView"/>
</bean>
<!-- URL Mappings -->
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true"/>
<property name="mappings">
<props>
<prop key="/example.html">exampleController</prop>
</props>
</property>
</bean></beans>

We then define the various tiles. Our example layout contains 4 tiles, one each for static content for the header and footer, one for the left navigation toolbar, and one for the main body of the page. The tiles-def.xml lives in src/main/webapp/WEB-INF and is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
       "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">
<tiles-definitions>
<!-- Components -->
<definition name="head-tile" path="/example/tiles/head.jsp"/>
<definition name="left-nav-tile" path="/example/tiles/leftnav.jsp"/>
<definition name="body-tile" path="/example/tiles/body.jsp"/>
<definition name="foot-tile" path="/example/tiles/foot.jsp"/>
<!-- Pages --><!-- Example --> <definition name="example" path="/example/example.jsp"> <put name="head-position" value="head-tile"/> <put name="left-nav-position" value="left-nav-tile"/> <put name="body-position" value="body-tile"/> <put name="foot-position" value="foot-tile"/> </definition> </tiles-definitions>

Currently the only dynamic component is the main body, which uses the "who" parameter to fill out the "Hello ${who}" header. All others are static. The example.jsp page appears below, followed by the different tiles. The locations are in the path attribute in the definitions in the tiles-def.xml file. The root is at src/main/webapp, so /example is actually src/main/webapp/example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<%-- src/main/webapp/example/example.jsp --%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<html>
<head><title>Example Page</title></head>
<body>
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td colspan="2">
<tiles:insert attribute="head-position"/>
</td>
</tr>
<tr>
<td width="25%">
<tiles:insert attribute="left-nav-position"/>
</td>
<td width="75%">
<tiles:insert attribute="body-position"/>
</td>
</tr>
<tr>
<td colspan="2">
<tiles:insert attribute="foot-position"/>
</td>
</tr>
</table>
</body>
</html>

I realize that using table tags to layout pages are kind of frowned upon nowadays, but if you have been reading my posts, you will realize that I am not exactly a UI guru. So please bear with me, and mentally replace the table tags with the appropriate CSS magic that is less offensive. The tiles are quite simple, and they are shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- src/main/webapp/example/tiles/head.jsp -->
<h1>Da Korporate Header go here</h1>
<!-- src/main/webapp/example/tiles/leftnav.jsp -->
<ol>
<li>Foo</li>
<li>Bar</li>
</ol>
<!-- src/main/webapp/example/tiles/body.jsp -->
<h2>Hello ${who}</h2>
... body text filler ...<!-- src/main/webapp/example/tiles/foot.jsp -->
<h1>Da Korporate Footer go here</h1>

So in effect, tiles have given us the ability to reuse JSP snippets on different pages. It is quite likely that the header and footer tiles, and perhaps the left nav tile, will be used across the entire application. So we need to create new tiles for only the body element for different applications.

The controller that backs this is referenced as exampleController in the myapp-servlet.xml and defined more fully in the applicationContext.xml file in src/main/resources. This file currently contains only the controller definition, but could be used to declare beans that the controller(s) depend on as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/util 
       http://www.springframework.org/schema/util/spring-util-2.0.xsd"><!-- ExampleController -->
<bean id="exampleController" class="com.mycompany.myapp.example.ExampleController">
<property name="viewName" value="example"/>
</bean>
</beans>

The actual Java code is quite simple. All it does is pick up the parameter "who" from the URL, and pass it through to the view as a ModelAndView attribute. The java tree is rooted at src/main/java, in case you did not already know.

1
2
3
4
5
6
7
8
9
10
11
12
public class ExampleController extends ParameterizableViewController {public ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String who = ServletRequestUtils.getStringParameter(request, "who");
ModelAndView mav = new ModelAndView();
mav.addObject("who", (who == null ? "NULL" : who));
mav.setViewName(getViewName());
return mav;
}
}

Start up the web application from the command line with "mvn jetty6:run" and hit the URL: http://localhost:8081/myapp/example.html?who=Sujit to see the following page:

We can also make certain tiles "smarter", in the sense that the Java logic backing these components need not be supplied by the main Spring controller, but can be specified separately. This can be useful when designing widgets for your web pages, which need to do significant processing on the request parameters before rendering the output. We could also refactor the logic out to some kind of service and have the main controller make a single call into it to get the renderable data, but this still means that we have to remember to pull data for each component in every new page controller we write. Specifying a controller for a tile is done in the controllerClass attribute in the tiles definitions.

For our example, we will make the left nav component smart. Depending on the value of the parameter "type" in the URL, it will display different lists. This requires specifying the controllerClass in the tiles definition for left-nav-tile in tiles-def.xml.

1
2
<definition name="left-nav-tile" path="/example/tiles/leftnav.jsp"
controllerClass="com.mycompany.myapp.example.LeftNavController"/>

The controller is not a Spring controller, but a Tiles Controller. The code for that is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class LeftNavController extends ControllerSupport {
private String[][] menuItems = {
new String[] {"Foo", "Bar"},
new String[] {"London", "New York", "San Francisco", "Brussels"},
new String[] {"Engineering", "Finance", "Marketing"}
};public void execute(ComponentContext tileContext, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws Exception { // decide what kind of menu to show based on parameter "type" String menuTypeStr = (String) tileContext.getAttribute("type"); int menuType = 0; try { menuType = Integer.parseInt(menuTypeStr); } catch (NumberFormatException e) {} if (menuType < 0 || menuType > (menuItems.length - 1)) { menuType = 0; } String[] selectedMenuItem = menuItems[menuType]; request.setAttribute("menu", selectedMenuItem); } }

One small wrinkle. The type parameter has to be injected into the tile context for the left-nav tile. This is done by setting it in the layout example.jsp file from the request using a tiles:put element, like so:

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<html>
...
<td width="25%">
<tiles:insert attribute="left-nav-position">
<tiles:put name="type" value="${param.type}"/>
</tiles:insert>
</td>
...
</html>

The corresponding tile leftnav.jsp in src/main/webapp/example/tiles also has to be modified to show the "menu" object we just pushed into the context using the LeftNavController. Here it is:

1
2
3
4
5
6
7
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<ol>
<c:forEach var="menuItem" items="${menu}">
<li>${menuItem}</li>
</c:forEach>
</ol>

Now, hitting the application with http://localhost:8081/aetna/example.html?who=Sujit&type=1 will produce the following page, which shows us that the type parameter is being correctly interpreted.

So this is it. The whole thing is not terribly complicated, but requires you to mess with a lot of XML files. The good news is that working with Tiles can significantly speed up your web application development and make it easier, as well as enforce a uniform look and feel to your web application. And once you set it up, and developers get used to the process of adding components and layouts, it will just become second nature and you will wonder how you worked without Tiles.

출처 : http://sujitpal.blogspot.com/2007/06/springtiles-example-web-application-on.html

Dynamic Tiles2 Maven Repository

2010/04/19 17:59 | Posted by Royalvip

원저작자가 게시해 놓은거 보고 적용시켰는데 에러가 났다 ㅡ.,ㅡ;;;;

직접 사이트로 찾아들어가 확인해보니 디펜던시 설정은 다음과 같이 해야한다.

1. Repository

<dependency>

<groupId>org.springbyexample</groupId>

<artifactId>dynamic-tiles2</artifactId>

<version>1.1</version>

</dependency>

2. Dependency

<dependency>

<groupId>org.springbyexample</groupId>

<artifactId>dynamic-tiles2</artifactId>

<version>1.1</version>

</dependency>

이클립스에서 유니코드로 인코딩된 한글파일을 보려며 새로운 플러그인 추가에 다음 경로를 추가하여

properties editor를 설치한다.

http://propedit.sourceforge.jp/eclipse/updates

[에러] lelvel numver 20 is not recognized.

2010/04/08 16:31 | Posted by Royalvip

java.lang.IllegalStateException: Level number 20 is not recognized.

slf4j .1.3.x 버전을 사용할 때 나타나는 에러

slf4j 1.5.x 버전으로 바꾸면 된다.

전자정부프레임워크를 권장사항(?)에 따라

JDK 1.6, Tomcat 6 에서 돌리면

TagSupport, c.Tld 어쩌고 저쩌고 하는 에러가 날 수 있다.

이는 웹 어플리케이션의 WEB-INF/lib 디렉토리에 구동하는 톰캣의 jsp-api.jar, servlet-api.jar와 다른 버전의 라이브러리가 들어가서 그렇다.

컴파일러 빌드패스에서 개발환경에서 구동하는 톰캣의 servlet-api.jar와 jsp-api.jar 파일을 임포트 시켜서 WEB-INF/lib로 라이브러리 출력으로

설정을 걸어두던지 직접 TOMCAT/lib에서 위의 두 파일을 복사하면 말끔하게 태그라이브러리 관련한 에러가 사라진다.

2010-04-05 23:58:46,831 ERROR [org.springframework.web.context.ContextLoader] Context initialization failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘egovJDBCAppender’: Autowiring of methods failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void egovframework.rte.fdl.logging.db.EgovJDBCAppender.setDataSource(javax.sql.DataSource); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [javax.sql.DataSource] is defined:


이런 에러가 날 때가 있다.

전자정부 프레임워크 사이트에서는 관리자가 귀찮아서 알려주는 짓 따위 안한다.

그래서 혼자 두시간 동안 삽질한 결과 ..

..

..



public class EgovJDBCAppender extends JDBCAppender {


/** 로그 실행 위치 정보 flag */

boolean locationInfo = false;


/** 싱글톤 dataSource provider - Spring 연동 dataSource 제공 */

private final SingletonDataSourceProvider provider;


/**

   * ‘@Autowired’ Annotation 형식으로 dataSource 를 받아와 이를 SingletonDataSourceProvider 의 setDataSource 메서드를 호출하여 설정해 준다.

   * @param dataSource

   * - Spring 에서 설정한 dataSource

   */

@Resource(name = “dataSource”) <— 여기의 주석을 지워주면 된다.

@Autowired(required = false)

public void setDataSource(DataSource dataSource) {

provider.setDataSource(dataSource);

}





그렇다. 아래의 주석만 지워주면 되는 것이었다…

어쩌라구.. ㅠ_ㅡ

@Resource(name = “dataSource”)

제가 직접 설치를 해보면서 진행중인데 가이드 사이트에 올라와있는 그대로 사용하면 MYSQL은 에러납니다.

오라클 쪽은 아직 셋팅을 안해봐서 모르겠습니다.

MYSQL 쪽이 에러가 나는 이유는 테이블 생성시 Foreign-Key를 걸 때 부모와 자식 테이블의 순서가 바뀌어서 걸리지 않기 때문에 에러가 납니다.

일일히 찾아가면서 순서를 맞추어 다시 배포합니다.

유용하게 쓰시길 바랍니다.

첨부파일을 다운받아서 사용하시면 됩니다.


참고로 이 스크립트는 기본적으로 com 이라는 DB를 생성해 공통 컴포넌트 관련 테이블을 생성하도록 스크립팅 되어 있습니다.

별도의 DB를 사용하시려면

1단계 스크립트의 첫부분에서 DB create 부분과 use DB관련 부분 수정해서 사용하시면 되겠습니다.=

해당 가이드 페이지 링크

1. pom.xml에 다음을 추가한다.

<repositories>

<repository>

<id>mvn2</id>

<url>http://repo1.maven.org/maven2/</url>

<releases>

<enabled>true</enabled>

</releases>

<snapshots>

<enabled>true</enabled>

</snapshots>

</repository>

<repository>

<id>jboss</id>

<url>http://repository.jboss.com/maven2/</url>

<releases>

<enabled>true</enabled>

</releases>

<snapshots>

<enabled>true</enabled>

</snapshots>

</repository>

<repository>

<id>atlassian</id>

<url>http://maven.atlassian.com/repository/public/</url>

<releases>

<enabled>true</enabled>

</releases>

<snapshots>

<enabled>true</enabled>

</snapshots>

</repository>


<repository>

<id>egovframe</id>

<url>http://www.egovframe.go.kr/maven/</url>

<releases>

<enabled>true</enabled>

</releases>

<snapshots>

<enabled>false</enabled>

</snapshots>

</repository>

</repositories>

2. 프로젝트의 pom.xml의 <dependencies>에 아래 내용을 붙인다.

<dependency>

<groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>2.0.4</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>2.0.4</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-acl</artifactId> <version>2.0.4</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core-tiger</artifactId> <version>2.0.4</version> </dependency>

준비물

아래 설명에서 url은 이클립스의 Help -> Install New Software -> Add...

에 추가하는 링크다. (Amatears 제외)

1. 이클립스 3.5 갈릴레오 For JavaEE Developers 최신버전 - 다운로드

2. Help -> Install New Software -> Add...

3. EMF 추가 - http://download.eclipse.org/modeling/emf/updates/

4. EMF SDK 2.5.0 (EMF + XSD) 만 선택해서 설치

5. UML2 설치 - http://download.eclipse.org/modeling/mdt/updates/releases/

6. MDT UML2 SDK 3.0.1 설치

7. AJDT 설치 (이클립스 3.5용) http://download.eclipse.org/tools/ajdt/35/dev/update

8. Amateras UML, ERD 설치

업데이트 사이트가 아닌 http://sourceforge.jp/projects/amateras/releases/에 직접 방문하여 Amateras UML, Amateras ERD 최신버전을 다운받아

Eclipse의 plugin 디렉토리에 복사한다.

9. SVN 설치 http://download.eclipse.org/technology/subversive/0.7/update-site/

10. SVN 설치 후 Eclipse를 재시작하면 SVN Connector 다운로더가 자동으로 뜬다. Connector 설치

11. m2eclipse 설치 - http://m2eclipse.sonatype.org/sites/m2e

12. PMD 설치 : http://pmd.sourceforge.net/eclipse

PMD For Eclipse 3만 선택하여 설치

13. Spring IDE 설치 - http://springide.org/updatesite/

14. 첨부파일을 다운받아 각각 features와 plugins 디렉토리에 압축을 푼 파일을 복사


15. 이클립스를 재시작

16. eGovFramework 설치 - http://www.egovframe.go.kr/update

첨부파일을 먼저 설치하는 이유는 업데이트 사이트에 참조하는 구버전 파일이 없어 에러가 발생하기 때문임.

17. Maven 환경설정 페이지의 Maven 환경설정 Part를 따라서 환경설정 및 설치를 해주세요

18. 이클립스 재시작 후 File - New - eGovFramework Web Project에서 Sample Project를 생성하여 파일이 생성되는지 확인


이전 1 2 다음