2010. 6. 28. 15:59
출처


Rich web application 어쩌구 하면서 이런 저런 제품들이 쏟아져 나왔고.. 웹 어플의 한 주류를 차지하고 있는듯 싶다. 우선은 남들이 하니까.. 나도 한번 해볼까?? 라는 생각은 있었지만, 왠지 모를 거부감에 아직까지 손도 못대고 있었다. 오늘 왠지 할짓도 없고, 심심하기도 해서 Apache open source 를 뒤적이다가 Click 이라는 넘을 보게 되었다.

Click 이라는 넘은 현대적인 JEE web application framework(web 2.0 을 의미하는듯) 라고 소개하고 있다. 물론 rich client 프로그래밍 스타일도 지원한다. 뭐 이런 잘낳다고 떠드는 건 솔직히 필요 없고 하루만에 배우고 사용할 수 있다는 말에 쵸큼 끌린다. ^^

IBM developerworks 에 올라온 기사를 보면 JSP, MVC framework 를 사용안하고 웹 어플리케이션을 개발할 수있다고 소개하고 있다. 유사한 다른 넘들보다는 좀 가벼운 프레임웤이라고 하는데.. 뭐 다른 넘들을 사용 안해봐서 비교불가다. 쩌ㅃ~

Apache click 은 HTML template, POJOs 를 사용한다고 한다.
HTML 템플릿은 Apache Velocity template engine(?) 을 사용하고, 특별한 tag 없이 사용할 수 있다고 한다.
대 충 이런 놈이다..라는 것만 알고, 오늘부터 요넘을 study 해봐야 할듯.


'study' 카테고리의 다른 글

추상화(abstraction), 일반화(generalization)  (0) 2016.03.02
[도서] - 자바 병렬 프로그래밍  (0) 2010.06.30
[도서] - Java Performance Fundamental  (0) 2010.06.30
용어정리  (0) 2010.06.28
Posted by 짱가쟁이
참조


Excel file을 다루는 Java APIs 를 소개한다. 위 참조를 보면 자세한 설명이 있음. 간략하게 소개하면..
1. Andy Khan's Java Excel API
2. The xlSQL Excel JDBC Driver
3. OpenXLS
4. Apache POI



Posted by 짱가쟁이
Tomcat 5.0 이상에서 한글 인코딩을 지원하지 않는 경우가 생긴다. 이럴때 server.xml 파일에서 다음과 같이 uri 인코딩을 현재 작업 인코딩에 맞게 지정하자.

<Connector port="8080" maxHttpHeaderSize="8192"
        maxThreads="100" minSpareThreads="25" maxSpareThreads="75"
        enableLookups="false" redirectPort="8443" acceptCount="100"
        connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="euc-kr"/>

Posted by 짱가쟁이
ThreadLocal
하나의 쓰레드에서 객체를 전파하는 방법으로 파라미터를 사용하기 않고 코드에서 동일한 객체를 사용할 수 있게 해준다.

활용 예)
- 객체를 쓰레드에 안전하게 해준다.
- 쓰레드 단위로 트랜잭션 컨텍스트를 관리하고자 할때 사용.
(static으로 선언된 ThreadLoacl 변수에 트랜잭션 컨텍스트를 넣어두면 쓰레드에 안전하게 사용가능)
- ThreadLocal을 사용하여 공유 데이터를 사용할 때 현재 실행중인 스레드의 정보를 넘겨줘야 할 필요는 없지만, 이런 방법은 해당 프레임웍에 대한 의존성을 가지고 된다.
- 전역변수처럼 사용되기 때문에 일반적인 전역 변수가 갖는 단점처럼 재사용성을 떨어뜨릴 수 있고, 객체 간에 눈에 보이지 않는 연결 관계를 만들어내기 쉽기 때문에 애플리케이션에 어떤 영향을 미치는지 정확하게 알고 사용해야 한다.

사용 예)

ThreadLocalClass.java
public class ThreadLocalClass {

    public static ThreadLocal<UserInfo> local = new ThreadLocal<UserInfo>();
}

WorkerRunnable.java
- ThreadLocal 변수 사용
- 객체는 할당한 쓰레드에서만 사용할 수 있다.
public class WorkerRunnable implements Runnable {

    private String name;
  
    public WorkerRunnable(String name) {
        this.name = name;      
    }
  
    public void setObject() {
        UserInfo info = new UserInfo();
        info.setName(name);      
        ThreadLocalClass.local.set(info);
    }
  
