Microsoft MVP성태의 닷넷 이야기
Java: 7. 닷넷 개발자가 구현해 본 자바 웹 서비스 (1) [링크 복사], [링크+제목 복사]
조회: 29356
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 2개 있습니다.)

닷넷 개발자가 구현해 본 자바 웹 서비스 (1)

아직, 자바에 대한 큰 그림이 그려지지 않아서 정확히는 모르겠지만 자바에서는 자체적인 클래스 라이브러리에 웹 서비스 기능이 포함되어 있지 않아서, 공개된 외부 라이브러리를 사용해야 하는 것 같습니다. 자바 웹 서비스로 검색해 보면, 대표적으로 "Apache SOAP 3.0"이 나오는데 그 이름보다는 Axis(Apache eXtensible Interaction System)라고 알려주면 아시는 분들이 더 많을 것입니다. ^^ 저 역시 예전에 자바 개발자와 일한 적이 있었는데, 웹 서비스 노출을 Axis로 했다고 해서 ^^ 들어보기는 했었습니다.

Apache Web Services - Axis
; http://ws.apache.org/axis/

마지막 업데이트가 2006년 4월의 1.4 버전이니, 5년이 넘었군요.

Axis를 얹을 웹 서버가 필요한데, 저는 쉽게 Tomcat 기반으로 해보았습니다. (아직, 웹 로직 같은 것은 잘 모르는 단계입니다. ^^) 웹 검색을 해보면 다행히 이에 대한 자료가 쉽게 검색됩니다.

Axis 설치 및 톰캣과의 연동
; http://tequiero35.egloos.com/901100

(닷넷과 비교해서) 자바의 웹 서비스가 특이한 점이 있다면, XML 파서가 별도로 존재한다는 점입니다. 아마도 기본 파서가 있는 것 같은데, 외부에서 제공된 더 나은 XML Parser를 plug-in식으로 사용하는 것이 가능한 것 같습니다. 알아본 바로는, 보통 Xerces XML Parser를 쓰는 것이 권장된다고 하는데, 톰캣의 경우 기본 라이브러리에 포함되어 있다고 하지만 웹 서비스 접속을 하는 클라이언트 측 어플리케이션의 경우에는 xerces.jar 파일을 같이 배포해 주어야 한다고 합니다.





Tomcat에 Axis 설치

자, 그럼 이제 Axis를 Tomcat에 설치해 보겠습니다. 사실 윈도우 사용자들은 설치하면 setup.exe를 떠올릴 텐데 자바 쪽으로 오게 되면 전부 '파일 복사' 정도로 생각하시면 편합니다.

따라서, Axis 역시 다운로드한 파일의 압축을 풀고, [axis 폴더]\webapps\axis 폴더를 [tomcat 설치폴더]\webapps\axis 폴더로 복사해 주는 것으로 설치 과정이 끝납니다.

java_webservice_0.png

확인을 위해 tomcat을 실행하고 "http://localhost:8080/axis/" 경로를 방문해서 다음과 같이 나오면 정상적으로 설치가 된 것입니다.

java_webservice_1.png

위의 단계는 Axis 모듈이 잘 구동되고 있다는 사실만을 알려주는 것이고, 부가적으로 Axis가 주변 라이브러리와의 연동을 통해 정상적인 웹 서비스를 할 수 있는 환경이 마련되어 있는지를 확인하기 위해 위의 링크에서 "Validation"을 눌러서 방문해 보는 것이 좋습니다.

참고로, 위의 그림에 나온 "List"에 한번 관심을 가져볼까요? ^^ 이를 누르면 다음과 같이 2가지 웹 서비스가 나열됩니다.

java_webservice_2.png

이 중에서 "AdminService" 항목이 재미있는데요. 닷넷의 경우에는 asmx 파일을 Web Application 폴더에 복사하고 asmx.cs 파일이 빌드된 것을 /bin 폴더에 위치시키기만 하면 웹 서비스가 가능해지는데요. (닷넷의 용어와 비교해서 설명하면) Axis에서는 웹 서비스의 주소 역할을 하는 asmx가 없는 대신 별도의 등록 과정을 거쳐야만 asmx.cs에 해당하는 .class 파일이 외부로 노출이 됩니다. 바로 그 등록 과정을 위해 Axis에서는 AdminService라는 웹 서비스를 제공해 주는 구조입니다.

