아래 블로그에 작성한 JAXB HttpClient 코드를 Spring OXM으로 수정해서 돌려보았다. 비교해볼만함

http://knight76.tistory.com/entry/JAXB-Http-Client-Example샘플

 

 

특정 URL을 호출하면 사원 정보가 나온다고 가정한다.

 

<ROOT>

<EMPLOYEE>

<id></id>

<nm></nm>

….

</EMPLOYEE>

<EMPLOYEE>

<id></id>

<nm></nm>

….

</EMPLOYEE>

</ROOT>

 

# ROOT.java

package spring;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="ROOT")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
   
    @XmlElement(name="EMPLOYEE")
    private List<Employee> employees;

    public Root() {
        employees = new ArrayList<Employee>();
    }

    public List<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }

}

 

# Employee.java

package test;

public class Employee {

private String id;
private String nm;

….

… // set, get

}

 

# XEmployee.java

 

public class XEmployee {

    private static List<String> employeeList;
    public static List<String> getEmployeeList() {
        return employeeList;
    }
    static {
        employeeList = new ArrayList<String>();

        employeeList.add("aaa");
         employeeList.add("bbb");
         employeeList.add("ccc");

    }
}

여기까지는 바뀌는 것이 없다.  Spring 연동 코드가 바뀌었다. 연동코드는 형광펜으로 칠해놨다.

applicationContext.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:oxm="http://www.springframework.org/schema/oxm"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/oxm
           http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">

    <oxm:jaxb2-marshaller id="jaxb2Marshaller">
        <oxm:class-to-be-bound name="spring.Root" />
    </oxm:jaxb2-marshaller>
   
    <!-- oxm:jaxb2-marshaller 에서 사용했던 것과 동일한 효과(예전 방식) 
    <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>spring.Root</value>
            </list>
        </property>
    </bean>
    -->

    <bean id="application" class="spring.CheckEmp">
        <property name="marshaller" ref="jaxb2Marshaller" />
        <property name="unmarshaller" ref="jaxb2Marshaller" />
    </bean>

</beans>

 

main 메서드

package spring;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

import javax.annotation.Resource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.transform.stream.StreamSource;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class CheckEmp {
    @Resource(name = "jaxb2Marshaller")
    Unmarshaller unmarshaller;

    @Resource(name = "jaxb2Marshaller")
    Marshaller marshaller;
   
    public void setMarshaller(Marshaller marshaller) {
        this.marshaller = marshaller;
    }

    public void setUnmarshaller(Unmarshaller unmarshaller) {
        this.unmarshaller = unmarshaller;
    }
   
    public static final boolean isSaved = false;
    public static final String URL = "http://aaaaaaaaa";
    public static JAXBContext jaxbContext;
    static {
        try {
            jaxbContext = JAXBContext
                    .newInstance(new Class[] { test.Root.class });
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

       public static void main(String[] args) throws Exception {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        CheckEmp application = (CheckEmp) appContext.getBean("application");
        application.start();
    }

    private void start() throws Exception {
        BufferedReader reader = connectURL();
        if (isSaved) {
            saveFile(reader);
        }

        Root root = getRoot(reader);

         for (String retiredEmpID : XEmployee.getEmployeeList()) {
            boolean found = false;
            for (Employee emp : root.getEmployees()) {
                if (emp.getID().trim().equalsIgnoreCase(retiredEmpID)) {
                      found = true;
                }
            }
            if (found == false) {
                System.out.println(retiredEmpID);
            }
        }
    }

    private Root getRoot(BufferedReader reader) throws Exception {
        StreamSource source = new StreamSource(reader);
        Root root = (Root) unmarshaller.unmarshal(source);
        return root;
    }

    private BufferedReader connectURL() throws IOException,
            ClientProtocolException, UnsupportedEncodingException {
        HttpGet httpget = new HttpGet(URL);
        HttpClient httpclient = new DefaultHttpClient();
        httpclient.getParams().setParameter("http.socket.timeout", 999000);

        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        if (entity == null) {
            throw new RuntimeException("url error");
        }
        InputStream instream = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                instream, "utf-8"));
        return reader;
    }

    private static void saveFile(BufferedReader reader) throws IOException {
        Writer fstream = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream("aaa.txt"), "utf-8"));
        BufferedWriter out = new BufferedWriter(fstream);
        char[] a = new char[1024];
        while (reader.read(a) > 0) {
            out.write(a);
        }
        out.flush();
        System.out.println("File created successfully.");
    }

}

 

