프로그래밍/Web Service

jax-ws 웹서비스 서버 구축하기

말춘이 2020. 2. 22. 14:44
반응형

  웹서비스는 서비스에 대한 정의서(WSDL)를 발행하여 클라이언트가 그 서비스를 어떻게 이용하면 되는지 보다 쉽게 알 수 있다.

 

  자바 웹서비스는 자바 스펙 요구서(Java Specification Request) 224번에 기재되어있다. JSR 224에 보면 자바 1.5 이상에서 사용할 수 있다고 한다. 어노테이션도 1.5 이상부터 지원.

It will run on JavaTM 2 Platform, Standard Edition (J2SE) 1.5.

 

  자바 웹서비스를 제공하는 심플 모듈 예제는 다음과 같은 순서로 구현하겠다.

 

  • 요청 value object 구현.
package test.server.webservice.vo;
 
/**
 * 요청 메세지 value object.
 * @author ijyoon
 */
public class ReqInfo {
 
    // 이름.
    private String name;
    // 주소.
    private String address;
    // 나이.
    private int age;
     
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

  웹서비스 이용자가 제공자에게 어떤 요청 값을 보낼지 정의한 클래스이다. 이름, 주소, 나이 세 가지 정보를 제공자에게 보내도록 하였다.

 

  • 응답 value object 구현.
package test.server.webservice.vo;
 
/**
 * 응답 메시지 value object.
 * @author ijyoon
 */
public class ResInfo {
 
    // 응답 메세지.
    private String resultMessage;
 
    public String getResultMessage() {
        return resultMessage;
    }
 
    public void setResultMessage(String resultMessage) {
        this.resultMessage = resultMessage;
    }
}

  웹서비스는 제공자는 이용자에게 resultMessage란 값만 응답값으로 보내기로 한다.

 

  • 웹서비스 서버 구현.
package test.server.webservice; 
 
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
 
import test.server.webservice.vo.ReqInfo;
import test.server.webservice.vo.ResInfo;
 
/**
 * 개인정보 서비스
 * @author ijyoon
 */
@WebService
public class PersonalInfoService {
 
    /**
     * 개인정보를 등록한다.
     * Attach file 포함.
     * @param req
     * @return res 
     */
    @WebMethod
    public @WebResult(name="resInfo")ResInfo 
        register(@WebParam(name="reqInfo")ReqInfo req){
 
        // 요청값 출력.
        System.out.println("request message.");
        System.out.println(req.getName());
        System.out.println(req.getAge());
        System.out.println(req.getAddress());
         
        // 응답 메세지 생성.
        String resMessage = req.getName() +" : "+ req.getAge() +" : " + req.getAddress();
        // 응답 객체 생성
        ResInfo res = new ResInfo();
        res.setResultMessage(resMessage);
         
        return res;
    }
     
    /**
     * simple webservice test.
     * @param args
     */
    public static void main(String[] args){
        System.out.println("start web service.");
        Endpoint.publish("http://192.168.0.210:8080/personalInfoService", new PersonalInfoService());
    }
     
}

  눈여겨 봐야 할 곳이 어노테이션으로 정의된 부분이다.
  16line에 @WebService라는 어노테이션이 정의되었다. @WebService 어노테이션 API를 참조하면 6가지 엘리먼트가 존재한다. 지정하지 않을 경우 클래스명을 따라간다. 다음은 @WebService에 대한 6가지 엘리먼트를 설명한 것이다.


  @WebService
  – name
  웹서비스의 이름을 정의하는 엘리먼트이다. WSDL 발행 시 portType 엘리먼트에 정의되는 이름이다.

 

  – targetNamespace
  타켓네임스페이스를 정의하는 엘리먼트이다. WSDL 발행 시 definitions 엘리먼트의 targetNamespace 속성과 연관이 있다.

 

  – serviceName
  WSDL 발행시 service 엘리먼트에 정의되는 이름이다.

 

  – portName
  WSDL 발행시 port 엘리먼트에 정의되는 이름이다.

 

  – wsdlLocation
  기존에 발행된 WSDL 파일이나 URL을 참조한다.

 

  – endpointInterface
  구현클래스와 인터페이스를 분리할 수 있으며 분리된 인터페이스에 풀 패키지를 값으로 설정한다.

 

  @WebMethod 어노테이션은 target value가 메소드이기 때문에 메서드에만 선언할 수 있다. 앞서 본 예제의 25 line에 해당한다.

 

  @WebMethod
  – operationName
  WSDL 발행시 operation 엘리먼트에 정의되는 이름이다.

 

  – action
  soap:operation엘리먼트의 soapAction 속성 값을 정의한다.

 

  – exclude
  웹메소드에 포함하지 않는다. exclude=true 설정을 하면 WSDL발행 시 해당 메서드(오퍼레이션)는 제외된다.

 