자바는 위와 같이 .class 파일을 배포하는 것 외에, 소스 코드인 .java 파일을 확장자만 .jws로 바꿔서 배포하는 것도 가능합니다. 그런데, 소스 코드의 보안 상 .jws보다는 .class 파일 배포가 (불편함에도 불구하고) 더 선호된다고 합니다.

자, 그럼 준비가 되었으니 이 정도 지식을 가지고, 한번 도전해 볼까요? ^^





1. .class 유형으로 배포되는 자바 웹 서비스 제작

이클립스에 임의의 프로젝트를 하나 만들고, HelloService.java 파일을 추가합니다.

public class HelloService {

    public String Echo(String text)
    {
        return "Hello " + text;
    }
}

빌드를 한 후, HelloService.java 파일이 있는 폴더에 deploy.wsdd라는 텍스트 파일을 만들고, Axis 압축을 해제한 폴더의 하위에서 '\samples\stock\deploy.wsdd'의 내용을 적당히 베껴 다음과 같이 내용을 채워넣습니다. (아직 제 수준에서 wsdd 파일의 정확한 규격을 알 수는 없습니다. ^^;)

<deployment name="test" xmlns="http://xml.apache.org/axis/wsdd/" 
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

  <service name="HelloService" provider="java:RPC">
    <parameter name="className" value="HelloService"/>
    <parameter name="allowedMethods" value="Echo"/>
    <parameter name="wsdlServicePort" value="Echo"/>
  </service>

</deployment>

그리고 나서, 다음과 같은 빌드 및 배포를 할 수 있는 배치(Batch) 파일을 만듭니다.

REM =========== 아래와 같이 CLASSPATH를 걸어줘야
set CLASSPATH=.;D:\Interop\axis-1_4\lib\axis.jar;D:\Interop\axis-1_4\lib\jaxrpc.jar;D:\Interop\axis-1_4\lib\log4j-1.2.8.jar;D:\Interop\axis-1_4\lib\commons-logging-1.0.4.jar;D:\Interop\axis-1_4\lib\commons-discovery-0.2.jar

REM =========== 이 단계에서 org.apache.axis.client.AdminClient를 찾아서 실행하는 것이 가능하고,
REM =========== AdminClient 클래스는 "-l" 옵션으로 지정된 웹 서비스를 호출해서 deploy.wsdd의 내용을 등록
java org.apache.axis.client.AdminClient -lhttp://localhost:8080/axis/services/AdminService deploy.wsdd

REM =========== .class 파일을 tomcat에 배포된 Axis에서 찾을 수 있도록 복사
robocopy ..\bin ...[tomcat 설치 폴더]...\webapps\axis\WEB-INF\classes HelloService.class


이쯤에서 톰캣을 실행해 두고 위의 배치 파일을 실행하면 정상적으로 등록된 경우 다음과 같은 출력 결과를 볼 수 있습니다.

...[생략]...>set CLASSPATH=.;..[생략]...\axis-1_4\lib\axis.jar;...[생략]...\axis-1_4\lib\jaxrpc.jar;...[생략]...\axis-1_4\lib\log4j-1.2.8.jar;...[생략]...\axis-1_4\lib\commons-logging-1.0.4.jar;...[생략]...\axis-1_4\lib\commons-discovery-0.2.jar

...[생략]...\workspace\Test1\src>java org.apache.axis.client.AdminClient -lhttp://localhost:8080/axis/services/AdminService deploy.wsdd
log4j:WARN No appenders could be found for logger (org.apache.axis.i18n.ProjectResourceBundle).
log4j:WARN Please initialize the log4j system properly.
Processing file deploy.wsdd
<Admin>Done processing</Admin>

...[생략]...\workspace\Test1\src>robocopy ..\bin ...[tomcat 설치 폴더]...\webapps\axis\WEB-INF\classes HelloService.class

이어서, "http://localhost:8080/axis/servlet/AxisServlet" URL을 방문하면 다음과 같이 정상적으로 배포된 것을 확인할 수 있습니다.

java_webservice_3.png

휴... 복잡하군요. 일단 자바 웹 서비스가 목표이니 클라이언트 쪽은 닷넷으로 간단히 마무리 하겠습니다. 우선, WSDL을 알아야 하는데 위의 화면에서 링크가 제공되고 있으니 이를 가지고 Visual Studio에서 가져오기만 하면 됩니다.