삽질 방지를 위해서 spring debug log가 출력되게 한다.

log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Threshold" value="DEBUG"/>
        <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%-5p](%F:%L) %m%n"/>
        </layout>
    </appender>
    <appender name="general" class="org.apache.log4j.ConsoleAppender">
       <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%-5p](%F:%L) %m%n"/>
       </layout>
    </appender>

    <logger name="com" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="general"/>
    </logger>

    <logger name="org.springframework" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="general"/>
    </logger>

    <root>
        <level value="WARN"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test1123</groupId>
    <artifactId>teswt1</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <spring-version>3.1.0.RELEASE</spring-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-xjc</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
    </dependencies>

</project>

 

 

# 참조한 내용

Spring OXM 에 대한 자료 (Marshalling XML using O/X Mappers)

http://static.springsource.org/spring-ws/site/reference/html/oxm.html

 

 

# 기타

 

@Resource  annotation은 javax.annotation으로 플랫폼 독립적이며, jsr250에서 DI 의 리더들이 모여서 결정했다. jsr250-api.jar 를 반드시 pom.xml에 넣어야 한다.

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>

name속성에 자동으로 연결될 빈객체의 이름을 입력한다
@Resource(name="marshaller")
Marshaller marshaller;




# CheckEmp.java 코드를 Spring JUnit으로 만들기

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml"})
public class CheckEmp {

// 코드

 @Test
 public void testMarshaller() throws Exception {

 ...
}
}

Posted by '김용환'
,

mvn의 assembly 와 비슷한 기능을 가진 플러그인이 있다.
Spring Batch를 하면서 알게 된 건데..
maven-shade-plugin이다. mvn assembly는 파일명이 예쁘지가 않는다..
그러나 maven shade plugin을 활용하면 파일명도 예쁘게 나온다. 더 정확하게 말하면, 파일을 overwrite하기 때문이다.
maven-shade-plugin은 아래와 같이 버전명과 예쁘게 나옵니다.

[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing E:\sts\springbatch-mssql\target\springbatch-mssql-0.2.jar with
E:\sts\springbatch-mssql\target\springbatch-mssql-0.2-shaded.jar


하지만 제일 중요한 것은 스프링 프로젝트의 경우에는 스프링 설정파일인 applicationContext.xml의 namespace를 찾지 못해서 에러가 발생되는 경우가 종종 발생되기도 한다. 즉 spring lib 안의 dependecy 파일이 동일한 위치에 있다 그래서 META-INF안에 있는 spring.handlers와 spring.schemas 파일을 덮어버리는 일이 있다. 그래서, assembly 을 사용하면 문제가 되어서, 스프링 프로젝트에서는 maven-shade-plugin을 사용하고 있다.

 pom.xml 파일의 내용입니다.






<plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-shade-plugin</artifactId>
     <version>1.4</version>
     <executions>
       <execution>
       <phase>package</phase>
         <goals>
           <goal>shade</goal>
           </goals>
           <configuration>
             <transformers>
               <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                 <resource>META-INF/spring.handlers</resource>
              </transformer>
             <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
               <resource>META-INF/spring.schemas</resource>
             </transformer>
           </transformers>
         </configuration>
       </execution>
     </executions>
   </plugin>

Spring Batch는 transformer를 추가하고 AppendingTransformer를 사용하는데. 이 이유는 spring 관련 jar를 합치면서 overwrite되지 않고 계속 더해질 수 있도록 한 것이다.
xml에서 선언하는 namespace를 못찾는 것을 방지할 수 있도록 하기 위한 것이다..

* 주석 : Spring Batch Sample 소스에 좋은 것이 많다~


'Web service' 카테고리의 다른 글

Facebook 기술  (0) 2011.03.16
FTP command 사용하기  (0) 2011.03.03
tomcat 6.0.31 패치 눈에 띄는것  (0) 2011.03.02
tomcat 6.0.32 중요 패치 내용  (0) 2011.03.02
tomcat 6.0.30 중요 패치 내용  (0) 2011.03.02
Posted by '김용환'
,