블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

Apache Camel note

엔터프라이즈 솔루션 | 2013.02.12 19:10 | Posted by 조대협

1. 프로젝트 생성하기

mvn archetype:create -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-java -DarchetypeVersion=2.5.0 -DgroupId=camelinaction -DartifactId=order-router


으로  Camel Project 생성

2. 코드 
아래는 Spring을 이용하여, FTP로 파일을 읽어서 Local의 C:\temp에 복사하는 코드

public class MyRouteBuilder extends RouteBuilder {

    /**
     * A main() so we can easily run these routing rules in our IDE
     */
    public static void main(String... args) throws Exception {
        Main.main(args);
    }

    /**
     * Lets configure the Camel routing rules using Java code...
     */
    public void configure() {
        from("ftp://userid@168.1.2.3/camel/src/?password=password&stepwise=false")
        .to("file:c:/temp/");

    }
}


저작자 표시
신고

'엔터프라이즈 솔루션' 카테고리의 다른 글

Apache Camel note  (0) 2013.02.12
아키텍쳐에 있어서 레퍼런스의 중요성  (2) 2009.10.20
2009년 기술 전망  (2) 2009.01.06

MS SQL Replication 아키텍쳐

엔터프라이즈 솔루션/MS-SQL | 2010.04.28 17:44 | Posted by 조대협



MS SQL 데이타 베이스간의 실시간 데이타 복제를 위해서 "Replication"이라는 기능을 제공한다.

보면, Oracle Golden Gate, IBM Info sphere, Quest Shareflex,MySQL geo replication 비슷한 CDC 기능이다.

Replication 방식은 크게 두가지로 나뉘어 지는데, Snapshot replication TransactionalReplication이다.

 

  1. Snapshot Replication

복제 방식은 간단하게 생각하면 Source 데이타 베이스의 내용을 Export해서 Target Import하는 개념으로 생각하면 된다. 데이타 베이스에 대한 복제를 시작하기 전에 초기 데이타를 적재 하거나, 또는 업무가 없을때 데이타를 적재하거나 주기로 변경이 되는 곳에 사용할 있다.

Snapshot Agent 의해서 주기적 또는 스케쥴에 따라서 데이타를 Export하면여 파일로 저장되고 파일은 Distributor 서버로 FTP,윈도우 파일공유,HTTP등을이용하여 전송된다. Distributor 1 이상의 수신 데이타베이스에 데이타를 전송하여 데이타를 반영한다.

 

  1. Transactional Replication

이게 전통적인 CDC 방식이다. Transaction Log Log Reader 캡춰해서 Distributor 통해서 타겟으로 보내는것인데. 재미있는 것중에 하나가 Capture 최소 단위가 하나의 트렌젝션 이하라는 것이다. 최소 단위가 트렌젝션 하나하나를 잡는게 아니라 트렌젝션이 경우 하나의 트렌젝션을 잘라서도 Capture 가능하다.

 

오라클 연동

 

그외에 흥미로운것중 하나가, 송수신 DB 모두 오라클을 지원한다. TransactionalReplication 경우 오라클의 redo 로그를 잡는 것이 아니라 테이블에 트리거를 걸어서 데이타 변경 사항을 Interface table 넣은후, interface 테이블을 읽어서 반영하는 방식이고, 오라클과의 연결은 ADO.NET,OLEDB,ODBC 이용한다

저작자 표시
신고

'엔터프라이즈 솔루션 > MS-SQL' 카테고리의 다른 글

MS SQL Replication 아키텍쳐  (0) 2010.04.28
MS SQL 2008 Tutorial  (1) 2010.04.27

MS SQL 2008 Tutorial

엔터프라이즈 솔루션/MS-SQL | 2010.04.27 17:54 | Posted by 조대협
http://msdn.microsoft.com/ko-kr/library/ms167593(v=SQL.100).aspx

MS는 참 문서는 체계화 잘되어 있는듯.
신고

'엔터프라이즈 솔루션 > MS-SQL' 카테고리의 다른 글

MS SQL Replication 아키텍쳐  (0) 2010.04.28
MS SQL 2008 Tutorial  (1) 2010.04.27
고객사에서 딜을 진행할때, 가장 중요한 요소중의 하나가 "레퍼런스가 어디입니까?" 입니다.
레퍼런스의 중요성은 솔루션의 품질이나 아키텍쳐 그리고 실제 구현측면에서 매우 중요합니다.
레퍼런스가 있다는 것은 이미 한번 이상 해봤다는 것인데..
아키텍쳐를 그릴때 있어서 한번 해보고 안해보고는 그 차이가 매우 큽니다.
어디서 문제가 생길지, 그리고 어떻게 시스템을 설계해야할지를 알기 때문입니다.
제가 일하는 팀의 경우 EAI프로젝트를 정말 많이 했습니다.
그래서 요건을 들으면 대충 어떤 솔루션써서 어떻게 연계하면 되고, 개발 과정에서 무슨 문제가 생길것이며 어떤 기능에 신경을 써야 하는지 뻔히 알고 있습니다.
 결과적으로 프로젝트의 성공요인을 높일 수 있고, 불필요한 리소스나 시간과 비용이 낭비 되지 않습니다. 고객입장에서도 이득이 되는 것이지요.
 또한 아키텍쳐를 처음 그릴때는 아키텍쳐 검증을 위한 많은 프로토 타입과 테스팅 그리고 변경되는  요건이나 생각하지 못한 추가 요건에 의해서 아키텍쳐의 변경을 감수하면서 많은 시간을 소요하게 됩니다.

 그래서 흔히 Reference Architecture라는 것을 들고 다니는데, 이건 어떤 시스템을 구축할 때 통상적으로 사용하는 아키텍쳐입니다. 금융의 계정계 업무나, 통신의 SDP,제조의 MES와 같은 특정 도메인에 종속된 아키텍쳐도 있을 수 있고, BI,SOA,ROA와 같은 아키텍쳐 스타일에 맞는 Reference architecture도 존재합니다.

요즘 특히나 기존의 존재하지 않던 아키텍쳐를 그리는 프로젝트들이 많아서 요즘은 레퍼런스의 중요성을 실감하게 됩니다.
 
저작자 표시
신고

'엔터프라이즈 솔루션' 카테고리의 다른 글