    @Override
    public void run() {
        setObject();

        while(true) {
            Business business = new Business();
          business.logic_01();
        }
    }
}

Business.java
- 객체 사용
public class Business {

    public void logic_01() {
        UserInfo user = ThreadLocalClass.local.get();
        System.out.println(Thread.currentThread().getName() + ":" + user.getName());
    }
}

UserInfo.java
- 데이터 객체
public class UserInfo {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    } 
}

Launcher.java
- 테스트 클래스
public class Launcher {

    public static void main(String[] args) {      
              
        for(int i = 0;i<10;i++) {
            WorkerRunnable w = new WorkerRunnable("bbaeggar : " + i);
            Thread t = new Thread(w);
            t.start();
        }
    }
}

Posted by 짱가쟁이
apache cxf 는 기본적으로 thread safety를 지원 하지 않는다고 한다. 뭐 그래서 어쩌구 저쩌구 하지만... 다른 방법으로 할수 있다고는 한다.

cxf.xml
<?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:cxf="http://cxf.apache.org/core"
xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
xsi:schemaLocation="
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <httpj:engine-factory bus="cxf">
        <httpj:engine port="9000">
            <httpj:sessionSupport>true</httpj:sessionSupport>
        </httpj:engine>
    </httpj:engine-factory>
  
    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>
</beans>

Server Side - service class
package bbaeggar.jaxws.simple.server.service;

import javax.annotation.Resource;
import javax.jws.WebService;
import javax.servlet.http.HttpSession;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService(endpointInterface = "bbaeggar.jaxws.simple.server.service.Login",
        serviceName = "Login")
public class LoginImpl implements Login {

    //webServiceContext is injected by the JAXWS API
    @Resource private WebServiceContext wsContext;
  
    SessionVo sessionVo;
  
    @Override
    public boolean login(String id, String pw) {
        // TODO Auto-generated method stub

        MessageContext mc = wsContext.getMessageContext();
        HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession(true);
        // Get a session property "counter" from context
        if (session == null)
            System.out.println("session is null");
              
        sessionVo = new SessionVo();
      
        sessionVo.setId(id);
        sessionVo.setPw(pw);

        session.setAttribute("session", sessionVo);
              
        return true;

    }

    @Override
    public String getId() {
        // TODO Auto-generated method stub      
        MessageContext mc = wsContext.getMessageContext();      
        HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();      
        SessionVo vo = (SessionVo)session.getAttribute("session");

        return vo.getId();      
    }
}

Client side class
package bbaeggar.jaxws.simple.client;

import java.util.Map;

import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;

import bbaeggar.jaxws.simple.server.service.HelloWorld;
import bbaeggar.jaxws.simple.server.service.Login;

public class TestRunnable implements Runnable {
  
    @Override
    public void run() {
        login();      
    }
  