  위의 내용을 참조하여 구현했던 클래스의 @WebService, @WebMethod(16,25 line)의 엘리먼트를 수정하여 WSDL을 확인해 보자.

/**
 * 개인정보 서비스
 * @author ijyoon
 */
@WebService(name="PInfo_by_ijyoon", portName="PInfoPort", serviceName="PInfoService", targetNamespace="http://malchooni.name/PInfo")
public class PersonalInfoService {
 
    /**
     * 개인정보를 등록한다.
     * Attach file 포함.
     * @param req
     * @return res 
     */
    @WebMethod(operationName="PInfoOpr",action="PInfoAction")
    public @WebResult(name="resInfo")ResInfo 
        register(@WebParam(name="reqInfo")ReqInfo req){
 
        // 요청값 출력.
        System.out.println("request message.");
    }
}
       

  – 수정 전 WSDL

<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://webservice.server.test/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://webservice.server.test/" name="PersonalInfoServiceService">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://webservice.server.test/" schemaLocation="http://192.168.0.210:8080/personalInfoService?xsd=1" />
        </xsd:schema>
    </types>
    <message name="register">
        <part name="parameters" element="tns:register" />
    </message>
    <message name="registerResponse">
        <part name="parameters" element="tns:registerResponse" />
    </message>
    <portType name="PersonalInfoService">
        <operation name="register">
            <input wsam:Action="http://webservice.server.test/PersonalInfoService/registerRequest" message="tns:register" />
            <output wsam:Action="http://webservice.server.test/PersonalInfoService/registerResponse" message="tns:registerResponse" />
        </operation>
    </portType>
    <binding name="PersonalInfoServicePortBinding" type="tns:PersonalInfoService">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
        <operation name="register">
            <soap:operation soapAction="" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
        </operation>
    </binding>
    <service name="PersonalInfoServiceService">
        <port name="PersonalInfoServicePort" binding="tns:PersonalInfoServicePortBinding">
            <soap:address location="http://192.168.0.210:8080/personalInfoService" />
        </port>
    </service>
</definitions>

 

  – 수정 후 WSDL

<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://malchooni.name/PInfo" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://malchooni.name/PInfo" name="PInfoService">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://malchooni.name/PInfo" schemaLocation="http://192.168.0.210:8080/personalInfoService?xsd=1" />
        </xsd:schema>
    </types>
    <message name="PInfoOpr">
        <part name="parameters" element="tns:PInfoOpr" />
    </message>
    <message name="PInfoOprResponse">
        <part name="parameters" element="tns:PInfoOprResponse" />
    </message>
    <portType name="PInfo_by_ijyoon">
        <operation name="PInfoOpr">
            <input wsam:Action="PInfoAction" message="tns:PInfoOpr" />
            <output wsam:Action="http://malchooni.name/PInfo/PInfo_by_ijyoon/PInfoOprResponse" message="tns:PInfoOprResponse" />
        </operation>
    </portType>
    <binding name="PInfoPortBinding" type="tns:PInfo_by_ijyoon">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
        <operation name="PInfoOpr">
            <soap:operation soapAction="PInfoAction" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
        </operation>
    </binding>
    <service name="PInfoService">
        <port name="PInfoPort" binding="tns:PInfoPortBinding">
            <soap:address location="http://192.168.0.210:8080/personalInfoService" />
        </port>
    </service>
</definitions>

  @WebParam @WebResult는 요청,응답 xml 스키마 발행 시 엘리먼트의 이름과 연관이 깊다. 두 어노테이션은 따로 언급하지 않겠다.

 

  마지막으로 만든 모듈을 서비스 해 보겠다. was 기반이 아닌 간단하게 서비스 발행하려면 javax.xml.ws.Endpoint 클래스의 publish 메서드를 사용하면 프로바이더를 생성하여 준다.

 

/**
 * simple binding test.
 * @param args
 */
public static void main(String[] args){
    System.out.println("start web service.");
    Endpoint.publish("http://192.168.0.198:8080/personalInfoService", new PersonalInfoService());
}

  파라미터로 URL과 해당 웹서비스의 객체를 넘겨주었다. 서비스 주소 끝에 ?wsdl 파라미터를 넘겨주면 서비스의 WSDL을 열람할 수 있다.

http://192.168.0.198:8080/personalInfoService?wsdl

  was기반에 올려야 할 경우 구현된 서블릿클래스가 있는 라이브러리를 참조한다. 대표적으로 apache cxf metro, apache axis 여러가지가 있다. 라이브러리 별로 web.xml(servlet class설정)과 그 종속적인 설정 파일이 존재한다.

 

wsdl2java 간편한 웹서비스 클라이언트 생성

웹서비스 제공자가 발행하는 WSDL만 있으면 손쉽게 웹서비스 클라이언트를 생성할 수 있다. Apache CXF 라이브러리를 다운로드하고 wsdl2java 명령어를 사용하여 손쉽게 자바 코드를 생성할 수 있다. �

malchooni.name

 

반응형