Apache Camel note  (0) 2013.02.12
아키텍쳐에 있어서 레퍼런스의 중요성  (2) 2009.10.20
2009년 기술 전망  (2) 2009.01.06
1. edelivery.oracle.com에서 ALUI IDK를 다운 받는다.
2. 압축풀고
3. Eclipse WTP에서 devkit/WEB-INF 디렉토리를 통채로 import
4. JSP 작성
"<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ page import="com.plumtree.remote.portlet.*" %>
This is ALUI Portlet<P>
<%
IPortletContext portletContext =
PortletContextFactory.createPortletContext(request,response);
IPortletUser portletUser = portletContext.getUser();
out.write("Hello ,"+portletUser.getUserName());
%>
"
5. WebLogic에 해당 WebApp을 배포
6. ALUI Admin Console에서 Remote WebService로 등록하고 해당 WebService를 Portlet으로 배포하여 등록하면 완료.

소감.
WLP보다 훨씬 쉽다. 제품의 각 세부 엔진이 나뉘어져 있어서 장애 전파 방지와 효율적인 리소스 배분이 가능할 수 있고. 개발용 IDK가 매우 쉬운 느낌이.. 아직 개념은 더 잡아야 겠지만 잘 디자인된 제품같다.
저작자 표시
신고
TAG ALUI, Portlet, WCI

ALUI 포탈 스터디..

엔터프라이즈 솔루션/포탈 | 2009.08.27 13:00 | Posted by 조대협

1. Admin 화면은 포탈 초기 화면에서 id:administrator passwd:없음 으로 로그인한다.

Tutorial로 해봐야할것들

1) 포틀릿 등록해서 페이지에 등록 8/28 완료

2) 페이지 레이아웃 변경 포틀릿 추가 삭제
3) 커뮤니티 생성 (8/28완료)
4) 커뮤니티 페이지 생성 / 레이아웃 변경 / 포틀릿 추가(8/28완료)

5) 추가로 JSP 포틀릿 개발(8/28 완료)
6) ADF 포틀릿 개발 Ensemble 연동
신고

ALUI (WCI) Architecture

엔터프라이즈 솔루션/포탈 | 2009.08.25 23:17 | Posted by 조대협

From http://edocs.bea.com/alui/devdoc/docs60/Overview_of_the_Portal_Architecture/PlumtreeDevDoc_Overview_Intro.htm
저작자 표시
신고

Enterprise Service Bus(ESB)를 이용한

차세대 JEE 아키텍쳐의 확장

 

한국 오라클 컨설팅
Principal Consultant
조병욱(byungwook.cho골뱅이oracle.com)

 

서론

근래의 JEE애플리케이션 아키텍쳐를 보면 전통적인 JSP/Servlet과 같은 HTML방식의 UI에서 AJAX/FLASH같은 X-Internet 솔루션을 사용하는 경우가 많다. 그래서 애플리케이션 아키텍쳐 역시 비즈니스 모듈이 XML+HTTP 형태로 기능을 제공하고, XML 데이터를 X-Internet 솔루션에서 처리하는 경우가 통상적이다. (국내의 가우스 플랫폼등)


기존의 아키텍쳐에서는 UI에서 BIZ LOGIC으로의 호출이 Java Language에 의존적인 형태의 호출로 이루어져 왔다. 단순하게 Java Method Invoke하는 형태 였는데, X-Internet 솔루션의 도입후의 아키텍쳐는 아래 그림과 같이


클라이언트에서 BIZ LOGIC까지 HTTP등의 프로토콜을 이용한 Remote 호출형태로 변화되었다.

 

전통적인 X-Intenet 기반의 JEE 아키텍쳐의 문제점

비표준 전문 형태 사용

 X-Internet 플랫폼 특히, 국내에서 개발된 X-Internet 플랫폼의 문제는 그 프로토콜이 어떤 표준을 따르지 않는다는 것이다. SOAP을 기반으로한 웹서비스나 REST 스타일이 아닌 단순하게, HTTP XML을 실어 보내는 형태의 XML-RPC 형태로 그 X-Internet 플랫폼에 특화된 프로토콜을 정의하여 사용하는 경우가 많다.

 그래서 이 프로토콜에 맞춰서 개발된 시스템들의 경우 제공되는 서비스는 오로지 그 X-Internet 플랫폼에서만 호출하여 사용할 수 있고, 다른 애플리케이션에서 호출하고자 할때는 별도의 인터페이스를 개발해야 하는 일이 발생한다. 또한 프로토콜의 SPEC 자체가 조악하거나 기능이 매우 빈약하여 추후 유지 보수나 관리 관점에서 많은 문제를 유발한다.

     실예로, 모 통신회사의  X-Internet 클라이언트 형태가 이러하다.

중복된 Cross cutting concern의 개발

HTTP 형태로 컴포넌트 기능을 제공하는 아키텍쳐의 공통적인 문제점중 하나는 Cross Cutting Concern (공통 기능)이 각각의 컴포넌트에서 구현이 된다는 것이다.

 인증과 인가, 로깅과 같은 공통적인 처리 요건이 각각의 컴포넌트 모듈에서 중복되서 개발이 된다. 이로 인해서, 같은 코드를 반복해서 개발해서 생산성이 떨어지고, 또한 만약 이러한 공통 처리 요건이 변경되었을 때, 전체 시스템의 코드를 변경해야 하는 문제가 발생한다.


 Oracle Service Bus를 이용한 아키텍쳐 개선

이러한 문제는 HTTP 기반의 컴포넌트 모델을 지원할 수 있는 유연한 인프라를 가지지 못해서 발생하는 것인데, Oracle Service Bus(이하 OSB-Oracle에서 판매하는 Enterprise Service Bus)로 이러한 문제를 해결할 수 있다. 특히 OSB의 장점중의 하나는 SOAP 기반의 WebService만을 지원하는 것이 아니라 AnySOAP, AnyXML,Text 등과 같은 다양한 형태의 Message Format을 지원하기 때문에, 단순히 웹서비스 기반의 플랫폼뿐만이 아니라 자체 표준을 사용하는 다양한 형태의 비즈니스 애플리케이션에도 적용이 가능하다

1)    다양한 프로토콜을 지원