HelloService WSDL - http://localhost:8080/axis/services/HelloService?wsdl

역시, 음... 제게는 Eclipse보다는 Visual Studio가 편하군요. 아래와 같이 ^^ 금방, 자바 웹 서비스를 닷넷에서 호출한 결과를 볼 수 있습니다.

java_webservice_4.png


2. .jws 유형으로 배포되는 자바 웹 서비스 제작

위에서는 복잡하게 AdminService를 이용해서 웹 서비스를 등록해 주는 과정이 필요했지만, jws 파일로 배포하는 경우에는 이런 불편함이 없어집니다.

예를 들어, 다음과 같이 CalcService.java 코드를 만들고,

public class CalcService {
    public int Add(int a, int b)
    {
        return a + b;
    }
}

해당 파일을 빌드해서 오류가 없다는 것만 확인하고, 확장자를 .jws로 변경한 다음 ...[tomcat 설치 폴더]...\webapps\axis 폴더에 복사해 주면 됩니다.

오~~~ 훨씬 간결하군요. ^^

이제 웹 브라우저로 "http://localhost:8080/axis/CalcService.jws" 링크를 방문해서 확인해보면 WSDSL 링크가 출력되고,

java_webservice_5.png

이렇게 얻어진 "http://localhost:8080/axis/CalcService.jws?wsdl" 주소를 Visual Studio의 '웹 서비스 참조' 대화상자를 이용해서 프록시 코드를 생성하면 정상적으로 호출할 수 있게 됩니다.

참고로, jws로 배포한 경우, Axis는 CalcService.jws로 요청이 들어오는 시점에 컴파일을 해서 "...[tomcat 설치 폴더]...\webapps\axis\WEB-INF\jwsClasses" 폴더에 CalcService.class 파일로 보관하고 서비스를 합니다.

(여기까지 실습한 서버 측 자바 코드클라이언트 측 닷넷 코드를 첨부합니다.)



실행 시에 아래와 같은 식의 오류들이 발생한다면 Axis에 포함된 jar 파일들에 대한 CLASSPATH가 정상적으로 잡히지 않은 것이니 참고하시고.

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/axis/client/AdminClient
Caused by: java.lang.ClassNotFoundException: org.apache.axis.client.AdminClient
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: org.apache.axis.client.AdminClient.  Program will exit.

Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/rpc/ServiceException
Caused by: java.lang.ClassNotFoundException: javax.xml.rpc.ServiceException
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: org.apache.axis.client.AdminClient.  Program will exit.

Exception in thread "main" java.lang.NoClassDefFoundError: org.apache.commons.logging.LogFactory
        at org.apache.axis.components.logger.LogFactory.class$(LogFactory.java:45)
        at org.apache.axis.components.logger.LogFactory$1.run(LogFactory.java:45)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.apache.axis.components.logger.LogFactory.getLogFactory(LogFactory.java:41)
        at org.apache.axis.components.logger.LogFactory.<clinit>(LogFactory.java:33)
        at org.apache.axis.client.AdminClient.<clinit>(AdminClient.java:48)
Could not find the main class: org.apache.axis.client.AdminClient.  Program will exit.

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/discovery/tools/DiscoverSingleton
        at org.apache.axis.components.logger.LogFactory$1.run(LogFactory.java:45)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.apache.axis.components.logger.LogFactory.getLogFactory(LogFactory.java:41)
        at org.apache.axis.components.logger.LogFactory.<clinit>(LogFactory.java:33)
        at org.apache.axis.client.AdminClient.<clinit>(AdminClient.java:48)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.discovery.tools.DiscoverSingleton
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 5 more
Could not find the main class: org.apache.axis.client.AdminClient.  Program will exit.

그리고, "http://localhost:8080/axis/servlet/AxisServlet"으로 확인했는데 다음과 같은 오류가 발생한다면?

And now... Some Services
AXIS error
Sorry, something seems to have gone wrong... here are the details:

Fault - Could not find class for the service named: HelloService
Hint: you may need to copy your class files/tree into the right location (which depends on the servlet system you are using).; nested exception is: 
    java.lang.ClassNotFoundException: HelloService
AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.generalException
 faultSubcode: 
 faultString: Could not find class for the service named: HelloService