    public void login() {
                  
        Service service = Service.create(Client.SERVICE_LOGIN);
        String endpointAddress = "http://localhost:9000/Login";
        service.addPort(Client.PORT_LOGIN, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
      
        Login login = service.getPort(Login.class);
      
        Map requestContext = ((BindingProvider)login).getRequestContext();
        requestContext.put(BindingProvider.SESSION_MAINTAIN_PROPERTY,true);
      
        String id = "bbaeggar" + Thread.currentThread().getId();
      
        boolean isLogin = login.login(id, "aaaa");
      
        System.out.println("client : " + login.getId());
      
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      
        if(id.equals(login.getId())) {
            System.out.println("같은 세션임");
        } else {
            System.out.println("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
        }
    }
}


위 코드는 미친척하고 테스트용으로 만든거임.. 테스트용으로만 사용하삼.  쩌ㅃ~
Posted by 짱가쟁이
KTF Khub 작업을 하던중... jdk 1.6 버전에서 khub 테스트 코드가 동작을 안하더라.. 이유를 찾아보니.. jaxb 버전 문제로 클라이언트 코드가 동작은 안함. 뭐. jdk 버전을 낮춰서 작업하면 되것지만.. cxf를 공부하고 있는 도중이였기에 cxf에서 제공하는 "wsdl2java" 툴을 사용하게 되었음.

우선 콘솔창에서 작업해도 무난히 동작하지만.. 이클립스를 사용하기 때문에 편하게 ant로 작업했음.(이클립스 너무 편한듯.. 쩌ㅃ~)

khub_wsdl2java.xml
<?xml version="1.0"?>
<project name="cxf khub_wsdl2java" basedir="."> 
   <property name="cxf.home" location ="C:\Develop\02. Documents\01. Apache cxf\apache-cxf-2.2.7\apache-cxf-2.2.7"/>

   <path id="cxf.classpath">
      <fileset dir="${cxf.home}/lib">
         <include name="*.jar"/>
      </fileset>
   </path>
    
   <target name="cxfWSDLToJava">
      <java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true">
         <arg value="-client"/>
         <arg value="-d"/>
         <arg value="D:\wsdl2java\khub_client"/>
         <arg value="http://125.131.85.42/khub/WebService?wsdl"/>
         <classpath>
            <path refid="cxf.classpath"/>
         </classpath>
      </java>
   </target>
</project>

cxf 홈 디렉트리, java code 생성 경로, wsdl 경로만 변경하면.. 무난히 동작함.
Ant로 빌드하면 코드가 생성되는데.. 패키지 구조가 좀 지져분한게 생성됨.. 뭐 따로 설정하면 되것지만.. 이거는 수작업을 함.
생성된 빌드를 보면 "IWebService_IWebServicePort_Client" 라는 넘이 있는데.. 이놈이 실제로 Entry point 가 된다.
jdk1.6 으로 작업하고 싶다면.. Apache CXF를 사용하는 것도 무난할듯..

Posted by 짱가쟁이
IBM developersorks 를 뒤적이다가 흥미로운 기사가 있어 참고용으로 남긴다. (난중에 쓸일이 있을지도 모를듯 ^^)
우선 일반적인 케이스와, WS-Security 상태로 나눠서 결과를 통계로 보여준다. 자세한 내용은 기사를 참조하기 바란다.

출처 

'framework > apache cxf' 카테고리의 다른 글

[Apache cxf] - session support  (0) 2010.06.28
[Apache cxf] - WSDL to Java  (0) 2010.06.28
[Apache cxf] - Spring 에서 endpoint 설정하자  (0) 2010.06.28
[Apache cxf] - client remote ip 가져오자  (1) 2010.06.28
[CXF] - cxf 소개  (0) 2010.06.28
Posted by 짱가쟁이
웹 서비스 작업을 하면서 아쉽지만 Request를 각 서비스별로 생성하게 되었다. 유연하게 Request 객체를 하나만 생성해서 작업하면 좋것지만, Http binding(GET) 을 지원해야 한다는 제약 사항 때문에 이래저래 귀찮은 일이 좀 생긴듯.

여 기서 하나.. 각 request 별 입력값을 로그로 남겨야 하는데.. 각 value object 에 toString()을 구현하기가 참 귀찮다는 것이다. 그래서 생각한 것이 reflection 을 이용해서 한번에 해결하자 라는 취지로 만들게 되었음.

public class Test {

    public String getRequestStringMethods(Object obj) {
  
        StringBuffer buffer = new StringBuffer();
      
        try {
            Class dymClass      = obj.getClass();
            Method[] methods = dymClass.getMethods();
          
            buffer.append(dymClass.getSimpleName());
            buffer.append(" : ");
            for(int i = 0;i<methods.length;i++) {
                String methodName = methods[i].getName();
                if("get".equals(methodName.substring(0, 3)) && !"getClass".equals(methodName)) {                
                    String value = (String)methods[i].invoke(obj, null);                  
                    buffer.append("[" + methodName.substring(3, 4).toLowerCase() + methodName.subSequence(4, methodName.length()) + "]");
                    buffer.append(":\"" + value + "\"");
                    buffer.append(" ");
                }
            }
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      
        return buffer.toString();
    }
  
    public String getRequestStringFields(Object obj) {
      
        StringBuffer buffer = new StringBuffer();
      
        try {
            Class dymClass      = obj.getClass();
            Field[] fields      = dymClass.getDeclaredFields();
          
            buffer.append(dymClass.getSimpleName());
            buffer.append(" : ");
            for(int i = 0;i<fields.length;i++) {
                String methodName = "get" + fields[i].getName().substring(0, 1).toUpperCase() + fields[i].getName().substring(1, fields[i].getName().length());              
                Method method       = obj.getClass().getMethod(methodName, null);
                String value = (String)method.invoke(obj, null);                  
                buffer.append("[" + methodName.substring(3, 4).toLowerCase() + methodName.subSequence(4, methodName.length()) + "]");
                buffer.append(":\"" + value + "\"");
                buffer.append(" ");
            }
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      
        return buffer.toString();
    }
  
    public static void main(String[] args) {
      
        TestVo vo = new TestVo();
        vo.setAge("33");
        vo.setId("service_01");
        vo.setMsg("message");
        vo.setName("bbaeggar");
        vo.setValue("value");
      
        vo.setValue1("value1");
        vo.setValue2("value2");
        vo.setValue3("value3");
        vo.setValue4("value4");
        vo.setValue5("value5");
        vo.setValue6("value6");
        vo.setValue7("value7");
        vo.setValue8("value8");
        vo.setValue9("value9");
        vo.setValue10("value10");
        System.out.println(new Test().getRequestStringFields(vo));
        System.out.println(new Test().getRequestStringMethods(vo));

    }
}

Result
TestVo : [id]:"service_01" [name]:"bbaeggar" [msg]:"message" [value]:"value" [age]:"33" [value1]:"value1" [value2]:"value2" [value3]:"value3" [value4]:"value4" [value5]:"value5" [value6]:"value6" [value7]:"value7" [value8]:"value8" [value9]:"value9" [value10]:"value10"

TestVo : [name]:"bbaeggar" [value]:"value" [id]:"service_01" [msg]:"message" [age]:"33" [value1]:"value1" [value2]:"value2" [value3]:"value3" [value4]:"value4" [value5]:"value5" [value6]:"value6" [value7]:"value7" [value8]:"value8" [value9]:"value9" [value10]:"value10"

getRequestStringFields() 메소드를 사용하면 필드를 선언한 순서대로 값을 가지고 온다.
getRequestStringMethods() 는 좀 멍청한 넘임.
Posted by 짱가쟁이
우선은 JAX-WS 에서 soap 과 http binding 의 endpoint sample을 올린다. http binding은 RS 가 좀더 낳다는 의견이 많지만, soap과 같이 서비스하며, 코드를 재사용할 수 있다는 장점 때문에 WS를 사용하게 됨.

sample
<?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:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://cxf.apache.org/jaxws
    http://cxf.apache.org/schemas/jaxws.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-http-binding.xml" />

<!-- The service bean -->
   <bean id="demoServiceImpl" class="cxf.demo.service.DemoServiceImpl" />

   <jaxws:endpoint id="getServiceHttp"
      implementor="#demoServiceImpl"
      implementorClass="cxf.demo.service.DemoService"
      address="/DemoService"
      bindingUri="http://apache.org/cxf/binding/http">
      <jaxws:serviceFactory>
         <ref bean="jaxWsServiceFactoryBean"/>
      </jaxws:serviceFactory>
   </jaxws:endpoint>
  
   <jaxws:endpoint
      id="getServiceSoap"
      implementor="#demoServiceImpl"
      implementorClass="cxf.demo.service.DemoService"
      address="/DemoService/soap" />
           
   <bean id="jaxWsServiceFactoryBean"
    class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean" scope="prototype">
      <property name="wrapped" value="false" />
   </bean>    
</beans>
<!-- END SNIPPET: beans -->


'framework > apache cxf' 카테고리의 다른 글

[Apache cxf] - session support  (0) 2010.06.28
[Apache cxf] - WSDL to Java  (0) 2010.06.28
[Apache cxf] cxf, axis2, metro 성능 비교  (0) 2010.06.28
[Apache cxf] - client remote ip 가져오자  (1) 2010.06.28
[CXF] - cxf 소개  (0) 2010.06.28
Posted by 짱가쟁이
졸라 할게 많아서 짜증이 나기는 하지만.. 하나하나 찾는 재미는 쏠쏠한듯..

밑에 코드는 웹 서비스에 Request를 보내는 넘의 IP를 가져오는 코드임

@Resource
private WebServiceContext context;
  
/**
* Clinet IP 를 가져온다.
* @return
*     remote ip
*/
private String getRemoteAddr() {
   MessageContext msgCtxt = context.getMessageContext();
   HttpServletRequest req = (HttpServletRequest)msgCtxt.get(MessageContext.SERVLET_REQUEST);
   String clientIP = req.getRemoteAddr();

   return clientIP;
}

'framework > apache cxf' 카테고리의 다른 글

[Apache cxf] - session support  (0) 2010.06.28
[Apache cxf] - WSDL to Java  (0) 2010.06.28
[Apache cxf] cxf, axis2, metro 성능 비교  (0) 2010.06.28
[Apache cxf] - Spring 에서 endpoint 설정하자  (0) 2010.06.28
[CXF] - cxf 소개  (0) 2010.06.28
Posted by 짱가쟁이