WEB 2.0이 도래하면서 HTTP 기반의 프로토콜이 웹서비스뿐만 아니라 용도에 따라 REST with XML이나 REST with JSON, XML RPC등 여러가지 형태의 프로토콜을 사용하고 있다. 이러한 프로토콜을 각각의 업무 비즈니스에서 지원하려면 중복된 개발이 필요하고, 컴포넌트 개발자가 비즈니스 로직뿐만 아니라 프로토콜 변환에도 상당한 노력을 들여야 한다.


OSB를 사용함으로써 얻을 수 있는 장점중의 하나가 Entry Point OSB로 단일화 함으로써, IN/OUT 프로토콜에 대한 변환 지원이 가능하며 이는 OSB에서 중앙 집중화된 형태로 처리가 가능하기 때문에, 업무 개발자의 노력을 경감시켜서 개발 생산성의 향상을 이끌어 올 수 있고, 추가적인 프로토콜 변화 요청에 대해서 유연하게 대응할 수 있다

또한 내부의 컴포넌트 프로토콜을 하나의 표준 프로토콜로 단일화 할 수 있어서, 아키텍쳐의 단순성과 함께 표준화를 통한 관리의 용이성을 얻을 수 있다.  

2)    Cross Cutting Concern(공통모듈) 처리의 단일화

위에서도 언급했듯이, 컴포넌트 개발에 있어서 문제점중의 하나가 공통 모듈에 대한 중복 개발 문제이다. 이는 중복적인 개발로 인하여 개발의 생산성을 떨어뜨리고 또한 공통 모듈의 변화는 전체 프로그램의 수정을 일으켜서 아키텍쳐의 유연성과 생산성을 급격하게 감소 시키는 문제점을 야기 하였다.

이러한 공통 모듈 (Cross cutting concern) OSB에 중앙 집중화 시킴으로써, 컴포넌트 개발자가 비즈니스 업무 로직 개발에 집중하도록 하고, 변경시에서도 OSB 단일 지점만 변경하도록 하여 유연하고 생산성이 높은 아키텍쳐를 구축할 수 있다.

 

3)    Mediation을 통한 비즈니스 변화에 대한 적응

아키텍쳐 설계에 있어서 중요한 점 중의 하나는 비즈니스 변화에 대한 대응 능력이다.

예를 들면

Ÿ  Function Adding

기존 기능에 대해서 새로운 기능이 더해진 경우. 예를 들어결재 서비스에 캐쉬백 기능이나 포인트 적립이 추가되는 경우

Ÿ  Data Transformation

입력이나 출력 받는 데이터의 형식이 바뀐 경우. 예를 들어 게시판에 글을 올리는데 기존에는 사용자 ID만 필요했는데, 실명제로 인해서 주민등록 번호를 조회해야 하는 경우 입력값이 사용자 ID만에서 사용자 ID와 주민등록 번호를 받는 입력형태로 변경되고, 기존의 글 올리기 서비스는 변경이 없고 입력 받은 주민등록 번호로 실명 인증하는 기능을 추가하는 경우

Ÿ  Routing

어떤 조건에 따라서 호출되는 서비스가 달라지는 경우. 예를 들어 신용카드 서비스 정책이 일반 회원만 있다가 플레티넘 회원에 대한 서비스와 포인트 적립 방식이 달라지는 경우 회원 등급에 따라서 호출해야 하는 서비스가 달라진다.

이러한 시나리오는 비즈니스 요구사항 변화에 따라서 발생을 하고, 이는 실제 비즈니스 컴포넌트에 변경 요건을 준다. 특히 해당 비즈니스 컴포넌트가 여러곳에서 사용되고 있을 경우(의존성을 갖는 경우) 이에 대한 변경 여파가 매우 크다.

 위와 같이 기존의 비즈니스 로직에 변화를 줘서 동작 방식을 바꾸거나 개선하는 것을 Mediation이라고 하는데, OSB에서 이 Mediation 계층을 추가하여 비즈니스 요건이 변경되었을 경우 비즈니스 컴포넌트에 대한 변경이 없이 이를 OSB내에서 반영하여 업무 요구 사항에 대한 변화에 쉽고 빠르게 대응할 수 있다

4)    모니터링과 서비스 통제 (SLA/Throttling )

마지막으로 서비스에 대한 통제와 모니터링 기능을 꼽을 수 있는데, 특정 서비스의 사용률이나 응답시간등의 모니터링을 통해서 비즈니스 컴포넌트의 건강성과 재사용률을 파악할 수 있다.

그리고 비즈니스 컴포넌트에 문제가 있을 때 빠르게 검출 및 대응을 할 수 있다. (응답시간이 5초내로 떨어지는등 현상),  무엇보다 통제 기능을 부여할 수 있는게 큰 장점중의 하나이다. 해당 비즈니스 컴포넌트의 TPS 100이상을 넘으면 더 이상 요청을 받지 않고 에러 처리를 해서 시스템을 보호한다거나 관리자에게 알려서 용량 증설등의 조치를 할 취할 수 있게 한다.

 이런한 모니터링 및 관제 기능을 별도로 비즈니스 컴포넌트단에서 구현하기 위해서는 별도의 아키텍쳐 설계와 함께, 공통 모듈의 개발과 테스트를 거쳐야 하는데, 이런 과정이 패키지화 되어 있기 때문에, 이 과정에 소요 되는 많은 리소스들을 절약할 수 있다

4가지 주요 기능을 정리해서 보면 다음과 같은 그림으로 나타낼 수 있다.

 

아키텍쳐 구현시 주의 사항

 

OSB ESB를 이용한 아키텍쳐 구현에서 있어서 가장 흔하게 발생하면서 가장 치명적인 실수중의 하나가 Mediation Orchestration에 대한 잘못된 이해이다.

 Mediation은 기존의 비즈니스 기능에 추가로 기능을 덧붙여서 비즈니스에 기능을 추가 (정확히 말하면 enrich)하는 것이다. Orchestration은 하나 이상의 비즈니스 컴포넌트를 묶어서 새로운 기능을 구현해 내는 것이다.

 언뜻 보면 비슷할 수 도 있지만, 결정적인 차이는 추가되는 양에 있다. 예를 들면 Mediation이 자동차를 튜닝하여 자동차의 기능을 개선하는 것이라면, Orchestration LCD 생산 라인과 전화기 생산라인을 연계해서 컬러 LCD 전화기를 만들어내는것과 같다고 할까? (예를 들기가 참 어렵군요)