Hint: you may need to copy your class files/tree into the right location (which depends on the servlet system you are using).; nested exception is: 
    java.lang.ClassNotFoundException: HelloService
 faultActor: 
 faultNode: 
 faultDetail: 
    {http://xml.apache.org/axis/}hostname:TESTPC

HelloService.class 파일을 찾을 수 없다는 것인데, ...[tomcat 설치 폴더]...\webapps\axis\WEB-INF\classes 폴더에 HelloService.class 파일을 정상적으로 배포했는지 검사하면 됩니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/21/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13382정성태6/25/20233480.NET Framework: 2130. C# - Win32 API를 이용한 윈도우 계정 정보 (예: 마지막 로그온 시간)파일 다운로드1
13381정성태6/25/20233869오류 유형: 869. Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
13380정성태6/24/20233303스크립트: 52. 파이썬 3.x에서의 동적 함수 추가
13379정성태6/23/20233309스크립트: 51. 파이썬 2.x에서의 동적 함수 추가
13378정성태6/22/20233208오류 유형: 868. docker - build 시 "CANCELED ..." 뜨는 문제
13377정성태6/22/20237082오류 유형: 867. 파이썬 mysqlclient 2.2.x 설치 시 "Specify MYSQLCLIENT_CFLAGS and MYSQLCLIENT_LDFLAGS env vars manually" 오류
13376정성태6/21/20233429.NET Framework: 2129. C# - Polly를 이용한 클라이언트 측의 요청 재시도파일 다운로드1
13375정성태6/20/20233110스크립트: 50. Transformers (신경망 언어모델 라이브러리) 강좌 - 2장 코드 실행 결과
13374정성태6/20/20233216오류 유형: 866. 파이썬 - <class 'AttributeError'> module 'flask.json' has no attribute 'JSONEncoder'
13373정성태6/19/20234534오류 유형: 865. 파이썬 - pymssql 설치 관련 오류 정리
13372정성태6/15/20233214개발 환경 구성: 682. SQL Server TLS 통신을 위해 사용되는 키 길이 확인 방법
13371정성태6/15/20233245개발 환경 구성: 681. openssl - 인증서 버전(V1 / V3)
13370정성태6/14/20233416개발 환경 구성: 680. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 - TLS 1.2 지원
13369정성태6/13/20233239개발 환경 구성: 679. PyCharm(을 비롯해 JetBrains에 속한 여타) IDE에서 내부 Window들의 탭이 없어진 경우
13368정성태6/13/20233373개발 환경 구성: 678. openssl로 생성한 인증서를 SQL Server의 암호화 인증서로 설정하는 방법
13367정성태6/10/20233504오류 유형: 864. openssl로 만든 pfx 인증서를 Windows Server 2016 이하에서 등록 시 "The password you entered is incorrect" 오류 발생
13366정성태6/10/20233284.NET Framework: 2128. C# - 윈도우 시스템에서 지원하는 암호화 목록(Cipher Suites) 나열파일 다운로드1
13365정성태6/8/20233022오류 유형: 863. MODIFY FILE encountered operating system error 112(failed to retrieve text for this error. Reason: 15105)
13364정성태6/8/20233818.NET Framework: 2127. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 [1]
13363정성태6/7/20233378스크립트: 49. 파이썬 - "Transformers (신경망 언어모델 라이브러리) 강좌" - 1장 2절 코드 실행 결과
13362정성태6/1/20233322.NET Framework: 2126. C# - 서버 측의 요청 제어 (Microsoft.AspNetCore.RateLimiting)파일 다운로드1
13361정성태5/31/20233748오류 유형: 862. Facebook - ASP.NET/WebClient 사용 시 graph.facebook.com/me 호출에 대해 403 Forbidden 오류
13360정성태5/31/20233136오류 유형: 861. WSL/docker - failed to start shim: start failed: io.containerd.runc.v2: create new shim socket
13359정성태5/19/20233467오류 유형: 860. Docker Desktop - k8s 초기화 무한 반복한다면?
13358정성태5/17/20233797.NET Framework: 2125. C# - Semantic Kernel의 Semantic Memory 사용 예제 [1]파일 다운로드1
13357정성태5/16/20233576.NET Framework: 2124. C# - Semantic Kernel의 Planner 사용 예제파일 다운로드1
1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...