그래서 전통적으로 Orchestration Volume이 비슷한 2개 이상의 비즈니스 컴포넌트가 묶여져서 하나의 새로운 비즈니스 기능을 만들어내고, 많게는 10여개 이상의 비즈니스 컴포넌트가 로직에 따라서 흐름을 이어가는 경우가 많다. 종종 이 과정에서는 stateful 하거나 long running한 프로세스가 구현되기도 하는데, 이런 Orchestration 요건은 BPM과 같은 솔루션을 이용해서 구현되는 것이 바람직하고, ESB는 비즈니스 컴포넌트를 하나의 BUS라는 Entry point (진입점)을 통해서 외부에 서비스 하면서, 비즈니스의 변화에 유연하게 대응할 수 있도록 Mediation을 하는 기능을 갖추어야 한다.

ESB 단에서 종종 Orchestration이 발생하는 경우를 봤는데. (기능상으로는 BPM이나 ESB Workflow를 구현할 수 있는 기능이 있기 때문에 언뜻보면 비슷하다.) 성능상으로 엄청난 부하를 유발해서 프로젝트 후반에는 잘못된 아키텍쳐로 엄청난 하드웨어 증설이 필요한 경우를 종종 봤다

결론

웹애플리케이션의 트렌드가 Servlet/JSP 처럼 비즈니스 로직과 같이 패키징 되는 형태에서 UI X-Internet 클라이언트 형식으로 구현되고, HTTP를 통해서 서버에 있는 비즈니스 로직을 호출하는 형태로 변화되고 있다.

 이런 시스템 환경 변화에서 비즈니스 로직 개발자에게는 좀더 비즈니스 로직 자체 개발에만 집중하고 기타 Cross Cutting Concern에 대해서는 공통된 BUS에서 처리하도록하고, 또한 비즈니스비 변화에 대한 유연한 대응성과, 통제(SLA) 및 모니터링을 ESB를 통해서 현실화 할 수 있다

 또한, 클라이언트 입장에서는 비즈니스 로직이 어떤 형태로 구현이 되었던간에, ESB 라는 단일 포인트를 통해서 통신하게 되고, 비즈니스 로직은 추가되는데로 ESB PLUG IN어 무제한적인 확장이 가능한 GRID 아키텍쳐를 구현할 수 있다

참고

본 문서에서는 ESB를 통한 JEE 아키텍쳐에 대한 확장 개념만을 간략하게 설명하였고, 구현 아키텍쳐에 대한 자세한 내용은 Generic Proxy Pattern 문서를 참고하기 바란다.

저작자 표시
신고
@ page import="java.util.*" %> @ page import="javax.naming.*" %> @ page import="com.oracle.bpel.client.Locator" %> @ page import="com.oracle.bpel.client.NormalizedMessage" %> @ page import="com.oracle.bpel.client.dispatch.IDeliveryService" %> try{ String title="CALLING FROM JSP"; String xml = "<ns1:DBSensorNotifierProcessRequest xmlns:ns1=\"http://xmlns.oracle.com/DBSensorNotifier\">" + "<ns1:input>"+title+"</ns1:input>" +"</ns1:DBSensorNotifierProcessRequest>"; Hashtable jndi = new Hashtable(); // assign RMI port which can be found in OAS console jndi.put(Context.PROVIDER_URL, "ormi://localhost:12401/orabpel"); jndi.put(Context.INITIAL_CONTEXT_FACTORY, "com.evermind.server.rmi.RMIInitialContextFactory"); jndi.put(Context.SECURITY_PRINCIPAL, "oc4jadmin"); jndi.put(Context.SECURITY_CREDENTIALS, "asdf1234"); jndi.put("dedicated.connection", "true"); // domain id and domain password Locator locator = new Locator("default","bpel",jndi); IDeliveryService ds = (IDeliveryService)locator.lookupService(IDeliveryService.SERVICE_NAME); NormalizedMessage nm = new NormalizedMessage(); nm.addPart("payload",xml); ds.post("DBSensorNotifier","initiate",nm); out.println("SEND"); }catch(Exception e){ e.printStackTrace(); throw e; }

신고
1. 턱시도를 oracle 사이트에서 다운 받는다.
2. 턱시도 라이센스를 다운 받는다. http://licensecodes.oracle.com/bea.html
3. 턱시도를 설치한다.
4. MS 사이트에서 Visual Studio 9.0 Express 버전을 다운 받는다.
5. c:\Program files\Microsoft Visual Studio 9\VC\vcvarsall.cmd 를 실행한다. (CL 컴파일러용 환경 변수 설정)
6. 턱시도 환경 변수를 설정한다.
예)
SET APPDIR=d:\tux\lab4
SET TUXDIR=d:\dev\bea\tux10
SET PATH=%TUXDIR%\bin;%PATH%
SET TUXCONFIG=%APPDIR%\tuxconfig
SET BDMCONFIG=%APPDIR%\bdmconfig
set WSNADDR=//127.0.0.1:8003
SET PMID=bwcho
@rem SET CC=gcc

set FLDTBLDIR=%APPDIR%;%TUXDIR%/udataobj;
set FIELDTBLS=account_fml,Usysflds

7. buildserver 명령으로 컴파일한다.

근 3년만에 턱시도를 손을 델려니까는 삽질이 느는군요..


저작자 표시
신고

Multiple row에 대한 리턴값 처리시에, FML 값의 순서에 대한 테스트

Tuxedo Transport에서
Transformation Style 설정에 따른 결과

입력 데이타
<FML>
  <ACCOUNT_ID>10</ACCOUNT_ID>
  <ACC_TYPE>A</ACC_TYPE>
  <ADDRESS>10</ADDRESS>
  <AMOUNT>10</AMOUNT>
  <ACCOUNT_ID>20</ACCOUNT_ID>
  <ACC_TYPE>B</ACC_TYPE>
  <ADDRESS>20</ADDRESS>
  <AMOUNT>20</AMOUNT>
</FML>

None일 경우

Ordered 를 적용한 경우

<FML>
<ACC_TYPE>B</ACC_TYPE>
<ACC_TYPE>C</ACC_TYPE>
<AMOUNT>10.0</AMOUNT>
<AMOUNT>20.0</AMOUNT>
<ADDRESS>10</ADDRESS>
<ADDRESS>20</ADDRESS>
<ACCOUNT_ID>10</ACCOUNT_ID>
<ACCOUNT_ID>20</ACCOUNT_ID>
</FML>

Grouped and Ordered


<FML>
<ACCOUNT_ID>10</ACCOUNT_ID>
<ACC_TYPE>A</ACC_TYPE>
<AMOUNT>10.0</AMOUNT>
<ADDRESS>10</ADDRESS>
<ACCOUNT_ID>20</ACCOUNT_ID>
<ACC_TYPE>B</ACC_TYPE>
<AMOUNT>20.0</AMOUNT>
<ADDRESS>20</ADDRESS>
</FML>


저작자 표시
신고


(FML인 경우)
1. Tuxedo에서 도메인 Config 설정을 한다.
2. FML 파일을 java weblogic.wtc.jatmi.mkfldclass fmldata 로 해서 JAVA 클래스를 생성한다.
3. WLS에서 WTC 설정을 하고 Resource 탭에서 위에서 설정한 JAVA 클래스를 적는다.
4. 2에서 작성한 클래스를 JAR로 묶어서 클래스 패스에 추가한다.
== 여기까지가 WLS의 WTC설정
5. SB에서 AnyXML로 비지니스 서비스를 만들고
6. JAR를 SB 프로젝트에 추가한후, CLASS에서 해당 JAR를 고른다.
7. 비지니스 서비스를 완성한후 테스트시에

FML이 다음과 같을때
#name           number          type    flags   comments
ACCOUNT_ID      10              long    -       -
ACC_TYPE        11              char    -       -
ADDRESS         12              string  -       -
AMOUNT          13              float   -       -

Input XML은 다음과 같아진다.
<FML>
  <ACCOUNT_ID>10</ACCOUNT_ID>
  <ACC_TYPE>10</ACC_TYPE>
  <ADDRESS>10</ADDRESS>
  <AMOUNT>10</AMOUNT>
</FML>


루트 엘리먼트가 <FML>이 된다.
만약 FML32를 사용할 경우에는 <FML32>로 명시하면 된다.

저작자 표시
신고

2009년 기술 전망

엔터프라이즈 솔루션 | 2009.01.06 09:42 | Posted by 조대협

1. Cloud and grid computing

클라우드 컴퓨팅과 이를 구현하기 위한 솔루션인 그리드 컴퓨팅은 금년에도 이슈가 될것같다.

구글이나 야후, 아마존들을 중심으로 한 글로벌 서비스 기업들이 그리드와 클라우드 컴퓨팅에 선두가 되고 있지만

정작, 기업에 있어서 클라우드 컴퓨팅이나 그리드 컴퓨팅의 도입은 소극적이다. 특히 클라우드 컴퓨팅의 경우

보안이나 성능상의 이슈로 기업에 도입이 될지 않될지는 지켜봐야 할것 같지만

그리드 컴퓨팅의 경우 Coherence와 같은 Data Grid제품이나, Hadoop과 같은 File grid, grid dbms등은 기업에도 충분히 사용이 가능한 솔루션이다. 얼마나 기업 고객들이 이 개념들을 이해하고 적응하느냐가 관건일테고, 다른 한축으로는 대부분의 그리드 솔루션이 오픈 소스로 구축 된 경우가 많기 때문에 기업의 오픈 소스에 대한 반감을 어떻게 풀어내느냐도 하나의 숙제가 될것이다.

 

2. Virtualization

여기서 언급하고자 하는 가상화는 특히 서버의 자원 가상화이다. 여러개의 CPU와 메모리가 있는 장비를 Partition해서 사용함으로써 자원의 효율성을 극대화 시키는 기술인데.

예를 들면 이전에 2 CPU 서버 3대로 3개의 업무를 하고 있다고 했을때, 1서버의 평균 CPU 사용률이 1.2 2서버 1.5, 3서버 1.5라고 했을때 이렇게 되면 총 6개의 CPU가 있지만, 사용되는 CPU수는 실제로는 4.2이다. 가상화를 사용하게 되면, 하나의 큰 서버에 CPU 사용률을 상황에 따라서 배정할 수 있기 때문에 초기에 5장의 CPU로도 충분히 운영이 가능하게 된다 또한, 갑자기 부하량이 늘어나는 경우에는 여분의 CPU를 해당 업무에 할당 할 수 있기 때문에 자원활용의 유연성을 더할 수 있다.

 

가상화의 다른 특징중의 하나는 가상화된 환경과 애플리케이션을 이미지로 관리하기 때문에, 쉽게 다른 하드웨어 환경으로 배포가 가능하다는 것이다. 이는 SM관점에서 많은 장점을 가질 수 있게 된다.

 

3. Saas,Pass,Iass

Saas (Software as a service)는 이미들 많이 사용되는 컨셉이고 내년에는 Iaas와 Pass가 화두가 되지 않을까?

Iaas(Infrastructure as a service)는 OS,CPU,메모리,디스크와 같은 자원을 서비스로 제공하는 형태이다. 이미 아마존이 Message Q, OS,Disk,DBMS등에 대해서 E3라는 형태의 서비스로 Iaas 서비스를 제공하고 있다. 단기적으로 컴퓨팅 파워가 필요한 캠페인이나, CPU가 많이 필요한 3D 렌더링 작업들에는 매우 유용하게 사용될 수 있고, IDC 센터가 세계에 나눠져 있기 때문에, 여러 위치에서 테스트가 필요한 경우 유용하게 사용할 수 있다.

이미 아마존 E3 서비스에서는 OS별로 이미지를 만들어서 업로드하면 수행할 수 있도록 되어 있다.

다음으로는 Pass (Platform as a service)가 있는데, 플랫폼을 서비스로 제공하는 것이다. Open API도 일종의 Pass가 될 수 있고, Google의 Android 플랫폼 (OS+Open API환경,애플리케이션 Store)나 Apple의 AppStore도 일종의 Pass가 될 수 있다. 이러한 Paas가 Iaas와 결합하면서, 무제한적인 자원(Iass)을 유연성있게 제공받을 수 있으며, 그위에 Pass를 구현함으로써 개발자들에게 Application을 개발할 수 있는 플랫폼을 제공한다. 이 Pass를 이용하여 소프트웨어가 개발되고 일반 사용자에게 서비스되는 형태가 Saas로 될 수 있다.

사실 한국에서는 이 3가지에 대해서 움직임이 매우 늦은게 사실이다. 이 3가지 기술들은 주로 Google,Amazon과 같은 서비스 업체들의 주도로 시장이 움직여가고 있는데, 우리나라의 N이나, D사의 경우 이 부분에 있어서 아주 초보적인 단계에 밖에 이르지 못했다.

 

국내에서도 Service Platform이라는 형태로 기업 내부의 유용한 자원을 Open API화하여 밖으로 서비스하려는 움직임이 있는데, 이런 움직임이 Pass와 같은 서비스 형태로 구현되었으면 한다.

 

4. REST

작년의 하나의 화두중에 하나가 REST였다. Roy Fielding의 논문에서 소개된 아키텍쳐 스타일로 웹의 장점과 인프라를 최대한 활용한다는 개념에서 출발하였다.

 

문제는 REST는 사실상의 표준이 없다. Google이나 Amazon이 주도하는 Defactor 표준 (암묵적인 표준)은 있지만 Spec과 같은 표준이 없기 때문에, 기업에서 사용할 경우 관리(Gorverning)이 어렵다. Google이나 Amazon의 경우 자체 개발 조직과 관리 조직을 가지고 있기 때문에, 잘 관리된 형태로 REST 서비스를 제공 및 사용하고 있지만, 기업내에서 REST가 얼마나 힘을 발휘할 수 있을지 미지수다. WebService를 사용해보고 REST도 모두 사용해봤지만 개발 관점에서 드는 Burden은 REST라고 결코 낮지는 않다. WebService의 경우 이미 Infra가 잘되어 있고 개발툴이나 자동화 스크립트가 많기 때문에 실제로 JAX-WS와 같은 개발 표준을 따를 경우 개발 공수가 사실 매우 낮은 것이 사실이다.

 

국내 상황을 보면 아쉽게도, Open API를 서비스 하는 포탈에도 REST를 지원하는 업체는 없는 것으로 안다. 또한 REST의 이해도 자체도 상당히 떨어지는데 HTTP + POX (Plain Old XML)은 REST가 아니다. 대부분 XML-RPC형태를 띄는데, REST는 Resource를 정의하고, Resource 지향적인 아키텍쳐로 설계되어야 하며, 사람이 직관적으로 이해하고 쉽고, Link등을 통해서 Resource간의 관계를 정의하고 Resource의 다음 상태 전이에 대한 정의 능력등이 있어야 한다.

국내 BLOG에 올라오는 글들을 보면 Jersey나 Apache CXF등을 이용하여 REST를 구현하는 샘플이나 예제는 종종 올라오지만, REST를 아키텍쳐 관점에서 접근하는 글은 매우 드문 것 같다. (아직까지는 못봤다.)

 

어쨌거나, REST가 JAX-RS로 JSR311 표준으로 등록되었고, WSDL 2.0에도 REST가 반영되었기 때문에, REST의 영향력이 커진 것은 기정사실이고, Amazon도 기존의 Open API를 서서히 REST형식으로 바꾸겠다니 Service World에서는 대세인 것은 분명하나 기업 아키텍쳐에서 얼마나 힘을 발휘할지는 지켜봐야할 사항이다.

 

5. SOA Governance

SOA는 어떻게 보면 양극화가 발생하는 듯한 인상인데, 이미 SOA에 적응한 기업은 SOA에 대한 성숙도를 높이기 위한 해가 될테이고 아직도 SOA를 시작하지 못한 기업은 이미 어느정도 성숙된 SOA 플랫폼과 개념을 바탕으로 SOA를 시작할것이다.

공통점은 이미 여러 SOA 프로젝트를 통해서 거버넌스의 중요성이 인식되었기 때문에 무엇보다 거버넌스에 많은 집중을 할 해가 될것이라고 생각되며 REST의 영향을 받아서 Restful webservice 기반의 SOA가 시험될 해라고 생각된다.

 

6. Mobile platform

모바일 플랫폼에 대해서는 더 이상 말할 필요가 없을 것 같다. Google의 Android, Apple의 AppStore, Nokia의 모바일 플랫폼에 이어서 MS나 기타 모바일 업체도 일반 개발자들에게 개발 환경을 오픈함으로써 User created contents(application)을 생산하게 하고 이 과정에서 수익을 창출하는 비즈니스 모델이 유행이 될것이다. 아마 금년은 이 모바일 플랫폼의 최고 격전의 해가 되지 않을까?

 

7. Collaboration

협업에 대해서는 ALM과 Agile 방법론이 금년에도 작년에 이어서 크게 유행할것이고 좀더 실용적이고 실질적인 개발 및 협업 프로세스의 발전과 이를 구현하는 도구들이 사용될 것이다. 작년에 비해서 크게 변화한 점이 있기 보다는 좀더 성숙된 형태로 발전하는 해가 되지 않을까 싶다.

 

저작자 표시
신고

'엔터프라이즈 솔루션' 카테고리의 다른 글

Apache Camel note  (0) 2013.02.12
아키텍쳐에 있어서 레퍼런스의 중요성  (2) 2009.10.20
2009년 기술 전망  (2) 2009.01.06
ALSB에서
SOAP 을 REST POX (Plain Old Xml)로 변환하는 XmlBeans 구현 예제. ALSB에서 Java Callout으로 사용이 가능함
==
import javax.xml.namespace.QName;

import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor.TokenType;

public class RESTTransformer {
    public static XmlObject toREST(XmlObject soap){
       
        XmlCursor cur = soap.newCursor();
        cur.toFirstChild();
        cur.toChild(new QName("http://schemas.xmlsoap.org/soap/envelope/","Body"));

        traverse(cur);
        cur.dispose();
        return null;
    }
   
    public static void traverse(XmlCursor cur){
        if(cur.toFirstChild()){
            String name;
            do{
               
                name = cur.getName().getLocalPart();
                System.out.println("<"+name+">");
       
                traverse(cur);
                System.out.println("</"+name+">");

            }while(cur.toNextSibling());

            cur.toParent();
        }else{
            // is Leaf
            System.out.println(cur.getTextValue());
        }
    }
   
==
저작자 표시
신고
Mediation에서 Route To 추가하고
거기에 Dynamic Routing 추가한후에,
Expression에 다음과 같이 써줌
<ctx:route>
<ctx:service isProxy='true'>GeneralProxySampleProject/samplewebservice/localproxy/PersonService.local</ctx:service>
</ctx:route>
==
Route하고자 하는 destination이 Proxy일 경우 isProxy를 true로 해줄것.
service 경로는 "프로젝트명/폴더.../폴더/Proxy명"
예를 들어

default 프로젝트의 localproxy 폴더의 common.local.proxy의 경우
default/localproxy/common.local (.proxy를 뺀다.) 가 된다.

저작자 표시
신고
문제는 JMS Proxy에서는 Transaction start를 지원하지만
가장 많이 사용하는 WebService Proxy는 Global Transaction을 start하지 않기 때문에
Transactional EJB를 Composition하는 경우 분산 트렌젝션에 대한 구현 문제가 생긴다.

방법은 두가지 인데.
1) 단순하게 EJB를 하나 만들어서 ALSB(OSB)에 배포하여 Code로 Tx를 composition한후, 이 EJB를 Biz Service로 등록하고 WebService로 Expose하는 방법
2) 좀더 OSB 다운 방법은

WebService Proxy에서 JMS Q로 callout한후 JMS Proxy에서 읽어서 Tx 처리하고나서 Recv Q에 return하면 WebService Proxy에서 blocked wait하다가 response 받아서 처리하는 방식...
성능이 다소 떨어질테고, 클러스터에 고려해야할점도 있을테고, JMS Q를 관리해야 하는점, Tx Fail시 Hop이 늘어나는 점등이 풀어야할 문제이기는 한데, reference 아키텍쳐만 단단하게 만들어놓는 다면 가능할듯...

이럴때 그냥 WLI로 Service Enablement 시키고 Biz Service로 등록하면 얼마나 좋아.. ALINT가 그리워~~

저작자 표시
신고
1. OSB 설치시 Default로 하면 Eclipse를 인스톨 하기를 요청하기 때문에 Custom으로 선택하고 Workshop에서 Eclipse 모듈을 제외하고 설치할것.
2. Managed Server을 추가로 추가하기가 복잡하기 때문에, 아예 설치시부터 Managed Server를 추가하는 것이 좋다.
3. DBMS를 사용하기 때문에, 초반에 DB 설정을 해놓고 인스톨하는 것이 좋다.

신고

Non Blocking Sync Call

엔터프라이즈 솔루션/BEA WebLogic | 2008.10.29 19:48 | Posted by 조대협
WebLogic에서 간만에 재미있는 기능을 찾아서 포스팅.
ESB나 EAI 제품과 같은 아키텍쳐에서 Sync Call의 구조를 보면 다음과 같다.
Request가 들어오면 특정 Thread가 그 request를 받아서 Backend의 Component에 보내고, 응답을 기다린다.
응답이 오면 Client에게 그 응답을 전달하는 구조이다.
그런데 이 경우 Client에서 요청을 받은 후 그 요청을 Component에 전달하고 나면 Component로 부터 응답이 오기까지는 Request Thread는 아무것도 하지 않고 단지 기다리기만 한다. 즉 하는 일없이 Thread만 점유하고 있는 것이다.
만약에 Component에서의 처리시간이 오래 걸리게 되면 Request Thread가 held 되는 시간이 늘어나게 되고 이런 요청이 많을 수록, 시스템 내의 Idle Thread는 기하급수적으로 줄어들게 되고, 이는 Thread 부족으로 인한 Slow down이나 hang현상을 유발하게 된다.

이를 해결하기 위한 아키텍쳐가 Non-blocking Sync Mode인데
개념은 다음과 같다. 
Client에서 요청이 들어오면 그 요청을 Request Thread가 처리하여 Backend의 Component로 전달을 하고 Request Thread는 Idle 상태로 전환된다.
그리고 나서 Component로 부터 응답이 들어오면 그 응답을 Idle Thread중에 한 Thread가 응답을 받아서 Client에게 전달을 한다. (Response Thread)
이런 구조에서는 Component로 일단 요청이 전달된후 Component에서 응답이 올때까지는 Thread가 release되어 있기 때문에 Working Thread의 수를 줄일 수 있다.
Server <--> Component 단을 Async/Callback처럼 구현해놓은것인데 EAI나 ESB와 같은 중계 시스템에서는 매우 유용한 아키텍쳐가 될거 같다.

이를 구현한 구현체가 WebLogic에 Future Response model for HTTP 라는 모델이다. (아래 참조)
이 모델은 Backend에서 수행 시간이 오래 걸릴 경우나 비지니스 로직이 JMS등을 이용하는 것과 같은 Async 구조에서는 매우 유용하지만 일반적인 WebApplication에서는 오히려 유용하지 않다. (하나의 Request를 수행하는데 Thread를 두개나 사용하게 되고 어짜피 Response를 만들기 위해서는 비지니스 로직을 처리해야할 쓰레드가 필요하기 때문에..)

이러한 구조는 ALSB 3.0 내부에서 사용하고 있다니 장애 예방이나, 리소스 효율 면에서 상당히 뛰어날듯하다.
간만에 재미있는 아키텍쳐를 봤더니.. 뿌듯하네..

==

A Future Response Model for HTTP Servlets

In general, WebLogic Server processes incoming HTTP requests and the response is returned immediately to the client. Such connections are handled synchronously by the same thread. However, some HTTP requests may require longer processing time. Database connection, for example, may create longer response times. Handling these requests synchronously causes the thread to be held, waiting until the request is processed and the response sent.

To avoid this hung-thread scenario, WebLogic Server provides two classes that handle HTTP requests asynchronously by de-coupling the response from the thread that handles the incoming request. The following sections describe these classes.

Abstract Asynchronous Servlet

The Abstract Asynchronous Servlet enables you to handle incoming requests and servlet responses with different threads. This class explicitly provides a better general framework for handling the response than the Future Response Servlet, including thread handling.

You implement the Abstract Asynchronous Servlet by extending theweblogic.servlet.http.AbstractAsyncServlet.java class. This class provides the following abstract methods that you must override in your extended class.

doRequest

This method processes the servlet request. The following code example demonstrates how to override this method.

Listing 9-3 Overriding doRequest in AbstractAsynchServlet.java
public boolean doRequest(RequestResponseKey rrk) 
      throws ServletException, IOException {
      HttpServletRequest req = rrk.getRequest();
      HttpServletResponse res = rrk.getResponse();

      if (req.getParameter("immediate") != null) {
            res.setContentType("text/html");
            PrintWriter out = res.getWriter();
            out.println("Hello World Immediately!");
            return false ;
      }
      else {
            TimerManagerFactory.getTimerManagerFactory()
            .getDefaultTimerManager().schedule
            (new TimerListener() {
                  public void timerExpired(Timer timer)
                        {try {
                              AbstractAsyncServlet.notify(rrk, null);
                        }
                        catch (Exception e) {
                              e.printStackTrace();
                        }
                  }
            }, 2000);
      return true;
      }
}

doResponse

This method processes the servlet response.

Note: The servlet instance that processed the doRequest() method used to handle the original incoming request method will not necessarily be the one to process the doResponse() method.

If an exception occurs during processing, the container returns an error to the client. The following code example demonstrates how to override this method.

Listing 9-4 Overriding doResponse() in AbstractAsyncServlet.java
public void doResponse (RequestResponseKey rrk, Object context)
   throws ServletException, IOException
      {
      HttpServletRequest req = rrk.getRequest();
      HttpServletResponse res = rrk.getResponse();

      res.setContentType("text/html");
      PrintWriter out = res.getWriter();
      out.println("Hello World!");
}

doTimeOut

This method sends a servlet response error when the notify() method is not called within the timeout period.

Note: The servlet instance that processed the doRequest() method used to handle the original incoming request method will not necessarily be the one to process the doTimeOut() method.
Listing 9-5 Overriding doTimeOut() in AbstractAsyncServlet.java
public void doTimeout (RequestResponseKey rrk)
      throws ServletException, IOException
{
      HttpServletRequest req = rrk.getRequest();
      HttpServletResponse res = rrk.getResponse();

      res.setContentType("text/html");
      PrintWriter out = res.getWriter();
      out.println("Timeout!");
}

Future Response Servlet

Although Oracle recommends using the Abstract Asynchronous Servlet, you can also use the Future Response Servlet to handle servlet responses with a different thread than the one that handles the incoming request. You enable this servlet by extending weblogic.servlet.FutureResponseServlet.java, which gives you full control over how the response is handled and allows more control over thread handling. However, using this class to avoid hung threads requires you to provide most of the code.

The exact implementation depends on your needs, but you must override the service() method of this class at a minimum. The following example shows how you can override the service method.

Listing 9-6 Overriding the service() method of FutureResponseServlet.java
  public void service(HttpServletRequest req, FutureServletResponse rsp)
throws IOException, ServletException {
if(req.getParameter("immediate") != null){
PrintWriter out = rsp.getWriter();
out.println("Immediate response!");
rsp.send();
} else {
Timer myTimer = new Timer();
MyTimerTask mt = new MyTimerTask(rsp, myTimer);
myTimer.schedule(mt, 100);
}
}

private static class MyTimerTask extends TimerTask{
private FutureServletResponse rsp;
Timer timer;
MyTimerTask(FutureServletResponse rsp, Timer timer){
this.rsp = rsp;
this.timer = timer;
}
public void run(){
try{
PrintWriter out = rsp.getWriter();
out.println("Delayed Response");
rsp.send();
timer.cancel();
}
catch(IOException e){
e.printStackTrace();
}
}
}
신고

WebLogic 9.2 MP2 기준으로 작성
JMX 이용하여 XID를 입력하여 해당 트렌젝션에 대한 TM,RM,상태 정보들을 출력해주는 JSP 예제
==
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page import="javax.naming.*" %>
<%@ page import="javax.management.*" %>
<%@ page import="javax.management.remote.*" %>
<%@ page import="weblogic.management.runtime.*" %>

<%!
 public void printMap(Map map,JspWriter writer) throws Exception {
  for(Iterator i=map.keySet().iterator();i.hasNext();){
   Object key = i.next();
   writer.println(key+":"+map.get(key)+"\n<BR>");
  } 
 }
%>
<%
 // MBean 서버에 연결
 Hashtable h = new Hashtable();    
 
 h.put(Context.SECURITY_PRINCIPAL, "weblogic");     
 h.put(Context.SECURITY_CREDENTIALS, "weblogic" );     
 h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");     

 JMXServiceURL serviceURL = new JMXServiceURL(
   "t3","localhost",7001,"/jndi/weblogic.management.mbeanservers.runtime");
 
    JMXConnector connector = JMXConnectorFactory.connect(serviceURL,h);
    MBeanServerConnection conn = connector.getMBeanServerConnection();
 
    ObjectName service = new ObjectName("com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
   
 // ServerRuntime 얻어오기
 ObjectName  serverRuntime = (ObjectName)conn.getAttribute(service, "ServerRuntime");

 // xid를 이용해서 jtaRuntime으로 부터 JTATransaction객체를 읽어온다.
 String xid = request.getParameter("xid");
 
 ObjectName jtaRuntime = (ObjectName)conn.getAttribute(serverRuntime,"JTARuntime");
 JTATransaction tx = (JTATransaction)conn.invoke(jtaRuntime,"getJTATransaction",
   new Object[] {new String(xid)},new String[] {"java.lang.String"} );

 if(tx == null){ out.println("No transaction exist");return;}

 // 해당 트렌젝션에 대한 정보 출력
 // 참고
 // http://edocs.beasys.com/wls/docs92/javadocs_mhome/weblogic/management/runtime/JTATransaction.html
 
 out.println("# UserProperties");
 out.println("<BR>");
 printMap(tx.getUserProperties(),out);
 
 out.println("# Tx started before :"+tx.getSecondsActiveCurrentCount());
 out.println("<BR>");
 out.println("# Status :"+tx.getStatus());
 out.println("<BR>");
 out.println("# Server & Status");
 out.println("<BR>");
 printMap(tx.getServersAndStatus(),out);
 out.println("# Resource & Status");
 printMap(tx.getResourceNamesAndStatus(),out);
 

%>
==

신고

Liferay 다국어 지원 방법

엔터프라이즈 솔루션/포탈 | 2008.03.19 18:03 | Posted by 조대협

Note: The default Language.properties file is located at /portal/portal-impl/classes/content/Language.properties. The Language-ext.properties file referred to in the docs is located at /ext/ext-impl/classes/content/Language-ext.properties

http://wiki.liferay.com/index.php/Development_in_the_ext_environment
신고